Prompt for MFA code on certain AWS Cli actions - amazon-web-services

We force MFA for AWS web console access. But I also want some aws actions to be prompted for MFA code.
aws iam delete-users --user-name theusername
Enter MFA: *********
Is this possible?

You should be able to add an MFA condition on the relevant API actions. For example, here's a IAM policy that allows the bearer to invoke EC2 actions freely, but requires MFA when invoking StopInstances or TerminateInstances.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["ec2:*"],
"Resource": ["*"]
},{
"Effect": "Deny",
"Action": ["ec2:StopInstances", "ec2:TerminateInstances"],
"Resource": ["*"],
"Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": false}}
}]
}
For a more detailed example, see here.

The exact use case is not possible. However, you can give the necessary permission e.g. StopInstances to an IAM Role and give the IAM user permission only to assume the role if and only if the user uses MFA. The role's trust policy will be as following:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:root" },
"Action": "sts:AssumeRole",
"Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
}
}
So while using the Console, IAM user will sign in with credentials and MFA token and will be able to assume the role to stop the instance.
While using CLI, you can use named profiles with "mfa_serial" variable and when the user will try to stop the instance with the named profile parameter, the CLI will ask for the MFA code (note that the returned credentials will be cached in CLI).
Alternatively, you can use the suggestion provided by jarmod and use custom script because you need to call GetSessionToken and pass the MFA token. There is a sample Python and C# script here.

Related

AWS SNS ConfirmSubscription authorization never granted to IAM user

Goal: Grant permissions to IAM user to confirm an SNS Topic Subscription
Problem: Using AWS Web Console, I am unable to grant the proper SNS permissions to the IAM user account no matter what permissive policies I attach to it.
Steps completed: I created a Topic which tracks changes to S3 objects and pushes that information to my application via an SNS subscription (HTTPS/JSON calls).
My code that receives the request:
def self.confirm(arn, token)
client = retrieve_client
client.confirm_subscription(topic_arn: arn, token: token)
end
def self.retrieve_client
creds = Aws::Credentials.new(
Rails.application.credentials.dig(:aws, :access_key_id),
Rails.application.credentials.dig(:aws, :secret_access_key)
)
Aws::SNS::Client.new(region: 'us-east-2', credentials: creds)
end
When my code receives the SNS confirmation request, I receive this error message:
Aws::SNS::Errors::AuthorizationError (User: arn:aws:iam::12345678912:user/user_name is not authorized to perform: SNS:ConfirmSubscription on resource: arn:aws:sns:us-east-2:12345678912:topic_name because no boundary policy allows the SNS:ConfirmSubscription action)
The above code works well with a different application (but different IAM user), so I don't believe the code is the culprit, yet.
I've attempted adding policies to a group, then the user to the group, nothing changes.
I've resorted to directly adding policies to the user, nothing changes.
Here are the two most permissive policies I've tried and I don't know what other blanket permissions I can give this user to make this subscription confirmation work.
Topic arn: arn:aws:sns:us-east-2:12345678912:topic_name
Topic access policy:
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-2:12345678912:topic_name
"StringEquals": {
"AWS:SourceAccount": "12345678912"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:*:*:*"
}
}
}
]
}
Policy 1 (from the AWS Managed AmazonSNSFullAccess policy):
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Policy 2, where I just click as many Action selections as possible to see if anything will work:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"sns:TagResource",
"sns:DeleteTopic",
"sns:ListTopics",
"sns:Unsubscribe",
"sns:CreatePlatformEndpoint",
"sns:SetTopicAttributes",
"sns:UntagResource",
"sns:OptInPhoneNumber",
"sns:CheckIfPhoneNumberIsOptedOut",
"sns:ListEndpointsByPlatformApplication",
"sns:SetEndpointAttributes",
"sns:Publish",
"sns:DeletePlatformApplication",
"sns:SetPlatformApplicationAttributes",
"sns:VerifySMSSandboxPhoneNumber",
"sns:Subscribe",
"sns:ConfirmSubscription",
"sns:RemovePermission",
"sns:ListTagsForResource",
"sns:DeleteSMSSandboxPhoneNumber",
"sns:ListSubscriptionsByTopic",
"sns:GetTopicAttributes",
"sns:ListSMSSandboxPhoneNumbers",
"sns:CreatePlatformApplication",
"sns:SetSMSAttributes",
"sns:CreateTopic",
"sns:GetPlatformApplicationAttributes",
"sns:GetSubscriptionAttributes",
"sns:ListSubscriptions",
"sns:AddPermission",
"sns:ListOriginationNumbers",
"sns:DeleteEndpoint",
"sns:ListPhoneNumbersOptedOut",
"sns:GetEndpointAttributes",
"sns:SetSubscriptionAttributes",
"sns:GetSMSSandboxAccountStatus",
"sns:CreateSMSSandboxPhoneNumber",
"sns:ListPlatformApplications",
"sns:GetSMSAttributes"
],
"Resource": "*"
}
]
}
It's completely unclear to me what other policies are required to give this user the authorization necessary to confirm the SNS subscription.
Thanks to the question Marcin asked about the "boundary policy," I learned that the concept of an IAM boundary policy existed, what it was, and then fixed my problem.
At some point, when the IAM user was setup, a boundary policy was attached to the user account, which precludes any other policies that may be given to that user by other service or group policies.
Thus, when I inspected the IAM user in question, I found a boundary policy that only permitted access to AWS S3 services. This policy prevented my efforts to give the user access to AWS SNS services.
After removing the boundary policy, the IAM user settings now read "Permissions boundary (not set)" and the confirmation of the SNS subscriptions work as expected.
Thanks for the help, Marcin!

