AWS IAM Cloudformation error: "Syntax error at position (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument - aws-cloudformation

AWSTemplateFormatVersion: '2010-09-09'
Description: ' '
Parameters:
ExternalAccount:
Type: String
Description: Enter the external account whicg
Resources:
NewRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
- AWS: "arn:aws:s3:::${ExternalAccount}:root"
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonKinesisReadOnlyAccess
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
- arn:aws:iam::aws:policy/CloudWatchFullAccess

Related

How can I set a cloudformation field with function shorthand (ie. !Sub) using yq?

I need to add a managed policy to a large number of lambda and ecs task roles across many cloudformation yaml files. Some of them already have this array field with items in it while some do not. I need to add an item to the ManagedPolicyArns array field where that item contains cloudformation shorthand such as !Sub. I'm using yq, which is a fantastic tool, but I can't figure out handling this shorthand using the docs.
cloudformation.yaml:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
MyPrefix:
Description: MyPrefix
Type: String
Resources:
MyRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- Fn::ImportValue: !Sub "${MyPrefix}-my-policy-arn"
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
- lambda.amazonaws.com
Action:
- sts:AssumeRole
- sts:TagSession
Path: /
Expected output .yaml:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
MyPrefix:
Description: MyPrefix
Type: String
Resources:
MyRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- Fn::ImportValue: !Sub "${MyPrefix}-my-policy-arn"
- Fn::ImportValue: !Sub "${MyPrefix}-my-new-policy-arn"
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
- lambda.amazonaws.com
Action:
- sts:AssumeRole
- sts:TagSession
Path: /
My failed attempt:
add_policy.yq:
( .Resources[] |=
select(.Properties.AssumeRolePolicyDocument.Statement[].Principal.Service.[] == "ecs-tasks.amazonaws.com" or .Properties.AssumeRolePolicyDocument.Statement[].Principal.Service.[] == "lambda.amazonaws.com")
.Properties.ManagedPolicyArns += {"Fn::ImportValue": {"!Sub": "${MyPrefix}-my-new-policy-arn"} }
)
command:
yq --from-file add_policy.yq cloudformation.yaml
which outputs:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
MyPrefix:
Description: MyPrefix
Type: String
Resources:
MyRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- Fn::ImportValue: !Sub "${MyPrefix}-my-policy-arn"
- Fn::ImportValue:
'!Sub': ${MyPrefix}-my-new-policy-arn
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
- lambda.amazonaws.com
Action:
- sts:AssumeRole
- sts:TagSession
Path: /
How do I get
- Fn::ImportValue: !Sub "${MyPrefix}-my-policy-arn"
- Fn::ImportValue: !Sub "${MyPrefix}-my-new-policy-arn"
instead of
- Fn::ImportValue: !Sub "${MyPrefix}-my-policy-arn"
- Fn::ImportValue:
'!Sub': ${MyPrefix}-my-new-policy-arn
?
Use the tag operator
add_policy.yq:
( .Resources[] |=
select(.Properties.AssumeRolePolicyDocument.Statement[].Principal.Service.[] == "ecs-tasks.amazonaws.com" or .Properties.AssumeRolePolicyDocument.Statement[].Principal.Service.[] == "lambda.amazonaws.com")
.Properties.ManagedPolicyArns += {"Fn::ImportValue": "${AuthAuditBucketStackName}-logging-policy-arn" | . tag = "!Sub" }
)
results in:
- Fn::ImportValue: !Sub "${MyPrefix}-my-policy-arn"
- Fn::ImportValue: !Sub ${MyPrefix}-my-new-policy-arn
Now I'm not sure why the string value isn't quoted.

SAM create new role and new policy

I am trying to create a new role and a new policy which would be attached
to the same role created in the template in the same template and getting
this error:
Error:
Missing required field Principal(Service:AmazonIdentityManagement;
Status Code: 400;
Error Code: MalformedPolicyDocument;
Proxy: null)
Resources:
lambdaFullPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: "*"
Resource: "*"
LambdaFullRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version : '2012-10-17'
Statement :
- Effect : Allow
- Principal :
service :
- lambda.amazonaws.com
- Action :
- sts: AssumeRole
ManagedPolicyArns:
- !Ref lambdaFullPolicy
DependsOn:
- lambdaFullPolicy
#------------------------------output -----------------------#
Outputs:
PolicyFullLambda:
Description: table
Value: !Ref lambdaFullPolicy
Export:
Name:
"Fn::Sub": "${AWS::StackName}-PolicyFullLambda"
RollFullLambda:
Value: !Ref LambdaFullRole
Export:
Name:
"Fn::Sub": "${AWS::StackName}-RollFullLambda"
There is an extra space in sts: AssumeRole and it should read sts:AssumeRole. This is because this is not a YAML component, but a string literal that AWS uses for the Action section of the Role creation/update.

lambda error while trying to remove parameters

