In my troposphere code i basically want to create an sns topic and a lambda execution role to which i can attach a few managed policy from aws. But the issue is i cannot find a way to just reference the arn name of the managed policy. Below is my code but here i am copying and pasting the managed policy json document.
Is there a better way out ?
from troposphere import FindInMap, GetAtt, Join, Output, Template, Ref, ImportValue
from troposphere.sns import Topic
from troposphere.iam import Role, Policy
t = Template()
t.set_version("2010-09-09")
sns_topic = Topic(TopicName='IngestStateTopic', title='IngestStateTopic')
t.add_resource(sns_topic)
LambdaExecutionRole = t.add_resource(
Role(
"LambdaExecutionRole",
Path="/",
Policies=[
Policy(PolicyName="CloudWatchLogsFullAccess",
PolicyDocument={
"Version":
"2012-10-17",
"Statement": [{
"Action": ["logs:*"],
"Effect": "Allow",
"Resource": "*"
}]
}),
Policy(PolicyName="SnsReadOnlyAccess",
PolicyDocument={
"Version":
"2012-10-17",
"Statement": [{
"Effect":
"Allow",
"Action": ["sns:GetTopicAttributes", "sns:List*"],
"Resource":
"*"
}]
}),
Policy(PolicyName="LambdaBasicExecutionRole-Test",
PolicyDocument={
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:eu-west-1:498129003450:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:eu-west-1:498129003450:log-group:/aws/lambda/lambda_layers_test:*"
]
}
]
})
],
AssumeRolePolicyDocument={
"Version":
"2012-10-17",
"Statement": [{
"Action": ["sts:AssumeRole"],
"Effect": "Allow",
"Principal": {
"Service": ["lambda.amazonaws.com"]
}
}]
},
))
t.add_output(
Output(
"IngestServiceArn",
Description="ARN of the sns topic",
Value=Ref(sns_topic),
))
t.add_output(
Output(
"LambdaExcecutionRole",
Description="ARN of the lambda plocy document",
Value=GetAtt(LambdaExecutionRole, "Arn"),
))
with open('sns_lambda_role.yaml', 'w') as s:
s.write(t.to_yaml())
And below is my cloud formation yaml file name:
AWSTemplateFormatVersion: '2010-09-09'
Outputs:
IngestServiceArn:
Description: ARN of the sns topic
Value: !Ref 'IngestStateTopic'
LambdaExcecutionRole:
Description: ARN of the lambda plocy document
Value: !GetAtt 'LambdaExecutionRole.Arn'
Resources:
IngestStateTopic:
Properties:
TopicName: IngestStateTopic
Type: AWS::SNS::Topic
LambdaExecutionRole:
Properties:
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Version: '2012-10-17'
Path: /
Policies:
- PolicyDocument:
Statement:
- Action:
- logs:*
Effect: Allow
Resource: '*'
Version: '2012-10-17'
PolicyName: CloudWatchLogsFullAccess
- PolicyDocument:
Statement:
- Action:
- sns:GetTopicAttributes
- sns:List*
Effect: Allow
Resource: '*'
Version: '2012-10-17'
PolicyName: SnsReadOnlyAccess
- PolicyDocument:
Statement:
- Action: logs:CreateLogGroup
Effect: Allow
Resource: arn:aws:logs:eu-west-1:498129003450:*
- Action:
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- arn:aws:logs:eu-west-1:498129003450:log-group:/aws/lambda/lambda_layers_test:*
Version: '2012-10-17'
PolicyName: LambdaBasicExecutionRole-Test
Type: AWS::IAM::Role
You can do this by specifying a list of ManagedPolicyArns
for Role cloudformation resource, but not the Policies
- Documentation:
{
"Type" : "AWS::IAM::Role",
"Properties" : {
"AssumeRolePolicyDocument" : Json,
"ManagedPolicyArns" : [ String, ... ],
"MaxSessionDuration" : Integer,
"Path" : String,
"PermissionsBoundary" : String,
"Policies" : [ Policy, ... ],
"RoleName" : String
}
}
For ManagedPolicy CloudFormation has separate resource type - AWS::IAM::ManagedPolicy:
SampleManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Sid: AllowAllUsersToListAccounts
Effect: Allow
Action:
- iam:ListAccountAliases
- iam:ListUsers
- iam:GetAccountSummary
Resource: "*
Examle:
RootRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- !Ref awsExampleManagedPolicyParameterOne
- !Ref awsExampleManagedPolicyParameterTwo
So, if we are talking about the tropopshere - it also has separate class for ManagedPolicy:
class ManagedPolicy(AWSObject):
resource_type = "AWS::IAM::ManagedPolicy"
props = {
'Description': (basestring, False),
'Groups': ([basestring], False),
'ManagedPolicyName': (basestring, False),
'Path': (iam_path, False),
'PolicyDocument': (policytypes, True),
'Roles': ([basestring], False),
'Users': ([basestring], False),
}
And you refer to it using Ref
function.