How to use AWS CloudFormation pseudoparameter inside IAM Policy Document - amazon-web-services

I am using AWS CloudFormation (YAML-based) to deploy an IAM role. This role should both be allowed to deploy other CloudFormation resources and to have the root of the AWS account it gets deployed into as a trusted entity.
I am trying to supply the account-id using the built-in pseudo-parameter AWS::AccountId:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html#cfn-pseudo-param-accountid .
Here is what I have tried, following the official doc: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html (just showing the resources section of my CFN template):
Resources:
IAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: ["sts:AssumeRole"]
Effect: Allow
Principal:
Service: [cloudformation.amazonaws.com]
AWS: arn:aws:iam::AWS::AccountId:root # <-- ERROR HERE !
Which causes a MalformedPolicyDocument error due to an Invalid principal in the CloudFormation stack (in the AWS Management Console, under Events):
Invalid principal in policy: "AWS":"arn:aws:iam::AWS::AccountId:root" (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument
I have tried varying the syntax for the AWS Principal's value:
with and without quotation marks
with and without square brackets
Where is the error in the Principal, and how can it be corrected ?

We need to use Intrinsic functions !Sub for variables like AWS::Region, AWS::AccountId, AWS::StackName, etc
AWS: !Sub arn:aws:iam::${AWS::AccountId}:root

Related

Send message from lambda account A to an SQS of account B

I need to send message from lambda account A to an SQS of another account B.
In account B, I have created the sqs like this:
Resources:
SampleSqs:
Type: "AWS::SQS::Queue"
Properties:
QueueName: sample-sqs-service-queue.fifo
FifoQueue: true
VisibilityTimeout: 400
ContentBasedDeduplication: true
and created the access role policy as:
SqsRole:
Type: AWS::IAM::Role
Properties:
RoleName: sample-sqs-Account-Role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS:
- arn:aws:iam::<Account-A>:root
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSQSFullAccess
I also tried adding the sqs queue as resource under statement section, but is failing at the time of deployment with the below message:
SqsRole - Has prohibited field Resource (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument;
In account A, I am trying to acces the account B sqs SampleSqs, by importing the queue url,but i am getting access denied, code for account A:
iamRoleStatements:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- arn:aws:iam::$<AccountB>:role/sample-sqs-Account-Role
trying to access that sqs through its url in my code but getting access denied.
I am quite new to aws and serverless framework, Could someone please help me with what serverless code setup I require in both interface's to give Account B sqs queue's access to account A.
I tried adding the sqs queue as resource under statement section in sqsRole, but is failing at the time of deployment with the below message:
SqsRole - Has prohibited field Resource (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument;
Have you checked Amazon documentation on error: https://aws.amazon.com/premiumsupport/knowledge-center/iam-principal-policy/
More importantly, I do not know your exact scenario here but I would think instead of creating a whole role in account be to be assumed to access sqs, it would be easier and probably more appropriate to simply grant necessary permissions by changing the policy on sqs (resource policy).
There are very easy to understand examples directly addressing this use-case here: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-examples-of-sqs-policies.html

Error in CloudFormation Stack: Syntax errors in policy. (Service: AmazonIdentityManagement; Status Code: 400;

This should be fairly straightforward (I hope). I'm working with a CloudFormation Stack through serverless framework and am getting a syntax error. The project is using Lambda to invoke QuickSight API for automated data ingestion.
The error I'm getting is:
Serverless Error ---------------------------------------
An error occurred: QuickSightPolicy - Syntax errors in policy. (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument; Request ID: b2982ca2-7518-4e7d-8258-78240d3a465e; Proxy: null).
And the portion Yaml file with that policy is bellow
LambdaAssumeRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: ['sts:AssumeRole']
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
QuickSightPolicy:
Type: 'AWS::IAM::Policy'
Properties:
PolicyDocument:
Statement:
- Action: ['quicksight:*']
Effect: Allow
Resorce: '*'
PolicyName: QuickSightPolicy
Roles: [!Ref 'LambdaAssumeRole']
I omitted the version property, but didn't think that would be an issue for it to run. I'm not exactly sure what else needs to be changed or what is causing the error
Resorce is a typo of Resource. Recommend trying the CloudFormation Linter in VSCode to see some of these errors inline while authoring templates along with autocompletion and documentation links:
[cfn-lint] E2507: IAM Policy statement missing Resource or NotResource
[cfn-lint] E2507: IAM Policy statement key Resorce isn't valid

Creating Role for EC2 Service in Cloudformation

I am trying to create a full access role (using an AWS Managed Policy) to all EC2 instances to call AWS services via Cloudformation in YAML.
This is my code:
AWSTemplateFormatVersion: 2010-09-09
Description: Ansible Role
Resources:
AnsibleRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: 'Allow'
Action: 'ec2:*'
Principal:
Service: 'ec2.awsamazon.com'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AmazonEC2FullAccess'
RoleName: 'EC2-FullAccess'
DeletionPolicy: Delete
I get the following error:
Invalid principal in policy: "SERVICE":"ec2.awsamazon.com"
(Service: AmazonIdentityManagement; Status Code: 400; Error
Code: MalformedPolicyDocument; Request ID: e43214f8-b6f9-11e9-9891-4dc84fd279dd)
I am perplexed as to why it doesn't recognize the service. Additionally, if I change Action: 'ec2:*' to Action: 'sts.AssumeRole' I get another error.
Any assistance is greatly appreciated.
There are multiple issues with your template:
The service identifier is malformed. It should be 'ec2.amazonaws.com'.
The action must be 'sts:AssumeRole'. This is the only action which is valid inside an IAM trust policy.
The DeletionPolicy is not necessary because it is the default for this resource.
Set the RoleName only if really necessary because IAM names are global on a per-account basis and you cannot execute multiple stacks when using this attribute.
For more information see the AWS CloudFormation template examples.
You use the correct managed policy ARN if you want to grant your new role permission to call all kinds of ec2 actions. If you want to restrict your Ansible role further, take a look at the example policies for EC2 in the docs [1][2]. They are much more restrictive (and thus secure) than the managed full access policy AmazonEC2FullAccess. Maybe also the other managed policies such as AmazonEC2ReadOnlyAccess [3] are feasible?
References
[1] https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ExamplePolicies_EC2.html
[2] https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-policies-for-amazon-ec2.html
[3] https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/UsingIAM.html#intro-to-iam

Give Lambda Invoke permission to ApiGateway with one deployment

I wrote resources in my serverless.yml like below:
resources:
Resources:
RestApi :
Type : AWS::ApiGateway::RestApi
Properties :
Body : ${file(./swagger.yaml)}
LoginApiToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: login
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
When I sls deploy, below error occured:
An error occurred: LoginApiToInvokeLambda - Function not found: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:api-dev-login (Service: AWSLambda; Status Code: 404; Error Code: ResourceNotFoundException
In the initial deployment, I thought that permissions were set before creating lambda functions. Therefore, I commented out LoginApiToInvokeLambda in my serverless.yml. I sls deploy again, it succeeded. But ApiGateway does not have permission to invoke lambda. After that I restored the commented out part, and sls deploy. Finally I was able to give ApiGateway the permission of Lambda invoke.
Is there a way to accomplish this at the same time?
You can use DependsOn functionality of CloudFormation in the resources section.
resources:
Resources:
# ...
LoginApiToInvokeLambda:
Type: AWS::Lambda::Permission
DependsOn: LoginLambdaFunction
Properties:
FunctionName: login
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
I've assumed your lambda function key is login which gets translated to LoginLambdaFunction. If not, check the serverless documentation on how the resources get named.
In short serverless translates your configuration to a CloudFormation template, and the resources section allows you to customise what gets generated, which is why you can use DependsOn to solve your issue.

User is not authorized to perform: SNS:CreateTopic on resource

I wanted to monitor certain parameters (TotalErrorRate and Latency) with CloudWatch and I wanted a "Simple Notification Service" (SNS) to send me an email, when an (cloudWatch) alarm is thrown:
EscalationTopic:
Type: "AWS::SNS::Topic"
Properties:
DisplayName: My Monitoring
Subscription:
- Endpoint: !Ref EmailForNotification
Protocol: email
EscalationTopicEmailSubscriber:
Type: "AWS::SNS::Subscription"
Properties:
Endpoint: !Ref EmailForNotification
Protocol: email
TopicArn: !Ref EscalationTopic
But I get this error:
User is not authorized to perform: SNS:CreateTopic on resource(Service: AmazonSNS; Status Code: 403; Error Code: AuthorizationError (see screenshot)
What I did to solve it, is creating a topicPolicy:
SNSTopicPolicy:
Type: 'AWS::SNS::TopicPolicy'
Properties:
Topics:
- !Ref EscalationTopic
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: 'sns:CreateTopic'
Resource: !Ref EscalationTopic
Principal:
AWS: '*'
But the problem still persists.
EDIT:
In the SNS console, I could manually create a new topic. Shouldn't it mean that I got the permission in order to createTopic?
I had a similar issue with Amazon SES. Apparently my "AmazonSESFullAccess" permission wasn't enough and I solved it by adding the "AmazonSNSFullAccess" permission to my IAM user at https://console.aws.amazon.com/iam/home#/users/MY_IAM_USER_NAME_GOES_HERE
The error message states the problem quite accurately. The credentials used to create the CloudFormation stack (presumably your login credentials unless you specified a Role during stack creation) is not authorized to create an Amazon SNS topic.
You should look at the permissions associated with your IAM User and add the necessary permissions.
Adding an SNS Topic Policy will have no impact because it is used to give SNS a set of permissions, whereas you need permissions to create the Topic itself.