In short: if I create an IAM policy containing a cross-account Principal, but the account in question is the one I'm already operating in, is that a no-op?
My understanding (from here) is that an IAM statement like the following can be used for cross-account access, i.e. to delegate to another account, allowing it to allow access to the resource in question:
{
Action = "kms:*"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::XYZXYZXYZXYZ:root"
}
Resource = "*"
}
(where XYZXYZXYZXYZ is some account ID, obviously).
But what if the account ID isn't another account? I'd hope this does nothing. I'd fear it grants full access. Latter option seems insane: can anyone confirm?
I am assuming this is in a KMS key policy otherwise specifying the principal would not make sense / would be disallowed by IAM anyway.
Therefore I am quoting https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html:
The following default key policy statement is critical.
It gives the AWS account that owns the KMS key full access to the KMS key.
Unlike other AWS resource policies, an AWS KMS key policy does not automatically give permission to the account or any of its users. To give permission to account administrators, the key policy must include an explicit statement that provides this permission, like this one.
It allows the account to use IAM policies to allow access to the KMS key, in addition to the key policy.
Without this permission, IAM policies that allow access to the key are ineffective, although IAM policies that deny access to the key are still effective.
It reduces the risk of the key becoming unmanageable by giving access control permission to the account administrators, including the account root user, which cannot be deleted.
The principals within the account do not immediately have access to the key but just adding a policy to them will grant them access. KMS is one of the few services with where both the resource and the identity policies need to grant the access.
Related
From AWS docs
For most resources, you only need an explicit allow for the principal in either an identity-based policy or a resource-based policy to grant access. IAM role trust policies and KMS key policies are exceptions to this logic, because they must explicitly allow access for principals.
it's clear that for most resources (that support resource-based policies), a resource-based policy is enough to grant access to an IAM principal (meaning, without the need to add an explicit Allow to an identity-based policy of the principal). Trust policies and KMS policies are notable exceptions, since a resource-based policy must be attached to the resource.
Are there any other resources, where a standalone resource-based policy is not enough to grant access to an IAM principal? Or equivalently, are there any services where both an identity-based & resource-based policy at the same time is required to allow access?
The services I tried so far worked fine (S3, SQS, Lambda), but there are more than 20 services that support resource-based policies, so I can't check all of them.
I expect to be no service which supports resource-based policy and requires an identity-based changes to grant access to the particular resource.
In absence of an explicit Deny, one valid* explicit Allow is sufficient:
If either the identity-based policy or the resource-based policy within the same acccount allows the request and the other doesn't, the request is still allowed. source
* Identity policies are valid for KMS only if the key (resource) policy explicitly permits them: Unlike other AWS resource policies, an AWS KMS key policy does not automatically give permission to the account or any of its principals.
I have a resource policy on my KMS key that allows access from the root account and some additional IAM roles used with Jenkins (Role A).
I was able to update an IAM policy for a User (User B) that allows access to the KMS key ARN and KMS:* actions. This allowed the IAM User to access the key for necessary actions.
From the documentation I was reading I was under the assumption that the KMS key resource policy needed to be updated to allow access to the key, but it seems updating the IAM User's policy allows for access.
How can I secure my KMS key so that the KMS key resource policy is the source of truth for what users/roles are allowed access to the key? Do I need to set an explicit Deny on the KMS key policy and set an excluding condition for Users/Roles that are allowed access?
Is what I'm currently observing the expected behavior with the KMS key policy and IAM User policy? Is this due to the IAM User's policy having an explicit allow for the key?
The effective permissions will be a logical intersection between the identity based policy of the IAM role and the resource based policy of the KMS key.
How can I secure my KMS key so that the KMS key resource policy is the source of truth for what users/roles are allowed access to the key? Do I need to set an explicit Deny on the KMS key policy and set an excluding condition for Users/Roles that are allowed access?
If you wanted to setup a "single source of truth", you would have to have the identity based policy whitelist all KMS actions and have the resource based policy deny certain ones as required.
Right now I have my policy defined on my S3 bucket but it seems like the principles I have defined are root and when someone under an account who isn't root isn't falling into the allow part of the policy
"Principal": {
"AWS": [
"arn:aws:iam::123:root",
"arn:aws:iam::456:root",
"arn:aws:iam::789:root",
"arn:aws:iam::101:root"
]
},
I tired to specify it as
"arn:aws:iam::123:*"
but that doesn't work.
I also tried arn:aws:iam::123:user/sample#yahoo.com but that too doesn't seem to be correct as it fails with Invalid principal in policy
When granting cross-account permissions, you need both of:
A bucket policy on Bucket-A in Account-A (as above)
Permissions on the users in their own account to access Bucket-A (which can include wide permissions such as s3:*, but that's rarely a good idea)
Not only does the bucket need to permit access, but the users in the originating account must be granted permission to use S3 for the desired actions (eg s3:GetObject) on Bucket-A (or all buckets).
See: Bucket Owner Granting Cross-Account Bucket Permissions - Amazon Simple Storage Service
You define policies that Grant access to resources generally but can I use a policy that grants access to the IAM user it's applied to?
I guess I want a bucket access policy but for an IAM user. I want to attach a policy to a user that says give a specific iam role access to me.
I am trying to create IAM Policy which restricts passing the IAM Role to an EC2 instance that if instance id does not equal to i-1234567890abcd
There is no error in the policy but there is no effect of this policy either. If I remove Condition from the below policy, it works but it restricts the role to be attached to any EC2 instance.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": ["iam:PassRole"],
"Resource": ["arn:aws:iam::000000000000:role/MyEC2InstanceSpecificRole"],
"Condition": {
"ArnNotEquals": {
"ec2:SourceInstanceARN": "arn:aws:ec2:us-east-1:000000000000:instance/i-1234567890abcd"
}
}
}
]
}
I suspect that this is not possible.
The Granting a User Permissions to Pass a Role to an AWS Service documentation states:
To pass a role (and its permissions) to an AWS service, a user must have permissions to pass the role to the service. This helps administrators ensure that only approved users can configure a service with a role that grants permissions. To allow a user to pass a role to an AWS service, you must grant the PassRole permission to the user's IAM user, role, or group.
When a user passes a role ARN as a parameter to any API that uses the role to assign permissions to the service, the service checks whether that user has the iam:PassRole permission. To limit the user to passing only approved roles, you can filter the iam:PassRole permission with the Resources element of the IAM policy statement.
Also on Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances it states:
PassRole is not an API action in the same way that RunInstances or ListInstanceProfiles is. Instead, it's a permission that AWS checks whenever a role ARN is passed as a parameter to an API (or the console does this on the user's behalf). It helps an administrator to control which roles can be passed by which users.
The normal use-case for PassRole is to ensure that users do not grant AWS Services any more permissions that they should be allowed to use themselves. It tries to avoid a situation where a non-Admin user passes an Admin role to a service with the sinister intention of then using that service to access resources that they would not normally be allowed to access. For example, launching an Amazon EC2 instance with an Admin role, so that they can then login to that instance and issue Admin commands that they would not normally be entitled to use.
The above documentation suggests that the PassRole permission is evaluated to confirm their permission to pass a certain role to a certain service, rather than how that service is going to use the role itself (eg by then assigning it to an EC2 instance to generate STS credentials).