AWS allow user to create policies that doesn't create other policies? - amazon-web-services

Is it possible to allow a user to create policies that doesn't contain any IAM Write actions, such as iam:CreatePolicy or iam:AttachPolicyRole?
The reason I'm asking is that the company I work at has a single person which can create policies & roles for security reasons. But this is quickly becoming a bottleneck, and we would like to transfer the responsibility of creating roles & policies to more people in a secure fashion. One way I can think is to limit the actions a policy can have, and the most sensitive actions are IAM actions, but I don't know if this is possible.

IAM has an important feature called permissions boundaries:
A permissions boundary is an advanced feature for using a managed policy to set the maximum permissions that an identity-based policy can grant to an IAM entity. An entity's permissions boundary allows it to perform only the actions that are allowed by both its identity-based policies and its permissions boundaries.
A permissions boundary is designed to restrict permissions on IAM principals (IAM users and IAM roles). It enforces a centrally-managed boundary that can’t be exceeded, even if broader permissions are granted by some other policy attached to the IAM principal.
Permissions boundaries can also be used to restrict what permissions that IAM principal can grant when creating new IAM principals.
Here's an example of an IAM statement that you could add to an IAM user's policies that would allow that user to create new IAM users and roles but restrict the created roles and users to a specified permissions boundary:
"Statement": [
{
"Sid": "AllowIAMCreate",
"Effect": "Allow",
"Action": [ "iam:CreateUser", "iam:CreateRole" ],
"Resource": "*"
},
{
"Sid": "DenyIAMCreateWithoutBoundary",
"Effect": "Deny",
"Action": [ "iam:CreateUser", "iam:CreateRole" ],
"Resource": [
"arn:aws:iam::1234567890:user/*",
"arn:aws:iam::1234567890:role/*"
],
"Condition": {
"StringNotEquals": {
"iam":PermissionsBoundary": "arn:aws:iam::1234567890:policy/DevBoundary"
}
}
}
]
Here's a good introductory video: Prevent privilege escalation with AWS IAM permission boundaries

yes, you can create customer managed policies.by just a simply adding a permission in that policy.

Related

Restrict some Organizations Permissions on a specific OU in AWS IAM

With the new Organizations:CloseAccount permission in AWS IAM. I am trying to create a rôle which is only allowed to close account in a specific OU.
I tried many things in the Ressources field. But I can't find the correct way. It seems to only accept an organization ID and not ou ID.
To be more precise I have an account in the root/management account. I want to allow him to only close accounts in a specific OU freely but deny close accounts from other OU.
Thanks
EDIT : I add some precisions
In your AWS Organization create a Service Control Policy (SCP) that denies all users and roles to call that Organizations:CloseAccount action - except the one in the Condition (name-of-admin-role-to-allow).
Then attach it to the specific OU.
What is a SCP?
An SCP defines a guardrail, or sets limits, on the actions that the
account's administrator can delegate to the IAM users and roles in the
affected accounts. The administrator must still attach identity-based
or resource-based policies to IAM users or roles, or to the resources
in your accounts to actually grant permissions. The effective
permissions are the logical intersection between what is allowed by
the SCP and what is allowed by the IAM and resource-based policies.
Source
Example
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAccountCloseWithException",
"Effect": "Deny",
"Action": [
"Organizations:CloseAccount",
"iam:AttachRolePolicy",
"iam:DeleteRole",
"iam:DeleteRolePermissionsBoundary",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:PutRolePermissionsBoundary",
"iam:PutRolePolicy",
"iam:UpdateAssumeRolePolicy",
"iam:UpdateRole",
"iam:UpdateRoleDescription"
],
"Resource": [
"arn:aws:iam::*:role/name-of-role-to-deny"
],
"Condition": {
"StringNotLike": {
"aws:PrincipalARN":"arn:aws:iam::*:role/name-of-admin-role-to-allow"
}
}
}
]
}

AWS IAM assuming same role with session tag for tenant isolation

