Create IAM account with CloudFormation - amazon-web-services

I want to create an AWS IAMS account that has various permissions with CloudFormation.
I understand there are policies that would let a user change his password and let him get his account to use MFA here
How could I enforce the user to use MFA at first log in time when he needs to change the default password?
This is what I have:
The flow I have so far is:
User account is created
When user tries to log in for the first time is asked to change the default password.
User is logged in the AWS console.
Expected behavior:
User account is created
When user tries to log in for the first time is asked to change the default password and set MFA using Authenticator app.
User is logged in the AWS console and has permissions.
A potential flow is shown here. Is there another way?
Update:
This blog explains the flow
Again, is there a better way? Like an automatic pop up that would enforce the user straight away?
Update2:
I might have not been explicit enough.
What we have so far it is an ok customer experience.
This flow would be fluid
User tries to log in
Console asks for password change
Colsole asks for scanning the code and introducing the codes
User logs in with new password and the code from authenticator
5.User is not able to deactivate MFA

Allow users to self manage MFA is the way to go, if you are using regular IAM. You can try AWS SSO, it's easier to manage and free.
Allowing users to login, change password, setup MFA and Denying everything other than these if MFA is not setup as listed here
We could create an IAM Group with an inline policy and assign users to that group.
This is CF for policy listed in the docs.
Resources:
MyIamGroup:
Type: AWS::IAM::Group
Properties:
GroupName: My-Group
MyGroupPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- iam:GetAccountPasswordPolicy
- iam:GetAccountSummary
- iam:ListVirtualMFADevices
- iam:ListUsers
Effect: Allow
Resource: "*"
- Action:
- iam:ChangePassword
- iam:GetUser
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::1234567891111:user/${aws:username}
- Action:
- iam:CreateVirtualMFADevice
- iam:DeleteVirtualMFADevice
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::1234567891111:mfa/${aws:username}
- Action:
- iam:DeactivateMFADevice
- iam:EnableMFADevice
- iam:ListMFADevices
- iam:ResyncMFADevice
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::1234567891111:user/${aws:username}
- NotAction:
- iam:CreateVirtualMFADevice
- iam:EnableMFADevice
- iam:GetUser
- iam:ListMFADevices
- iam:ListVirtualMFADevices
- iam:ListUsers
- iam:ResyncMFADevice
- sts:GetSessionToken
Condition:
BoolIfExists:
aws:MultiFactorAuthPresent: "false"
Effect: Deny
Resource: "*"
PolicyName: My-Group-Policy
Groups:
- Ref: MyIamGroup

I think this is the way to go and one could extract the knowledge of creating users with whatever permissions he wants after the user sets up the MFA.
The policy template it is useful.
instructions

Related

Permission required for create aws backup vault

TableBackupVault:
Type: AWS::Backup::BackupVault
Properties:
BackupVaultName: tabel-vault
What permission are required for creating backup vault?
I tried these
- Sid: Backup
Effect: Allow
Action:
- backup:CreateBackupVault
- backup:CreateBackupPlan
- backup:CreateBackupSelection
- backup:TagResource
- backup:UntagResource
Resource:
- *
But I am getting
Error:
CREATE_FAILED: BackupVault (AWS::Backup::BackupVault)
Resource handler returned message: "Insufficient privileges to perform this action"
For anyone with this error, you have to add the following iam rule additionnaly:
backup-storage:MountCapsule
As it is required here: https://docs.aws.amazon.com/aws-backup/latest/devguide/access-control.html

Dynamodb is not authorised to perform dynamodb:PutItem

I'm getting this error while performing PutItem on dynamodb
AccessDeniedException: User: arn:aws:sts::8**************2:assumed-role/AmazonSSMRoleForInstancesQuickSetup/i-0**************2 is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-east-2:8**************2:table/test-dynamodb-table
This is how my permissions.yml file look like.
Effect: Allow
Action:
- 'dynamodb:DescribeTimeToLive'
- 'dynamodb:BatchGet*'
- 'dynamodb:DescribeStream'
- 'dynamodb:DescribeTable'
- 'dynamodb:Get*'
- 'dynamodb:Query'
- 'dynamodb:Scan'
- 'dynamodb:BatchWrite*'
- 'dynamodb:CreateTable'
- 'dynamodb:Delete*'
- 'dynamodb:Update*'
- 'dynamodb:PutItem'
Resource:
- 'arn:aws:dynamodb:*'
I've given all the required permissions but it's still failing. Any help on this??
According to documentation if you want to add permission for all DynamoDB tables in all regions for specific account you need to write it like this:
"arn:aws:dynamodb:*:123456789012:table/*/"
I assume that you can replace account number with * also, but if that is not working you can put your account number.

