Skip to content

[AWS::Logs::ResourcePolicy] - [BUG] - False-positive drift when PolicyDocument Principal.AWS is a bare account ID #2557

Description

@abidhasan-aws

Resource Name

AWS::Logs::ResourcePolicy

Issue Description

Deploying an AWS::Logs::ResourcePolicy whose PolicyDocument uses a bare account ID as the principal (for example "Principal": {"AWS": "123456789012"}) causes CloudFormation drift detection to always report the resource as MODIFIED, with no template changes and no manual edits to the policy.

The obvious fix (write the principal as the root ARN so it matches what is stored) does not work: CloudWatch Logs rejects that form at deploy time with HTTP 400 Principal section of policy contains ARN instead of account ID. One form deploys but always drifts; the other form does not deploy at all.

What happens step by step:

  1. Template sends "Principal": {"AWS": "123456789012"}.
  2. CloudWatch Logs stores it as "arn:aws:iam::123456789012:root".
  3. Drift detection diffs "123456789012" against "arn:aws:iam::123456789012:root" and reports drift.
  4. Re-deploying the same template is a no-op ("No changes to deploy"); drift is still reported. Forcing an update on an unrelated property (for example RetentionInDays) does not clear it, because CloudFormation only re-calls PutResourcePolicy when the policy body itself changes.

Impact: any stack that grants an account-root principal on a CloudWatch log group is permanently reported as drifted. This includes every CDK-managed log group whose resource policy takes an account principal, since CDK converts principals to the bare account ID form on purpose in LogGroup.addToResourcePolicy() (aws/aws-cdk#37797) precisely because CloudWatch Logs rejects the ARN form. Drift-based compliance checks and CI gates that require IN_SYNC produce constant false alarms.

Expected Behavior

StackDriftStatus: IN_SYNC immediately after deploy, since the template has not been modified and no one edited the policy out of band.

Observed Behavior

StackDriftStatus: DRIFTED
ResourceType:     AWS::Logs::ResourcePolicy
StackResourceDriftStatus: MODIFIED
PropertyDifferences[0]:
  PropertyPath:  /PolicyDocument
  ExpectedValue: ... "Principal":{"AWS":"123456789012"} ...
  ActualValue:   ... "Principal":{"AWS":"arn:aws:iam::123456789012:root"} ...
  DifferenceType: NOT_EQUAL

Test Cases

Save as repro.yaml (replace 123456789012 with your account ID):

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  LG:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: /cwl-drift-repro
      RetentionInDays: 1
  RP:
    Type: AWS::Logs::ResourcePolicy
    Properties:
      PolicyName: cwl-drift-repro-policy
      PolicyDocument: !Sub |
        {
          "Version":"2012-10-17",
          "Statement":[{
            "Sid":"AllowAccount",
            "Effect":"Allow",
            "Principal":{"AWS":"123456789012"},
            "Action":"logs:PutLogEvents",
            "Resource":"${LG.Arn}"
          }]
        }

Deploy, then run drift detection immediately (no changes in between):

STACK=cwl-drift-repro; REGION=us-east-1
aws cloudformation deploy --stack-name $STACK --template-file repro.yaml --region $REGION

TOKEN=$(aws cloudformation detect-stack-drift --stack-name $STACK --region $REGION \
  --query StackDriftDetectionId --output text)
while :; do
  S=$(aws cloudformation describe-stack-drift-detection-status \
        --stack-drift-detection-id $TOKEN --region $REGION --query DetectionStatus --output text)
  [ "$S" != "DETECTION_IN_PROGRESS" ] && break; sleep 5
done
aws cloudformation describe-stack-resource-drifts --stack-name $STACK --region $REGION

Direct CloudWatch Logs repro (confirms the rewrite happens in CloudWatch Logs, not CloudFormation):

# Rejected on write
aws logs put-resource-policy --policy-name test-arn \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Sid":"X","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"logs:PutLogEvents","Resource":"*"}]}'
# InvalidParameterException: Principal section of policy contains ARN instead of account ID

# Accepted, but read-back shows it was rewritten
aws logs put-resource-policy --policy-name test-bare \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Sid":"X","Effect":"Allow","Principal":{"AWS":"123456789012"},"Action":"logs:PutLogEvents","Resource":"*"}]}'
aws logs describe-resource-policies --query 'resourcePolicies[?policyName==`test-bare`].policyDocument' --output text
# "Principal":{"AWS":"arn:aws:iam::123456789012:root"}

Other Details

Reproduced in region: us-east-1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions