Related
I am trying to follow this article for Secret Manager and tried applying attribute based access controll (ABAC) for AWS Lambda by using this user role policy linkage:
Create IAM user
Assign a role to this IAM user
Role is assigned an ABAC policy for lambda.
currently my ABAC policy for Lambda usage for different users in a project is as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaPolicyForProject",
"Effect": "Allow",
"Action": [
"cloudformation:DescribeStacks",
"cloudformation:ListStackResources",
"cloudwatch:GetMetricData",
"cloudwatch:ListMetrics",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"kms:ListAliases",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:ListRoles",
"logs:DescribeLogGroups",
"lambda:Get*",
"lambda:List*",
"states:DescribeStateMachine",
"states:ListStateMachines",
"tag:GetResources",
"xray:GetTraceSummaries",
"xray:BatchGetTraces"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/accessproject": "${aws:PrincipalTag/accessproject}",
"aws:ResourceTag/accessteam": "${aws:PrincipalTag/accessteam}",
"aws:ResourceTag/costcenter": "${aws:PrincipalTag/costcenter}"
}
}
}
]
}
This does not work for a user when the costcenter, accessteam, accessproject tags are similar for both IAM user and lambda.
However, it works when I remove the condition in the above policy (this shows IAM is able to access lambda policy).
Can I know what I am missing from the tutorial above? I did cross check all tags for lambda, policies and IAM users, and they are same as per the docs.
The issue seems to be in the Actions you defined. According to the tutorial you followed:
[...] see Actions, Resources, and Condition Keys for AWS Secrets Manager. That page shows that actions performed on the Secret resource type support the secretsmanager:ResourceTag/tag-key condition key. Some Secrets Manager actions don't support that resource type, including GetRandomPassword and ListSecrets.
Have a look at actions, resources, and condition keys for AWS services and for each service make sure the action supports the aws:ResourceTag/${TagKey} condition. I didn't go through all the permissions but already the CloudWatch actions GetMetricData and ListMetrics do not support the aws:ResourceTag/${TagKey} condition. Same goes for ec2:DescribeSecurityGroups,
ec2:DescribeSubnets, ec2:DescribeVpcs, and probably a few more.
You must create additional statements to allow those actions i.e:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaPolicyForProject",
"Effect": "Allow",
"Action": [
"cloudformation:DescribeStacks",
"cloudformation:ListStackResources",
"kms:ListAliases",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:ListRoles",
"logs:DescribeLogGroups",
"lambda:Get*",
"lambda:List*",
"states:DescribeStateMachine",
"states:ListStateMachines",
"tag:GetResources",
"xray:GetTraceSummaries",
"xray:BatchGetTraces"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/accessproject": "${aws:PrincipalTag/accessproject}",
"aws:ResourceTag/accessteam": "${aws:PrincipalTag/accessteam}",
"aws:ResourceTag/costcenter": "${aws:PrincipalTag/costcenter}"
}
}
},{
"Sid": "LambdaPolicyForProjectNoTags",
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricData",
"cloudwatch:ListMetrics",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs"
],
"Resource": "*"
}
]
}
Once you have a working policy, please familiarize yourself with the IAM best practices as the use of wildcard resouce access should be avoided whenever possible (principle of granting least privilege).
My team has an account with full permission on SNS as long as we act on resources based on a certain prefix
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:CreateTopic",
// ...
"sns:ListTopics",
// ...
],
"Resource": "arn:aws:sns:eu-west-1:{redacted}:team-prefix-*"
},
We can do most operations just fine, at least the ones we most need, but if we try to list the topics we get a forbidden error
SNS: ListTopics, AuthorizationError: User xxx is not authorized to perform: SNS:ListTopics on resource: arn:aws:sns:eu-west-1:{redacted}:*
We are using the new go SDK v2, and we cannot find a way to query only for our topics, is there a way to list them or do we need list permissions on all the account topics?
sns:ListTopics does not have a resource filter per (https://docs.aws.amazon.com/sns/latest/api/API_ListTopics.html) its an all or nothing operation.
Except from amazon docs: if you specify a resource type in a statement with an action that does not support that resource type, then the statement doesn't allow access. link
Typically, this is what the IAM document should look like if you want to be able to list.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:CreateTopic"
],
"Resource": "arn:aws:sns:eu-west-1:{redacted}:team-prefix-*"
},
{
"Effect": "Allow",
"Action": [
"sns:ListTopics",
],
"Resource": "*"
},
...
If separation at the granular level is really that big of a concern, separate AWS accounts should be used.
I am having trouble connecting to AWS Transfer for SFTP. I successfully set up a server and tried to connect using WinSCP.
I set up an IAM role with trust relationships like follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "transfer.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
I paired this with a scope down policy as described in the documentation using a home directory homebucket and home directory homedir
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListHomeDir",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketAcl"
],
"Resource": "arn:aws:s3:::${transfer:HomeBucket}"
},
{
"Sid": "AWSTransferRequirements",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "*"
},
{
"Sid": "HomeDirObjectAccess",
"Effect": "Allow",
"Action": [
"s3:DeleteObjectVersion",
"s3:DeleteObject",
"s3:PutObject",
"s3:GetObjectAcl",
"s3:GetObject",
"s3:GetObjectVersionAcl",
"s3:GetObjectTagging",
"s3:PutObjectTagging",
"s3:PutObjectAcl",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::${transfer:HomeDirectory}*"
}
]
}
I was able to authenticate using an ssh key, but when it came to actually reading/writing files I just kept getting opaque errors like "Error looking up homedir" and failed "readdir". This all smells very much like problems with my IAM policy but I haven't been able to figure it out.
We had similar issues getting the scope down policy to work with our users on AWS Transfer. The solution that worked for us, was creating two different kinds of policies.
Policy to attach to the role which has general rights on the whole bucket.
Scope down policy to apply to the user which makes use of the transfer service variables like {transfer:UserName}.
We concluded that maybe only the extra attached policy is able to resolve the transfer service variables. We are not sure if this is correct and if this is the best solution, because this opens the possible risk when forgiving to attach the scope down policy to create a kind of "admin" user. So I'd be glad to get input to further lock this down a little bit.
Here is how it looks in my console when looking at the transfer user details:
Here are our two policies we use:
General policy to attach to IAM role
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListingOfUserFolder",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-s3-bucket"
]
},
{
"Sid": "HomeDirObjectAccess",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObjectVersion",
"s3:DeleteObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3::: my-s3-bucket/*"
}
]
}
Scope down policy to apply to transfer user
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListingOfUserFolder",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::${transfer:HomeBucket}"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"${transfer:UserName}/*",
"${transfer:UserName}"
]
}
}
},
{
"Sid": "AWSTransferRequirements",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "*"
},
{
"Sid": "HomeDirObjectAccess",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObjectVersion",
"s3:DeleteObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::${transfer:HomeDirectory}*"
}
]
}
I had a similar problem but with a different error behavior. I managed to log in successfully, but then the connection was almost immediately closed.
I did the following things:
Make sure that the IAM role that allows bucket access also contains KMS access if your bucket is encrypted.
Make sure that the trust relationship is also part of that role.
Make sure that the server itself has a Cloudwatch role also with a trust relationship to transfer.amazonaws.com! This was the solution for me. I don't get why this is needed but without the trust relationship in the Cloudwatch role, my connection get's closed.
I hope that helps.
Edit: Added a picture for the settings of the CloudWatch role:
The bucket policy for the IAM user role can look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::<your bucket>"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::<your bucket>/*"
]
}
]
}
Finally, also add a Trust Relationship as shown above for the user IAM role.
If you can connect to your sftp but then get a readdir error when trying to list contents, e.g. with the command "ls", then that's a sign that you have no bucket permission. If your connection get's closed right away it seems to be a Trust Relationship issue or a KMS issue.
According to the somewhat cryptic documentation #limfinity was correct. To scope down access you need a general Role/Policy combination granting access to see the bucket. This role gets applied to the SFTP user you create. In addition you need a custom policy which grants CRUD rights only to the user's bucket. The custom policy is also applied to the SFTP user.
From page 24 of this doc... https://docs.aws.amazon.com/transfer/latest/userguide/sftp.ug.pdf#page=28&zoom=100,0,776
To create a scope-down policy, use the following policy variables in your IAM policy:
AWS Transfer for SFTP User Guide
Creating a Scope-Down Policy
• ${transfer:HomeBucket}
• ${transfer:HomeDirectory}
• ${transfer:HomeFolder}
• ${transfer:UserName}
Note
You can't use the variables listed preceding as policy variables in an IAM role definition. You create these variables in an IAM policy and supply them directly when setting up your user. Also, you can't use the ${aws:Username}variable in this scope-down policy. This variable refers to an IAM user name and not the user name required by AWS SFTP.
Can't comment, sorry if I'm posting incorrectly.
Careful with AWS's default policy!
This solution did work for me in that I was able to use scope-down policies for SFTP users as expected. However, there's a catch:
{
"Sid": "AWSTransferRequirements",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "*"
},
This section of the policy will enable SFTP users using this policy to change directory to root and list all of your account's buckets. They won't have access to read or write, but they can discover stuff which is probably unnecessary. I can confirm that changing the above to:
{
"Sid": "AWSTransferRequirements",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "${transfer:HomeBucket}"
},
... appears to prevent SFTP users from listing buckets. However, they can still cd to directories if they happen to know buckets that exist -- again they dont' have read/write but this is still unnecessary access. I'm probably missing something to prevent this in my policy.
Proper jailing appears to be a backlog topic: https://forums.aws.amazon.com/thread.jspa?threadID=297509&tstart=0
We were using the updated version of SFTP with Username and Password and had to spend quite some time to figure out all details. For the new version, the Scope down policy needs to be specified as 'Policy' key within Secrets Manager. This is very important for the whole flow to work.
We have documented the full setup on our site here - https://coderise.io/sftp-on-aws-with-username-and-password/
Hope that helps!
I wanted to restrict IAM user from creating new group/roles and allow only if user attaches custom policy BaseDeny along with other policies. Meaning there has to be BaseDeny policy in every group/roles created by user in order for him to create new group/roles.
I tried to add following policy to the user to achieve this, however this is allowing only BaseDeny to be added, but I wanted to allow if user adds any other policy along with BaseDeny.
What condition is needed to achieve this? Or any other way to make this work?
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "ManageUsersPermission",
"Effect": "Allow",
"Action": [
"iam:ChangePassword",
"iam:CreateAccessKey",
"iam:CreateLoginProfile",
"iam:DeleteAccessKey",
"iam:DeleteLoginProfile",
"iam:UpdateAccessKey",
"iam:ListAttachedUserPolicies",
"iam:ListPolicies",
"iam:ListUserPolicies",
"iam:ListGroups",
"iam:ListGroupsForUser",
"iam:GetPolicy",
"iam:GetAccountSummary",
"iam:GetGroup",
"iam:ListGroupPolicies"
],
"Resource": "*"
},
{
"Sid": "CreateGroupRoleLimited",
"Effect": "Allow",
"Action": [
"iam:CreateGroup",
"iam:AddUserToGroup",
"iam:CreateRole",
"iam:ListAttachedGroupPolicies",
"iam:ListAttachedRolePolicies"
],
"Resource": "*"
},
{
"Sid": "AttachDettachLimitedPolicy",
"Effect": "Allow",
"Action": [
"iam:AttachGroupPolicy",
"iam:AttachRolePolicy",
"iam:AttachUserPolicy"
],
"Resource": "*",
"Condition": {
"ArnLike": {
"iam:PolicyArn": [
"arn:aws:iam::*:policy/BaseDeny"
]
}
}
}
]
}
To solve this problem have a look at IAM Permissions Delegation
What you are trying to do is exactly what the delegation feature was built for. Instead of trying to make sure that a particular BaseDeny policy is included on new groups (one way to attempt to achieve a permissions boundary), follow the linked blog entry to create a permissions boundary that excludes what you wanted to deny with BaseDeny.
This is not possible.
The closest option would be to create an AWS Config rule to check for Roles/Groups that do not contain that policy.
This is checking "after-the-fact", but you could automate the rule to disable a Role/Group that violates the rule.
See: How to develop custom AWS Config rules using the Rule Development Kit | AWS Management Tools Blog
I am looking to enforce all IAM users(local and remote) to enable and activate their MFA devices.
I want them all to enable MFA to do their respective tasks.
I am trying with the following policy
{
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
}
However; this policy applies irrespective of how you are accessing the services, through console or through APIs.
There is a lot of automation done by all users and their automation breaks as MFA authentication was not implied.
As a first step, we wish everybody to at least enables MFA for console login; but the same should not enforce them to use MFA for API calls used in automation.
Is this achievable through IAM policy?
Thanks
The trick is to reverse the check...rather than only allowing if aws:MultiFactorAuthPresent is true, deny if it's false.
Here's the doc on self-service MFA management: http://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_users-self-manage-mfa-and-creds.html
The full policy suggested in there is:
{
"Version": "2012-10-17",
"Statement":[
{
"Sid": "AllowAllUsersToListAccounts",
"Effect": "Allow",
"Action":[
"iam:ListAccountAliases",
"iam:ListUsers",
"iam:GetAccountSummary"
],
"Resource": "*"
},
{
"Sid": "AllowIndividualUserToSeeAndManageTheirOwnAccountInformation",
"Effect": "Allow",
"Action":[
"iam:ChangePassword",
"iam:CreateAccessKey",
"iam:CreateLoginProfile",
"iam:DeleteAccessKey",
"iam:DeleteLoginProfile",
"iam:GetAccountPasswordPolicy",
"iam:GetLoginProfile",
"iam:ListAccessKeys",
"iam:UpdateAccessKey",
"iam:UpdateLoginProfile",
"iam:ListSigningCertificates",
"iam:DeleteSigningCertificate",
"iam:UpdateSigningCertificate",
"iam:UploadSigningCertificate",
"iam:ListSSHPublicKeys",
"iam:GetSSHPublicKey",
"iam:DeleteSSHPublicKey",
"iam:UpdateSSHPublicKey",
"iam:UploadSSHPublicKey"
],
"Resource": "arn:aws:iam::accountid:user/${aws:username}"
},
{
"Sid": "AllowIndividualUserToListTheirOwnMFA",
"Effect": "Allow",
"Action":[
"iam:ListVirtualMFADevices",
"iam:ListMFADevices"
],
"Resource":[
"arn:aws:iam::accountid:mfa/*",
"arn:aws:iam::accountid:user/${aws:username}"
]
},
{
"Sid": "AllowIndividualUserToManageTheirOwnMFA",
"Effect": "Allow",
"Action":[
"iam:CreateVirtualMFADevice",
"iam:DeactivateMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:RequestSmsMfaRegistration",
"iam:FinalizeSmsMfaRegistration",
"iam:EnableMFADevice",
"iam:ResyncMFADevice"
],
"Resource":[
"arn:aws:iam::accountid:mfa/${aws:username}",
"arn:aws:iam::accountid:user/${aws:username}"
]
},
{
"Sid": "BlockAnyAccessOtherThanAboveUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": "iam:*",
"Resource": "*",
"Condition":{
"BoolIfExists":{ "aws:MultiFactorAuthPresent": "false"}
}
}
]
}
The most important part is the last statement, which does the deny. If you change it to this:
{
"Sid": "BlockAnyAccessOtherThanAboveUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": "iam:*",
"Resource": "*",
"Condition":{
"Bool":{ "aws:MultiFactorAuthPresent": "false"}
}
}
(BoolIfExists changed to Bool) it will allow IAM access keys to bypass the requirement of MFA, while still requiring you to use MFA when logging in through the AWS Console. (Note: this doesn't work for all APIs; some, such as ECR, always supply the "MultiFactorAuthPresent" property, which breaks this work-around)
Be careful if you decide to use that full policy from the docs. Note that it allows a user to create access keys and change their password, and the deny clause only blocks non-IAM actions...this means that, if MFA gets disabled on an account, a user's password could be changed or new access keys could be provisioned without an MFA check, and if you've made the Bool change, those new access keys would be able to access anything that the user has permissions for, without MFA. I.E., all of the security vulnerabilities of unsecured keys, with some potential for account hijacking on top.
I would suggest using a policy similar to this instead:
Note: This policy should not be used verbatim, due to security issues mentioned in the comments
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAllUsersToListAccounts",
"Effect": "Allow",
"Action": [
"iam:ListAccountAliases",
"iam:ListUsers"
],
"Resource": [
"arn:aws:iam::accountid:user/*"
]
},
{
"Sid": "AllowIndividualUserToSeeTheirAccountInformation",
"Effect": "Allow",
"Action": [
"iam:GetAccountPasswordPolicy",
"iam:GetAccountSummary",
"iam:GetLoginProfile"
],
"Resource": [
"arn:aws:iam::accountid:user/${aws:username}"
]
},
{
"Sid": "AllowIndividualUserToListTheirMFA",
"Effect": "Allow",
"Action": [
"iam:ListVirtualMFADevices",
"iam:ListMFADevices"
],
"Resource": [
"arn:aws:iam::accountid:mfa/*",
"arn:aws:iam::accountid:user/${aws:username}"
]
},
{
"Sid": "AllowIndividualUserToManageThierMFA",
"Effect": "Allow",
"Action": [
"iam:CreateVirtualMFADevice",
"iam:DeactivateMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ResyncMFADevice"
],
"Resource": [
"arn:aws:iam::accountid:mfa/${aws:username}",
"arn:aws:iam::accountid:user/${aws:username}"
]
},
{
"Sid": "DoNotAllowAnythingOtherThanAboveUnlessMFAd",
"Effect": "Deny",
"NotAction": "iam:*",
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
Create 2 IAM users for each person:
one for AWS Console sign-in which enforces MFA, and
one for API usage that doesn't have a password and that does not enforce MFA
Posting for posterity.
I tried using the methods posted by Josh Hancock but the api calls from enforced console MFA accounts fail for some AWS services like elastic filesystem and some s3 api calls.
When raised a support ticket, the response from AWS was that, "There is a feature request for this precise issue as there is currently no reliable mechanism to enforce MFA for the console only. I have added your account to the list of requesting accounts for this feature request. Unfortunately, I do not have a reliable workaround other than enable MFA everywhere, or only apply the IAM MFA policy to users that are console only."
I have a different solution. I have a "ForceMFA" group, which doesn't allow you to do anything (other than assign MFA) unless you have MFA enabled. I have a small script that runs every hour that scans all users and adds any users without MFA to the "ForceMFA" group. The same script also removes users that have MFA enabled from the group. This way, I enforce people to enable MFA, but don't require MFA for API calls.
Here's the small Powershell 6 script I use: https://gist.github.com/kalpik/36beffd25bda2a0c38905176f7e557aa
After a few years of waiting. AWS finally provide a way to do this.
https://aws.amazon.com/premiumsupport/knowledge-center/mfa-iam-user-aws-cli/
{
"Sid": "BlockMostAccessUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:ListVirtualMFADevices",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:ListAccountAliases",
"iam:ListUsers",
"iam:ListSSHPublicKeys",
"iam:ListAccessKeys",
"iam:ListServiceSpecificCredentials",
"iam:ListMFADevices",
"iam:GetAccountSummary",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "false",
"aws:ViaAWSService": "false"
}
}
}
I'm sure you probably found the solution to this already, but here's an official guide from the AWS Security team on setting up MFA on login for IAM users if anyone is struggling with this too:
https://blogs.aws.amazon.com/security/post/Tx2SJJYE082KBUK/How-to-Delegate-Management-of-Multi-Factor-Authentication-to-AWS-IAM-Users
Basically, this can be achieved by creating a few User Groups and doing checks on whether MFA is set or not upon login.
For your use case, it's sufficient to just activate an MFA device for the IAM user. This will require the user to provide an MFA code whenever they sign into the AWS Management Console, but not for AWS API calls.
Writing an IAM policy using the "MultiFactorAuthPresent" condition is only needed if you also want to enforce MFA for API calls.
Btw, posting AWS-related questions on the AWS forums (https://forums.aws.amazon.com/index.jspa) is a great way to get responses.