how to control access via policy in cfn templates? - amazon-web-services

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.

Related

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']

CloudFormation - IAM - Access Control with Tags

I have this requirement to create a role which can be used by developers. We only have a single account for Dev and Prod (Not recommended, I know). The created resources are tagged with either dev or prod to identify the environments. The requirement is that Developers can have ReadOnlyAccess on both environments but can only have full access on resources tagged with 'dev'
So if a developer wants to create a resource, he should tag it with dev. Also, he can modify the other resources created by other users which are also tagged with dev. From the AWS Documentation, I created a CloudFormation template with the snippet below but I noticed that only ReadOnlyAccess is allowed. The Developer could not create resources with 'dev' tag and cannot modify resources which already have the tag 'dev'. Any pointers would be helpful.
I wanted to use PowerUseAccess which is a managed policy but unaware, how I could provide a condition on top of a managed policy.
RoleDeveloper:
Type: AWS::IAM::Role
Properties:
RoleName: DeveloperRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS: !Sub arn:aws:iam::${UserAccountId}:root
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: FullDeveloperAccessWithDevTag
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "*"
Resource: "*"
Condition:
StringEquals:
aws:ResourceTag/env:
- dev
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
The wildcard isn't the problem. Rather, the issue is that not every API call will honor the Condition.
For example, s3:ListBucket doesn't take a tag as a condition. Nor does dynamodb:ListTables.
Also, while some commands (which I refer to as Actions) will accept conditions, they won't necessarily accept tags as Conditions.
Here is the documentation that shows Conditions for DynamoDB: DynamoDB API Permissions: Actions, Resources, and Conditions Reference - Amazon DynamoDB. I can't see any reference to tags.
However, tags are available as condition keys for Amazon EC2: Actions, Resources, and Condition Keys for Amazon EC2 - AWS Identity and Access Management
Thus, some services and API calls simply can't be limited by tags.

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

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.

AWS CloudFormation template

I am trying to understand the below policy
Policies:
- PolicyName: InstanceIAMPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'ssm:DescribeAssociation'
- 'ssm:GetDeployablePatchSnapshotForInstance'
- 'ssm:GetDocument'
- 'ssm:GetManifest'
- 'ssm:GetParameters'
- 'ssm:ListInstanceAssociations'
- 'ssm:PutComplianceItems'
- 'ssm:PutConfigurePackageResult'
- 'ssm:UpdateAssociationStatus'
- 'ssm:UpdateInstanceAssociationStatus'
- 'ssm:UpdateInstanceInformation'
Resource: '*'
Effect: Allow
Action:
- 'ec2messages:AcknowledgeMessage'
- 'ec2messages:FailMessage'
- 'ec2messages:GetEndpoint'
- 'ec2messages:GetMessages'
- 'ec2messages:SendReply'
Resource: '*'
My question is related to resource parameter mentioned as *. Does that mean that the actions can be performed on any resource within your AWS infrastructure ? I am really new to CloudFormation templates and AWS. Thanks for your help.
The short answer is YES.
In your template you have two sections under Statements. Each section is defining "allow" actions. For each section you are "allowing" the APIs for ALL RESOURCES. The first section is for SSM and the second is for SSM EC2Messages.
Note: based upon the allow actions, you can merge those two sections together.
This link will help you with CloudFormation Templates:
Working with AWS CloudFormation Templates
The CloudFormation template in your question is creating an IAM policy. Your question is really about how wildcards work in IAM policies. The * wildcard in an IAM policy Resource element means that something with this IAM policy applied to it can perform the listed actions against any resource in your AWS account.
The policy appears to be a policy you would apply to an EC2 instance profile to allow the AWS SSM agent to perform any SSM tasks on that EC2 instance. Since thee resource is specifie as the * wildcard then the SSM agent could, for example, download any SSM document you send it (ssm:GetDocument). This basically allows the SSM agent to work correctly on the EC2 instance, without requiring you to grant it specific access to each thing you need it to do, every time you trigger it in the future.