Amazon Web Services (AWS) Key Management Service (KMS) is a huge part of security in AWS and on the “AWS Certified Security — Specialty” exam. How do you control access toyourkeys in KMS?
Grants can be added and removed for a given key, whereas a key’s key policy can only be replaced. You can runCreateGrant
(with an API call) toadd specific permissions orRevokeGrant
to remove those permissions again. If you usePutKeyPolicy
, on the other hand, thatreplacesthe entire key policy.
The risk when replacing the key policy is that, if you’re not careful, you could removeall users’ access to a key. Then you’d need to contact AWS Support to recover the key.
If you keep the default KMS key policy, you won’t lock yourself out, because that policy gives complete permissions to the root user:
{
"Id": "key-consolepolicy-3",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Your AWS Account ID>:root"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
If the key policy is empty, the key becomes effectively useless. You can’t encrypt or decrypt with it anymore until you get AWS Support to help you out. If you haven’t issued any grants, on the other hand, you aren’t locked out, as long as you still have some permissions in the key policy.
There are three API calls you can make with grants and only one for key policies. Just take a look at the Identity and Access Management (IAM) console, under KMS permissions management actions:
WithCreateGrant
, you can get so granular as toset conditions (“constraints”) based on key metadata (“encryption context”) and also specify a specific AWS principal that can “retire” the grant. Whereas with key policies, only the principal that created the key policy can modify the key policy, because there’s onlyPutKeyPolicy
.
Stackoverflow hasa longer explanation of the differences between RetireGrant and RevokeGrant.
In this CLI example, the grant is getting the name “foo”:
aws kms create-grant \
--key-id d69a54b0-0250-467d-b7bd-f3a72f346c62 \
--grantee-principal arn:aws:iam::<Account ID>:user/yann_personal \
--operations Decrypt \
--name foo
If you try to run the following command:
aws kms create-grant \
--key-id d69a54b0-0250-467d-b7bd-f3a72f346c62 \
--grantee-principal yann_personal \
--operations "TagResource"
…you’ll get this error:
An error occurred (ValidationException) when calling the CreateGrant operation: 1 validation error detected: Value '[TagResource]' at 'operations' failed to satisfy constraint: Member must satisfy constraint: [Member must satisfy enum value set: [CreateGrant, GenerateDataKey, RetireGrant, Encrypt, ReEncryptTo, Decrypt, GenerateDataKeyWithoutPlaintext, DescribeKey, Verify, ReEncryptFrom, Sign]]
That’s because, when you create a grant, the API actions (or “operations”) you can assign must be one of these:
[CreateGrant, GenerateDataKey, RetireGrant, Encrypt, ReEncryptTo, Decrypt, GenerateDataKeyWithoutPlaintext, DescribeKey, Verify, ReEncryptFrom, Sign]
So if you run this instead:
aws kms create-grant \
--key-id d69a54b0-0250-467d-b7bd-f3a72f346c62 \
--grantee-principal yann_personal \
--operations "Encrypt"
…youwill get a successful result:
{
"GrantToken": "AQpAM2RhZTk1MGMyNTk2ZmZmMzEyYWVhOWViN2I1MWM4Mzc0MWFiYjc0ZDE1ODkyNGFlNTIzODZhMzgyZjBlNGY3NiKAAgEBAgB4Pa6VDCWW__MSrqnre1HIN0Grt00ViSSuUjhqOC8OT3YAAADXMIHUBgkqhkiG9w0BBwaggcYwgcMCAQAwgb0GCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM8AyPXJIfFCBpmRghAgEQgIGP48IGvk5g2TEKrCjAzcvY6rDOkGSkCHHGP0XDOqFNiubyOOvLa0WPE-sEKHvAKDLzBJPMGxLcKy3xFUM2JKp4-GnCfPGBejOJTGggykmPsRtSw29RilZA7xcG-KUGiYXf38fIpxAZPJPz6A9LJbPrpQtyFQNUpSrqCSzRmQ3zXw_xrcGUKuKVPOneGPV-tDEqIM_Q42hYwk_ALMqGbq4vkrHMk9gkb-EpmQ0cKHJdkAcW",
"GrantId": "cfd0e36858c24fc02cca866eae2f92b1cc93d8246fe129990d1c28725d900716"
}
With a key policy, however, youcanspecify all KMS actions, includingTagResource
, in the policy. For example, if you include the following statement in the key policy…
{
"Sid": "Enable IAM User Permissions",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::<Account ID>:root"
},
"Action": "kms:TagResource",
"Resource": "*"
}
…it successfully blocks the user’s ability to tag KMS keys, as you can see in this screenshot:
As it saysin the AWS docs, “to retrieve a list of grants attached to a [Customer Master Key (CMK)], use the AWS KMSListGrants API (orlist-grants AWS CLI command).” Notice that the console isn’t mentioned as an option.
The console, however,does let you view and edit the key policy:
When a feature doesn’t exist in the console, it’s a good clue that it’s a more advanced feature. As the docs say, “Grants areadvanced[emphasis added]mechanisms for specifying permissions…”
You can use [grants] to allow access, but not deny it.
—AWS Docs
There are more differences, but these were enough to get me a general idea. I’d love to hear about any differences you noticed in your experience!
Last but not least, if you are not a Medium Member yet and plan to become one, I kindly ask you to do so using the following link. I will receive a portion of your membership fee at no additional cost to you.
Staff Solutions Architect, giving technology language @ Cohere | Ex-AWS. Support blog by becoming member here:https://ystoneman.medium.com/membership