Allow AWS resources deletion only by delete CloudFormation stack - amazon-web-services

Please help with this case:
There is a CF stack that creates some AWS resources (created by admin account).
There is a AWS user (power user) that allowed to delete CF stack.
My goal:
Allow the user to delete CF stack and all created resources via CF stack deletion.
Deny the user to delete (and modify) resources from the resource console.
The problem:
If the user has permission cloudformation:DeleteStack only, he can only initiate deletion, as he have no permissions for resources deletion (for example, lambda:DeleteFunction)
If he has these permissions he can delete resources from the resource console (for example, Lambda console), not only by CF stack deletion.
Any ideas?

CloudFormation can assume a role to do its work: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html
So create a role that has all permissions needed to deploy the stack, and make sure that it is only assumable by CloudFormation. Then grant that user the permission to create and delete the stack, as well as list roles and whatever else is needed to do the create/delete (you'll have to experiment a bit, as some of the required permissions are non-obvious).

Related

Is that possible to delete a managed policy in AWS IAM from my account?

In web console of AWS IAM policies, the option "Delete" out of the "Action" drop down menu is disabled when selecting any managed policy.
In CLI, when trying to delete a managed policy, I got:
$ aws iam delete-policy --policy-arn arn:aws:iam::aws:policy/service-role/AWSQuickSightElasticsearchPolicy
An error occurred (AccessDenied) when calling the DeletePolicy operation: Cannot delete policies outside your own account.
the simple question: is that possible to remove any managed policy from my account? If yes, how?
"Cannot delete policies outside your own account" is telling. The policy-arn parameter has an account ID of aws, which I doubt is one that your authenticated identity can delete. (Unless you authed as Jeff Bezos, LOL.)
To remove a managed policy, the docs say:
Detach the policy from all users, groups, and roles that the policy is attached to, using DetachUserPolicy, DetachGroupPolicy, or DetachRolePolicy.
Delete all versions of the policy using DeletePolicyVersion.
Delete the policy (this automatically deletes the policy's default version) using this operation.
My guess is that the Web Console was greyed out because either the policy was attached or because there were versions. Make sure to delete those, per the instructions.
The command line failed because of the given ARN. When doing that last step, make sure to use the account ID for the account holding the managed policy to delete.
No, you cannot delete IAM policies that are managed by AWS. The policy in your example seems to be the one managed by AWS and hence cannot be deleted.
You can however delete customer managed IAM policies if you have appropriate permission to do so.
Ref: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-delete.html#:~:text=You%20cannot%20delete%20AWS%20managed%20policies

Why is iam:PassRole required in this project?

I cloned this solution azure-devops-on-aws and used dotnet lambda deploy-serverless ... to deploy the MyLizardApp to my personal AWS account.
During the learning curve, I created an S3 bucket my-lizard-test, IAM user group MyLizardGroup with user lizard-user and group policy MyLizardApp-Policy. Included in the policy are these services:
API Gateway (full access, all resources)
CloudFormation (full access, all resources)
Lambda (full access, all resources)
S3 (full access, all resources)
(Eventually) the deployment succeeded and I had a Lambda application serving the simple razor page showing the time.
I then copied the LambdaEntryPoint.cs, aws-lambda-tools-defaults.json and serverless.template files to my own dotnet core webapp (also a razor project) and attempted to deploy it to the same AWS account with the same command. The only changes made were the namespace of the LambdaEntryPoint class (reflected in the serverless.template file) and the .csproj file to include:
<AWSProjectType>Lambda</AWSProjectType>
and:
<PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="5.0.0" />
The dotnet lambda deploy-serverless ... command failed with the message:
User: arn:aws:iam::123456789120:user/lizard-user is not authorized to perform: iam:PassRole on resource: arn:aws:iam::123456789120:role/MyLizardAppServiceRole (Service: AWSLambdaInternal; Status Code: 403; Error Code: AccessDeniedException; Request ID: 12345678-1234-1234-1234-123456789012; Proxy: null)
I got the command to succeed by adding the IAM service to the MyLizardApp-Policy with the PassRole (all resources).
Why was this necessary for my personal app and not the demo solution from github? If the answer is not clear, what should I be looking for as differences? My personal app is not significantly different from the demo solution and I don't think the functional differences (in C#) would matter.
Whenever an AWS Service assumes (uses) an IAM Role, the service must have iam:PassRole permission to grant permission to use the Role. This required to prevent users from gaining too much permission.
For example, imagine a normal (non-Admin) user who launches an Amazon EC2 instance. When launching the instance, they can nominate an IAM Role to be assigned to the instance. If this user was permitted to select any IAM Role, they could select an Admin role and assign it to the EC2 instance. They could then login to the instance and use the credentials to make API calls as an Admin. This is an unwanted "privilege escalation".
Similarly, when an AWS Lambda function executes, it uses an IAM Role to obtain permissions. The iam:PassRole permission is used to control which roles a user can assign to the Lambda function.
So, there is something in that project that is trying to use an IAM Role and needs appropriate permissions.
First of all, we need to know what PassRole is:
iam:PassRole is the permission that controls which users can delegate an IAM role to an AWS resource.
As I can see in the repo, there is a file for CodeDeploy which already have credentials so maybe you are using CodeDeploy.
But btw, you are using an instances to deploy a Lambda function, and you need to pass the role to that Lambda so that is what PassRole do
AWS Services cannot directly assume service-linked roles. The role must be passed to the service by a user with the iam::PassRole permission.
The role-passing needs to be done only once, when a resource (e.g. EC2 instance) is created. After that the resource can assume the role repeatedly.
EC2 Instance profile is implemented this way. When a user launches an instance, it passes a role to the instance to act as an instance profile (it in addition needs iam:AddRoleToInstanceProfile for this case).
Other service-linked roles are also passed in this way.
Do not confuse it with the iam::CreateRole permission. A user may freely create service-linked roles, but is unable to pass the role to a service when needed.
In the management console, and to some extent in the CLI commands, role-passing is implicit, so you may encounter it without clear error messages when using non-root accounts.
As for why sometimes you need this permission, ands sometimes you don't, that is because when you use the root user, it will have AdministratorAccess which basically allows all actions on all resources.
If you create a new IAM user or account with blank permissions then you will need to add this permission manually.

Only allow CloudFormation to delete resources created by CloudFormation

I want to create permissions for AWS CloudFormation.
I have to provide delete permission. How can I restrict in a way so that it can only delete resources which were created by CloudFormation?
AWS CloudFormation will only delete resources that it originally created.
When deploying a stack, CloudFormation will create resources using the permissions associated with the credentials that created the stack. Or, if an IAM Role is specified when the stack is created, it will use those credentials to create resources.
When deleting resources, it will use the same credentials.
It is not possible to create permissions that say "only delete resources that were created by CloudFormation" because the permissions are defined outside of CloudFormation.
I know that CloudFormation adds tags to most (all?) of the resources it creates, so you might be able to do some fancy stuff with tags, but it generally shouldn't be necessary because CloudFormation will only delete resources it originally created.

Can I use existing AWS IAM role to create S3 bucket via Cloudformation template?

I want to create a S3 Bucket via CloudFormation template. I found there is a way to do it for EC2 instance on this link.
Do we have a way to create S3 bucket using existing IAM role via cloudformation?
It looks like what you're looking for is a service role. From AWS:
A service role is an AWS Identity and Access Management (IAM) role that allows AWS CloudFormation to make calls to resources in a stack on your behalf. You can specify an IAM role that allows AWS CloudFormation to create, update, or delete your stack resources. By default, AWS CloudFormation uses a temporary session that it generates from your user credentials for stack operations. If you specify a service role, AWS CloudFormation uses the role's credentials.
For more information, you might want to take a look at this, specifically the permission part to find out how to use an existing IAM role for creating a Cloudformation stack.
By the way: Unfortunately the link that you've provided doesn't seem to be accessible anymore.
When deploying infrastructure using creating Cloudformation template, you can have 2 ways to do it:
Cloudformation can deploy resources using the permissions of the current user who deploys the CF template. This is the default way
Secondly (Optional), you can choose an existing role that can be attached to the CF template. Cloudformation service will use the permissions of that attached role to deploy all the required services. Given that the attached role has permissions to S3, you can create an S3 bucket as can be seen in the attached screenshot

Adding a role to an opsworks instance

I am trying to figure out if there is a way to change an OpsWorks role of a running stack (without having to clone the entire stack)
You can change the role in the stack settings, but the instances you have created up to now will still have the old role. Any new instances you create after that will have the new role.
Opsworks or not, once an instance is assigned a role, it cannot be changed, you can only create a new instance with a different role.
The role policies can be changed any time though, so if you need to make changes, you can just attach a new policy to an existing role rather than creating a new role.