Integralist
Integralist

Reputation: 2211

AWS CloudFormation IAM policy and SQS policy seems to have similar settings, but not sure why?

I'm new to AWS CloudFormation and I'm trying to figure out some pre-existing CloudFormation JSON. I've read through the documentation many times, but I seem to end up with more questions than answers.

Below is a modified version of my CloudFormation file. I've tried to strip out as much as I can from the CloudFormation example to hopefully reduce the visual noise. I appreciate that readers wont know the reasoning for why certain things are done, but I'm hoping my questions (below) will highlight a more fundamental issue with how the CF has been written.

The CF JSON creates an SQS Queue, an SQS Queue Policy and an IAM policy.

The SQS Queue Policy allows complete API access to the SQS Queue (it also restricts access to certain ip addresses via a Condition) and appears to assign those permissions to the Queue itself.

But we also have an IAM policy which appears to do a similar thing? It assigns specific SQS Queue permissions, but this time to a Role rather than to the Queue itself like the SQS Queue Policy seems to be doing.

My question is why the duplication? Could we not just have the access permissions applied to the SQS Queue Policy and just remove the "QueuesPolicy" IAM policy?

I can kind of understand why the IAM policy "QueuesPolicy" would set SQS Queue access permissions: because you could have multiple roles accessing a single queue and you want them to have a different set of permissions (rather than the Queue having a concrete set of permissions for all roles). But if that's the case then why have permissions set on the queue as well? Does that look like a mistake or used as some kind of "fallback"?

I would also assume we could keep the SQS Queue Policy but just remove the API permissions and keep the ability to restrict its own access to certain ip addresses. Would that work in this example?

Also, the AWS::IAM::Role confuses me because I'm not really sure I understand what it's doing. It seems to suggest that the EC2 instance will have the ability to assume the FooRole, is that correct? I guess as we have a single set of AWS credentials, that an application running on the EC2 instance may well use the credentials to gain access to our AWS account but as there is no individual "users" we would need to have a role created and the EC2 instance have access to that role for a request (such as sending a message to the queue from the application) to be authorised?

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "EC2ComponentPolicy": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "EC2ComponentPolicy",
        "PolicyDocument": {
          "Statement": [
            {
              "Action": [
                "cloudformation:Describe*"
              ],
              "Resource": [
                "*"
              ],
              "Effect": "Allow"
            },
            {
              "Action": [
                "ec2:Describe*"
              ],
              "Resource": [
                "*"
              ],
              "Effect": "Allow"
            }
          ]
        },
        "Roles": [
          {
            "Ref": "FooRole"
          }
        ]
      }
    },
    "SQSFooQueue": {
      "Type": "AWS::SQS::Queue",
      "Properties": {
        "MessageRetentionPeriod": 86400,
        "VisibilityTimeout": {
          "Ref": "VisibilityTimeout"
        }
      }
    },
    "ComponentInstanceProfile": {
      "Type": "AWS::IAM::InstanceProfile",
      "Properties": {
        "Path": "/",
        "Roles": [
          {
            "Ref": "FooRole"
          }
        ]
      }
    },
    "SQSFooQueuePolicy": {
      "Type": "AWS::SQS::QueuePolicy",
      "Properties": {
        "Queues": [
          {
            "Ref": "SQSFooQueue"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Id": "SQSFooQueuePolicy",
          "Statement": [
            {
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "SQSFooQueue",
                    "Arn"
                  ]
                }
              ],
              "Effect": "Allow",
              "Sid": "Allow-User-SendMessage",
              "Action": [
                "sqs:*"
              ],
              "Condition": {
                "IpAddress": {
                  "aws:SourceIp": [
                    "xxx.xx.xxx.x/xx",
                    "xxx.xx.xxx.x/xx",
                    "xxx.xx.xxx.x/xx"
                  ]
                }
              },
              "Principal": {
                "AWS": "*"
              }
            }
          ]
        }
      }
    },
    "QueuesPolicy": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "QueuesPolicy",
        "PolicyDocument": {
          "Statement": [
            {
              "Action": [
                "sqs:AddPermission",
                "sqs:ChangeMessageVisibility",
                "sqs:ChangeMessageVisibilityBatch",
                "sqs:CreateQueue",
                "sqs:DeleteMessage",
                "sqs:DeleteMessageBatch",
                "sqs:DeleteQueue",
                "sqs:GetQueueAttributes",
                "sqs:GetQueueUrl",
                "sqs:ListQueues",
                "sqs:ListDeadLetterSourceQueues",
                "sqs:ReceiveMessage",
                "sqs:RemovePermission",
                "sqs:SendMessage",
                "sqs:SendMessageBatch",
                "sqs:SetQueueAttributes"
              ],
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "SQSFooQueue",
                    "Arn"
                  ]
                }
              ],
              "Effect": "Allow"
            }
          ]
        },
        "Roles": [
          {
            "Ref": "FooRole"
          }
        ]
      }
    },
    "FooRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "Path": "/",
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": [
                "sts:AssumeRole"
              ],
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "ec2.amazonaws.com"
                ]
              }
            }
          ]
        }
      }
    }
  }
}

Upvotes: 1

Views: 3053

Answers (1)

nik.shornikov
nik.shornikov

Reputation: 1935

I'll try to take your questions in order, but first give my general interpretation of this snippet. This might be a template for a AWS-based application that's going to run under an instance profile tied to the role in the snippet, and will use SQS to integrate with some off-cloud system in known IP ranges. Presumably it'll be updated to use the SDK, but obviously can't get temp credentials quite as easily as via the metadata endpoint.

  1. The queue policy and the IAM policy resource-reference the same queue, but they don't appear to be redundant. One's for anonymous users (which an IAM policy can't accomplish), the other for your EC2 instances.

  2. You may expand the queue policy to cover both apparent needs, but I personally prefer the principal-centric IAM policies. Likewise I'd use legacy S3 control options, for example, only when you can't use an IAM policy. But it's mainly a preference except where you must use a resource-tied policy.

Upvotes: 1

Related Questions