I am working on a serverless app powered by API gateway and AWS lambda. Each lambda has a separate role for least privilege access. For tenant isolation, I am working on ABAC and IAM
Example of the role that provides get object access to s3 bucket having <TenantID> as the prefix.
Role Name: test-role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
],
"Resource": "arn:aws:s3:::test-bucket/${aws:PrincipalTag/TenantID}/*"
},
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole",
],
// Same role ARN: Ability to assume itself
"Resource": "arn:aws:iam::<aws-account-d>:role/test-role"
}
]
}
I am assuming the same role in lambda but the the session tag as
const credentials = await sts.assumeRole({
RoleSessionName: 'hello-world',
Tags: [{
Key: 'TenantID',
Value: 'tenant-1',
}],
RoleArn: 'arn:aws:iam::<aws-account-d>:role/test-role'
}).promise();
I am trying to achieve ABAC with a single role instead of two(one role with just assuming role permission, another role with actual s3 permission) so that it would be easier to manage the roles and also won't reach the hard limit of 5000.
Is it a good practice to do so, or does this approach has security vulnerability?
It should work, but feels a bit strange to re-use the role like this. It would make more sense to me to have a role for the lambda function, and a role for the s3 access that the lambda function uses (for a total of two roles).
Also make sure that you're not relying on user input for the TenantID value in your code, because it could be abused to access another tenant's objects.
TLDR: I would not advise you to do this.
Ability to assume itself
I think there is some confusion here. The JSON document is a policy, not a role. A policy in AWS is a security statement of who has access to what under what conditions. A role is just an abstraction of a "who".
As far as I understand the question, you don't need two roles to do what you need to do. But you will likely need two policies.
There are two types of policies in AWS, of interest to this question: Identity based policies and Resource Based policies:
Identity-based policies are attached to some principal, which could be a role.
Resource-based policies are attached to a resource - which also could be a role!
A common use case of roles & policies is for permission delegation. In this case, we have:
A Role, that other principals can assume, maybe temporarily
A trust policy, which controls who can assume the role, under what conditions, and what actions they can take in assuming it. The trust policy is a special case of a resource policy, where the resource is the role itself.
A permissions policy, which is granted to anyone who assumes the role. This is a special case of an identity policy, which is granted based on the assumption of a role.
Key point: both policies are associated to the same role. There is one role, two policies.
Now, let's take a look at your policy. Clearly, it's trying to be two things at once: both a permissions policy and a trust policy for the role in question.
This part of it is trying to be the trust policy:
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole",
],
// Same role ARN: Ability to assume itself
"Resource": "arn:aws:iam::<aws-account-d>:role/test-role"
}
Since the "Principal" section is missing, looks like it's allowing anyone to assume this role. Which looks a bit dodgy to me, especially since one of your stated goals was "least privilege access".
This part is trying to be the permissions policy:
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
],
"Resource": "arn:aws:s3:::test-bucket/${aws:PrincipalTag/TenantID}/*"
},
This doesn't need a "Principal" section, because it's an identity policy.
Presumably you're resuing that policy as both the trust policy and the permissions policy for the given role. Seems like you want to avoid hitting the policy (not role) maximum quota limit of 5000 defined here:
Customer managed policies in an AWS account
Even if somehow it worked, it doesn't make sense and I wouldn't do it. For example, think about the trust policy. The trust policy is supposed to be a resource-based policy attached to the role. The role is the resource. So specifying a "Resource" in the policy doesn't make sense, like so:
"Resource": "arn:aws:s3:::test-bucket/${aws:PrincipalTag/TenantID}/*"
},
Even worse is the inclusion of this in the trust policy:
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
],
"Resource": "arn:aws:s3:::test-bucket/${aws:PrincipalTag/TenantID}/*"
},
What does that even mean?
Perhaps I'm misunderstanding the question, but from what I understand my advice would be:
Keep your one role - that's OK
Create two separate policies: a trust policy & a permissions policy
Consider adding a "Principal" element to the trust policy
Attach the trust & permissions policies to the role appropriately
Explore other avenues to avoid exceeding the 5000 policy limit

Can IAM user assume a role, if the user is not described in the Trust policy of the role?

Can a role be assumed if it does not have a Trust policy?
If a given IAM user has an attached identity based policy saying that he/she can call sts:AssumeRole for a given role (inside the same account), but the user is not described in the Trust policy of this role, will he/she be able to assume the role?
Usually only the resource based policy or the identity based policy should be enough to give rights for the user, but is it different for the roles?
Thanks
will he/she be able to assume the role?
Yes, of course she/he will be able to do it, as long the trust policy allows the account to assume the role. For example, a role has to have the trust policy of:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "<account-number>"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
This way, your IAM user does not need to be explicitly listed in the trust policy, but trust policy is required and at least you should specify the account which can assume it. But the drawback is that any IAM user or role from the <account-number> account that has sts:AssumeRole permissions can assume the role.
it does not have a Trust policy?
Trust policy is required, so you can't have a role without such such a policy.
Update
Lets assume you have a role with a trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxx:user/UserA"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
The role can be assumed only by userA. UserB will not be able to assume this policy, regardless of his permissions.
A Trust Policy specifies the "Principal" which can assume the role it is attached to. That principal can be various different types of entity, such as an AWS service (e.g. to create a role applied to EC2 instances), or the identifier of another AWS account (to grant cross-account access). It cannot be omitted or be a wildcard.
If the principal identifies an AWS account, then it is trusting the AWS account as a whole. In a sense, all users in that account have been included in the trust policy, but to assume the role they also need permission to make the appropriate AssumeRole API call. This delegates responsibility to the administrator of the other AWS account to decide which users should be able to assume the role.
This can be used to create a hierarchical arrangement of accounts:
All users are created in a single AWS account, which has no other resources.
The actual resources - EC2 instances, S3 buckets, etc - are in separate AWS accounts.
Each account defines roles granting access to some of these services, with a trust policy listing the central account as the Principal. These roles do not list individual users or groups as trusted, they just define sets of permissions.
The users in the central account are each granted AssumeRole access to an appropriate subset of the roles in the different accounts. The effect is similar to using Groups or Managed Policies to grant multiple users the same access.

