amazon-web-services - 如何使用 CloudFormation 将 IAM 角色与 Aurora 集群关联?

标签 amazon-web-services amazon-s3 amazon-iam aws-cloudformation amazon-aurora

按照说明找到 here ,我创建了以下 IAM 角色

"DatabaseS3Role": {
    "Type": "AWS::IAM::Role",
    "Properties": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": ["rds.amazonaws.com"]
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        },
        "Policies": [
            {
                "PolicyName": "AllowAuroraToReadS3",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": ["s3:GetObject", "s3:GetObjectVersion", "s3:ListBucket"],
                            "Resource": {"Fn::Join": ["", [
                                "arn:aws:s3:::",
                                {"Fn::Join": ["-",[
                                    {"Ref": "ClientName"}, 
                                    {"Ref": "SourceBucketName"},
                                    {"Ref": "EnvironmentType"},
                                    { "Fn::FindInMap" : [ "Regions", { "Ref" : "AWS::Region" }, "Name" ] }
                                ]]} ,
                                "*"
                            ]]}
                        }
                    ]
                }
            }
        ]
    }
}

我可以将其添加到集群参数组并使用以下命令将其关联。

"RDSDBClusterParameterGroup" : {
    "DependsOn": "DatabaseS3Role",
    "Type": "AWS::RDS::DBClusterParameterGroup",
    "Properties" : {
        "Description" : "CloudFormation Aurora Cluster Parameter Group",
        "Family" : "aurora5.6",
        "Parameters" : {
            "time_zone" : "US/Eastern",
            "aws_default_s3_role": {"Fn::GetAtt": ["DatabaseS3Role", "Arn"]}
        }
    }
},
"RDSAuroraCluster" : {
    "Type" : "AWS::RDS::DBCluster",
    "Properties" : {
        "MasterUsername" : { "Ref" : "Username" },
        "MasterUserPassword" : { "Ref" : "Password" },
        "Engine" : "aurora",
        "DBSubnetGroupName" : { "Ref" : "RDSSubnetGroup" },
        "DBClusterParameterGroupName" : { "Ref" : "RDSDBClusterParameterGroup" },
        "VpcSecurityGroupIds" : [ { "Ref" : "SecurityGroupId" } ],
        "Tags" : [
              { "Key" : "Name", "Value" : { "Fn::Join" : [ "-", [ 
              { "Ref" : "ClientName" }, 
              "aurclstr001",
              {"Ref" : "EnvironmentType" },
              { "Fn::FindInMap" : [ "Regions", { "Ref" : "AWS::Region" }, "Name" ] }
          ] ] } }
        ]
    }
}

但是,Aurora 仍然无法连接到 S3,除非我通过控制台或使用 cli 命令 add-role-to-db-cluster 手动将角色与集群关联。

挖掘云形成文档并没有提供任何通过模板执行此操作的方法。 This documentation不提供任何允许角色关联的参数。

如何在无需向部署过程中添加手动步骤的情况下执行此操作?

最佳答案

截至August 29, 2019这终于支持了!

有一个名为 AssociatedRoles 的新属性需要一个数组 DBClusterRoles 。这些基本上是一个带有 RoleArn 和可选 FeatureName 的对象,目前只能根据显示 SupportedFeatureNames.member.N 的引用文献进行 s3Import。 。

2017-06-30的原始答案:

这不是一个很好的解决方案,但我决定生成在输出中运行所需的命令。我将向 Amazon 提出支持请求,以确认无法通过 DSL 将角色添加到集群。

当我运行 aws rds describe-db-clusters 时,我看到“AssociatedRoles”条目,其中包含具有 Status 和 RoleArn 的对象数组。

PostRunCommand:
  Description: You must run this awscli command after the stack is created and may also need to reboot the cluster/instance.
  Value: !Join [" ", [
    "aws rds add-role-to-db-cluster --db-cluster-identifier",
    !Ref AuroraSandboxCluster,
    "--role-arn",
    !GetAtt AuroraS3Role.Arn,
    "--profile",
    !FindInMap [ AccountNameMap, !Ref AccountNamespace, profile ]
  ]]

您很可能不需要 WRT 配置文件的最后一部分...

亚马逊回复我后的后续行动。他们说:

I understand that you were looking for a way to associate an IAM role with an Aurora cluster in Cloudformation to access other AWS services on your behalf.

As you correctly state there's no role property for a RDS cluster resource as CloudFormation does not support it yet. There's an already open feature request for this as it's a very common issue and I have added your voice to it to add the feature with even more weight. As usual, I can't provide you with an ETA, however as soon as it's released it should be published in the Cloudformation release history page:

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/ReleaseHistory.html

However you can create a CFN Template which creates a RDS Aurora setup and in the end of the template a Custom Resource 1, as a Lambda Function, which makes an API call to attach the IAM Role to the RDS Cluster, this way the whole RDS Aurora Cluster setup stay centralized inside the CFN Template without manual actions and the cluster will be able to invoke the Lambda Function.

