SCP evaluation mechanism and inheritance.
Organization administrator can use Service Control Policy (SCP) to control which AWS services can be used in member accounts. SCP are json documents which looks like an IAM policy. SCP can be attached at root level, at OU level, and at account level.
SCP works as filters. Multiple levels of SCP can be thought of as filters refining at each level. Inheritance does not aggregate like object oriented programming. This is a key concept to grasp.
One can deny a service in an SCP, which blocks the use of that service at the attached level and every level below it. Once denied at a upper level, the actions cannot be allowed at lower level.
One can also allow a service in an SCP. The following diagram illustrates how to allow selected services using permissive policies (no denial policy at all). By default, the FullAWSAccess policy is attached at every level. At the root level, that means all AWS services are allowed. If I detach the FullAWSAccess policy and replace it with a more restrictive policy, allowing only CloudTrail, Ec2, and Rds. That means all OUs and accounts below this root will only be able to use these 3 services.
Then at the OU level, I can remove the FullAWSAccess policy and attach another restrictive policy, allowing only Ec2 and Rds. That means any account under this OU will only be able to use Ec2 and Rds.
Finally, I can remove the FullAWSAccess policy on the account, and attach a third policy to the account, allowing only Ec2. The final effect on the account, is that only Ec2 will be allowed.
SCP works in implicit deny design. Any service that’s not explicitly allowed is denied. Therefore, in the above example, Rds cannot be used by the account, because it’s not explicitly allowed at the account level.
If you do not want to filter any permissions at account level, attach the OU policy to the account. AWS requires at least 1 policy be attached at every level. One cannot have 0 policy at account level.
Alternatively, one may attach the FullAWSAccess policy at account level and disable filtering at account level. The account will then inherit permissions from the OU level.
Here is an actual demo. In my AWS organization, I have 2 policies:
I attach the AllowNamedService policy at Root and OU level, and attach MinimalPermission policy at the account level. From the first look, it would seem like I’m allowing read permission for cloudtrail at the account level. But when I go to the account, I will be denied access to cloudtrail.
In order to allow that, I must add cloudtrail actions at the OU and root level. AWS also describe this requirement in the user guide.
This means that to allow an AWS service API at the member account level, you must allow that API at *every* level between the member account and the root of your organization.AWS User Guide
To explain it using the filter diagram above, CloudTrail actions are filtered out at the root and OU level, which means it’s implicitly denied. Allowing it at account level will have no effect.
Use SCP to control allowable services. For granular control, for example allowing a certain IAM role to perform certain action, it is recommended to use IAM policies.
SCP is not effective on the management account, aka the master payer account. Therefore, it is recommended to use the master payer account for payment consolidation and organization management. Deploying workload resources in the master payer account is not suggested.
When I work on SCP, I find https://asecure.cloud incredibly useful. They have some SCP template derived from well-architect review. They’re available in cloudformation and terraform format.