understanding kms policy?

I have a IAM group called group-dev and couple of users attached to this group, I have custom IAM policy(below). Does this IAM policy alone be sufficient for users in that group to encrypt and list kms keys?
Basically My goal is to create IAM group with policy attached to couple of users, and when new users are added i don't want to go about do double work like adding them to group and then adding them to kms key policy. So would it work with the below policies ?
IAM group inline policy
{
"Action": [
"kms:List*",
"kms:Encrypt",
"kms:Decrypt",
"kms:Describe*",
"kms:Get*"
],
"Effect": "Allow",
"Resource": "*"
},
kms policy
{
"Id": "key-consolepolicy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxx:root"
},
"Action": "kms:*",
"Resource": "*"
}
Below are snippets from aws doc: https://docs.amazonaws.cn/en_us/kms/latest/developerguide/kms-dg.pdf#page=95&zoom=100,96,105
Allowing multiple IAM users to access a CMK
IAM groups are not valid principals in a key policy. To allow multiple IAM users to access a CMK, do one of
the following:
• Add each IAM user to the key policy. This approach requires that you update the key policy each time
the list of authorized users changes.
• Ensure that the key policy includes the statement that enables IAM policies to allow access to the
CMK (p. 72). Then create an IAM policy that allows access to the CMK, and then attach that policy to
an IAM group that contains the authorized IAM users. Using this approach, you don't need to change
any policies when the list of authorized users changes. Instead, you only need to add or remove those
users from the appropriate IAM group.
Looks like there are contradicting statements, or is it something i misunderstood?
. Enables IAM policies to allow access to the CMK.
IAM policies by themselves are not sufficient to allow access to a CMK. However, you can use them
in combination with a CMK's key policy if the key policy enables it. Giving the AWS account full
access to the CMK does this; it enables you to use IAM policies to give IAM users and roles in the
account access to the CMK. It does not by itself give any IAM users or roles access to the CMK, but it
enables you to use IAM policies to do so. For more information, see Managing access to AWS KMS
CMKs (p. 69).
First to compare how these work together each CMK (Customer Managed Key) is created with a key policy that restricts which principal (the caller of the action i.e. IAM Role/IAM User/Service) can access it (and the permissions that the principal will have). It does not matter whichever IAM permissions you grant, if your key policy does not allow the permission no IAM user (including the root user) can perform the action.
The IAM policy attached to the users will grant the maximum permissions that the user can perform. When the action is evaluated the key policy permissions are evaluated as well, if the permission is allowed in both policies the principal will be allowed to perform the action.
So in summary, for KMS both the key policy and the IAM policy permissions must allow access. The permissions you have would allow the users to have the majority of access to the KMS key.

Am I allowed to connect to arbitrary RDS DB instances if given the RDS DbiResourceId?

I am checking the steps of setting up IAM auth in RDS: https://aws.amazon.com/premiumsupport/knowledge-center/users-connect-rds-iam/ And one of the steps is to attach the IAM role with proper permission: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:us-east-2:1234567890:dbuser:db-ABCDEFGHIJKL01234/db_user"
]
}
]
}
The resource follows this format:
arn:aws:rds-db:region:account-id:dbuser:DbiResourceId/db-user-name
If I understand correctly, as long as I know someone's account-id, DbiResourceId and db-user-name (or maybe db-user-name as I can use wildcard?), then I am able to connect to that DB instance, right?
This sounds insecure. Did I miss anything?
No this would not be possible. The only want to interact with this resource would be to assume a role in the target account.
You can use an IAM role to allow someone (a trusted principal) in a different account to access resources in your account. Roles are the primary way to grant cross-account access. However, with some AWS services, you can attach a policy directly to a resource (instead of using a role as a proxy). To learn the difference between roles and resource-based policies for cross-account access, see How IAM Roles Differ from Resource-based Policies in the IAM User Guide