Search code examples
amazon-web-servicesaws-cloudformationamazon-iamserverlesspolicy

Cloudformation update stack policy condition on stack name or environment


I have a policy attached to my CloudFormation stack:

{
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "Update:*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Resource": "*",
      "Action": [
        "Update:Replace",
        "Update:Delete"
      ],
      "Condition": {
        "StringEquals": {
          "ResourceType": [
            "AWS::SNS::Topic",
            "AWS::SQS::Queue"
          ]
        }
      }
    }
  ]
}

The policy prevents accidental deleting of SNS/SQS resources. I want to make the policy more liberal in a dev environment. How do I disable the Deny statement conditionally, for example, if my CF (cloudformation) stack name is my-app-dev or the CF stack has a tag STAGE equal to dev?

Btw the policy is generated by the serverless framework, so I will have to write it in serverless.yml


Solution

  • This can be done by using the environment variables of the serverless framework.

    serverless.yml

    service: sample
    
    provider:
      name: aws
      stage: ${opt:stage,"dev"}
      region: ap-northeast-1
    
    custom:
      policyChange: 
        prd: Deny
        dev: Allow
    
    resources:
      - ${file(iam.yml)}
    

    iam.yml

    Resources:
      SampleRole:
        Type: AWS::IAM::Role
        Properties:
          RoleName: SampleRole
          AssumeRolePolicyDocument:
            Version: '2012-10-17'
            Statement:
            - Effect: Allow
              Principal:
                Service:
                - lambda.amazonaws.com
              Action:
              - sts:AssumeRole
          Path: "/"
          Policies:
            - PolicyName: SamplePolicy
              PolicyDocument:
                Version: '2012-10-17'
                Statement:
                - Effect: '${self:custom.policyChange.${self:provider.stage}}'
                  Resource: "*"
                  Action:
                  - sqs:*