Transforming a CommaDelimitedList of Roles to list of Arns in Cloudformation - aws-cloudformation

I have a cloudformation template generating a kms key with a policy document to grant roles access to the key. Now I want the roles to be a CommaDelimitedList Parameter of the Cloudformation template and I do not know the size in advanced. So I have input like this:
["role1", "role2", ...]
and have to generate this:
Principal:
AWS:
- !Sub "arn:aws:iam::${AWS::AccountId}:role/role1",
- !Sub "arn:aws:iam::${AWS::AccountId}:role/role2",
...
Is this transformation possible in cloudformation?

Not possible.
What you need to do is to pass the ARNs list. For example:
SomeParam:
"Fn::Join":
- ","
-
- !GetAtt "role1.Arn"
- !GetAtt "role2.Arn"
And just use it directly, CommaDelimitedList is automatically transformed into list by CloudFormation when passed as a parameter:
Principal:
AWS: !Ref "RolesParameter"
If you have just role names, you need to build the ARNs on your own, like in your question, but before passing as an argument:
SomeParam:
"Fn::Join":
- ","
-
- !Sub "arn:aws:iam::${AWS::AccountId}:role/role1"
- !Sub "arn:aws:iam::${AWS::AccountId}:role/role2"

Related

CloudFormation template to update the IAM Role's policy

Is it possible to create a CloudFormation template that takes the IAM role's ARN as the input and updates its policy assigned to it to add more privileges?I tried to work with the CloudFormation designer but it is very confusing and not straightforward,
Yes, you can do this with a template such as this:
Description: Add policy to existing role
Parameters:
MyExistingRoleName:
Type: String
Description: Name of the Role you want to add a policy to
Resources:
MyNewPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: "my-new-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "s3:ListAllMyBuckets"
Resource:
- "*"
Roles:
- !Ref MyExistingRoleName

How to call a resource from one yaml template to another yaml template using cloudformation

I need some guidance on cloudformation templates.
I have a stack called test1.yaml, there i created an IAM role called S3Role.
Now I have another stack called test2.yaml, there i created a managed policy to attach to existing iam role.
Now i want to call test1.yml file S3Role in test2.yml file of managed policy.
Can anyone help me with the script?
Can anyone help me with the script.
Obviously due to lack of details in your question, its not possible to provide any script. But I can provide general psudo-code.
test1.yaml
You will have to export the S3Role Arn or Name
Resources:
S3Role:
Type: IAM::ROLE
<rest of role definition>
Outputs:
RoleArn:
Value: !GetAtt S3Role.Arn
Exports:
Name: RoleArn
test2.yml
You will have to import the role exported Arn (or name) from test1.yaml:
Resources:
SomeResouce:
Properties:
Role: !ImportValue RoleArn
Hope this helps.
You need export the role from stack 1 and then import it in stack 2
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
Providing the complete script for cross-referencing an AWS resource in CloudFormation template.
test1.yaml has an IAM role (logical ID: IAMRole) which we export through the Outputs block. Also notice that the indentation of Outputs block is same as that of Resources block.
The Outputs block serves many purposes. From the AWS Documentation
The optional Outputs section declares output values that you can
import into other stacks (to create cross-stack references), return in
response (to describe stack calls), or view on the AWS CloudFormation
console.
test1.yaml
Resources:
IAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: TrustPolicy
Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
Path: /
RoleName: IAMRole
Outputs:
ExportIAMRole:
Description: Export the IAMRole to use in test2.yaml
Value: !Ref IAMRole
Export:
Name: IAMRole
In test2.yaml we import the value by referencing the name we have given under Export in Outputs block.
test2.yaml
Resources:
IAMPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: IAMPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- kms:ListAliases
- kms:Encrypt
- kms:Decrypt
Resource: "*"
Roles:
- !ImportValue IAMRole

ARN of the role that is automatically created with an Lambda function

