Key policies are the primary resource for controlling who has access to do what with your CMKs.
Up to now, the assigned IAM role (KMSWorkshop-InstanceInitRole) of our working instance allows us to perform many things in AWS KMS. Following best practices like Least Privilege and Separation of Duties, Our instance is meant to be used only for uploading data with server side encryption, but not decrypt it and download it. Maybe the download and decrypt operation needs to be done from another instance with more specific security constraints.
How can we comply with these requirements? We will use two main resources:
Each key that is generated in AWS KMS, has an initial policy attached. Execute the below command to check the policy of the CMK whose alias is ImportedCMK
aws kms get-key-policy --key-id <key ID of the CMK whose alias is ImportedCMK> --policy-name default
The default key policy gives the AWS account (root user) that owns the CMK full access to the CMK. This has policy has two important effects:
Decrypt
into the search barsudo python WebAppEncSSE.py 80
Now this role is able to encrypt but not to decrypt. Furthermore, we want to enforce “Least Privilege” access and ensure that the encryption Role, providing capability to encrypt, is only used from our account, and not subject to Cross-Account Role access policies that could grant access to the CMK.
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<your acount id>:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow for Use only within our Account",
"Effect": "Allow",
"Principal": {
"AWS": "<the ARN we copied in the step 11>"
},
"Action": "kms:*",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "<your acount id>"
}
}
}
]
}
Another type of key policy that can become very useful when enforcing “Least Privilege” is the capability to also ensure that this CMK is only called by our role and other roles or user can´t use the key for encryption or decryption.
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<your acount id>:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow for Use only within our Account",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [ "arn:aws:iam::<your acount id>:role/KMSWorkshop-InstanceInitRole", "arn:aws:iam::<your acount id>:root"]
},
"Action": "kms:*",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "<your acount id>"
}
}
}
]
}
Furthermore, you can also include conditions over key policies to help you fine tune access and link to several other parameters.
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<your acount id>:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow for Use only within our Account",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<your acount id>:user/userA"
]
},
"Action": [
"kms:DeleteAlias",
"kms:DeleteImportedKeyMaterial",
"kms:PutKeyPolicy",
"kms:ScheduleKeyDeletion"
],
"Resource": "*",
"Condition": {
"NumericLessThan": {
"aws: MultiFactorAuthAge": "300"
}
}
}
]
}