CloudFormation: Limited-Privilege IAM Policies With cfn-nag

Hello!

This article is about security testing in CloudFormation, if you’re looking for functional testing, check out this.

When you write IAM policies, you should grant the smallest set of permissions that work. So, looking at this policy defined in a CloudFormation resource:

DemoPolicy:
  Type: AWS::IAM::Policy
  Properties:
    PolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
        Action:
          - ec2:DescribeInstances
        Resource: '*'
    PolicyName: star-required

The Resource: '*' looks wrong. It grants permission to make the DescribeInstances on all resources. It would be better if that were limited to specific resources. It’s easy to see in a code snippet like this one, but in a full template that defines a dozen policies it’s easy to miss.

Enter cfn-nag, a Ruby gem designed to detect insecure patterns in CloudFormation templates. If we run it on the template that contains the resource above, we get a warning (cfn_nag_scan is the CLI for the cfn-nag gem):

cfn_nag_scan --input-path ./demo_failing.yaml
------------------------------------------------------------
./demo_failing.yaml
------------------------------------------------------------------------------------------------------------------------
| WARN W12
|
| Resources: ["DemoPolicy"]
| Line Numbers: [5]
|
| IAM policy should not allow * resource

Failures count: 0
Warnings count: 1

Great! It auto-detects the '*' (star).

Here’s the problem: in this case star is required. Not all IAM permissions support resource-specification. Some of them, like ec2:DescribeInstances, require star as their resource. You can confirm this in the IAM documentation. Like most AWS services, EC2 has an Actions, Resources, and Condition Keys for Amazon EC2 page. Its Actions Defined by Amazon EC2 section describes when star is required.

So, we need to silence the warning for this resource. Fortunately, cfn-nag supports this. Here’s the modified CF:

DemoPolicy:
  Type: AWS::IAM::Policy
  Metadata:
    cfn_nag:
      rules_to_suppress:
        - id: W12
          reason: |
            At time of writing, ec2:DescribeInstances required '*' as its resource.
            https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonec2.html#amazonec2-actions-as-permissions
  Properties:
    PolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
        Action:
          - ec2:DescribeInstances
        Resource: '*'
    PolicyName: star-required

Now, cfn-nag runs without warning:

cfn_nag_scan --input-path ./demo_working.yaml 
------------------------------------------------------------
./demo_working.yaml
------------------------------------------------------------
Failures count: 0
Warnings count: 0

I recommend always including an explanation and a link to AWS documentation when you suppress a failure on a star resource. That way it’s clear to future readers (and auditors) why you granted all those permissions.

There’s a way to globally suppress warnings about star resources, but I recommend suppressing only on specific resources. This way, as you add new policies you’ll get warnings about cases where it is possible to limit the resources permissions apply to.

Happy securing!

Adam

If this was helpful and you want to save time by getting “copy and paste” patterns for Cloud DevOps in your inbox, subscribe here. If you don’t want to wait for the next one, check out these: