diff --git a/src/content/docs/aws/services/organizations.mdx b/src/content/docs/aws/services/organizations.mdx index a3e39d31..50a0cec7 100644 --- a/src/content/docs/aws/services/organizations.mdx +++ b/src/content/docs/aws/services/organizations.mdx @@ -88,6 +88,52 @@ To get started, start your LocalStack instance using your preferred method: awslocal organizations delete-organization ``` +## Service Control Policy enforcement + +[Service Control Policies (SCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) set the maximum permissions for accounts in your organization. +When IAM enforcement is enabled, LocalStack checks SCPs together with identity-based policies. +A request goes through only if both the principal's identity-based policies and the SCPs covering its account allow the action. + +To turn on SCP enforcement, start LocalStack with [`ENFORCE_IAM=1`](/aws/developer-tools/security-testing/iam-policy-enforcement) and enable the `SERVICE_CONTROL_POLICY` policy type on your organization root (see the [getting started](#getting-started) steps above). + +LocalStack evaluates SCPs at each level of the organization hierarchy: root, organizational unit, and account. +An action must be allowed by an SCP at every level between the root and the account. +If any level lacks an `Allow`, the result is an implicit deny, and an explicit `Deny` overrides any `Allow`. + +:::note +The organization's management (master) account is exempt from SCPs. +Principals in the management account are never restricted by SCPs, even with an explicit `Deny` SCP attached. +::: + +### Cross-account access + +LocalStack enforces SCPs for [cross-account access](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html), where a principal in one account uses a resource owned by another account. + +For a cross-account request, LocalStack checks the SCPs of the source account (the account making the request). +A deny in those SCPs blocks the request even when the target resource's policy grants access. + +Consider a member account that lists the objects of an S3 bucket in another account of the same organization, with a bucket policy that grants the member account access: + +```bash +# Run as the member (source) account +awslocal s3api list-objects-v2 --bucket cross-account-bucket +``` + +The default `FullAWSAccess` SCP lets the request succeed on the bucket policy. +Attach an SCP that denies `s3:ListBucket` to the member account, and the request fails: + +```bash title="Output" +An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::111111111111:user/test is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::cross-account-bucket" with an explicit deny in a service control policy +``` + +An SCP that allows only unrelated actions (for example, an `ec2:*`-only SCP) produces an implicit deny, since no SCP allows `s3:ListBucket`: + +```bash title="Output" +An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::111111111111:user/test is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::cross-account-bucket" because no service control policy allows the s3:ListBucket action +``` + +The management account stays exempt from SCPs for cross-account requests too. + ## API Coverage