I used this article to create my stack.
https://aws.amazon.com/blogs/infrastructure-and-automation/scheduling-automatic-deletion-of-aws-cloudformation-stacks/
But getting an error:
User:
arn:aws:sts::xxx:assumed-role/deleteCurrent-DeleteAfter-DeleteCFNLambdaExecution-T1WHQG2UTLWM/DeleteCFNLambda-deleteCurrent
is not authorized to perform: ssm:DeleteParameter on resource:
arn:aws:ssm:us-east-1:xxx:parameter/CFN-DemoParameter-plOl5Hg4QuI5
(Service: AmazonSSM; Status Code: 400; Error Code:
AccessDeniedException;
The template can be viewed here...
https://datameetgeobk.s3.amazonaws.com/cftemplates/delete_after_5m.template
Any suggestion to correct the error will be appreciated.
The error says that your lambda execution role does not have permissions to execute ssm:DeleteParameter role. Thus you can add the missing permission to the lambda role:
Resources:
DeleteCFNLambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: ["lambda.amazonaws.com"]
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: "lambda_policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "arn:aws:logs:*:*:*"
- Effect: "Allow"
Action:
- "cloudformation:DeleteStack"
Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${StackName}/*"
- Effect: "Allow"
Action:
- "ssm:DeleteParameter"
Resource: "*"

cloudtrail log using cloudformation template

In cloud-trail, I can select the existing log group CloudTrail/DefaultLogGroup under CloudWatch Logs section. Is it possible to complete this step using cloudformation Template?
Assuming you are creating the log group with CloudFormation as well:
LogGroup: # A new log group
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: 365 # optional
CloudTrailLogsRole: # A role for your trail
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Version: '2012-10-17'
CloudTrailLogsPolicy: # The policy for your role
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- logs:PutLogEvents
- logs:CreateLogStream
Effect: Allow
Resource:
Fn::GetAtt:
- LogGroup
- Arn
Version: '2012-10-17'
PolicyName: DefaultPolicy
Roles:
- Ref: CloudTrailLogsRole
CloudTrail: # The trail
Type: AWS::CloudTrail::Trail
Properties:
IsLogging: true
CloudWatchLogsLogGroupArn:
Fn::GetAtt:
- LogGroup
- Arn
CloudWatchLogsRoleArn:
Fn::GetAtt:
- CloudTrailLogsRole
- Arn
DependsOn:
- CloudTrailLogsPolicy
- CloudTrailLogsRole
If using an existing log group:
CloudTrailLogsRole: # A role for your trail
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Version: '2012-10-17'
CloudTrailLogsPolicy: # The policy for your role
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- logs:PutLogEvents
- logs:CreateLogStream
Effect: Allow
Resource: <your existing log group arn here>
Version: '2012-10-17'
PolicyName: DefaultPolicy
Roles:
- Ref: CloudTrailLogsRole
CloudTrail: # The trail
Type: AWS::CloudTrail::Trail
Properties:
IsLogging: true
CloudWatchLogsLogGroupArn: <your existing log group arn here>
CloudWatchLogsRoleArn:
Fn::GetAtt:
- CloudTrailLogsRole
- Arn
DependsOn:
- CloudTrailLogsPolicy
- CloudTrailLogsRole

Set up Cloudtrail s3 Bucket with proper Policy

I'm trying to get Cloudtrail on the road and want to set up a Cloudtrail s3bucket. but the Policy does not complete. Here is my code:
CloudtrailBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Description: Stores all Trails for this account
Properties:
AccessControl: BucketOwnerFullControl
BucketName: !Sub "${AWS::AccountId}-invoice-cloudtrail"
LifecycleConfiguration:
Rules:
- Id: GlacierRule
Prefix: glacier
Status: Enabled
ExpirationInDays: '365'
Transitions:
- TransitionInDays: '1'
StorageClass: Glacier
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Tags:
- Key: Name
Value: !Sub '${EnvironmentName} ${Project}-CloudtrailBucket'
VersioningConfiguration:
Status: Suspended
and this is the Policy I want to use:
CloudtrailBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref CloudtrailBucket
PolicyDocument:
Statement:
- Sid: AWSCloudTrailAclCheck
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action:
- s3:GetBucket*
Resource:
- !Sub "arn:aws:s3:::${AWS::AccountId}-invoice-cloudtrail/*"
- Sid: AWSCloudTrailWrite
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action: s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${AWS::AccountId}-invoice-cloudtrail/*"
Condition:
StringEquals:
s3:x-amz-acl: bucket-owner-full-control
I really dont know what might wrong. the error message is the following:
Action does not apply to any resource(s) in statement (Service: Amazon S3; Status Code: 400; Error Code: MalformedPolicy; Request ID: 7A458D04A5765AC6; S3 Extended Request ID: EYn2is5Oph1+pnZ0u+zEH067fWwD0fyq1+MRGRxJ1qT3WK+e1LFjhhE9fTLOFiBnhSzbItfdrz0=)
I believe you have to change your policy to match the following:
CloudtrailBucketPolicy:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref CloudtrailBucket
PolicyDocument:
Statement:
- Sid: AWSCloudTrailAclCheck
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action:
- s3:GetBucketAcl
Resource:
- !Sub "arn:aws:s3:::${AWS::AccountId}-invoice-cloudtrail"
- Sid: AWSCloudTrailWrite
Effect: Allow
Principal:
Service: cloudtrail.amazonaws.com
Action: s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${AWS::AccountId}-invoice-cloudtrail/*"
Condition:
StringEquals:
s3:x-amz-acl: bucket-owner-full-control
The reasoning is that s3:GetBucket* expands to s3:GetBucketAcl, s3:GetBucketCORS, etc (all here), all of these expecting a bucket as resource, and you have provided many objects on your original policy.
So I've changed the resource (removed /*) and also cleaned the policy a bit, since CloudTrail should required only s3:GetBucketAcl.