This project is being archived as of Jan 2024. The application has been tested using CDK 2.122.0
and NodeJS 18
.
- Outcome
- Problem statement
- What do I need?
- How will this work?
- Where are my policies and tests?
- How are the tests written?
- Steps to deploy the stack
- Cleanup
- Security
- License
- Multi-OU service control policies (SCP) deployment pipeline
- Acceptance tests for the SCPs using behave tests and policy simulator
Customers need deployment and testing of their service control policies used for enabling services using AWS Organizations.
Let's consider the below AWS organisation structure.
- The AWS Organizations has three OUs
- Tools OU has the builder account for building the infrastructure
- Member accounts are split into production and sandbox OUs for the demo
- We have a test account in each OU
- As a pre-requisite for this code sample, you will need 3 AWS accounts
- Org management account which is the root account
- Builder account in the tools OU
- Test account in a sandbox OU
- Store the SCPs in a code-commit repository of the builder account
- This builder account will have a metadata file with the details of the SCPs and the OUs where it will be delivered
- The code pipeline will read the metadata file and execute the create or update for the SCPs
- The test account of the selected OU will be having a test suite which can be executed to verify the SCPs
- The test report output will provide us the summary of SCP acceptance tests
Contains all the SCPs you want to apply to your OUs within the organization. The source code is here
- Each folder within the scp folder maps to an organization unit (OU) in the org
infra-policies
└── scp
├── metadata.json
├── production
│ ├── allowed.json
│ └── restricted.json
├── sandbox
│ ├── allowed.json
│ └── restricted.json
└── tools
├── allowed.json
└── restricted.json
- Provide SCPs destination and files as declarative specifications in JSON
{
"ou-ids": [
{
"id": "ou-abcd-e3fghj1k",
"dir_name": "production",
"scps": ["allowed.json", "restricted.json"]
},
{
"id": "ou-abcd-vsp4rv23",
"dir_name": "sandbox",
"scps": ["allowed.json", "restricted.json"]
},
{
"id": "ou-abcd-un0t6khx",
"dir_name": "tools",
"scps": ["allowed.json", "restricted.json"]
}
]
}
Contains the acceptance tests using the policy simulator. Will be executed within the selected AWS test account residing in the OU. The source code is here
acceptance-tests
├── behave.ini
├── buildspec.yml
├── features
│ ├── appmesh-actions.feature
│ ├── appstream-actions.feature
│ ├── cloudformation-actions.feature
│ ├── dynamodb-actions.feature
│ ├── ec2-actions.feature
│ ├── iam-actions.feature
│ └── lambda-actions.feature
├── requirements.txt
└── steps
├── policy_simulator.py
└── step_impl.py
- We will use policy simulator to verify the IAM actions
- Below is a sample feature file for testing the IAM actions
Feature: Verify IAM actions
Scenario Outline: Check if the IAM actions are allowed
Given I invoke <service>:<action>
When the region selected is <region>
Then the status should be <result>
Examples:
| service | action | region | result |
| iam | ListPolicies | eu-west-2 | allowed |
| iam | GetPolicy | eu-west-2 | allowed |
| iam | TagRole | eu-west-2 | allowed |
| iam | DeleteRole | eu-west-2 | allowed |
| iam | DeleteRolePermissionsBoundary | eu-west-2 | allowed |
- The result of allowed or denied is based on the policy simulator response object
key
EvalDecision
- Below snippet asserts the response in the test implementation
if eval_decision in ['explicitDeny', 'implicitDeny']:
eval_decision = 'denied'
assert eval_decision == result
assert allowed_by_organisation is False
elif eval_decision == 'allowed':
assert eval_decision == result
assert allowed_by_organisation is True
- Ensure the AWS CLI v2 is configured and
AWS_DEFAULT_REGION
is setexport AWS_DEFAULT_REGION=$(aws configure get region) echo $AWS_DEFAULT_REGION
- Ensure you have node and npm installed
node -v npm -v
- Install
jq
. For macOS,brew install jq
- Install
git-remote-codecommit
-pip install git-remote-codecommit
- Clone this repository and install dependencies
npm install -g -f aws-cdk@2.122.0 cd $HOME && mkdir -p environment && cd environment git clone https://github.com/aws-samples/aws-service-control-policies-deployment cd $HOME/environment/aws-service-control-policies-deployment
- Export the AWS builder account ID for your infrastructure
export BUILDER_AWS_ACCOUNT_ID=123456789012 echo $BUILDER_AWS_ACCOUNT_ID
- Install project dependencies and build the project
npm install npm run build npm run test
- Export the AWS credentials for the org management account and execute the below commands
cdk bootstrap cdk deploy SetupOrgManagementStack export ORG_MANAGEMENT_ASSUMABLE_ROLE_ARN=$(aws cloudformation describe-stacks --stack-name SetupOrgManagementStack --query 'Stacks[*].Outputs[?ExportName==`orgManagementAssumableRoleArn`].OutputValue' --output text) echo $ORG_MANAGEMENT_ASSUMABLE_ROLE_ARN
- Export the AWS credentials of the builder account and clone the CodeCommit repository for storing
SCPs
cdk bootstrap cdk deploy SetupBuilderAccountStack export SCP_REPO_NAME=service-control-policies export SCP_REPO_URL=$(aws cloudformation describe-stacks --stack-name SetupBuilderAccountStack --query 'Stacks[*].Outputs[?ExportName==`scpRepoCloneUrlGrc`].OutputValue' --output text) cd $HOME/environment && git clone $SCP_REPO_URL && cd $SCP_REPO_NAME
- Edit the metadata.json to use the OU ids from your AWS Organizations
- Push the SCPs into the CodeCommit repository
cp -R $HOME/environment/aws-service-control-policies-deployment/repos-for-code-commit/policies/ . git checkout -b main git remote -v git add . git commit -m "First commit" git push --set-upstream origin main
- This will trigger the SCP deployment. Here is the successful execution screenshot
- Once completed successfully, proceed with below steps
- Export the AWS credentials of the test account and clone the CodeCommit repository for storing
acceptance tests
cdk bootstrap cdk deploy SetupMemberAccountStack export TESTS_REPO_NAME=acceptance-tests export TESTS_REPO_URL=$(aws cloudformation describe-stacks --stack-name SetupMemberAccountStack --query 'Stacks[*].Outputs[?ExportName==`acceptanceTestsRepoCloneUrlGrc`].OutputValue' --output text) cd $HOME/environment && git clone $TESTS_REPO_URL && cd $TESTS_REPO_NAME
- Push the acceptance tests into the CodeCommit repository
cp -R $HOME/environment/aws-service-control-policies-deployment/repos-for-code-commit/tests/ . git checkout -b main git remote -v git add . git commit -m "First commit" git push --set-upstream origin main
- This will trigger the acceptance tests using AWS CodeBuild
- The reports will be generated in the test account. Below is a sample acceptance test report.
- Delete the AWS CloudFormation stacks in following order
- SetupMemberAccountStack in test account
- SetupBuilderAccountStack in builder account
- SetupOrgManagementStack in org management account
- Detach the tools, sandbox and production SCPs created by this code from OUs in the org management account
- Delete the detached SCPs
- You will need to manually delete the S3 bucket in the builder account
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.