Reputation: 1390
I have a bash script which pulls information from a CloudFormation stack and places it into a Python script. The Python script is intended to connect to a Redshift database, create a table, then import data from a file downloaded from an S3 bucket.
The first part works:
endpoint=$(aws cloudformation describe-stacks --stack-name=BallotOnlineRS --region=us-west-2 \
--query 'Stacks[0].Outputs[?OutputKey==`RedshiftClusterEndpointAddress`].OutputValue' \
--output text)
role=$(aws cloudformation describe-stack-resources --stack-name=BallotOnlineRS --region=us-west-2 \
--logical-resource-id RawDataBucketAccessRole |grep 'PhysicalResourceId' |cut -d: -f2 |sed 's/^ //; s/,//; s/"//g')
sed -i "s/ENDPOINT/${endpoint}/; s/ROLE/${role}/" /tmp/ballotonline_data.py
This results in the the necessary strings going where they need to:
HOST = 'ballotonliners-redshiftcluster-xxxxxxxxxxxx.cgsdneukfjtv.us-west-2.redshift.amazonaws.com'
ARN_CREDENTIALS = 'arn:aws:iam::xxxxxxxxxxx:role/BallotOnlineRS-RawDataBucketAccessRole-xxxxxxxxxxxx
However, when I execute the Python script, I get the following error from sqlalchemy
:
sqlalchemy.exc.InternalError: (psycopg2.errors.InternalError_) User arn:aws:redshift:us-west-2:xxxxxxxxxxx:dbuser:ballotonliners-redshiftcluster-1qb2hxkta10t9/admin is not authorized to assume IAM Role arn:aws:iam::xxxxxxxxxxx:role/BallotOnlineRS-RawDataBucketAccessRole-1U56NHFY528VW
DETAIL:
-----------------------------------------------
error: User arn:aws:redshift:us-west-2:xxxxxxxxxxx:dbuser:ballotonliners-redshiftcluster-xxxxxxxxxxxx/admin is not authorized to assume IAM Role arn:aws:iam::xxxxxxxxxxx:role/BallotOnlineRS-RawDataBucketAccessRole-xxxxxxxxxxxx
code: 8001
context: IAM Role=arn:aws:iam::xxxxxxxxxxx:role/BallotOnlineRS-RawDataBucketAccessRole-xxxxxxxxxxxx
query: 76
location: xen_aws_credentials_mgr.cpp:272
process: padbmaster [pid=13823]
-----------------------------------------------
The admin
user mentioned in the error is created when the Redshift stack is created and if I access the database through the Redshift UI by logging into the Query Editor, I get no error using the same account. The difference in that situation is that I'm logging in with the username:password rather than, I'm guessing, assuming a role. Specifically, the one in the error.
The Redshift stack is built using a template provided by Thorntech. This also is successful when executed.
Any thoughts on what the issue is?
EDIT:
I found what should be an identical issue on the AWS Developer forum that indicates that rather than using the physical resource ID, I should be using the logical ID. In this case, instead of BallotOnlineRS-RawDataBucketAccessRole-xxxxxxxxxxxx
I should just use RawDataBucketAccessRole
. However, that results in the same error with difference being that the logical ID replaces the physical ID.
EDIT2: In response to John Rotenstein's question regarding associating the role, here is the section that defines the cluster and its relevant components:
Resources:
RedshiftCluster:
Type: AWS::Redshift::Cluster
Properties:
ClusterSubnetGroupName: !Ref RedshiftClusterSubnetGroup
ClusterType: !If [ SingleNode, single-node, multi-node ]
NumberOfNodes: !If [ SingleNode, !Ref 'AWS::NoValue', !Ref RedshiftNodeCount ] #'
DBName: !Sub ${DatabaseName}
IamRoles:
- !GetAtt RawDataBucketAccessRole.Arn
MasterUserPassword: !Ref MasterUserPassword
MasterUsername: !Ref MasterUsername
PubliclyAccessible: true
NodeType: dc2.large
Port: 5439
VpcSecurityGroupIds:
- !Sub ${RedshiftSecurityGroup}
PreferredMaintenanceWindow: Sun:09:15-Sun:09:45
DataBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${DataBucketName}
RawDataBucketAccessRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- redshift.amazonaws.com
Action:
- sts:AssumeRole
RawDataBucketRolePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: RawDataBucketRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Action: s3:ListAllMyBuckets
Resource: arn:aws:s3:::*
-
Effect: Allow
Action:
- 's3:Get*'
- 's3:List*'
Resource: '*'
-
Effect: Allow
Action: cloudwatch:*
Resource: "*"
Roles:
- !Ref RawDataBucketAccessRole
Does it matter that the cluster is defined prior to the role? I suspect it doesn't since the role is listed under the stack's Resources tab in the CF UI.
EDIT3: I found another, similar issue but for a product. The OP states that he found the solution. Being that he was using the wrong role to authenticate with. When I looked into that avenue for my issue, it does not appear to apply since I only have the one role.
Upvotes: 1
Views: 4936
Reputation: 1390
I reached a point where I was throwing things at the wall to see what would stick. Eventually I got it to work. What I don't know is, which of the final two changes that I made at one time solved the problem (or why): adding the Path:
property to the IAM::Role
definition or placing the policy inline with the role definition and removing the external policy definition. What I ended up with is (compare this to what I've placed in the body of the question above)
RawDataBucketAccessRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- 'redshift.amazonaws.com'
Action:
- 'sts:AssumeRole'
Path: '/'
RoleName: RawDataBucketAccessRole
Policies:
-
PolicyName: RawDataBucketRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Action:
- 's3:Get*'
- 's3:List*'
Resource: '*'
This allows the admin
user (defined in the MasterUsername
parameter) to assume the role and access the S3 bucket.
Upvotes: 1