In a SAM template, is there a way to reference the ARN of the role that is automatically created with an Lambda function?
I would need to use that ARN somewhere else in the template.
# this is the role
Role:
Type: AWS::IAM::Role
Properties:
RoleName: client-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
- Effect: Allow
Principal:
AWS: "arn:aws:iam::xxxx:role/xxxxxxx-ApiHandlerRole-12UWXALxxxxx"
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
# this is the lambda
ApiHandler:
Type: AWS::Serverless::Function
Properties:
FunctionName: api-handler
......
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Table
- S3ReadPolicy:
BucketName: !Ref Bucket
- S3WritePolicy:
BucketName: !Ref Bucket
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action: sts:AssumeRole
Resource: !GetAtt Role.Arn
I think what you do is separate the Resource build of the Role.
Then you can use the !Ref Role anywhere you need it, including in your lambda Role.
You can construct the ARN of the role yourself. It has fixed format. From docs:
If a role isn't specified, one is created for you with a logical ID of function-logical-idRole.
For example using Sub:
!Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/function-logical-idRole"
where function-logical-id is your lambda function logical id.
Something like...
# this is the lambda
ApiHandler:
Type: AWS::Serverless::Function
Properties:
FunctionName: api-handler
Policies:
......
# this is the role
Role:
Type: AWS::IAM::Role
Properties:
RoleName: client-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
- Effect: Allow
Principal:
AWS: !GetAtt ApiHandlerRole.Arn
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
Assuming that you have not specified the "AssumeRolePolicyDocument" for your function.
(code above based on the pastebin), the SAM cli will generate a role called "ApiHandlerRole" for you.
from the docs:
If this property isn't specified, AWS SAM adds a default assume role
for this function.
Which from the looks of it you may want to just explore that property some more. I'm new to AWS SAM but there has got to be way to plug "arn:aws:iam::aws:policy/AmazonS3FullAccess" at it. :)
Hope this helps all
docs link : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-assumerolepolicydocument
SOLUTION:
So, I bumped into this situation today.
Suppose your Resource Lambda is named MyLambda, then use
!Ref MyLambdaRole.Arn
Tried and tested, works like a charm.
Reason why it works: If you expand the processed template, the IAM Role resource is named using the following nomenclature
<lambda-logical-id>Role
Don't forget to upvote! :D
What worked for me is refer the ARN Attribute of the autogenerated role like
SomeLambdaFunction:
Type: AWS::Serverless::Function
Properties:
...other properties...
Policies:
... Some sam policies...
.... different resource reference Lambda autogenerate role...
- Action: //some actions here
Effect: Allow
Principal:
AWS: !GetAtt SomeLambdaFunctionRole.Arn
Resource: "*"
.... More template code...

store the values to a variable after executing the template

This cloudformation template is working as expected:
https://github.com/shantanuo/cloudformation/blob/master/updated/esbck.yml
But how do I output the ARN of IAM role that it creates?
To add to Marcins answer, if you export the output, it becomes available for use in other Cloudformation templates deployed in the same AWS account (in the same region)
Add an export to the output:
Outputs:
RoleArn:
Value: !GetAtt EsSnapshotRole.Arn
Export:
Name: EsSnapshotRoleArn
Once this is done, you can use the Fn::ImportValue intrinsic function in other templates
# some-other-template.yml
Resources:
SomeResourceRequiringRoleArn:
Type: AWS::SomeService::SomeResource
Properties:
IamRoleArn: !ImportValue EsSnapshotRoleArn
Have to add output section:
Outputs:
RoleArn:
Value: !GetAtt EsSnapshotRole.Arn

CloudFormation: Return ARN of Subnet

Is there another way to get ARN of created Subnet Resource AWS::EC2::Subnet via Fn::GetAtt intrinsic function. Subnet resource only returns AvailabilityZone, Ipv6CidrBlocks, NetworkAclAssociationId, VpcId.
Documentation: https://docs.aws.amazon.com/en_pv/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html#aws-resource-ec2-subnet-return-values
Since the ARN of a Subnet is in the format arn:aws:ec2:REGION:ACCOUNT_ID:subnet/SUBNET_ID. By using intrinsic function Fn::Join you can generate the ARN of the subnet.
Example: arn:aws:ec2:ap-southeast-1:767022272945:subnet/subnet-0d42d2235s3a2531d
!Join
- ''
- - 'arn:aws:ec2:'
- !Ref 'AWS::Region'
- ':'
- !Ref 'AWS::AccountId'
- ':subnet/'
- Fn::ImportValue:
Fn::Sub: VPC-SubnetId
A simpler solution, as noted in the comment by #sigpwned, is to just use !Sub
Even if the subnet you're referencing isn't local to your template, you can still pass it in as a parameter to the template or import it like in the original answer if it is available to the stack.
!Sub "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${Subnet}"