AWS ALB Ingress Controller with IRSA authorization error

I am trying to setup an AWS ALB Ingress Controller using the IRSA method instead of kube2iam. There is however some lack of documentation so I came to a dead end.
What I did so far:
Configured the OIDC provider for my cluster
eksctl utils associate-iam-oidc-provider --cluster devops --approve
Created the proper policy by using the template
Created the IAM service account that will be used by the Ingress Controller and associated the policy
eksctl create iamserviceaccount --name alb-ingress --namespace default --cluster devops --attach-policy-arn arn:aws:iam::112233445566:policy/eks-ingressController-iam-policy-IngressControllerPolicy-1111111111 --approve
Deployed required rbac rules provided
kubectl apply -f rbac-role.yaml
Deployed the AWS Ingress Controller by using this template. Payed attention so the ServiceAccount matches the service account I created previously.
Everything up to here is deployed fine. Now I try to deploy my Ingress service but I get this error (in the controller logs)
kubebuilder/controller "msg"="Reconciler error" "error"="failed to build LoadBalancer configuration due to failed to get AWS tags. Error: AccessDeniedException: User: arn:aws:sts::1122334455:assumed-role/eksctl-devops-nodegroup-ng-1-work-NodeInstanceRole-J08FDJHIWPI7/i-000000000000 is not authorized to perform: tag:GetResources\n\tstatus code: 400, request id: 94d614a1-c05d-4b92-8ad6-86b450407f6a" "Controller"="alb-ingress-controller" "Request"={"Namespace":"superset","Name":"superset-ingress"}
Obviously the node doesn't have the proper permissions for the ALB creation, and I guess that if I attached my policy to the role stated in the log it would work. But that defeats the whole purpose of doing the IRSA method right?
What I would expect is for the Ingress Controller pod to need the appropriate permissions -by using the service account- to create the ALB and not the Node. Am I missing something here?
I've got a similar error (not identical) when using version v1.1.8 of this controller:
kubebuilder/controller "msg"="Reconciler
error"="failed get
WAFv2 webACL for load balancer arn:aws:elasticloadbalancing:...:
AccessDeniedException: User:
arn:aws:sts:::assumed-role/eks-node-group-role/
is not authorized to perform: wafv2:GetWebACLForResource on resource:
arn:aws:wafv2:us-east-2::regional/webacl/*\n\tstatus code:
400, request id: ..."
"controller"="alb-ingress-controller"
"request"={"Namespace":"default","Name":"aws-alb-ingress"}
I'll add it because I think it can help people which search under the same error message.
The reason for the error described above was the fact that version v1.1.7 of this controller needs new IAM permissions in the nodegroup role's *PolicyALBIngress policy.
(!) Be aware that the new IAM permission is required even no wafv2 annotation is used.
Solution 1
Adding the section of wafv2 allow actions to the policy:
{
"Effect": "Allow",
"Action": [
"wafv2:GetWebACL",
"wafv2:GetWebACLForResource",
"wafv2:AssociateWebACL",
"wafv2:DisassociateWebACL"
],
"Resource": "*"
}
Solution 2
WAFV2 support can be disabled by controller flags as mentioned here.
A) If you install it via kubectl, add - --feature-gates=waf=false to the spec -> containers -> args section.
B) If you install it via helm, add --set extraArgs."feature-gates"='waf=false' in helm upgrade command.
Notice that this requirment was already being updated in the eksctl tool (Review also in here).
Additional reference.
So, in case someone comes up to the same problem.
The solution is, when creating the rbac roles, to comment out from the rbac-role.yaml (as provided here) the last part which creates the service account.
Since we already created a service account with eksctl and attached to it the aws policy, we can attach to this service account the rbac permissions also. Then this service account can be used normally in the ingress controller pod to do its magic.
According to the documentation need the permission to CRUD an ALB. You could if you wanted to try giving just the ALB driver Pod a role with permissions create the ALB but I have not tested it and I am not sure it matters, if your entire scheduler has been given access to to use the ALB driver/pod to create these objects on AWS.
I am not using EKS's 3.0's cluster creation tool, instead I have my own CFT that I use to create workers due to my orgs additional security requirements.
I have have created and attached the bellow managed policy to workers that need to create ALB's and it just works.
ALBPolicy:
Type: "AWS::IAM::ManagedPolicy"
Properties:
Description: Allows workers to CRUD alb's
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "acm:DescribeCertificate"
- "acm:ListCertificates"
- "acm:GetCertificate"
Resource: "*"
-
Effect: "Allow"
Action:
- "ec2:AuthorizeSecurityGroupIngress"
- "ec2:CreateSecurityGroup"
- "ec2:CreateTags"
- "ec2:DeleteTags"
- "ec2:DeleteSecurityGroup"
- "ec2:DescribeAccountAttributes"
- "ec2:DescribeAddresses"
- "ec2:DescribeInstances"
- "ec2:DescribeInstanceStatus"
- "ec2:DescribeInternetGateways"
- "ec2:DescribeNetworkInterfaces"
- "ec2:DescribeSecurityGroups"
- "ec2:DescribeSubnets"
- "ec2:DescribeTags"
- "ec2:DescribeVpcs"
- "ec2:ModifyInstanceAttribute"
- "ec2:ModifyNetworkInterfaceAttribute"
- "ec2:RevokeSecurityGroupIngress"
Resource: "*"
-
Effect: "Allow"
Action:
- "elasticloadbalancing:AddListenerCertificates"
- "elasticloadbalancing:AddTags"
- "elasticloadbalancing:CreateListener"
- "elasticloadbalancing:CreateLoadBalancer"
- "elasticloadbalancing:CreateRule"
- "elasticloadbalancing:CreateTargetGroup"
- "elasticloadbalancing:DeleteListener"
- "elasticloadbalancing:DeleteLoadBalancer"
- "elasticloadbalancing:DeleteRule"
- "elasticloadbalancing:DeleteTargetGroup"
- "elasticloadbalancing:DeregisterTargets"
- "elasticloadbalancing:DescribeListenerCertificates"
- "elasticloadbalancing:DescribeListeners"
- "elasticloadbalancing:DescribeLoadBalancers"
- "elasticloadbalancing:DescribeLoadBalancerAttributes"
- "elasticloadbalancing:DescribeRules"
- "elasticloadbalancing:DescribeSSLPolicies"
- "elasticloadbalancing:DescribeTags"
- "elasticloadbalancing:DescribeTargetGroups"
- "elasticloadbalancing:DescribeTargetGroupAttributes"
- "elasticloadbalancing:DescribeTargetHealth"
- "elasticloadbalancing:ModifyListener"
- "elasticloadbalancing:ModifyLoadBalancerAttributes"
- "elasticloadbalancing:ModifyRule"
- "elasticloadbalancing:ModifyTargetGroup"
- "elasticloadbalancing:ModifyTargetGroupAttributes"
- "elasticloadbalancing:RegisterTargets"
- "elasticloadbalancing:RemoveListenerCertificates"
- "elasticloadbalancing:RemoveTags"
- "elasticloadbalancing:SetIpAddressType"
- "elasticloadbalancing:SetSecurityGroups"
- "elasticloadbalancing:SetSubnets"
- "elasticloadbalancing:SetWebACL"
Resource: "*"
-
Effect: "Allow"
Action:
- "iam:CreateServiceLinkedRole"
- "iam:GetServerCertificate"
- "iam:ListServerCertificates"
Resource: "*"
-
Effect: "Allow"
Action:
- "cognito-idp:DescribeUserPoolClient"
Resource: "*"
-
Effect: "Allow"
Action:
- "waf-regional:GetWebACLForResource"
- "waf-regional:GetWebACL"
- "waf-regional:AssociateWebACL"
- "waf-regional:DisassociateWebACL"
Resource: "*"
-
Effect: "Allow"
Action:
- "tag:GetResources"
- "tag:TagResources"
Resource: "*"
-
Effect: "Allow"
Action:
- "waf:GetWebACL"
Resource: "*"

How do I access the current user in a cloudformation template?

I want to create a KMS key using CloudFormation. I want to be able to provide the user executing the cloudformation YAML file (I'll call them "cloudformation-runner"), administrative access to the key they create.
I can setup the IAM policy to provide that user ("cloudformation-runner") access to the KMS Administrative APIs. However, for the user to be able to update/delete the key that was just created, I also need to specify a KeyPolicy that lets them do it. To do this, how can I get the current username ("cloudformation-runner") within the CloudFormation script?
Here is how my template for the KMS key looks, how do I get the current user as the principal?
MyKey:
Type: AWS::KMS::Key
Properties:
Description: "..."
KeyPolicy:
Version: "2012-10-17"
Id: "MyId"
Statement:
-
Sid: "Allow administration of the key"
Effect: "Allow"
Principal:
AWS:
- # TODO: Get Current User
Action:
- "kms:Create*"
- "kms:Describe*"
- "kms:Enable*"
- "kms:List*"
- "kms:Put*"
- "kms:Update*"
- "kms:Revoke*"
- "kms:Disable*"
- "kms:Get*"
- "kms:Delete*"
- "kms:ScheduleKeyDeletion"
- "kms:CancelKeyDeletion"
Resource: "*"
I can manually hardcode the ARN for the IAM user. However, that makes the template less portable - as people need to manually update the username within this file.
You can't access the current user once it can be an IAM Role running the CloudFormation template instead of an IAM User. But you can pass the username as a parameter.
I would like to give you an example that I think works well for your context:
The "cloudformation-runner" can be a Role instead of a user. This Role can have a policy giving privileges to create KMS keys.
The CloudFormation template can receive the IAM username and key name as parameters. From an IAM username, you can create the user ARN using CF functions.
Besides creating the KMS keys, the parameters can be used to create the IAM policy and attach to the user giving read/write privileges to the newly created key.
That way your key creation process can create the key and give user privileges at the same time.
Credit to this answer for the idea.
You can pass current user's ARN as CloudFormation parameter:
Parameters:
...
CallingUserArn:
Description: Calling user ARN
Type: String
Resources
KmsKey:
Type: AWS::KMS::Key
Properties:
...
KeyPolicy:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: !Ref CallingUserArn
...
aws cloudformation deploy \
--template-file cloudformation/stack.yml \
--stack-name my-stack \
--parameter-overrides CallingUserArn="$(aws sts get-caller-identity --query Arn --output text)"

How to enable IAM users to set the Name and other custom tags when limited by tag restricted resource-level permissions in EC2

I have been playing with configuring tag based resource permissions in EC2, using an approach similar to what is described in the answer to the following question: Within IAM, can I restrict a group of users to access/launch/terminate only certain EC2 AMIs or instances?
I have been using this in conjunction with a lambda function to auto tag EC2 instances, setting the Owner and PrincipalId based on the IAM user who called the associated ec2:RunInstances action. The approach I have been following for this is documented in the following AWS blog post: How to Automatically Tag Amazon EC2 Resources in Response to API Events
The combination of these two approaches has resulted in my restricted user permissions for EC2 looking like this, in my CloudFormation template:
LimitedEC2Policy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: UserLimitedEC2
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: ec2:RunInstances
Resource:
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${PrivateSubnetA}'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${PrivateSubnetB}'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${PrivateSubnetC}'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/${BasicSSHAccessSecurityGroup.GroupId}'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:key-pair/${AuthorizedKeyPair}'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:network-interface/*'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*'
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:volume/*'
- !Sub 'arn:aws:ec2:${AWS::Region}::image/ami-*'
Condition:
StringLikeIfExists:
ec2:Vpc: !Ref Vpc
StringLikeIfExists:
ec2:InstanceType: !Ref EC2AllowedInstanceTypes
- Effect: Allow
Action:
- ec2:TerminateInstances
- ec2:StopInstances
- ec2:StartInstances
Resource:
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*'
Condition:
StringEquals:
ec2:ResourceTag/Owner: !Ref UserName
Users:
- !Ref IAMUser
These IAM permissions restricts users to running EC2 instances within a limited set of subnets, within a single VPC and security group. Users are then only able to start/stop/terminate instances which have been tagged with their IAM user in the Owner tag.
What I'd like to be able to do is allow users to also create and delete any additional tags on their EC2 resources, such as setting the Name tag. What I can't work out is how I can do this without also enabling them to change the Owner and PrincipalId tags on resources they don't "own".
Is there a way one can limit the ec2:createTags and ec2:deleteTags actions to prevent users from setting certain tags?
After much sifting through the AWS EC2 documentation I found the following: Resource-Level Permissions for Tagging
This gives the example:
Use with the ForAllValues modifier to enforce specific tag keys if
they are provided in the request (if tags are specified in the
request, only specific tag keys are allowed; no other tags are
allowed). For example, the tag keys environment or cost-center are
allowed:
"ForAllValues:StringEquals": { "aws:TagKeys": ["environment","cost-center"] }
Since what I want to achive is essentially the opposite of this (allow users to specify all tags, with the exception of specific tag keys) I have been able to prevent users from creating/deleting the Owner and PrincipalId tags by adding the following PolicyDocument statement to my user policy in my CloudFormation template:
- Effect: Allow
Action:
- ec2:CreateTags
- ec2:DeleteTags
Resource:
- !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:*/*'
Condition:
"ForAllValues:StringNotEquals":
aws:TagKeys:
- "Owner"
- "PrincipalId"
This permits users to create/delete any tags they wish, so long as they aren't the Owner or PrincipalId.