Key Management
Leveraging an External KMS
OBLV Deploy provides an internal API for user applications running inside the enclave to talk to AWS KMS Service. This interface also allows communication to KMS present in external AWS accounts.
-
We can define a KMS key policy in an external account (ACCOUNT_EXT) that gives permission to be used by another AWS account (ACCOUNT_1). In this policy, we will set
Principal
to the other AWS account's enclave instance profile role. We will also give limited permission for the KMS operations we need in the user application. We will add theCondition Key
, which only allows it to be used from within the enclave.# key_policy.json
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Allow an external account to use this KMS key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_1>:role/EC2_S3_KMS_Role"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEqualsIgnoreCase": {
"kms:RecipientAttestation:PCR0": "<PCR0>",
"kms:RecipientAttestation:PCR1": "<PCR1>",
"kms:RecipientAttestation:PCR2": "<PCR2>"
"kms:RecipientAttestation:PCR2": "<PCR16>"
}
}
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_EXT>:user/<ADMIN_ROLE_NAME>"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion",
"kms:RotateKeyOnDemand"
],
"Resource": "*"
}
]
} -
We can create a key using this policy.
aws kms create-key --description "KMS Key for enclave running in another account" \
--policy file://key_policy.json \
--query KeyMetadata.Arn --region us-east-2 --output text
arn:aws:kms:us-east-2:<ACCOUNT_EXT>:key/<KEY_ID> -
To use the external KMS key, we need to add a new policy to our enclave instance profile, which allows the enclave to talk to the external account KMS. In the policy, we set the
Resource
as the key ARN of the external AWS account (ACCOUNT_EXT).{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUseOfKeyInAccount831856270177",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:eu-west-1:831856270177:key/3db356d8-8fbc-4f83-a325-0bfae898ed1b"
}
]
} -
Now, we can create the IAM policy from this file and attach it to the role.
# create policy
aws iam create-policy --policy-name policy_to_use_external_kms \
--policy-document file://iam_policy_to_use_external_kms_key.json
# attach policy to role
aws iam attach-role-policy --role-name EC2_S3_KMS_Role \
--policy-arn arn:aws:iam::<ACCOUNT_1>:policy/policy_to_use_external_kms -
Now, we can use this key in our user application by calling the HTTP Service running inside the enclave at port
12000
. We can generate a data key using the below API. It gives the plain text key which can be used to encrypt any data. After use, we should remove the key from memory. It also returns an encrypted private key which we can store safely for decrypting.curl -X POST \
-H "Content-Type: application/json" \
-d '
{
"awsRegion" : "eu-east-2",
"kmsKeyId": "arn:aws:kms:us-east-2:<ACCOUNT_EXT>:key/<KEY_ID>",
"kmsKeySpec": "AES-128"
}' \
"http://oblv-kms-enclave:12000/oblv/kms/v1/generateDataKey" | jq
{
"success": true,
"message": "Success",
"data": {
"plaintext": "di6hQKI4MQp5TZFmlY1Mrw==",
"ciphertext": "AQIDAHiG0+Joi/uAvIHAiTUBmZMyRA7JvkJKsuBHY5/3EV4u7AH2BOZjW1W659Gfz+311DKkAAAAbjBsBgkqhkiG9w0BBwagXzBdAgEAMFgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMd7Zj4XT4TUFzn9WsAgEQgCtsA4b944vyLwYWnYX6F3XheTvyxe34lugMXKMfg8NCn5UpiH1fQjYh7mFi"
}
} -
Whenever the user wants to decrypt the data, he makes a call to the external KMS with the encrypted private key using the
decrypt
API. The external KMS returns the plain text key which can be used to decrypt the encrypted data. Once that is done, the plain text key is ideally deleted from memory.curl -X POST \
-H "Content-Type: application/json" \
-d '
{
"awsRegion" : "eu-east-2",
"kmsKeyId": "arn:aws:kms:eu-east-2::<ACCOUNT_EXT>:key/<KEY_ID>",
"encryptionAlgorithm": "SYMMETRIC_DEFAULT",
"ciphertext": "AQIDAHiG0+Joi/uAvIHAiTUBmZMyRA7JvkJKsuBHY5/3EV4u7AH2BOZjW1W659Gfz+311DKkAAAAbjBsBgkqhkiG9w0BBwagXzBdAgEAMFgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMd7Zj4XT4TUFzn9WsAgEQgCtsA4b944vyLwYWnYX6F3XheTvyxe34lugMXKMfg8NCn5UpiH1fQjYh7mFi"
}' \
"http://oblv-kms-enclave:12000/oblv/kms/v1/decrypt" | jq
{
"success": true,
"message": "Success",
"data": {
"plaintext": "di6hQKI4MQp5TZFmlY1Mrw=="
}
}