AWS: Enforce MFA for Console users but not CLI

I am trying to give admin rights to a specific user group and enforcing MFA for the same group. MFA should be only enforced for console users though, not when using the AWS CLI.
These are the policies I have been testing with:
Policy 1 - Administrator access granted if MFA
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAdminAccessIfSignedInWithMFA",
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
}
Policy 2 - Still, allow the user to set up MFA in case it is not yet active
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowViewAccountInfo",
"Effect": "Allow",
"Action": "iam:ListVirtualMFADevices",
"Resource": "*"
},
{
"Sid": "AllowManageOwnVirtualMFADevice",
"Effect": "Allow",
"Action": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice"
],
"Resource": "arn:aws:iam::*:mfa/${aws:username}"
},
{
"Sid": "AllowManageOwnUserMFA",
"Effect": "Allow",
"Action": [
"iam:DeactivateMFADevice",
"iam:EnableMFADevice",
"iam:GetUser",
"iam:ListMFADevices",
"iam:ResyncMFADevice"
],
"Resource": "arn:aws:iam::*:user/${aws:username}"
}
]
}
This last policy was adapted from this one.
The official documentation for aws:MultiFactorAuthPresent says, as I understand it, that the combination of "Allow", "BoolIfExists" and "true" should work well for my purpose:
This condition matches either if the key exists and is present or if the key does not exist. This combination of Allow, BoolIfExists, and true allows requests that are authenticated using MFA, or requests that cannot be authenticated using MFA. This means that AWS CLI, AWS API, and AWS SDK operations are allowed when the requester uses their long-term access keys. This combination does not allow requests from temporary credentials that could, but do not include MFA.
If you are wondering why I'm not using any (seemingly simpler) policy containing a "Deny" effect, like:
"Effect" : "Deny",
"Condition" : { "BoolIfExists" : { "aws:MultiFactorAuthPresent" : "false" } }
...the reason is:
This combination of Deny, BoolIfExists, and false denies requests that are not authenticated using MFA. Specifically, it denies requests from temporary credentials that do not include MFA. It also denies requests that are made using long-term credentials, such as AWS CLI or AWS API operations made using access keys. The *IfExists operator checks for the presence of the aws:MultiFactorAuthPresent key and whether or not it could be present, as indicated by its existence. Use this when you want to deny any request that is not authenticated using MFA. This is more secure, but can break any code or scripts that use access keys to access the AWS CLI or AWS API.
Everything works as expected, except for when I try to access resources using the AWS CLI (with an access key).
Am I missing something or is the documentation misleading?
PS: I would like to avoid having separate user groups for console and CLI users.

Why is this s3 Bucket policy invalid?

{
"Version": "2012-10-17",
"Id": "Policy1612574490300",
"Statement": [
{
"Sid": "Stmt1612574488073",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:ec2:us-east-1:258977512672:instance/i-041123c1993c370ba"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my_bucket",
"arn:aws:s3:::my_bucket/*"
]
}
]
}
response is Invalid Principal. I dont see why it's invalid.
An EC2 instance isn't a valid principal. I think what you actually need to do here is use the ARN of the IAM role assigned to the EC2 instance.
You can specify following Principal in a policy
AWS account and root user
IAM users
Federated users (using web identity or SAML federation)
IAM roles
Assumed-role sessions
AWS services
Anonymous users (not recommended)
S3 Documentation Principal
AWS JSON policy elements: Principal
If you wanna give that instant access to the bucket then you can use Instance profiles

AWS Assume Role: "Invalid information in one or more fields."

I am planning to implement AssumeRole scenario so below is scenario
user will have ability to create/stop Ec2 instances but not terminate.
To terminate he has to assume role (role to be assumed Ec2FullAccess)
I have done the following
Create a user Test1 with permission to start/stop/launch Ec2 instance and have provided permission to assume role (EC2FullAccess) below is the Policy for user
{
"Version": "2012-10-17",
"Statement": [<br>
{
"Action": "ec2:*",
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Deny",
"Action": "ec2:TerminateInstances",
"Resource": "*"
},
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Resource": "arn:aws:iam::226904037275:role/EC2FullAccess"
}
]
}
Create a role in same account with name EC2FullAccess which would give permission to terminate Ec2 instance
Ec2FullAccess uses AmazonEC2FullAccess Permission Policy below is its Trust Policy
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Now when i login as IAM user Test1 and then click on switch role ,i provide below details
Account: 1234
Role: EC2FullAccess
When i click on Switch Role i get Below error
Invalid information in one or more fields. Check your information or contact your administrator.
What is that I am missing
You can create the Role this way:
Create Role
For Type of Trusted Entity, select Another AWS Account and enter the Account ID for the same account (it is displayed in the same menu as the 'Switch Role' command) -- This might seem odd, but it creates the correct principal in the Trust Policy.
Attach desired policies and Save
Then, use Switch Role.
By the way, assigning EC2FullAccess is probably overkill -- it gives permission to do anything in EC2, including deleting VPCs, deleting Amazon EBS volumes, changing network settings, etc. I suggest you create a specific policy that grants TerminateInstances permission, and possibly even reduce that down to specific instances (eg by tag or VPC).

AWS PowerUser with MFA (IAM policy)

I templated the PowerUser policy and added MFA condition, resulting in MFA-PowerUser like the following
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
}
The description and intention is:
Provides full access to AWS services and resources, but does not allow management of Users and groups. MFA needed by login.
test on EC2 with policy simulator all EC2 actions are denied with the reason
implicitly denied (no matching statement)
solved by myself. Should give the environment variable MultiFactorAuthPresent into the simulator