Skip to main content

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.

  1. 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 the Condition 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": "*"
    }
    ]
    }
  2. 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>
  3. 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"
    }
    ]
    }
  4. 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

  5. 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"
    }
    }
  6. 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=="
    }
    }