使用 AWS CloudFormation 时,如何解决 Amazon Redshift 中的“IAM 角色必须委托对 Amazon Redshift 账户的访问权限”错误?
我正在尝试使用 AWS CloudFormation 创建 Amazon Redshift 集群或计划的操作。但是,我收到 AWS Identity and Access Management (IAM) 角色错误。如何解决此错误?
简短描述
借助 AWS CloudFormation,您可以在 JSON 或 YAML 中创建一个模板,其中描述您需要的所有 AWS 资源。然后,AWS CloudFormation 会为您预置和配置 AWS 资源。您甚至可以使用 AWS CloudFormation 模板创建 Amazon Redshift 集群或计划的操作。
但是,您必须正确引用 IAM 角色,该角色授权 Amazon Redshift 集群访问其他 AWS 服务。否则,您将会收到以下错误:
"The IAM role <role> is not valid. The IAM role must delegate access to an Amazon Redshift account."
要解决此问题,请确保使用 CloudFormation 正确创建并附加 AWS IAM 角色。创建 CloudFormation 模板文件后,您的 Amazon Redshift 集群和任何指定的 AWS 资源 (例如堆栈) 也会自动创建。不需要对堆栈进行额外的 (手动) 更新。
解决方法
更新您的 AWS CloudFormation 模板参数 (在 YAML 中)
要更新 YAML 中的 AWS CloudFormation 模板参数,请执行以下步骤:
1. 定义参数:
AWSTemplateFormatVersion: 2010-09-09 Description: Create Redshift Stack. Parameters: Environment: Description: Environment of the resources. Type: String Default: staging AllowedValues: - production - staging - testing Name: Description: Cluster name. Type: String Default: 'mycluster' Service: Description: Service name. Type: String Default: redshift AllowedValues: - redshift DatabaseName: Description: Database name. Type: String Default: dev AllowedPattern: "([a-z]|[0-9])+" ClusterType: Description: The type of cluster Type: String Default: multi-node AllowedValues: - single-node - multi-node NumberOfNodes: Description: Compute nodes count. For multi-node clusters, the NumberOfNodes parameter must be greater than 1 Type: Number Default: '2' NodeType: Description: The type of node to be provisioned Type: String Default: dc2.large AllowedValues: - dc2.large - dc2.8xlarge - ra3.4xlarge - ra3.16xlarge MasterUsername: Description: Master user name. Type: String Default: awsuser AllowedPattern: "([a-z])([a-z]|[0-9])*" MasterUserPassword: Description: Master user password. Must have a length of 8-64 characters, contain one uppercase letter, one lowercase letter, and one number. Also only contain printable ASCII characters except for '/', '@', '"', ' ', '\' and '\'. Type: String NoEcho: 'true' PortNumber: Description: The port number on which the cluster accepts incoming connections. Type: Number Default: '5439' Conditions: IsMultiNodeCluster: Fn::Equals: - Ref: ClusterType - multi-node
注意:最佳实践是在堆栈模板中使用动态引用,而不是直接将敏感信息嵌入 AWS CloudFormation 模板。有关最佳实践的更多信息,请参阅 AWS CloudFormation 的安全性最佳实践。
2. 在 Resources(资源)下,创建 RedShift 服务为了访问其他 AWS 服务而将代入的 IAM 角色:资源:RedshiftRole:类型:AWS::IAM::Role 属性:
Resources: RedshiftRole: Type: AWS::IAM::Role Properties: RoleName: !Sub ${Environment}-${Name}-${Service} AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - redshift.amazonaws.com Action: - sts:AssumeRole Condition: StringEquals: sts:ExternalId: !Sub 'arn:aws:redshift:${AWS::Region}:${AWS::AccountId}:dbuser:${Environment}-${Name}-${Service}/awsuser' Path: "/"
3. 在策略下,指定要附加到 IAM 角色的 IAM 策略:
Policies: - PolicyName: policy-s3 PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 's3:AbortMultipartUpload' - 's3:GetBucketLocation' - 's3:ListBucket' - 's3:ListBucketMultipartUploads' - 's3:GetObject' - 's3:PutObject' Resource: - !Sub "arn:aws:s3:::${Environment}-${Name}-tier1" - !Sub "arn:aws:s3:::${Environment}-${Name}-tier1/log-internal-${Service}/*" - !Sub "arn:aws:s3:::${Environment}-${Name}-tier2" - !Sub "arn:aws:s3:::${Environment}-${Name}-tier2/*" - Effect: Allow Action: - 's3:DeleteObject' Resource: - !Sub "arn:aws:s3:::${Environment}-${Name}-tier1/log-internal-${Service}/*" - !Sub "arn:aws:s3:::${Environment}-${Name}-tier2/*" - PolicyName: policy-cloudwatch PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' Resource: "*"
4. 使用 Function Fn::GetAtt 函数创建 Amazon Redshift 集群,然后附加 IAM 角色 (RedshiftRole):
RedshiftCluster: Type: AWS::Redshift::Cluster Properties: IamRoles: - Fn::GetAtt: [ RedshiftRole, Arn ] AllowVersionUpgrade: true AutomatedSnapshotRetentionPeriod: 7 ClusterIdentifier: !Sub ${Environment}-${Name}-${Service} ClusterVersion: 1.0 ClusterType: Ref: ClusterType NumberOfNodes: Fn::If: - IsMultiNodeCluster - Ref: NumberOfNodes - Ref: AWS::NoValue NodeType: Ref: NodeType DBName: Ref: DatabaseName MasterUsername: Ref: MasterUsername MasterUserPassword: Ref: MasterUserPassword Port: Ref: PortNumber PreferredMaintenanceWindow: Sun:18:30-Sun:19:30 PubliclyAccessible: yes AvailabilityZone: !Select [0, !GetAZs ""]
Fn::GetAtt 函数返回指定属性的值。
**注意:**如果您使用不正确的引用形式附加到 IAM 角色 (例如 Ref 函数),则会收到 IAM 角色错误。
更新您的 AWS CloudFormation 模板参数 (以 JSON 格式)
要更新 JSON 中的 AWS CloudFormation 模板参数,请执行以下步骤:
1. 定义参数:
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Create Redshift Stack.", "Parameters": { "Environment": { "Description": "Environment of the resources.", "Type": "String", "Default": "staging", "AllowedValues": [ "production", "staging", "testing" ] }, "Name": { "Description": "Cluster name.", "Type": "String", "Default": "mycluster" }, "Service": { "Description": "Service name.", "Type": "String", "Default": "redshift", "AllowedValues": [ "redshift" ] }, "DatabaseName": { "Description": "Database name.", "Type": "String", "Default": "dev", "AllowedPattern": "([a-z]|[0-9])+" }, "ClusterType": { "Description": "The type of cluster", "Type": "String", "Default": "multi-node", "AllowedValues": [ "single-node", "multi-node" ] }, "NumberOfNodes": { "Description": "Compute nodes count. For multi-node clusters, the NumberOfNodes parameter must be greater than 1", "Type": "Number", "Default": "2" }, "NodeType": { "Description": "The type of node to be provisioned", "Type": "String", "Default": "dc2.large", "AllowedValues": [ "dc2.large", "dc2.8xlarge", "ra3.4xlarge", "ra3.16xlarge" ] }, "MasterUsername": { "Description": "Master user name.", "Type": "String", "Default": "awsuser", "AllowedPattern": "([a-z])([a-z]|[0-9])*" }, "MasterUserPassword": { "Description": "Master user password. Must have a length of 8-64 characters, contain one uppercase letter, one lowercase letter, and one number. Also only contain printable ASCII characters except for '/', '@', '\"', ' ', '\\' and '\\'.", "Type": "String", "NoEcho": "true" }, "PortNumber": { "Description": "The port number on which the cluster accepts incoming connections.", "Type": "Number", "Default": "5439" } }, "Conditions": { "IsMultiNodeCluster": { "Fn::Equals": [ { "Ref": "ClusterType" }, "multi-node" ] } },
注意:最佳实践是在堆栈模板中使用动态引用,而不是直接将敏感信息嵌入 AWS CloudFormation 模板。有关最佳实践的更多信息,请参阅 AWS CloudFormation 的安全性最佳实践。
2. 在资源下,创建用于访问 Amazon Redshift 集群的 IAM 角色:
"Resources": { "RedshiftRole": { "Type": "AWS::IAM::Role", "Properties": { "RoleName": { "Fn::Sub": "${Environment}-${Name}-${Service}" }, "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "redshift.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ], "Condition": { "StringEquals": { "sts:ExternalId": { "Fn::Sub": "arn:aws:redshift:${AWS::Region}:${AWS::AccountId}:dbuser:${Environment}-${Name}-${Service}/awsuser" } } } } ] }, "Path": "/",
3. 在策略下,指定要附加到 IAM 角色的 IAM 策略:
"Policies": [ { "PolicyName": "policy-s3", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:GetBucketLocation", "s3:ListBucket", "s3:ListBucketMultipartUploads", "s3:GetObject", "s3:PutObject" ], "Resource": [ { "Fn::Sub": "arn:aws:s3:::${Environment}-${Name}-tier1" }, { "Fn::Sub": "arn:aws:s3:::${Environment}-${Name}-tier1/log-internal-${Service}/*" }, { "Fn::Sub": "arn:aws:s3:::${Environment}-${Name}-tier2" }, { "Fn::Sub": "arn:aws:s3:::${Environment}-${Name}-tier2/*" } ] }, { "Effect": "Allow", "Action": [ "s3:DeleteObject" ], "Resource": [ { "Fn::Sub": "arn:aws:s3:::${Environment}-${Name}-tier1/log-internal-${Service}/*" }, { "Fn::Sub": "arn:aws:s3:::${Environment}-${Name}-tier2/*" } ] } ] } }, { "PolicyName": "policy-cloudwatch", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] } } ] } },
4. 使用 Function Fn::GetAtt 函数创建 Amazon Redshift 集群,然后附加 IAM 角色 (RedshiftRole):
"RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "IamRoles": [ { "Fn::GetAtt": [ "RedshiftRole", "Arn" ] } ], "AllowVersionUpgrade": true, "AutomatedSnapshotRetentionPeriod": 7, "ClusterIdentifier": { "Fn::Sub": "${Environment}-${Name}-${Service}" }, "ClusterVersion": 1, "ClusterType": { "Ref": "ClusterType" }, "NumberOfNodes": { "Fn::If": [ "IsMultiNodeCluster", { "Ref": "NumberOfNodes" }, { "Ref": "AWS::NoValue" } ] }, "NodeType": { "Ref": "NodeType" }, "DBName": { "Ref": "DatabaseName" }, "MasterUsername": { "Ref": "MasterUsername" }, "MasterUserPassword": { "Ref": "MasterUserPassword" }, "Port": { "Ref": "PortNumber" }, "PreferredMaintenanceWindow": "Sun:18:30-Sun:19:30", "PubliclyAccessible": "true", "AvailabilityZone": { "Fn::Select": [ 0, { "Fn::GetAZs": "" } ] } } } } }
Fn::GetAtt 函数返回指定属性的值。
**注意:**如果您使用不正确的引用形式附加到 IAM 角色 (例如 Ref 函数),则会收到 IAM 角色错误。
在 AWS CloudFormation 中创建新堆栈
要使用 JSON 或 YAML 模板创建堆栈,请执行以下步骤:
1. 打开 AWS CloudFormation 控制台。
2. 选择创建堆栈以创建新堆栈。
3. 在步骤 1 中的先决条件 - 准备模板下,选择模板已准备就绪。
4. 在步骤 1 中的指定模板下,选择模板来源。
5. (可选) 如果必须上传模板文件,请上传模板文件。
6. 选择下一步。
7. 在步骤 2 中的指定堆栈详细信息下,指定堆栈名称和参数。
8. 选择下一步。
9. 查看步骤 3 中的配置堆栈选项下的详细信息。
10. (可选) 要修改堆栈选项,请选择上一步,直至到达想要更新的页面。根据需要更新堆栈选项,然后选择下一步,直到返回配置堆栈选项页面。
11. 选择创建堆栈。
相关信息
相关内容
- AWS 官方已更新 3 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 8 个月前