/** * Generates the standard KMS key policy statement for the Cerberus Management Service */ protected Statement generateStandardCMSPolicyStatement() { Statement cmsStatement = new Statement(Statement.Effect.Allow); cmsStatement.withId(CERBERUS_MANAGEMENT_SERVICE_SID); cmsStatement.withPrincipals(new Principal(AWS_PROVIDER, cmsRoleArn, false)); cmsStatement.withActions( KMSActions.Encrypt, KMSActions.Decrypt, KMSActions.ReEncryptFrom, KMSActions.ReEncryptTo, KMSActions.GenerateDataKey, KMSActions.GenerateDataKeyWithoutPlaintext, KMSActions.GenerateRandom, KMSActions.DescribeKey, KMSActions.ScheduleKeyDeletion, KMSActions.CancelKeyDeletion); cmsStatement.withResources(new Resource("*")); return cmsStatement; }
public String subscribeQueueToTopic(String snsTopicArn, String sqsQueueUrl){ Map<String, String> queueAttributes = sqsClient.getQueueAttributes(new GetQueueAttributesRequest(sqsQueueUrl) .withAttributeNames(QueueAttributeName.QueueArn.toString())).getAttributes(); String sqsQueueArn = queueAttributes.get(QueueAttributeName.QueueArn.toString()); Policy policy = new Policy().withStatements( new Statement(Effect.Allow) .withId("topic-subscription-" + snsTopicArn) .withPrincipals(Principal.AllUsers) .withActions(SQSActions.SendMessage) .withResources(new Resource(sqsQueueArn)) .withConditions(ConditionFactory.newSourceArnCondition(snsTopicArn))); logger.debug("Policy: " + policy.toJson()); queueAttributes = new HashMap<String, String>(); queueAttributes.put(QueueAttributeName.Policy.toString(), policy.toJson()); sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueUrl, queueAttributes)); SubscribeResult subscribeResult = snsClient.subscribe(new SubscribeRequest() .withEndpoint(sqsQueueArn) .withProtocol("sqs") .withTopicArn(snsTopicArn)); return subscribeResult.getSubscriptionArn(); }
/** * Generates a list of resources from the Resource Json Node. * * @param resourceNodes * the resource Json node to be parsed. * @return the list of resources. */ private List<Resource> resourcesOf(JsonNode resourceNodes) { List<Resource> resources = new LinkedList<Resource>(); if (resourceNodes.isArray()) { for (JsonNode resource : resourceNodes) { resources.add(new Resource(resource.asText())); } } else { resources.add(new Resource(resourceNodes.asText())); } return resources; }
/** * Writes the list of <code>Resource</code>s to the JSONGenerator. * * @param resources * the list of resources to be written. */ private void writeResources(List<Resource> resources) throws JsonGenerationException, IOException { List<String> resourceStrings = new ArrayList<String>(); for (Resource resource : resources) { resourceStrings.add(resource.getId()); } writeJsonArray(JsonDocumentFields.RESOURCE, resourceStrings); }
private static Statement getObjectCreatingStatement(String bucket, String userName) { return new Statement(Statement.Effect.Allow) .withActions( () -> "s3:PutObject", () -> "s3:GetObject" ) .withResources(new Resource("arn:aws:s3:::" + bucket + "/" + userName + "/*")); }
private static Statement getListBucketStatement(String bucket, String userName) { return new Statement(Statement.Effect.Allow) .withActions( () -> "s3:ListBucket" ) .withResources(new Resource("arn:aws:s3:::" + bucket)) .withConditions( new Condition() .withType("StringEquals") .withConditionKey("s3:prefix") .withValues(userName+"/") ); }
private String getPolicy(List<String> accountIds) { Policy policy = new Policy("AuthorizedWorkerAccessPolicy"); Statement stmt = new Statement(Effect.Allow); Action action = SQSActions.SendMessage; stmt.getActions().add(action); stmt.setResources(new LinkedList<>()); for(String accountId : accountIds) { Principal principal = new Principal(accountId); stmt.getPrincipals().add(principal); } stmt.getResources().add(new Resource(getQueueARN())); policy.getStatements().add(stmt); return policy.toJson(); }
public String generateStandardKmsPolicy(String iamRoleArn) { Policy kmsPolicy = new Policy(); Statement rootUserStatement = new Statement(Statement.Effect.Allow); rootUserStatement.withId("Root User Has All Actions"); rootUserStatement.withPrincipals(new Principal(AWS_PROVIDER, rootUserArn, false)); rootUserStatement.withActions(KMSActions.AllKMSActions); rootUserStatement.withResources(new Resource("*")); Statement keyAdministratorStatement = new Statement(Statement.Effect.Allow); keyAdministratorStatement.withId("Admin Role Has All Actions"); keyAdministratorStatement.withPrincipals(new Principal(AWS_PROVIDER, adminRoleArn, false)); keyAdministratorStatement.withActions(KMSActions.AllKMSActions); keyAdministratorStatement.withResources(new Resource("*")); Statement instanceUsageStatement = generateStandardCMSPolicyStatement(); Statement iamRoleUsageStatement = new Statement(Statement.Effect.Allow); iamRoleUsageStatement.withId(CERBERUS_CONSUMER_SID); iamRoleUsageStatement.withPrincipals( new Principal(AWS_PROVIDER, iamRoleArn, false)); iamRoleUsageStatement.withActions(KMSActions.Decrypt); iamRoleUsageStatement.withResources(new Resource("*")); kmsPolicy.withStatements(rootUserStatement, keyAdministratorStatement, instanceUsageStatement, iamRoleUsageStatement); return kmsPolicy.toJson(); }
public static String getPublicReadPolicy(String bucket_name) { Policy bucket_policy = new Policy().withStatements( new Statement(Statement.Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(S3Actions.GetObject) .withResources(new Resource( "arn:aws:s3:::" + bucket_name + "/*"))); return bucket_policy.toJson(); }
private String provisionKmsCmkForBackupRegion(String region) { Policy kmsPolicy = new Policy(); final List<Statement> statements = new LinkedList<>(); // allow the configured admin iam principals all permissions configStore.getBackupAdminIamPrincipals().forEach( principal -> { log.debug("Adding principal: {} to the CMK Policy for region {}", principal, region); statements.add(new Statement(Statement.Effect.Allow) .withId("Principal " + principal + " Has All Actions") .withPrincipals(new Principal(AWS_PROVIDER, principal, false)) .withActions(KMSActions.AllKMSActions) .withResources(new Resource("*"))); }); kmsPolicy.setStatements(statements); String policyString = kmsPolicy.toJson(); log.debug("Creating key for region {} with policy {}", region, policyString); AWSKMS kms = AWSKMSClient.builder().withCredentials(getAWSCredentialsProviderChain()).withRegion(region).build(); CreateKeyResult createKeyResult = kms.createKey( new CreateKeyRequest() .withPolicy(policyString) .withBypassPolicyLockoutSafetyCheck(true) .withDescription(String.format("Cerberus Backup Encryption key for env: %S region: %s", environmentMetadata.getName(), region)) .withTags( new Tag().withTagKey("env").withTagValue(environmentMetadata.getName()), new Tag().withTagKey("region").withTagValue(region), new Tag().withTagKey("cerberus-backup-key").withTagValue("true") ) ); String keyId = createKeyResult.getKeyMetadata().getKeyId(); log.info("Created new backup KMS CMK with id: {} for region: {}", keyId, region); return keyId; }
/** * Adds a permission to allow the specified actions to the given KMS key id. * * @param kmsKeyId Full ARN to the kms key * @param actions List of actions * * @return This builder */ @SuppressWarnings("PMD.CloseResource") public AwsPolicyBuilder withKms(String kmsKeyId, KmsActions... actions) { Statement statement = new Statement(Effect.Allow); statement.setActions(Arrays.asList(actions)); statement.setResources(Arrays.asList(new Resource(kmsKeyId))); policy.getStatements().add(statement); return this; }
/** * Adds a permission to allow the specified actions to the given bucket and s3 object key. The permission will allow the given actions only to the specified * object key. If object key is null, the permission is applied to the bucket itself. * * @param bucketName S3 bucket name * @param objectKey S3 object key * @param actions List of actions to allow * * @return This builder */ @SuppressWarnings("PMD.CloseResource") public AwsPolicyBuilder withS3(String bucketName, String objectKey, S3Actions... actions) { Statement statement = new Statement(Effect.Allow); statement.setActions(Arrays.asList(actions)); String resource = "arn:aws:s3:::" + bucketName; if (objectKey != null) { resource += "/" + objectKey; } statement.setResources(Arrays.asList(new Resource(resource))); policy.getStatements().add(statement); return this; }
private Boolean statementEquals(Statement statement1, Statement statement2) { List<Action> actions1 = statement1.getActions(); List<Action> actions2 = statement2.getActions(); boolean actionMatches = actions1.size() == actions2.size() && actions1.stream().allMatch(action1 -> actions2.stream().anyMatch(action2 -> action1.getActionName().equals(action2.getActionName()))); if (!actionMatches) return false; boolean effectMatches = statement1.getEffect().equals(statement2.getEffect()); if (!effectMatches) return false; List<Resource> resources1 = statement1.getResources(); List<Resource> resources2 = statement2.getResources(); boolean resourceMatches = resources1.size() == resources2.size() && resources1.stream().allMatch(resource1 -> resources2.stream().anyMatch(resource2 -> resource1.getId().equals(resource2.getId()))); if (!resourceMatches) return false; List<Condition> conditions1 = statement1.getConditions(); List<Condition> conditions2 = statement2.getConditions(); boolean conditionMatches = conditions1.size() == conditions2.size() && conditions1.stream().allMatch(condition1 -> conditions2.stream().anyMatch(condition2 -> conditionEquals(condition1, condition2))); if (!conditionMatches) return false; List<Principal> principals1 = statement1.getPrincipals(); List<Principal> principals2 = statement2.getPrincipals(); boolean principleMatches = principals1.size() == principals2.size() && principals1.stream().allMatch(principle1 -> principals2.stream().anyMatch(principal2 -> principleEquals(principle1, principal2))); if (!principleMatches) return false; return true; }
/** * Converts the given <code>Policy</code> into a JSON String. * * @param policy * the policy to be converted. * @return a JSON String of the specified policy object. */ private String jsonStringOf(Policy policy) throws JsonGenerationException, IOException { generator.writeStartObject(); writeJsonKeyValue(JsonDocumentFields.VERSION, policy.getVersion()); if (isNotNull(policy.getId())) writeJsonKeyValue(JsonDocumentFields.POLICY_ID, policy.getId()); writeJsonArrayStart(JsonDocumentFields.STATEMENT); for (Statement statement : policy.getStatements()) { generator.writeStartObject(); if (isNotNull(statement.getId())) { writeJsonKeyValue(JsonDocumentFields.STATEMENT_ID, statement.getId()); } writeJsonKeyValue(JsonDocumentFields.STATEMENT_EFFECT, statement .getEffect().toString()); List<Principal> principals = statement.getPrincipals(); if (isNotNull(principals) && !principals.isEmpty()) writePrincipals(principals); List<Action> actions = statement.getActions(); if (isNotNull(actions) && !actions.isEmpty()) writeActions(actions); List<Resource> resources = statement.getResources(); if (isNotNull(resources) && !resources.isEmpty()) writeResources(resources); List<Condition> conditions = statement.getConditions(); if (isNotNull(conditions) && !conditions.isEmpty()) writeConditions(conditions); generator.writeEndObject(); } writeJsonArrayEnd(); generator.writeEndObject(); generator.flush(); return writer.toString(); }
private static Statement getMultipartUploadStatement(String bucket, String userName) { return new Statement(Statement.Effect.Allow) .withActions(() -> "s3:ListBucketMultipartUploads") .withResources(new Resource("arn:aws:s3:::" + bucket)); }
@Override public void run(SetBackupAdminPrincipalsCommand command) { GetCallerIdentityResult identityResult = sts.getCallerIdentity(new GetCallerIdentityRequest()); String accountId = identityResult.getAccount(); String rootArn = String.format("arn:aws:iam::%s:root", accountId); String adminRoleArn = configStore.getAccountAdminArn().get(); Set<String> principals = new HashSet<>(); principals.add(rootArn); principals.add(adminRoleArn); principals.addAll(command.getAdditionalPrincipals()); configStore.storeBackupAdminIamPrincipals(principals); if (! configStore.getRegionBackupBucketMap().isEmpty()) { configStore.getRegionBackupBucketMap().forEach((region, backupRegionInfo) -> { final List<Statement> statements = new LinkedList<>(); principals.forEach( principal -> { log.debug("Adding principal: {} to the CMK Policy for region {}", principal, region); statements.add(new Statement(Statement.Effect.Allow) .withId("Principal " + principal + " Has All Actions") .withPrincipals(new Principal(AWS_PROVIDER, principal, false)) .withActions(KMSActions.AllKMSActions) .withResources(new Resource("*"))); }); Policy kmsPolicy = new Policy(); kmsPolicy.setStatements(statements); String policyString = kmsPolicy.toJson(); log.debug("Updating key {} for region {} with policy {}", backupRegionInfo.getKmsCmkId(), region, policyString); AWSKMS kms = AWSKMSClient.builder().withCredentials(getAWSCredentialsProviderChain()).withRegion(region).build(); PutKeyPolicyRequest request = new PutKeyPolicyRequest() .withKeyId(backupRegionInfo.getKmsCmkId()) .withPolicyName("default") .withBypassPolicyLockoutSafetyCheck(true) .withPolicy(policyString); kms.putKeyPolicy(request); log.info("Successfully updated key {} in region {} to allow the following principals access {}", backupRegionInfo.getKmsCmkId(), region, String.join(", ", principals)); }); } }
private static void allowSQSQueueToReceiveMessagesFromSNSTopic( AmazonSQS amazonSQS, String queueURL, String queueARN, String topicARN ) { GetQueueAttributesResult queueAttributesResult = amazonSQS.getQueueAttributes( new GetQueueAttributesRequest().withQueueUrl(queueURL).withAttributeNames( QueueAttributeName.Policy ) ); String policyJson = queueAttributesResult.getAttributes().get(QueueAttributeName.Policy.name()); final List<Statement> statements; if (policyJson != null) { statements = new ArrayList<>(Policy.fromJson(policyJson).getStatements()); } else { // no policies yet exist statements = new ArrayList<>(); } statements.add( new Statement(Statement.Effect.Allow) .withPrincipals(Principal.AllUsers) .withResources(new Resource(queueARN)) .withActions(SQSActions.SendMessage) .withConditions(ConditionFactory.newSourceArnCondition(topicARN)) ); Policy policy = new Policy(); policy.setStatements(statements); Map<String, String> queueAttributes = new HashMap<>(); queueAttributes.put(QueueAttributeName.Policy.name(), policy.toJson()); // Note that if the queue already has this policy, this will do nothing. amazonSQS.setQueueAttributes( new SetQueueAttributesRequest() .withQueueUrl(queueURL) .withAttributes(queueAttributes) ); }