Updating the KMS policy to authorize AWS Nitro Enclaves
In the previous section, you built an AWS Nitro Enclave that can decrypt a secret that was encrypted by the AWS KMS key. In this section, you will update the policy associated with that AWS KMS key to authorize this AWS Nitro Enclave to decrypt secrets ONLY IF it presents a valid attestation report.
As a reminder, the AWS Nitro Enclave measurements were shown in the previous section when you created the Enclave Image File. The output should look like this:
Start building the Enclave Image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "80cabd5643bccbc644bc299361b28d0fc095145733e4ef0552cf3491339d487fca325f1b497478bcf40d934051e79367",
"PCR1": "a5b4408152040f6ec87941abc5788d63ba1e74be5714408a271c5081ede76bfdfed00b84d3f04d31e51b844d22f343b8",
"PCR2": "fda83c68b97a328d07b7668897b34e5f705f2eec3035603fc65bbf1c93d9c240641220c8ffaa1d5d1a2e4dcc4831699e"
}
}
|
When an AWS Nitro Enclave started in DEBUG mode produces a signed attestation report, all PCR measurements other than PCR3 (IAM Role) and PCR4 (EC2 Instance ID) are always set to “000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000”. This allows KMS administrators to create access policies that can differentiate between debug enclaves and production enclaves. Use the |
As a first step, you will verify that the AWS Nitro Enclave (running in debug mode) can produce an attestation report and submit it to AWS KMS. Once this succeeds, you will try with a production enclave.
In a typical deployment scenario, multiple measurements should be used, and debug enclaves should never be allowed to access secrets intended for production enclaves.
Find your AWS KMS key policy
In a browser, navigate to the AWS Console for KMS. Select the AWS region for your KMS key.
Look for your AWS KMS key and select it to view its properties. On the “Policy” tab, click on the “Edit” button to update the policy.
Add the following statement to the JSON array Statement in the policy:
{
"Sid": "Enable decrypt from enclave",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT>:role/<IAM_ROLE>"
},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEqualsIgnoreCase": {
"kms:RecipientAttestation:PCR0": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
}
},
|
Make sure you update the following values to match your environment:
|
This policy tells AWS KMS to allow an enclave to use the AWS KMS key to decrypt data when all of the following are true:
-
The enclave provides an attestation report.
-
The enclave is running on an EC2 instance associated with the specified IAM Role.
-
The enclave PCR0 measurement (provided in the attestation report) matches the specified value.
Hardening the AWS KMS key policy for production
The Enable decrypt from enclave statement above authorizes your enclave,
but it does not close other paths to your secrets.
Depending on the rest of the key policy,
an IAM administrator could allow kms:Decrypt through an IAM policy or a grant,
with no attestation required.
They could also re-encrypt your secrets under another AWS KMS key.
For production AWS KMS keys, Anjuna recommends replacing the key policy with the following policy.
Then, for each production enclave you approve,
add one statement like the Enable decrypt from enclave statement above.
In the added statement, replace the all-zeros PCR0 value with the enclave’s PCR0 measurement.
Do not change the all-zeros value in the policy below.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnableIAMPoliciesExceptPlaintextOperations",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT>:root"
},
"NotAction": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:GenerateDataKeyPair",
"kms:DeriveSharedSecret"
],
"Resource": "*"
},
{
"Sid": "DenyPlaintextWithoutAttestation",
"Effect": "Deny",
"Principal": "*",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:GenerateDataKeyPair",
"kms:DeriveSharedSecret"
],
"Resource": "*",
"Condition": {
"Null": {
"kms:RecipientAttestation:PCR0": "true"
}
}
},
{
"Sid": "DenyPlaintextToDebugEnclaves",
"Effect": "Deny",
"Principal": "*",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:GenerateDataKeyPair",
"kms:DeriveSharedSecret"
],
"Resource": "*",
"Condition": {
"StringEqualsIgnoreCase": {
"kms:RecipientAttestation:PCR0": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
}
},
{
"Sid": "DenyPlaintextUnlessKeyMaterialIsKmsGenerated",
"Effect": "Deny",
"Principal": "*",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:GenerateDataKeyPair",
"kms:DeriveSharedSecret"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"kms:KeyOrigin": "AWS_KMS"
}
}
},
{
"Sid": "DenyGrantsForPlaintextOperations",
"Effect": "Deny",
"Principal": "*",
"Action": "kms:CreateGrant",
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"kms:GrantOperations": [
"Decrypt",
"GenerateDataKey",
"GenerateDataKeyPair",
"DeriveSharedSecret"
]
}
}
},
{
"Sid": "DenyMovingKeyOrCiphertextOutsideThisPolicy",
"Effect": "Deny",
"Principal": "*",
"Action": [
"kms:ReEncryptFrom",
"kms:ReplicateKey",
"kms:UpdatePrimaryRegion"
],
"Resource": "*"
}
]
}
|
Make sure you update the following value to match your environment:
|
This policy enforces the following rules:
-
IAM policies in your AWS account can manage and use the key, except for the operations that return secrets:
kms:Decrypt,kms:GenerateDataKey,kms:GenerateDataKeyPair, andkms:DeriveSharedSecret. Only a statement in the key policy itself can allow these operations. -
These operations are denied unless the request includes a signed attestation report from an AWS Nitro Enclave. AWS KMS then returns the result encrypted for that enclave only.
-
These operations are denied to enclaves running in debug mode.
-
These operations are denied if the key material was not generated by AWS KMS, for example if it was imported or is stored in a custom key store.
-
No grant can allow these operations.
-
Ciphertext cannot be re-encrypted under another AWS KMS key, and the key cannot be replicated to another AWS Region, where the replica would have its own key policy.
As a result, the only way to authorize a new enclave is to change the key policy itself.
Restrict which IAM principals can call kms:PutKeyPolicy, and monitor PutKeyPolicy events
for the key in AWS CloudTrail.
|
This policy denies access to debug enclaves, so the all-zeros statement from “Find your AWS KMS key policy”, which verifies a debug enclave, has no effect after you apply it. Apply this policy after you have verified a production enclave, or use it on a separate AWS KMS key for production. Grants that exist before you apply this policy remain in effect, and a grant that allows
|
Updating the KMS policy using anjuna-nitro-kms-policy
Anjuna provides a tool to easily manage specific enclave values in existing KMS policies. See the anjuna-nitro-kms-policy tool in the Command reference section to view, add, update, and delete attestation values on a policy.
|
The |
The anjuna-nitro-kms-policy tool manages KMS key policies directly.
If you allow IAM policies to manage access to the KMS key
without restrictions, any IAM administrator in the AWS account can
bypass the RecipientAttestation Condition for AWS Nitro by writing an IAM policy.
The recommended production key policy allows IAM policies to manage the key
while preventing this.
|
View the current policy
The following is an example of the command to view the contents of the policy.
You must specify an ARN value to the AWS KMS key flag, and it can be a direct ARN or an alias ARN as shown below:
$ anjuna-nitro-kms-policy show --cmk $KMS_KEY_ID
The output describes the current KMS key policy:
{
"Sid": "Enable decrypt from enclave",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT>:role/<IAM_ROLE>"
},
"Action": "kms:Decrypt",
"Resource": "*",
},
Provide access to a specific enclave
The following is an example of the command to modify the policy in order to provide access to a specific enclave:
$ anjuna-nitro-kms-policy allow \
--cmk arn:aws:kms:us-east-2:0123456789012:key/ea12c491-430c-4e69-85b1-be987379aa6c \
--role arn:aws:iam::0123456789012:role/nitro_instance_role \
--pcr0 f666e2eb6a5d999181e0a6bdb00fa60ac11717b7272fe8d010b50666f84945daeb8c4716b05cf4ed59ecd167af54f78b
You will see the following output:
Policy updated
After changing the AWS KMS key policy, AWS KMS will automatically grant permission to the specified enclave to decrypt data using that KMS key.
You are now ready to run the AWS Nitro Enclave and verify that it can decrypt the secret using AWS KMS.