AWS PowerUser with MFA (IAM policy) - amazon-web-services

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

Related

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.

S3 deny access to administrators

For one AWS S3 bucket, I would like to deny access to everyone except for one specific IAM role. I created a role-based policy to allow access and that works. But other IAM users are also able to access objects and I want to prevent this. I tried adding a bucket policy like this, which denies everyone except this principal and then allows this principal. But this policy blocks access to everyone including that role.
The other IAM users I am trying to block are attached to the built-in AdminstratorAccess policy.
{
"Version": "2012-10-17",
"Id": "PolicySecretBucket",
"Statement": [
{
"Sid": "StmtDenyAll",
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::********:role/service-role/my-role"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "StmtAllowLambdaBot",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::********:role/service-role/my-role"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
this is how I would do it:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::MyExampleBucket",
"arn:aws:s3:::MyExampleBucket/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAEXAMPLEID:*",
"ACCOUNT NUMBER"
]
}
}
}
]
}
this is how it works.
the user's will have an IAM policy which allows s3.* actions
we will deny all the s3 actions for the bucket MyExampleBucket for any user id but the user id of the role (and the user id of the root account in case if the role is deleted) using the bucket policy
to get the user id of the role:
aws iam get-role --role-name ROLE-NAME
And finally, why yours does not work: https://serverfault.com/a/988136
reference:
https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/
Denying access to a specific bucket is actually quite difficult.
For example, an Administrator might have permissions to assume the Role, so they can still access the bucket.
You would also need to review all policies to ensure that only authorized people can use iam:PassRole to assume the role via an Amazon EC2 instance.
An safer approach would be to put the bucket in a separate AWS Account. Then, only give cross-account access to specific users (not a Role). This way, the default is that Admins have zero access and you then grant access to the desired people. There are less ways to "get around" this type of access.

Prompt for MFA code on certain AWS Cli actions

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.

How to change s3 bucket policies with cloudformation?

I would like to be able to change the policies on s3 buckets using cloudformation. However when I attempt to do this I encounter the error:
2017-12-21 18:49:10 UTC TestBucketpolicyAwsS3Bucketpolicy CREATE_FAILED API: s3:PutBucketPolicy Access Denied
Here is an example of a cloudformation template that fails due to this issue:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "",
"Resources": {
"TestBucketpolicyAwsS3Bucketpolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": "alex-test-bucket-123",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Resource": "arn:aws:s3:::alex-test-bucket-123/*",
"Action": [
"s3:GetObject*",
"s3:DeleteObject*",
"s3:PutObject*"
]
}
]
}
}
}
}
}
I have tried changing policies on both my IAM user and the actual bucket I want to manage with cloudformation, but neither solution has resolved the issue. How can I get remove this "s3:PutBucketPolicy" restriction?
Edit: I think the issue may be that only IAM roles can access the "s3:PutBucketPolicy" operation. I may need to create a role with s3 access then establish a trust relationship with the user that runs this cloudformation template.
https://docs.aws.amazon.com/cli/latest/userguide/cli-roles.html
IAM users cannot directly run s3:PutBucketPolicy operations. You need to create a separate IAM role and attach it to your user with a trust relationship to assume that IAM role.
Your role will need s3 and cloudformation access. The policy document below will work.
{
"Version": "2012-10-17",
"Statement": {
"Action": [
"s3:*",
"cloudformation:*"
],
"Resource": "*",
"Effect": "Allow"
}
}
The arn of your IAM role will then need to be set in your config or the AWS_STS_ROLE_ARN environmental variable along with your aws access keys.
Once you assume the role you will then be able to change s3 bucket policies.
Note that this will override any permissions your user has when you set your AWS_STS_ROLE_ARN in your config or environmental variables.

Error: Access Denied in S3 bucket after applying VPC policy

I have applied a policy to allow only connections from my VPC:
{
"Version": "2012-10-17",
"Id": "Policy1415115909153",
"Statement": [
{
"Sid": "Access-to-specific-VPC-only",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["arn:aws:s3:::examplebucket",
"arn:aws:s3:::examplebucket/*"],
"Condition": {
"StringNotEquals": {
"aws:sourceVpc": "vpc-111bbb22"
}
},
"Principal": "*"
}
]
}
But now I'm getting "Access Denied" even when I try to access it from the AWS Console from an instance in the given VPC:
I've read https://aws.amazon.com/premiumsupport/knowledge-center/s3-regain-access/, but unfortunately I use a company-provided federated login and I don't have access to the full root user.
My question is why can't I access the bucket even when inside the VPC?
Some similar questions that I found - Policy Denying Access On Amazon S3 and S3 VPC end point Bucket policy
To prevent your policy from being applied to your federated users in AWS console, you could "whitelist" them using the NotPrincipal element instead of Principal in your policy statement. For example:
{
"Version": "2012-10-17",
"Id": "Policy1415115909153",
"Statement": [
{
"Sid": "Access-to-specific-VPC-only",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["arn:aws:s3:::examplebucket",
"arn:aws:s3:::examplebucket/*"],
"Condition": {
"StringNotEquals": {
"aws:sourceVpc": "vpc-111bbb22"
}
},
"NotPrincipal": {
"Federated": "arn:aws:iam::YOUR-AWS-ACCOUNT-ID:saml-provider/YOUR-PROVIDER-NAME"
}
}
]
}
Do you have a VPC endpoint for S3 set up?
There are two ways to access objects in S3. One is through the AWS console and the other is through HTTPS calls to the S3 object.
If you're trying to access the bucket from the AWS console, then permission is governed by your IAM user/role and bucket policy. You're using a federated login, so I'm assuming it's a role.
From an instance in VPC-111bbb222, log out of the AWS console and try to access an object in that bucket using the HTTPS URL.