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.
You might want to look at the awacs project which allows for policy definition.
Also, likely you need to just Ref() your policy to get the name of it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With