【问题标题】:Why does this CloudFormation Template script not work?为什么此 CloudFormation 模板脚本不起作用?
【发布时间】:2019-11-12 07:33:01
【问题描述】:

我正在尝试在 AWS CloudFormation 上创建一个堆栈,其中包含一个 EC2 实例和 2 个 S3 存储桶。我的脚本正在尝试将策略分配给允许访问存储桶的 EC2 实例,但无论我做什么,都没有分配权限。此外,根本不执行用户数据。

如果 EC2 真的没有权限,我尝试彻底测试:CLI 确认它没有权限。我用一个制作文本文件的简单脚本替换了用户数据,它确实没有被创建。 AWS Designer 没有任何抱怨,并显示了正确的模板结构。堆栈描述运行和执行没有错误,除了 S3 存储桶访问和用户数据不起作用(没有警告)。

在对文档进行了大量手动编辑和仔细检查后,我意识到我应该使用更高级的语言来完成这项工作。因此,我尝试使用 templateGenerator 在一个简单的 python Troposphere 脚本中导入脚本。这会导致以下错误(到目前为止,任何地方都没有创建其他错误,一切都只是默默地出错了,JSON 语法验证器也没有任何抱怨):

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

但是,显然我的 PolicyDocument 是字典类型,我不明白它如何被解释为列表。我已经盯着这个看了好几个小时了,我可能已经对这个问题视而不见,但我真的很感谢你在这一点上的任何帮助!!!!

安全组和入站流量设置工作正常,我的 dockerized flask 应用程序运行良好(在 EC2 上)但无法访问存储桶(尽管我必须通过 SSH 手动启动它,因为 userdata 不会执行,我还尝试使用 ec2 元数据中的 CFN-init 段(在命令下)执行此操作,但没有执行任何操作,即使我在通过 SSH 连接后尝试手动运行 CFNinit)。

这是我写的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"
          ]
        ]
      }
    }
  }
}

这是我的对流层脚本在导入上述内容时生成错误:

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())

我希望正确分配角色以及执行用户数据。我希望对流层能够导入 JSON,因为据我所见,它具有正确的语法和正确的类类型。我已经手动仔细检查了很多小时,我不确定如何继续查找此 CloudFormation 脚本的问题。将来(我会建议任何人都这样做)我不会再手动编辑 JSON(或更糟糕的是,YAML)文件,而只会使用更高级别的工具。

感谢您的任何帮助/指点!

亲切的问候

【问题讨论】:

    标签: python json amazon-web-services amazon-cloudformation


    【解决方案1】:

    您的用户数据未执行,因为您忘记了#!/bin/bash。来自documentation

    用户数据外壳脚本必须以 #!字符和要读取脚本的解释器的路径(通常是 /bin/bash)。有关 shell 脚本的详细介绍,请参阅 Linux 文档项目 (tldp.org) 上的 BASH Programming HOW-TO。

    对于存储桶权限,我认为问题在于您在策略中指定了 CloudFormation 资源名称,而不是实际的存储桶名称。如果您希望存储桶实际命名为mickmys3storageinstance,您需要:

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

    否则您应该在策略中使用RefFn::Sub 来获取实际的存储桶名称。

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

    【讨论】:

    • 非常感谢!!!非常感谢您的帮助!!!!!!!根据您的建议,我设法解决了该政策的问题。谢谢!!通过添加 shell 脚本行并没有解决 userdata 问题,但我最终通过使用 join 和 base64 函数解决了这个问题(不知道为什么,但我不再接触它了)。你真的帮了我很多,我非常感谢你的支持,无论是实际的还是象征性的!我不确定我是否应该在这里问这个,但如果你有一个 patreon 请给我一个链接。 :) 谢谢!!!!
    • 很高兴我能帮上忙。请通过在这里帮助其他人来支付它:)
    猜你喜欢
    • 2016-05-17
    • 2018-01-02
    • 2021-09-15
    • 2013-11-18
    • 1970-01-01
    • 2020-12-14
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多