I have been trying to build out a Bucket Policy to allow actions on a centralised account in CloudFormation to IAM Roles in a series of other accounts that share the same pattern - I.E:
arn:aws:iam::111111111111:role/my-role
arn:aws:iam::222222222222:role/my-role
I have found the following example, which gets me close, but not quite close enough: https://stackoverflow.com/a/50060983/1736704
Below is an Example of code that works:
Parameters:
MyAccounts:
Type: CommaDelimitedList
Default: '111111111111,222222222222'
MyBucket:
Type: String
Default: my-bucket
Resources:
MyBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref MyBucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: MyRoleAllow
Effect: Allow
Principal:
AWS: !Split
- ','
- !Sub
- 'arn:aws:iam::${inner}:role/my-role'
- inner: !Join
- ':role/my-role,arn:aws:iam::'
- Ref: 'MyAccounts'
Action:
- s3:PutObject
Resource: !Sub arn:aws:s3:::${MyBucket}/*
What I would like to be able to do is make the role name a parameter. When I attempt to do that, no matter how I structure the !Join function, I get errors.
If I modify the above code and have my-role as a string parameter called RoleName, and expand the !Join, it returns an error. The full modified code that doesn't work:
Parameters:
MyAccounts:
Type: CommaDelimitedList
Default: '111111111111,222222222222'
RoleName
Type: String
Default: my-role
MyBucket:
Type: String
Default: my-bucket
Resources:
MyBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref MyBucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: MyRoleAllow
Effect: Allow
Principal:
AWS: !Split
- ','
- !Sub
- 'arn:aws:iam::${inner}:role/my-role'
- inner: !Join
- ''
- - ':role/'
- !Ref 'RoleName'
- ',arn:aws:iam::'
- Ref: 'Accounts'
Action:
- s3:PutObject
Resource: !Sub arn:aws:s3:::${MyBucket}/*
This is the error message I am getting:
Template error: every Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined.
In the modified code, it is the Ref: 'Accounts' that is causing the issue, but I am confused why, because it works in the original code.
Edit:
The inputs I would like to use are:
Parameters:
MyAccounts:
Type: CommaDelimitedList
Default: '111111111111,222222222222'
RoleName
Type: String
Default: my-role
MyBucket:
Type: String
Default: my-bucket
My expected output (a S3 Bucket Policy) would look like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "MyRoleAllow",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:role/my-role",
"arn:aws:iam::222222222222:role/my-role"
]
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
Can anyone tell me if what I am trying to achieve is possible? If so, how can I modify my code to get it to work?
Thanks