Creating Role for EC2 Service in Cloudformation - amazon-web-services

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

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

how to control access via policy in cfn templates?

I have a policy, defined as cloudformation template below. I want to be able to describe what aws resources , they can create via cfn template. how do i do that? I have attached a sample example below?
Type: 'AWS::IAM::Policy'
Properties:
PolicyName: CFNUsers
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- 'cloudformation:Describe*'
- 'cloudformation:List*'
- 'cloudformation:Get*'
Resource: '*'
Your policy has three Actions:
- 'cloudformation:Describe*'
- 'cloudformation:List*'
- 'cloudformation:Get*'
These actions can be performed on all (*) CloudFormation (CFN) stacks, not "any IAM roles, users or other aws resources". This is because only CFN stacks can be acted upon using these three actions.
AWS::IAM::Policy is managed IAM policy. Such policies must be attacked to IAM user, role or group. This way you give permissions to perform the three actions on CFN stacks to who/what ever you are going to attach the policy to.

How to use AWS CloudFormation pseudoparameter inside IAM Policy Document

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

AWS CloudFormation - Attach existing managed policy to existing role through a template

I am deploying a CloudFormation template to AWS. A role for my Lambda invocation is being created by a template that I am importing, and I cannot modify it directly. I wish to modify that role to attach the AWS managed policy AWSLambdaVPCAccessExecutionRole that already exists in my AWS account. So far, all of my searches have come up empty.
I have found instructions for how to create a new role with an existing managed policy
I have found instructions for how to create a new policy and attach it to an existing role.
I have found instructions for how to Update a Stack using the AWS console or the CLI, but not via a template (YAML or JSON)
I have found instructions for calling something called aws_iam_role_policy_attachment in something called Terraform, but that is not available to me
I am hoping for something like the following but I cannot find any evidence of this existing anywhere. Is there anything that can do what I am trying to do?
---
Resources:
AdditionalRolePermissions:
Type: "AWS::IAM::RolePolicyAttachment"
Properties:
Roles:
- Ref: ExistingRole
PolicyName:
- Ref: ExistingPolicy
The best solution I have come up with so far is to create a new policy that has a manually created PolicyDocument that is the same as the existing one for AWSLambdaVPCAccessExecutionRole and attach it to the role upon creation. I would prefer not to do that though because it will be harder to maintain.
Unfortunately, you can not do this in pure CloudFormation unless you create a custom resource but this isn't really pure CloudFormation at that point as you'd need to create a lambda and other resources to implement the custom resource. There is no concept of a policy attachment in CloudFormation presently and these attachments only happen when you define a policy or role resource.
The simplest thing would be to go with your solution of creating a policy that duplicates AWSLambdaVPCAccessExecutionRole. That policy is fairly simple and shouldn't clutter up your CloudFormation template too much compared to some other complicated policies.
It is possible as of 2021. Please see: https://aws.amazon.com/premiumsupport/knowledge-center/cloudformation-attach-managed-policy/
Example:
AWSTemplateFormatVersion: '2010-09-09'
Description: something cool
Resources:
IAM:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
RoleName: some_role_name
Policies:
['arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole']

How to restrict IAM user to access (list) particular roles and CF stacks?

I have created multiple service roles and CF Stacks, using root account and I'm going to create one IAM user and I don't want to list all these roles and CF stacks. I want to show only some particular roles and CF Stacks.
Can you please let me know how I can do this? It will be great if you share a sample policy.
Displaying only a subset of all your IAM Roles in the console is not possible. The only way to restrict the iam:ListRoles call is with the PathPrefix argument (see https://docs.aws.amazon.com/IAM/latest/UserGuide/list_identityandaccessmanagement.html). However, the IAM Console issues a iam:ListRoles request without specifying the PathPrefix argument. You can still use the AWS CLI to request only a subset of IAM roles like this:
aws iam list-roles --path-prefix "/somepath"
And you can allow a user to list IAM Roles that have a path that starts with /somepath like this:
---
AWSTemplateFormatVersion: '2010-09-09'
Resources:
User:
Type: AWS::IAM::User
Properties:
Path: "/"
Policies:
- PolicyName: IamAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'iam:ListRoles'
Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/somepath*"
As for listing only a subset of all your CloudFormation stacks, that is not possible. The ListStacks call does not allow you to filter down which stacks to list. See See https://docs.aws.amazon.com/IAM/latest/UserGuide/list_awscloudformation.html . Just add the following snippet to the code above to allow your user to list all CloudFormation stacks:
- PolicyName: CloudFormationAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'cloudformation:ListStacks'
Resource: '*'
Note that listing CloudFormation stacks does not implicitly give access to listing the Resources or Outputs of these stacks. In other words, the user may list all Stacks, but will not be able to look at the contents of these stacks.