简体   繁体   English

为什么此CloudFormation模板脚本不起作用?

[英]Why does this CloudFormation Template script not work?

I'm trying to create a stack on AWS CloudFormation, with an EC2 instance and 2 S3 buckets. 我正在尝试在AWS CloudFormation上创建一个具有EC2实例和2个S3存储桶的堆栈。 My script is attempting to assign a Policy to the EC2 instance that allows access to the Storage bucket, but no matter what I do the rights are not assigned. 我的脚本试图将策略分配给允许访问存储桶的EC2实例,但是无论我做什么,都不会分配权限。 Additionally, the userdata is not executed at all. 另外,根本不执行用户数据。

I tried testing thoroughly if the EC2 really does not have the rights: the CLI confirmed that it does not. 我尝试彻底测试EC2是否真的没有权限:CLI确认没有。 I replaced the userdata with a simple script making a textfile, it really is not created. 我用制作文本文件的简单脚本替换了用户数据,但实际上并没有创建。 AWS Designer gives no complaints and shows the correct template structure. AWS Designer不提出任何投诉,并显示正确的模板结构。 The stack description runs and executes with no errors, except the S3 storage bucket access and the user data don't work (no warnings). 堆栈描述运行并执行没有错误,除了对S3存储桶的访问和用户数据不起作用(无警告)外。

After a LOT of manual editing and checking very carefully with the documentation, I realised I should have done this in a higher level language. 经过大量的手动编辑并非常仔细地检查了文档之后,我意识到我应该使用更高级别的语言来完成此操作。 Therefore I tried to import the script in a simple python Troposphere script using the templateGenerator. 因此,我尝试使用templateGenerator将脚本导入简单的python Troposphere脚本中。 This leads to the following error (no other errors are created anywhere so far, everything just silently goes wrong, JSON syntax validators also have no complaints): 这导致以下错误(到目前为止,其他任何地方都未创建其他错误,所有内容都静默地出错了,JSON语法验证器也没有任何抱怨):

TypeError: <class 'troposphere.iam.PolicyType'>: MickStorageS3BucketsPolicy.PolicyDocument is <class 'list'>, expected (<class 'dict'>,)

However, clearly my PolicyDocument is of type dictionary, and I don't understand how it can be interpreted as a list. 但是,很明显,我的PolicyDocument是字典类型的,并且我不明白如何将其解释为列表。 I have stared at this for many hours now, I may have become blind to the problem but I would Really really appreciate any help at this point!!!! 我已经盯着这个看了好几个小时了,我可能对这个问题视而不见,但是在这一点上,我真的很感谢任何帮助!

The security group and inbound traffic settings do work properly, my dockerized flask app runs fine (on the EC2) but just can't access the bucket (though I have to start it manually through SSH because userdata won't execute, I also tried doing that using the CFN-init segment in the ec2 metadata (under commands) but nothing executes, even if I try to run CFNinit manually after connecting by SSH). 安全组和入站流量设置正常运行,我的dockerized flask应用运行良好(在EC2上),但无法访问存储桶(尽管由于用户数据无法执行,我不得不通过SSH手动启动它,我也尝试了使用ec2元数据中的CFN-init段(在命令下)执行此操作,但不会执行任何操作,即使我尝试通过SSH连接后手动运行CFNinit也是如此)。

