diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/DBService.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/DBService.java index 6bdd8dc0f63..9c2951c6879 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/DBService.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/DBService.java @@ -572,6 +572,7 @@ boolean processPolicy(ObjectStoreConnection con, Policy originalPolicy, String d if (!processPolicyTags(policy, policyName, domainName, originalPolicy, con)) { return false; } + auditLogTags(auditDetails, policy.getTags()); auditDetails.append('}'); return true; @@ -582,8 +583,12 @@ private boolean processPolicyTags(Policy policy, String policyName, String domai String policyVersion = policy.getVersion(); - BiFunction, Boolean> insertOp = (ObjectStoreConnection c, Map tags) -> c.insertPolicyTags(policyName, domainName, tags, policyVersion); - BiFunction, Boolean> deleteOp = (ObjectStoreConnection c, Set tagKeys) -> c.deletePolicyTags(policyName, domainName, tagKeys, policyVersion); + BiFunction, Boolean> insertOp = + (ObjectStoreConnection c, Map tags) -> + c.insertPolicyTags(policyName, domainName, tags, policyVersion); + BiFunction, Boolean> deleteOp = + (ObjectStoreConnection c, Set tagKeys) -> + c.deletePolicyTags(policyName, domainName, tagKeys, policyVersion); return processTags(con, policy.getTags(), (originalPolicy != null ? originalPolicy.getTags() : null) , insertOp, deleteOp); } @@ -850,8 +855,10 @@ boolean processGroup(ObjectStoreConnection con, Group originalGroup, final Strin private boolean processGroupTags(Group group, String groupName, String domainName, Group originalGroup, ObjectStoreConnection con) { - BiFunction, Boolean> insertOp = (ObjectStoreConnection c, Map tags) -> c.insertGroupTags(groupName, domainName, tags); - BiFunction, Boolean> deleteOp = (ObjectStoreConnection c, Set tagKeys) -> c.deleteGroupTags(groupName, domainName, tagKeys); + BiFunction, Boolean> insertOp = + (ObjectStoreConnection c, Map tags) -> c.insertGroupTags(groupName, domainName, tags); + BiFunction, Boolean> deleteOp = + (ObjectStoreConnection c, Set tagKeys) -> c.deleteGroupTags(groupName, domainName, tagKeys); return processTags(con, group.getTags(), (originalGroup != null ? originalGroup.getTags() : null) , insertOp, deleteOp); } @@ -1178,6 +1185,7 @@ boolean processServiceIdentity(ResourceContext ctx, ObjectStoreConnection con, S if (!processServiceIdentityTags(service, serviceName, domainName, originalService, con)) { return false; } + auditLogTags(auditDetails, service.getTags()); auditDetails.append('}'); return true; @@ -1297,47 +1305,21 @@ public Policy executePutPolicyVersion(ResourceContext ctx, String domainName, St // now we need process our policy assertions - List newAssertions = originalPolicy.getAssertions(); - if (newAssertions != null) { - for (Assertion assertion : newAssertions) { - - // get assertion conditions for original assertion - - AssertionConditions assertionConditions = new AssertionConditions(); - if (assertion.getId() != null) { - assertionConditions.setConditionsList(con.getAssertionConditions(assertion.getId())); - } - - // insert assertion (and get new assertion id) - - if (!con.insertAssertion(domainName, policyName, version, assertion)) { - con.rollbackChanges(); - throw ZMSUtils.internalServerError("unable to put policy: " + originalPolicy.getName() + - ", version: " + version + ", fail inserting assertion", caller); - } - - // copy assertion conditions for new assertion id - - if (assertionConditions.getConditionsList() != null && !assertionConditions.getConditionsList().isEmpty()) { - if (!con.insertAssertionConditions(assertion.getId(), assertionConditions)) { - con.rollbackChanges(); - throw ZMSUtils.internalServerError("unable to put policy: " + originalPolicy.getName() + - ", version: " + version + ", fail inserting assertion conditions", caller); - } - } - } + if (!processPolicyCopyAssertions(con, originalPolicy, domainName, policyName, version, auditDetails)) { + con.rollbackChanges(); + throw ZMSUtils.internalServerError("unable to put policy: " + originalPolicy.getName() + + ", version: " + version + ", fail copying assertions", caller); + } - // Log copied assertions and assertion conditions + // include all the tags from the original version - auditLogAssertions(auditDetails, "copied-assertions", newAssertions); - for (Assertion assertion : newAssertions) { - if (assertion.getId() != null) { - auditLogAssertionConditions(auditDetails, con.getAssertionConditions(assertion.getId()), - "copied-assertion-conditions"); - } - } + if (!processPolicyTags(originalPolicy, policyName, domainName, null, con)) { + con.rollbackChanges(); + throw ZMSUtils.internalServerError("unable to put policy: " + originalPolicy.getName() + + ", version: " + version + ", fail copying tags", caller); } + auditLogTags(auditDetails, originalPolicy.getTags()); auditDetails.append('}'); // update our domain time-stamp and save changes @@ -1350,6 +1332,7 @@ public Policy executePutPolicyVersion(ResourceContext ctx, String domainName, St policyName, auditDetails.toString()); // add domain change event + addDomainChangeMessage(ctx, domainName, policyName, DomainChangeMessage.ObjectType.POLICY); return returnObj == Boolean.TRUE ? getPolicy(con, domainName, policyName, version) : null; @@ -1362,6 +1345,43 @@ public Policy executePutPolicyVersion(ResourceContext ctx, String domainName, St } } + boolean processPolicyCopyAssertions(ObjectStoreConnection con, Policy policy, final String domainName, + final String policyName, final String version, StringBuilder auditDetails) { + + List assertions = policy.getAssertions(); + if (assertions == null) { + return true; + } + + auditLogAssertions(auditDetails, "copied-assertions", assertions); + for (Assertion assertion : assertions) { + + // get assertion conditions for original assertion + + AssertionConditions assertionConditions = new AssertionConditions(); + if (assertion.getId() != null) { + assertionConditions.setConditionsList(con.getAssertionConditions(assertion.getId())); + auditLogAssertionConditions(auditDetails, assertionConditions.getConditionsList(), + "copied-assertion-conditions"); + } + + // insert assertion (and get new assertion id) + + if (!con.insertAssertion(domainName, policyName, version, assertion)) { + return false; + } + + // copy assertion conditions for new assertion id + + if (assertionConditions.getConditionsList() != null && !assertionConditions.getConditionsList().isEmpty()) { + if (!con.insertAssertionConditions(assertion.getId(), assertionConditions)) { + return false; + } + } + } + return true; + } + Policy executePutPolicy(ResourceContext ctx, String domainName, String policyName, Policy policy, String auditRef, String caller, Boolean returnObj) { @@ -6139,13 +6159,16 @@ boolean auditLogAssertionCondition(StringBuilder auditDetails, AssertionConditio .append(", \"conditionsMap\": {"); boolean innerFirstEntry = true; for (String key : assertionCondition.getConditionsMap().keySet()) { - innerFirstEntry = auditLogAssertionConditionData(auditDetails, assertionCondition.getConditionsMap().get(key), key, innerFirstEntry); + innerFirstEntry = auditLogAssertionConditionData(auditDetails, assertionCondition.getConditionsMap().get(key), + key, innerFirstEntry); } auditDetails.append("}}"); return firstEntry; } - boolean auditLogAssertionConditionData(StringBuilder auditDetails, AssertionConditionData assertionConditionData, String conditionKey, boolean firstEntry) { + boolean auditLogAssertionConditionData(StringBuilder auditDetails, AssertionConditionData assertionConditionData, + String conditionKey, boolean firstEntry) { + firstEntry = auditLogSeparator(auditDetails, firstEntry); auditDetails.append("\"").append(conditionKey) .append("\": {\"operator\": \"").append(assertionConditionData.getOperator().name()) diff --git a/servers/zms/src/test/java/com/yahoo/athenz/zms/DBServiceTest.java b/servers/zms/src/test/java/com/yahoo/athenz/zms/DBServiceTest.java index e58b3e6a211..37ee178ca55 100644 --- a/servers/zms/src/test/java/com/yahoo/athenz/zms/DBServiceTest.java +++ b/servers/zms/src/test/java/com/yahoo/athenz/zms/DBServiceTest.java @@ -933,17 +933,21 @@ public void testExecutePutPolicyVersionMaxReached() { policy1, auditRef, "putPolicy", false); // Put new version - zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", null, auditRef, "putPolicyVersion", false); + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", + null, auditRef, "putPolicyVersion", false); // Put third version (max number is 3) - zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version2", null, auditRef, "putPolicyVersion", false); + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version2", + null, auditRef, "putPolicyVersion", false); // Trying to put another version will throw an exception try { - zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version3", null, auditRef, "putPolicyVersion", false); + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version3", + null, auditRef, "putPolicyVersion", false); fail(); } catch (Exception ex) { - assertEquals(ex.getMessage(), "ResourceException (429): {code: 429, message: \"unable to put policy: policy1, version: new-version3, max number of versions reached (3)\"}"); + assertEquals(ex.getMessage(), "ResourceException (429): {code: 429, message: \"unable to put " + + "policy: policy1, version: new-version3, max number of versions reached (3)\"}"); } zms.deleteTopLevelDomain(mockDomRsrcCtx, domainName, auditRef); @@ -956,16 +960,31 @@ public void testExecutePutPolicyVersionFailure() { Domain domain = new Domain().setAuditEnabled(false); Mockito.when(mockJdbcConn.getDomain(domainName)).thenReturn(domain); + Policy originalPolicyVersion = createPolicyObject(domainName, policyName); - Mockito.when(mockJdbcConn.insertPolicy(domainName, originalPolicyVersion)).thenReturn(true).thenReturn(false).thenReturn(true); - Mockito.when(mockJdbcConn.listAssertions(eq(domainName), eq(policyName), isNull())).thenReturn(originalPolicyVersion.getAssertions()); - Mockito.when(mockJdbcConn.listAssertions(domainName, policyName, "new-version")).thenReturn(originalPolicyVersion.getAssertions()); - Policy newPolicyVersion = createPolicyObject(domainName, policyName); - newPolicyVersion.setVersion("new-version"); - newPolicyVersion.setActive(false); - Mockito.when(mockJdbcConn.insertAssertion(eq(domainName), eq(policyName), isNull(), any())).thenReturn(true).thenReturn(false); - Mockito.when(mockJdbcConn.getPolicy(eq(domainName), eq(policyName), isNull())).thenReturn(null).thenReturn(originalPolicyVersion); + Map tags = new HashMap<>(); + tags.put("tagKey1", new TagValueList().setList(Collections.singletonList("tagValue1"))); + + Mockito.when(mockJdbcConn.insertPolicy(domainName, originalPolicyVersion)) + .thenReturn(true).thenReturn(false).thenReturn(true); + Mockito.when(mockJdbcConn.insertPolicyTags(domainName, policyName, tags, null)) + .thenReturn(true); + Mockito.when(mockJdbcConn.listAssertions(eq(domainName), eq(policyName), isNull())) + .thenReturn(originalPolicyVersion.getAssertions()); + Mockito.when(mockJdbcConn.listAssertions(domainName, policyName, "new-version")) + .thenReturn(originalPolicyVersion.getAssertions()); + + Mockito.when(mockJdbcConn.insertAssertion(eq(domainName), eq(policyName), isNull(), any())) + .thenReturn(true).thenReturn(false); + Mockito.when(mockJdbcConn.insertAssertion(eq(domainName), eq(policyName), eq("new-version"), any())) + .thenReturn(false).thenReturn(true); + Mockito.when(mockJdbcConn.insertPolicyTags(eq(domainName), eq(policyName), any(), eq("new-version"))) + .thenReturn(false); + Mockito.when(mockJdbcConn.getPolicy(eq(domainName), eq(policyName), isNull())) + .thenReturn(null).thenReturn(originalPolicyVersion); + Mockito.when(mockJdbcConn.getPolicyTags(eq(domainName), eq(policyName), isNull())) + .thenReturn(tags); ObjectStore saveStore = zms.dbService.store; zms.dbService.store = mockObjStore; @@ -973,22 +992,39 @@ public void testExecutePutPolicyVersionFailure() { zms.dbService.defaultRetryCount = 2; // Put policy - zms.dbService.executePutPolicy(mockDomRsrcCtx, domainName, policyName, originalPolicyVersion, auditRef, "putPolicy", false); + zms.dbService.executePutPolicy(mockDomRsrcCtx, domainName, policyName, originalPolicyVersion, + auditRef, "putPolicy", false); // Put policy version - simulate failure in inserting policy try { - zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", null, auditRef, "putPolicyVersion", false); + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", + null, auditRef, "putPolicyVersion", false); fail(); } catch (ResourceException ex) { - assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put policy: policy-put-policy-version-failure:policy.policy1, version: new-version\"}"); + assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put " + + "policy: policy-put-policy-version-failure:policy.policy1, version: new-version\"}"); } // Put policy version - simulate failure in inserting assertion try { - zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", null, auditRef, "putPolicyVersion", false); + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", + null, auditRef, "putPolicyVersion", false); + fail(); + } catch (ResourceException ex) { + assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put " + + "policy: policy-put-policy-version-failure:policy.policy1, version: new-version, " + + "fail copying assertions\"}"); + } + + // Put policy version - simulate failure in inserting tags + try { + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", + null, auditRef, "putPolicyVersion", false); fail(); } catch (ResourceException ex) { - assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put policy: policy-put-policy-version-failure:policy.policy1, version: new-version, fail inserting assertion\"}"); + assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put " + + "policy: policy-put-policy-version-failure:policy.policy1, version: new-version, " + + "fail copying tags\"}"); } zms.dbService.defaultRetryCount = saveRetryCount; @@ -1004,13 +1040,16 @@ public void testExecutePutPolicyVersionConditionsFailure() { Mockito.when(mockJdbcConn.getDomain(domainName)).thenReturn(domain); Policy originalPolicyVersion = createPolicyObject(domainName, policyName); Map conditionsMap = new HashMap<>(); - conditionsMap.put("cond1", new AssertionConditionData().setValue("testVal")); + conditionsMap.put("cond1", new AssertionConditionData() + .setOperator(AssertionConditionOperator.EQUALS).setValue("testVal")); final List assertionConditions = new ArrayList<>(); assertionConditions.add(new AssertionCondition().setConditionsMap(conditionsMap)); - originalPolicyVersion.getAssertions().get(0).setConditions(new AssertionConditions().setConditionsList(assertionConditions)); + originalPolicyVersion.getAssertions().get(0).setConditions( + new AssertionConditions().setConditionsList(assertionConditions)); originalPolicyVersion.getAssertions().get(0).setId(1L); Mockito.when(mockJdbcConn.insertPolicy(domainName, originalPolicyVersion)).thenReturn(true); - Mockito.when(mockJdbcConn.listAssertions(eq(domainName), eq(policyName), isNull())).thenReturn(originalPolicyVersion.getAssertions()); + Mockito.when(mockJdbcConn.listAssertions(eq(domainName), eq(policyName), isNull())) + .thenReturn(originalPolicyVersion.getAssertions()); Mockito.when(mockJdbcConn.getPolicy(eq(domainName), eq(policyName), isNull())).thenReturn(originalPolicyVersion); Mockito.when(mockJdbcConn.insertAssertion(eq(domainName), eq(policyName), any(), any())).thenReturn(true); Mockito.when(mockJdbcConn.getAssertionConditions(anyLong())).thenReturn(assertionConditions); @@ -1022,16 +1061,24 @@ public void testExecutePutPolicyVersionConditionsFailure() { // Put policy version - simulate failure in inserting assertion conditions try { - zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", null, auditRef, "putPolicyVersion", false); + zms.dbService.executePutPolicyVersion(mockDomRsrcCtx, domainName, policyName, "new-version", + null, auditRef, "putPolicyVersion", false); fail(); } catch (ResourceException ex) { - assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put policy: policy-put-policy-version-condition-failure:policy.policy1, version: new-version, fail inserting assertion conditions\"}"); + assertEquals(ex.getMessage(), "ResourceException (500): {code: 500, message: \"unable to put " + + "policy: policy-put-policy-version-condition-failure:policy.policy1, version: new-version, " + + "fail copying assertions\"}"); } zms.dbService.defaultRetryCount = saveRetryCount; zms.dbService.store = saveStore; } + @Test + public void testProcessPolicyAssertionsNull() { + assertTrue(zms.dbService.processPolicyCopyAssertions(null, new Policy(), null, null, null, null)); + } + @Test public void testExecuteSetActivePolicyFailure() { String domainName = "policy-set-active-failure";