Please find attached an "example" template of this workaround described above.

I will as well send a feedback on your behalf about the lack of the principal property in the examples which is needed to create a Role to Delegate Permissions to an AWS Service.

{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS Cloud resources for DevTools services.",
"Metadata": {
    "Version": "0.2.0"
},
"Parameters": {
    "RDSPassword": {
        "Description": "Password for root user on the RDS instance.",
        "Type": "String",
        "NoEcho":"true"
    },
    "RDSDatabaseName": {
        "Description": "DB Identifier for RDS instance.",
        "Type": "String",
        "Default": "mydbname"
    },
    "RDSClass": {
        "Description": "RDS Instance Class",
        "Type": "String",
        "Default": "db.r3.xlarge"
    },
    "DBIdentifier": {
        "Description": "Database Instance Identifier",
        "Type": "String"
    },
    "DBSubnetGroupName": {
        "Description": " The Subnet group Group for the RDS instance",
        "Type": "String"
    },
    "RDSSecurityGroupId": {
        "Description": "Existing internal SG for RDS instance access",
        "Type": "AWS::EC2::SecurityGroup::Id"
    },
    "RDSRetention": {
        "Description": "How long to retain RDS snapshots",
        "Type": "String"
    },
    "RDSVpcId": {
        "Description": "VpcId for RDS instance",
        "Type": "AWS::EC2::VPC::Id"
    },
    "PubliclyAccessible": {
        "Description": "Set the RDS to be publically available",
        "Type": "String",
        "AllowedValues" : ["true", "false"],
        "Default": "true"
    },
    "DBClusterIdentifier": {
        "Description": "The name of the DBCluster",
        "Type": "String"
    },
    "RDSRoleTag": {
        "Description": "sets if the tag for dev/prod use",
        "Type": "String",
        "Default": "dev"
    }
},

"Resources": {

  "LambdaRole" : {
    "Type" : "AWS::IAM::Role",
    "Properties" : {
        "AssumeRolePolicyDocument" : {
            "Version" : "2012-10-17",
            "Statement" : [
                {
                    "Effect" : "Allow",
                    "Principal" : {
                        "Service" : [
                            "lambda.amazonaws.com"
                        ]
                    },
                    "Action"    : [
                        "sts:AssumeRole"
                    ]
                }
            ]
        }
      }
    },

    "LambdaPolicy": {
      "Type" : "AWS::IAM::Policy",
      "Properties" : {
         "PolicyName" : "LambdaPolicy",
         "PolicyDocument" : {
            "Version" : "2012-10-17",
            "Statement": [ {
            "Effect"   : "Allow",
            "Action"   : [
               "iam:*",
               "ec2:*",
               "rds:*",
               "logs:*"
            ],
            "Resource" : "*"
            } ]
         },
         "Roles": [ { "Ref": "LambdaRole" } ]
      }
   },

    "LambdaFunction": {
      "Type" : "AWS::Lambda::Function",
      "DeletionPolicy" : "Delete",
      "DependsOn"      : [
          "LambdaRole"
      ],
      "Properties"     : {
          "Code" : {
              "ZipFile" : {
                  "Fn::Join" : [
                      "\n",
                      [
                        "          var AWS = require('aws-sdk');",
                        "          var rds = new AWS.RDS();",
                        "          var response = require('cfn-response');",
                        "          exports.handler = (event, context, callback) => {",
                        "              var rolearn = event.ResourceProperties.RDSRole;",
                        "              var dbclusteridentifier = event.ResourceProperties.DBClusterIdentifier;",
                        "              var responseData = {};",
                        "              console.log('Role ARN: ' + rolearn);",
                        "              console.log('DBClusterIdentifier: ' + dbclusteridentifier);",
                        "              var addroleparams = {",
                        "                  RoleArn: rolearn,",
                        "                  DBClusterIdentifier: dbclusteridentifier",
                        "                };",
                        "                if (event.RequestType == 'Delete') {",
                        "                  response.send(event, context, response.SUCCESS);",
                        "                  return;",
                        "                }",
                        "                rds.addRoleToDBCluster(addroleparams, function(err, data) {",
                        "                  if (err) {",
                        "                  console.log(err, err.stack); // an error occurred",
                        "                  responseData = {Error: 'Create call failed'};",
                        "                  response.send(event, context, response.FAILED, responseData);",
                        "                  }",
                        "                  else {",
                        "                  response.send(event, context, response.SUCCESS, responseData);",
                        "                  console.log(data);  // successful response",
                        "                  }",
                        "                });",
                        "          };",
                      ]
                  ]
              }
          },
          "Handler" : "index.handler",
          "MemorySize" : 128,
          "Role"       : {
              "Fn::GetAtt" : [
                  "LambdaRole",
                  "Arn"
              ]
          },
          "Runtime"    : "nodejs4.3",
          "Timeout"    : 10
      }
    },

    "RDSRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": ["rds.amazonaws.com"]
              },
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Path": "/"
      }
    },

    "RDSPolicy": {
       "Type" : "AWS::IAM::Policy",
       "Properties" : {
          "PolicyName" : "RDSPolicy",
          "PolicyDocument" : {
             "Version" : "2012-10-17",
             "Statement": [ {
             "Effect"   : "Allow",
             "Action"   : [
                "lambda:InvokeFunction"
             ],
             "Resource" : "*"
             } ]
          },
          "Roles": [ { "Ref": "RDSRole" } ]
       }
    },

    "RDSDBClusterParameterGroup" : {
      "Type" : "AWS::RDS::DBClusterParameterGroup",
      "Properties" : {
        "Parameters" : {
          "aws_default_lambda_role" : { "Fn::GetAtt" : [ "LambdaFunction", "Arn" ] }

        },
        "Family" : "aurora5.6",
        "Description" : "A sample parameter group"
      }
    },

    "RDSDBCluster": {
        "Type" : "AWS::RDS::DBCluster",
        "DeletionPolicy": "Retain",
        "Properties" : {
            "BackupRetentionPeriod" : { "Ref": "RDSRetention" },
            "DatabaseName": { "Ref": "RDSDatabaseName" },
            "DBSubnetGroupName": { "Ref": "DBSubnetGroupName" },
            "DBClusterParameterGroupName": { "Ref" : "RDSDBClusterParameterGroup" },
            "Engine" : "aurora",
            "StorageEncrypted" : true,
            "MasterUsername" : "sa",
            "MasterUserPassword" : { "Ref": "RDSPassword" },
            "Port" : 3306,
            "Tags": [
                { "Key": "Role", "Value": { "Ref": "RDSRoleTag" } }
                ],
            "VpcSecurityGroupIds": [{ "Ref": "RDSSecurityGroupId" } ]
        }
    },
    "RDSInstance": {
        "Type": "AWS::RDS::DBInstance",
        "DeletionPolicy": "Retain",
        "Properties": {
            "AllowMajorVersionUpgrade": false,
            "AutoMinorVersionUpgrade": true,
            "DBClusterIdentifier" : { "Ref": "RDSDBCluster" },
            "DBInstanceIdentifier": { "Ref": "DBIdentifier" },
            "DBInstanceClass": { "Ref": "RDSClass" },
            "Engine": "aurora",
            "PubliclyAccessible": { "Ref": "PubliclyAccessible" },
            "Tags": [
                { "Key": "Role", "Value": { "Ref": "RDSRoleTag" } }
                ]
        }
    },
    "RDSInstanceSecurityGroup": {
        "Type": "AWS::EC2::SecurityGroup",
        "DeletionPolicy": "Retain",
        "Properties": {
            "GroupDescription": "Security group for the RDSInstance resource",
            "SecurityGroupEgress": [
                {
                    "IpProtocol": "tcp",
                    "CidrIp": "127.0.0.1/32",
                    "FromPort": "1",
                    "ToPort": "1"
                }
            ],
            "SecurityGroupIngress": [
                {
                    "IpProtocol": "tcp",
                    "SourceSecurityGroupId": { "Ref": "RDSSecurityGroupId" },
                    "FromPort": "3306",
                    "ToPort": "3306"
                }
            ],
            "VpcId": { "Ref": "RDSVpcId" },
            "Tags": [
                { "Key": "Role", "Value": { "Ref": "RDSRoleTag" } }
                ]
        }
    },

    "AddRoleToDBCluster": {
        "DependsOn" : [
            "RDSDBCluster",
            "RDSInstance"
        ],
        "Type": "Custom::AddRoleToDBCluster",
        "Properties" : {
            "ServiceToken" : {
                "Fn::GetAtt" : [
                    "LambdaFunction",
                    "Arn"
                ]
            },
            "RDSRole" : { "Fn::GetAtt" : [ "RDSRole", "Arn" ] },
            "DBClusterIdentifier" : {"Ref":"RDSDBCluster"}
        }
    }
}

}

关于amazon-web-services - 如何使用 CloudFormation 将 IAM 角色与 Aurora 集群关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42770067/

相关文章:

ios - 我正在将数据从我的 Swift 应用程序上传到 Amazon S3,它非常耗电。如何避免这种情况?

java - AWS Java SDK 错误 - IAM 用户的 withPermissionsBoundary

amazon-web-services - AWS S3 StringLike条件阻止对存储桶的请求

amazon-web-services - 我什么时候需要 CAPABILITY_NAMED_IAM

ssl - 用于 OwnCloud 的 Amazon EC2 上的 HTTPS

amazon-web-services - 如何在ec2上的tomcat上添加aws ssl证书

javascript - 如何使用 amazon-javascript-sdk 列出 AWS S3 存储桶?

amazon-web-services - 只能使用 Boto3 将 CloudFormation 模板部署到 us-east-1

c# - 一次调用即可接收按文档类型分组的搜索结果(NEST,AWS Elasticsearch)

c++ - 使用代码在 AWS SDK C++ 控制台应用程序上设置凭证