This is the cloudformation template I wrote: 这是我编写的cloudformation模板:

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "Attach IAM Role to an EC2",
  "Parameters" : {
    "KeyName" : {
      "Description" : "EC2 Instance SSH Key",
      "Type" : "AWS::EC2::KeyPair::KeyName",
      "Default" : "MickFirstSSHKeyPair"
    },
    "InstanceType" : {
      "Description" : "EC2 instance specs configuration",
      "Type" : "String",
      "Default" : "t2.micro",
      "AllowedValues" : ["t2.micro", "t2.small", "t2.medium"]
    }
  },
  "Mappings" : {
    "AMIs" : {
      "us-east-1" : {
        "Name" : "ami-8c1be5f6"
      },
      "us-east-2" : {
        "Name" : "ami-c5062ba0"
      },
      "eu-west-1" : {
        "Name" : "ami-acd005d5"
      },
      "eu-west-3" : {
        "Name" : "ami-05b93cd5a1b552734"
      },
      "us-west-2" : {
        "Name" : "ami-0f2176987ee50226e"
      },
      "ap-southeast-2" : {
        "Name" : "ami-8536d6e7"
      }     
    }
  },
  "Resources" : {
    "mickmys3storageinstance" : {
      "Type" : "AWS::S3::Bucket",
      "Properties" : {

      }
    },
    "mickmys3processedinstance" : {
      "Type" : "AWS::S3::Bucket",
      "Properties" : {

      }
    },

    "MickMainEC2" : {
      "Type" : "AWS::EC2::Instance",
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "config" : {
            "files" : {

            },
            "commands" : {

            }

          }
        }
      },
      "Properties" : {
        "UserData": {
            "Fn::Base64" : "echo 'Heelo ww' > ~/hello.txt" 
        },
        "InstanceType" : {
          "Ref" : "InstanceType"
        },
        "ImageId" : {
          "Fn::FindInMap" : [
            "AMIs",
            {
              "Ref" : "AWS::Region"
            },
            "Name"
          ]
        },
        "KeyName" : {
          "Ref" : "KeyName"
        },
        "IamInstanceProfile" : {
          "Ref" : "ListS3BucketsInstanceProfile"
        },
        "SecurityGroupIds" : [
          {
            "Ref" : "SSHAccessSG"
          },
          {
            "Ref" : "PublicAccessSG"
          }
        ],
        "Tags" : [
          {
            "Key" : "Name",
            "Value" : "MickMainEC2"
          }
        ]
      }
    },
    "SSHAccessSG" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Allow SSH access from anywhere",
        "SecurityGroupIngress" : [
          {
            "FromPort" : "22",
            "ToPort" : "22",
            "IpProtocol" : "tcp",
            "CidrIp" : "0.0.0.0/0"
          }
        ],
        "Tags" : [
          {
            "Key" : "Name",
            "Value" : "SSHAccessSG"
          }
        ]
      }
    },
    "PublicAccessSG" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Allow HTML requests from anywhere",
        "SecurityGroupIngress" : [
          {
            "FromPort" : "80",
            "ToPort" : "80",
            "IpProtocol" : "tcp",
            "CidrIp" : "0.0.0.0/0"
          }
        ],
        "Tags" : [
          {
            "Key" : "Name",
            "Value" : "PublicAccessSG"
          }
        ]
      }
    },
    "ListS3BucketsInstanceProfile" : {
      "Type" : "AWS::IAM::InstanceProfile",
      "Properties" : {
        "Path" : "/",
        "Roles" : [
          {
            "Ref" : "MickListS3BucketsRole"
          }
        ]
      }
    },
    "MickStorageS3BucketsPolicy" : {
        "Type" : "AWS::IAM::Policy",
        "Properties" : {
            "PolicyName" : "MickStorageS3BucketsPolicy",

            "PolicyDocument" : {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Sid": "ListObjectsInBucket",
                        "Effect": "Allow",
                        "Action": [
                        "s3:ListBucket"
                        ],
                        "Resource": [
                            "arn:aws:s3:::mickmys3storageinstance", "arn:aws:s3:::mickmys3storageinstance/*"
                        ]
                    },  
                    {
                        "Sid": "AllObjectActions",
                        "Effect": "Allow",
                        "Action": ["s3:*Object"],
                        "Resource": [
                            "arn:aws:s3:::mickmys3storageinstance", "arn:aws:s3:::mickmys3storageinstance/*"
                        ]
                    }
                ]
            },
            "Roles" : [
                {
                    "Ref" : "MickListS3BucketsRole"
                }
            ]           
        }
    },
    "MickListS3BucketsRole" : {
      "Type" : "AWS::IAM::Role",
      "Properties" : {
        "AssumeRolePolicyDocument": {
          "Version" : "2012-10-17",
          "Statement" : [
            {
              "Effect" : "Allow",
              "Principal" : {
                "Service" : ["ec2.amazonaws.com"]
              },
              "Action" : [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path" : "/"
      }
    }
  },
  "Outputs" : {
    "EC2" : {
      "Description" : "EC2 IP address",
      "Value" : {
        "Fn::Join" : [
          "",
          [
            "ssh ec2-user@",
            {
              "Fn::GetAtt" : [
                "MickMainEC2",
                "PublicIp"
              ]
            },
            " -i ",
            {
              "Ref" : "KeyName"
            },
            ".pem"
          ]
        ]
      }
    }
  }
}

Here is my troposphere script generating the error on importing the above: 这是我的对流层脚本,在导入以上内容时会产生错误:

from troposphere import Ref, Template
import troposphere.ec2 as ec2

from troposphere.template_generator import TemplateGenerator
import json
with open("myStackFile.JSON") as f:
    json_template = json.load(f)
template = TemplateGenerator(json_template)
template.to_json()


print(template.to_yaml())

I expected the roles to be assigned correctly, as well as the userdata to be executed. 我希望角色分配正确,以及要执行的用户数据。 I expected troposphere to import the JSON, as it has the correct syntax and also the correct class typing as according to the documentation as far as I can see. 我希望对流层能够导入JSON,因为据我所知,它具有正确的语法和正确的类输入。 I have doublechecked everything by hand for many many hours, I am not sure how to proceed finding the issue with this CloudFormation script. 我已经手工检查了许多小时,很多时间,我不确定如何继续使用CloudFormation脚本查找问题。 In the future (and I would advise anyone to do the same) I will not edit JSON (or worse, YAML) files by hand any more, and use higher level tools exclusively. 将来(我会建议任何人都这样做),我将不再手动编辑JSON(或更糟糕的是,YAML)文件,而将仅使用更高级别的工具。

Thank you for ANY help/pointers! 感谢您的任何帮助/指标!

Kind regards 亲切的问候

Your user data isn't executed because you forgot #!/bin/bash . 您的用户数据未执行,因为您忘记了#!/bin/bash From the documentation : 文档中

User data shell scripts must start with the #! 用户数据外壳脚本必须以#!开头。 characters and the path to the interpreter you want to read the script (commonly /bin/bash). 字符和要读取脚本的解释器的路径(通常为/ bin / bash)。 For a great introduction on shell scripting, see the BASH Programming HOW-TO at the Linux Documentation Project (tldp.org). 有关shell脚本的重要介绍,请参见Linux Documentation Project(tldp.org)上的BASH编程方法。

For the bucket permissions, I believe the issue is you specify the CloudFormation resource name in the policy instead of the actual bucket name. 对于存储桶权限,我认为问题在于您在策略中指定了CloudFormation资源名称,而不是实际的存储桶名称。 If you want the bucket to actually be named mickmys3storageinstance , you need: 如果要将存储桶实际命名为mickmys3storageinstance ,则需要:

"mickmys3storageinstance" : {
  "Type" : "AWS::S3::Bucket",
  "Properties" : {
    "BucketName": "mickmys3storageinstance"
  }
},

Otherwise you should use Ref or Fn::Sub in the policy to get the actual bucket name. 否则,您应该在策略中使用RefFn::Sub来获取实际的存储桶名称。

                {
                    "Sid": "ListObjectsInBucket",
                    "Effect": "Allow",
                    "Action": [
                    "s3:ListBucket"
                    ],
                    "Resource": [
                        {"Fn::Sub": "${mickmys3storageinstance.Arn}"},
                        {"Fn::Sub": "${mickmys3storageinstance.Arn}/*"}
                    ]
                },  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM