Search code examples
amazon-s3aws-cloudformationamazon-iamwindows-server-2022

CloudFormation::Init fails to download S3 file with Access Denied


I'm trying to download a file from an S3 bucket onto a EC2 Windows server. I'm set up the IAM role, policy, and profile. In the CloudFormation::Init section of the server, I have different configSets and one of them is downloading a file from the bucket.

--- Some items not shown ---
"Parameters": {
        "S3BucketName": {
            "Description": "The name of an existing S3 bucket that the server needs to access.",
            "Type": "String",
            "Default": "ccw-to-rds-poc-1"
        },
--- Some parameters not shown ---
"InstanceRole":{
         "Type":"AWS::IAM::Role",
         "Properties":{
            "AssumeRolePolicyDocument":{
               "Statement":[
                  {
                     "Effect":"Allow",
                     "Principal":{
                        "Service":[
                           "ec2.amazonaws.com"
                        ]
                     },
                     "Action":[
                        "sts:AssumeRole"
                     ]
                  }
               ]
            },
            "Path":"/"
         }
      },
      "RolePolicies":{
         "Type":"AWS::IAM::Policy",
         "Properties":{
            "PolicyName":"S3Download",
            "PolicyDocument":{
               "Statement":[
                  {
                     "Action":[
                        "s3:GetObject"
                     ],
                     "Effect":"Allow",
                     "Resource": {"Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "S3BucketName"}]]}
                  }
               ]
            },
            "Roles":[
               {
                  "Ref":"InstanceRole"
               }
            ]
         }
      },
      "InstanceProfile":{
         "Type":"AWS::IAM::InstanceProfile",
         "Properties":{
            "Path":"/",
            "Roles":[
               {
                  "Ref":"InstanceRole"
               }
            ]
         }
      },
      "myAppServer": {
        "Type": "AWS::EC2::Instance",
        "Metadata": {
            "AWS::CloudFormation::Authentication": {
                "S3AccessCreds": {
                    "type": "S3",
                    "roleName": {
                        "Ref": "InstanceRole"
                    },
                    "buckets" : [{"Ref": "S3BucketName"}]
                }
            },
            "AWS::CloudFormation::Init": {
                "configSets": {
                    "downloadS3Data": ["downloadS3"],
                    "Full": [{"ConfigSet": "downloadS3Data"}, "fullServer"],
                    "default": [ {"ConfigSet": "Full"}],
                    "App": [{"ConfigSet": "downloadS3Data"}, "appServer"],
                    "Interface": [{"ConfigSet": "downloadS3Data"}, "interfaceServer"],
                    "Notification": [{"ConfigSet": "downloadS3Data"}, "notificationServer"]
                },
                "downloadS3": {
                    "files": {
                        "C:\\Users\\Administrator\\Documents\\s3download.bak": {
                            "source": "https://ccw-to-rds-poc-1.s3.us-east-2.amazonaws.com/test.txt",
                            "authentication": "S3AccessCreds"
                        }
                    }
                },
                "fullServer": {
                    "commands": {
                        "test": {
                            "command": "echo \"$MAGIC\"",
                            "env": {"MAGIC": "I am from the full server env"},
                            "cwd": "C:\\Users\\Administrator\\Desktop"
                        }
                    }
                },
                --- Some config sets not shown ---
            }
        },
        "Properties": {
            "IamInstanceProfile": {
                "Ref": "InstanceProfile"
            },
            "ImageId": "ami-012bb86d0081c5240",
            "InstanceType": "t2.small",
            "KeyName": {"Ref": "keypair"},
            "SecurityGroupIds": ["sg-0d0b50ca1774707b7"],
            "UserData" : {
                "Fn::Base64" : {
                    "Fn::Join" : [
                        "",
                        [
                            "<powershell>\n",
                                "cfn-init.exe -v -s ", {"Ref" : "AWS::StackId"}, " -r YourInstance -c ", {"Ref": "CCWServerType"} , " --region ", {"Ref" : "AWS::Region"}, "\n",
                            "</powershell>\n",
                            "<persist>true</persist>"
                        ]
                    ]
                }
            }

        }
    }

When the server runs "cfn-init.exe -v -s ", {"Ref" : "AWS::StackId"}, " -r YourInstance -c ", {"Ref": "CCWServerType"} , " --region ", {"Ref" : "AWS::Region"}, "\n",,

It creates the s3download.bak, but it is empty and gives an Access Denied, (HTTP Error 403). Is there something I'm not doing correctly with the IAM configurations that is causing this?

EDIT: I thought that because I am accessing the entire bucket and not just a specific item, like mentioned in this article that might be the issue. However, after trying "Action":["s3:*Object"] and "Action":["s3.Get*"], I still get the same access denied error.


Solution

  • The issue is with my IAM policy. I specified the bucket ARN as the resource for the s3:GetObject action, but for this action the resource needs to be an object(s). See AWS S3 Docs

    So I ended up adding to the end of my S3 ARN with a wildcard so I can get any object in the bucket.

    "Resource": {"Fn::Join": ["", ["arn:aws:s3:::", {"Ref": "S3BucketName"}, "/*"]]}