Policy contains a statement with one or more invalid principals - AWS Cloudformation error

10,868

Solution 1

In my case, I was trying to deploy a CdkPipeline stack that had stages with multiple accounts. I needed to run cdk bootstrap ${account}/${region} on each account and region where my stack was deployed.

cdk bootstrap 123456789012/us-west-2
cdk bootstrap 123456789012/us-east-1
cdk bootstrap 987654321098/us-east-1

I also had to give the second account permission as per this link.

  1. Go to the Role in IAM
  2. Select the Trust Relationships tab ...
  3. Then Edit Trust Relationship to include codepipeline
  4. Also add the arn of the other account's root
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "codepipeline.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:root",
          "arn:aws:iam::987654321098:root"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Solution 2

You need to confirm that all the principal arn that you are assigning the resources to are available in your AWS account or have been referenced properly or they have the correct spelling in the template. Atleast these are what I experienced.

Solution 3

You can set up the trust relationship from the cli with a flag in cdk bootstrap call:

npx cdk bootstrap \
--profile PROFILE2 \
--trust ACCOUNT1 \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess aws://ACCOUNT2/us-east-1

Reference article

Share:
10,868

Related videos on Youtube

fledgling
Author by

fledgling

Updated on June 04, 2022

Comments

  • fledgling
    fledgling almost 2 years

    I have a CF template as shown below

     AWSTemplateFormatVersion: '2010-09-09'
    Transform: AWS::Serverless-2016-10-31
    Description: gtm platform Lampda application deployment for ELasticCloud
    Parameters:
      SystemUserAccount:
        Description: The syatem user account used to assume deployment role
        Type: String
        Default: usr-test1
      DeploymentRoleName:
        Description: The deployment role used to deploy cloudformation template
        Type: String
        Default: gtm-platform-deployment-role
      GTMPlatformLambdaRoleName:
        Description: The execution role for gtm platform
        Type: String
        Default: gtm-platform-lambda-role
      GTMPlatformKMSKeyAliasName:
        Description: The lambda function name for gtm platform
        Type: String
        Default: gtm-platform-kms-key
    Resources:
      GTMPlatformLambdaRole:
        Type: AWS::IAM::Role
        DependsOn:
          - GTMPlatformKMSKey
        Properties:
          RoleName: !Ref GTMPlatformLambdaRoleName
          AssumeRolePolicyDocument:
            Version: '2008-10-17'
            Statement:
              - Sid: ''
                Effect: Allow
                Principal:
                  Service: lambda.amazonaws.com
                Action: sts:AssumeRole
          Path: /
          ManagedPolicyArns:
            - arn:aws:iam::aws:policy/CloudWatchFullAccess
            - arn:aws:iam::aws:policy/AmazonVPCFullAccess
          Policies:
            - PolicyName: GTMPlatformLambdaPolicy
              PolicyDocument:
                Version: '2012-10-17'
                Statement:
                  - Effect: Allow
                    Action: cloudwatch:*
                    Resource: "*"
                  - Effect: Allow
                    Action:
                      - kms:EnableKeyRotation
                      - kms:EnableKey
                      - kms:ImportKeyMaterial
                      - kms:Decrypt
                      - kms:UntagResource
                      - kms:UpdateKeyDescription
                      - kms:GetKeyPolicy
                      - kms:GenerateDataKeyWithoutPlaintext
                      - kms:CancelKeyDeletion
                      - kms:ListResourceTags
                      - kms:DeleteImportedKeyMaterial
                      - kms:DisableKey
                      - kms:DisableKeyRotation
                      - kms:ListGrants
                      - kms:UpdateAlias
                      - kms:GetParametersForImport
                      - kms:TagResource
                      - kms:Encrypt
                      - kms:GetKeyRotationStatus
                      - kms:ScheduleKeyDeletion
                      - kms:CreateAlias
                      - kms:DescribeKey
                      - kms:DeleteAlias
                    Resource: !GetAtt GTMPlatformKMSKey.Arn
                  - Effect: Allow
                    Action:
                      - kms:GenerateRandom
                      - kms:GenerateDataKey
                      - kms:ReEncryptTo
                      - kms:ReEncryptFrom
                    Resource: "*"
      GTMPlatformKMSKey:
        Type: AWS::KMS::Key
        Properties:
          Description: Key used to encrypt decrypt EBS volumes at rest
          Enabled: true
          KeyPolicy:
            Version: '2012-10-17'
            Statement:
              - Sid: Enable permissions for admin
                Effect: Allow
                Principal:
                  AWS: !Join
                    - ''
                    - - 'arn:aws:iam::'
                      - !Ref 'AWS::AccountId'
                      - ':root'
                Action:
                  - 'kms:*'
                Resource: '*'
              - Sid: Allow access for Key Administrators
                Effect: Allow
                Principal:
                  AWS:
                    - !Sub
                      - 'arn:aws:iam::${accountId}:role/${gtmDeploymentRoleName}'
                      - accountId: !Ref 'AWS::AccountId'
                        gtmDeploymentRoleName: !Ref 'DeploymentRoleName'
                Action:
                  - kms:Create*
                  - kms:Describe*
                  - kms:Enable*
                  - kms:List*
                  - kms:Put*
                  - kms:Update*
                  - kms:Revoke*
                  - kms:Disable*
                  - kms:Get*
                  - kms:Delete*
                  - kms:TagResource
                  - kms:UntagResource
                Resource: "*"
              - Sid: Allow use of the key
                Effect: Allow
                Principal:
                  AWS:
                    - !Sub
                      - 'arn:aws:iam::${accountId}:role/${gtmPlatformLambdaRoleName}'
                      - accountId: !Ref 'AWS::AccountId'
                        gtmPlatformLambdaRoleName: !Ref 'GTMPlatformLambdaRoleName'
                Action:
                  - kms:Encrypt
                  - kms:Decrypt
                  - kms:ReEncrypt*
                  - kms:GenerateDataKey*
                  - kms:DescribeKey
                Resource: "*"
              - Sid: Allow attachment of persistent resources
                Effect: Allow
                Principal:
                  AWS:
                    - !Sub
                      - 'arn:aws:iam::${accountId}:role/${gtmPlatformLambdaRoleName}'
                      - accountId: !Ref 'AWS::AccountId'
                        gtmPlatformLambdaRoleName: !Ref 'GTMPlatformLambdaRoleName'
                Action:
                  - kms:CreateGrant
                  - kms:ListGrants
                  - kms:RevokeGrant
                Resource: "*"
                Condition:
                  Bool:
                    kms:GrantIsForAWSResource: 'true'
      GTMPlatformKMSKeyAlias:
        Type: AWS::KMS::Alias
        DependsOn:
          - GTMPlatformKMSKey
        Properties:
          AliasName: !Join ['/', ['alias', !Ref GTMPlatformKMSKeyAliasName]]
          TargetKeyId: !GetAtt GTMPlatformKMSKey.Arn
    

    I am getting an error when the resource GTMPlatformKMSKey is getting created. It fails with CREATE_FAILED and error message

    Policy contains a statement with one or more invalid principals. (Service: AWSKMS; Status Code: 400; Error Code: MalformedPolicyDocumentException; Request ID: 5673456f-b458-45c6-854b-9ed63c737772)
    

    If I remove the Sid Allow use of the key and Allow attachment of persistent resources from GTMPlatformKMSKey the template runs fine. Not sure what I am missing here. Any help is much appreciated

    P.S. - Resources SystemUserAccount and DeploymentRoleName already exists in the environment

    Edit - As per the suggestion reduced the template to just include the failing resource

    • Arun Kamalanathan
      Arun Kamalanathan over 4 years
      can the sid contain spaces. give SID a value without spaces
    • John Rotenstein
      John Rotenstein over 4 years
      Can you please reduce the template down to the most relevant parts? (That is, remove the portions that do not impact your particular problem.) That way, we can attempt to diagnose or reproduce. For tips on asking a good question, please see: How do I ask a good question?
    • fledgling
      fledgling over 4 years
      @JohnRotenstein I have reduced the template can you take a look now
    • John Rotenstein
      John Rotenstein over 4 years
      Which particular policy is generating the error?
    • OK999
      OK999 over 4 years
      Why are you using the !Sub with a map/array? Pass it like a String e.g: ` !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}' ` . The error is in the way how you are trying to construct the principal like here: ``` Principal: AWS: - !Sub - 'arn:aws:iam::${accountId}:role/${gtmDeploymentRoleName}' - accountId: !Ref 'AWS::AccountId' gtmDeploymentRoleName: !Ref 'DeploymentRoleName' ```
    • fledgling
      fledgling over 4 years
      @JohnRotenstein The Sid: Allow use of the key is the one failing. I am trying to create the key and attach to the role in the same template. Is that an issue?
    • John Rotenstein
      John Rotenstein over 4 years
      I agree with @OK999. Try simply using !Sub 'arn:aws:iam::${AWS::AccountId}:role/${GTMPlatformLambdaRole‌​Name}'