Encrypted ENV Vars in AWS Lambda
-
I'm having issues setting access policies properly in AWS to allow my service user to decrypt encrypted env vars.
lambda function (nodejs 6.10):
'use strict'; const AWS = require('aws-sdk'); const ekeys = [process.env['var1'], process.env['var2']]; let dkeys = {}; exports.handler = (event, context, callback) => { Promise.all(ekeys.map(decryptKMS)) .then(([var1, var2]) => { dkeys.var1 = var1; dkeys.var2 = var2; handle(event, context, callback); }) .catch(console.log); }; function handle (event, context, callback) { console.log(JSON.stringify(dkeys)); callback(null, 'Hello from Lambda'); } function decryptKMS(key) { return new Promise((resolve, reject) => { const kms = new AWS.KMS() kms.decrypt({ CiphertextBlob: new Buffer(key, 'base64') }, (err, data) => { if (err) { reject(err) } else { resolve(data.Plaintext.toString('ascii')) } }) }) }
Cloudwatch Logs:
START RequestId: 1333cc77-9973-11e7-82ee-df1685ee811f Version: $LATEST
2017-09-14T17:35:18.374Z 1333cc77-9973-11e7-82ee-df1685ee811f { AccessDeniedException: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:48:27)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
message: 'The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.',
code: 'AccessDeniedException',
time: 2017-09-14T17:35:18.374Z,
requestId: '136515f5-9973-11e7-a6a0-bf9d40e78864',
statusCode: 400,
retryable: false,
retryDelay: 36.392640096935345 }
END RequestId: 1333cc77-9973-11e7-82ee-df1685ee811f
REPORT RequestId: 1333cc77-9973-11e7-82ee-df1685ee811f Duration: 319.12 ms Billed Duration: 400 ms Memory Size: 128 MB Max Memory Used: 33 MBI can't seem to figure out what specific permission is missing; I've granted KMS:Decrypt to the user and granted access to the resource. The lambda function and the resource are also both in the same region.
Any suggestions would be most appreciated.
-
Here's the Key Policy for the encryption key (the lambda IAM user is one of the AWS principals that can read the key):
{ "Version": "2012-10-17", "Id": "key-consolepolicy-3", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "[REDACTED]" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": "[REDACTED]" }, "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" ], "Resource": "*" }, { "Sid": "Allow use of the key", "Effect": "Allow", "Principal": { "AWS": "[REDACTED]" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" }, { "Sid": "Allow attachment of persistent resources", "Effect": "Allow", "Principal": { "AWS": "[REDACTED]" }, "Action": [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": "true" } } } ] }
-
Nevermind; I solved it.
AWS has/had some sort of issue and no decryption policy was actually bound to my service account. The policy seems to not exist, so I created the following User Managed Policy and bound it to the role:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" } ] }
-
@rad131304 said in Encrypted ENV Vars in AWS Lambda:
The policy seems to not exist,
That seems to happen a lot when following tutorials that assume you know what you're doing...
-
@tsaukpaetra This more looks like it's supposed to be a policy that AWS has by default but is missing for us - it exists as a pre-defined add-able policy type during the role creation step of the function creation.
Though, yeah, bad AWS tutorials are everywhere which doesn't help much.