Come posso risolvere l'errore di ruolo IAM che ricevo in Amazon Redshift quando utilizzo CloudFormation?

6 minuti di lettura
0

Desidero creare un cluster Amazon Redshift o un'azione pianificata in AWS CloudFormation. Tuttavia, ricevo l'errore di ruolo AWS Identity and Access Management (IAM) "The IAM role must delegate access to an Amazon Redshift account".

Breve descrizione

Quando provi a creare un cluster Amazon Redshift o un'azione pianificata in CloudFormation, ricevi il seguente messaggio di errore:

"The IAM role is not valid. The IAM role must delegate access to an Amazon Redshift account."

Per risolvere l'errore, devi definire il ruolo IAM nei parametri del modello CloudFormation in modo che il cluster possa accedere ad altri servizi AWS.

Risoluzione

Aggiorna i parametri del modello CloudFormation in YAML

Per aggiornare i parametri del modello CloudFormation in YAML, completa i seguenti passaggi:

  1. Definisci i parametri per creare uno stack:

    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

    Nota: è consigliabile utilizzare riferimenti dinamici nel modello di stack. Per ulteriori informazioni sulle best practice, consulta Best practice di sicurezza per CloudFormation.

  2. Utilizza il seguente modello per creare un ruolo IAM per Amazon RedShift da assumere quando accede ad altri servizi AWS:

    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. In Policy, specifica le policy IAM da collegare al ruolo 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. Utilizza il seguente modello con la funzione Fn::GetAtt per creare il cluster Amazon Redshift e includere il ruolo 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 ""]

    Nota: un riferimento errato al ruolo IAM, ad esempio Ref, causa un errore.

Aggiorna i parametri del modello CloudFormation in JSON

Per aggiornare i parametri del modello CloudFormation in JSON, completa i seguenti passaggi:

  1. Definisci i parametri per creare uno stack:

    {
      "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"
          ]
        }
      },
  2. Utilizza il seguente modello per creare il ruolo IAM per accedere al cluster Amazon Redshift:

    "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. In Policy, specifica le policy IAM da collegare al ruolo 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. Utilizza il seguente modello con la funzione Fn::GetAtt per creare il cluster Amazon Redshift e includere il ruolo 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": ""
                }
              ]
            }
          }
        }
      }
    }

Crea un nuovo stack in CloudFormation

Dopo aver aggiornato i parametri del modello, utilizza il modello JSON o YAML per creare un nuovo stack CloudFormation.

Informazioni correlate

Amazon Redshift resource type reference (Riferimento al tipo di risorsa Amazon Redshift)

Frammenti di modello Amazon Redshift

Automate Amazon Redshift cluster creation using AWS CloudFormation (Automatizzazione della creazione di cluster Amazon Redshift utilizzando AWS CloudFormation)

AWS UFFICIALEAggiornata 3 mesi fa