UnapprovedServicesAndRolePlugin extends AbstractFullstopPlugin { @Override public void processEvent(final CloudTrailEvent event) { final String roleName = getRoleName(event); if (roleName == null) { LOG.info("Could not find roleName for event: {}, {} for account: {} and region: {}", event.getEventData().getEventId(), event.getEventData().getEventName(), event.getEventData().getAccountId(), event.getEventData().getAwsRegion()); return; } final List<String> errorMessages = newArrayList(); final RolePolicies rolePolicies = policyProvider.getRolePolicies(roleName, getRegion(event), getAccountId(event)); final Set<String> attachedPolicyNames = rolePolicies.getAttachedPolicyNames(); final Set<String> inlinePolicyNames = rolePolicies.getInlinePolicyNames(); final Set<String> expectedInlinePolicyNames = Collections.singleton(roleName); final String policyTemplate = policyTemplatesProvider.getPolicyTemplate(roleName); final String policy = rolePolicies.getMainPolicy(); if (!attachedPolicyNames.isEmpty()) { errorMessages.add("You MUST not attach additional policies to this role!"); } if (!Objects.equals(inlinePolicyNames, expectedInlinePolicyNames)) { errorMessages.add("You MUST not change the inline policies of this role"); } final JsonNode policyJson; final JsonNode templatePolicyJson; try { policyJson = objectMapper.readTree(policy); templatePolicyJson = objectMapper.readTree(policyTemplate); } catch (final IOException e) { LOG.warn("Could not read policy tree! For policy: {} and policy template: {}", policy, policyTemplate); return; } final JsonNode templateToPolicyDiff = JsonDiff.asJson(templatePolicyJson, policyJson); final JsonNode policyToTemplateDiff = JsonDiff.asJson(policyJson, templatePolicyJson); if (!templateToPolicyDiff.equals(emptyArray)) { errorMessages.add("You MUST not change the main policy document! See diffs for details."); } if (!errorMessages.isEmpty()) { violationSink.put( violationFor(event) .withPluginFullyQualifiedClassName(UnapprovedServicesAndRolePlugin.class) .withType(MODIFIED_ROLE_OR_SERVICE) .withMetaInfo(ImmutableMap .builder() .put("role_name", roleName) .put("error_messages", errorMessages) .put("attached_policy_names", attachedPolicyNames) .put("inline_policy_names", inlinePolicyNames) .put("expected_inline_policy_names", expectedInlinePolicyNames) .put("template_to_policy_diff", templateToPolicyDiff) .put("policy_to_template_diff", policyToTemplateDiff) .build()) .build()); } } @Autowired  UnapprovedServicesAndRolePlugin(final PolicyProvider policyProvider,
                                           final ViolationSink violationSink,
                                           final PolicyTemplatesProvider policyTemplatesProvider,
                                           final UnapprovedServicesAndRoleProperties unapprovedServicesAndRoleProperties); @Override boolean supports(final CloudTrailEvent event); @Override void processEvent(final CloudTrailEvent event);  }
@Test public void testProcessEventWithPolicyDiff() throws Exception { final RolePolicies rolePolicies = new RolePolicies(emptySet(), singleton("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), "{\"eventVersion\": \"1\"}"); when(policyProviderMock.getRolePolicies(any(), any(), any())).thenReturn(rolePolicies); when(policyTemplatesProviderMock.getPolicyTemplate(any())).thenReturn("{\"eventVersion\": \"2\"}"); plugin.processEvent(event); verify(policyProviderMock).getRolePolicies(eq("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), any(), any()); verify(policyTemplatesProviderMock).getPolicyTemplate(any()); verify(violationSinkMock).put(any(Violation.class)); }
@Test public void testProcessEventWithAdditionalAttachedPolicy() throws Exception { final String policy = "{\"eventVersion\": \"2\"}"; final RolePolicies rolePolicies = new RolePolicies(singleton("foo"), singleton("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), policy); when(policyProviderMock.getRolePolicies(any(), any(), any())).thenReturn(rolePolicies); when(policyTemplatesProviderMock.getPolicyTemplate(any())).thenReturn(policy); plugin.processEvent(event); verify(policyProviderMock).getRolePolicies(eq("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), any(), any()); verify(policyTemplatesProviderMock).getPolicyTemplate(any()); verify(violationSinkMock).put(any(Violation.class)); }
@Test public void testProcessEventWithChangedInlinePolicies() throws Exception { final String policy = "{\"eventVersion\": \"2\"}"; final RolePolicies rolePolicies = new RolePolicies(emptySet(), newHashSet("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ", "another-policy"), policy); when(policyProviderMock.getRolePolicies(any(), any(), any())).thenReturn(rolePolicies); when(policyTemplatesProviderMock.getPolicyTemplate(any())).thenReturn(policy); plugin.processEvent(event); verify(policyProviderMock).getRolePolicies(eq("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), any(), any()); verify(policyTemplatesProviderMock).getPolicyTemplate(any()); verify(violationSinkMock).put(any(Violation.class)); }
@Test public void testProcessEventNoViolation() throws Exception { final RolePolicies rolePolicies = new RolePolicies(emptySet(), singleton("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), POLICY_1); when(policyProviderMock.getRolePolicies(any(), any(), any())).thenReturn(rolePolicies); when(policyTemplatesProviderMock.getPolicyTemplate(any())).thenReturn(POLICY_2); plugin.processEvent(event); verify(policyProviderMock).getRolePolicies(eq("mint-worker-b17-AppServerRole-W5WX8WewafwO2MEWZ"), any(), any()); verify(policyTemplatesProviderMock).getPolicyTemplate(any()); }