尝试使用KMS解密Lambda函数中的密文会导致超时

zea*_*ker 23 amazon-web-services aws-sdk aws-lambda aws-kms aws-sdk-nodejs

使用AWS CLI从命令行解密密文时,密文会被解密而不会出现问题:

$ aws kms decrypt --ciphertext-blob fileb://encrypted-secrets --output text --query Plaintext --region us-east-1 | base64 --decode > decryped-secrets
Run Code Online (Sandbox Code Playgroud)

当尝试从js脚本执行此操作时,此解密操作也在本地工作:

#!/usr/local/bin/node

const fs = require('fs');
const AWS = require('aws-sdk');
const kms = new AWS.KMS({region:'us-east-1'});

const secretPath = './encrypted-secrets';
const encryptedSecret = fs.readFileSync(secretPath);

const params = {
      CiphertextBlob: encryptedSecret
};

kms.decrypt(params, function(err, data) {
  if (err) {
    console.log(err, err.stack);
  } else {
    const decryptedScret = data['Plaintext'].toString();
    console.log('decrypted secret', decryptedScret);
  }
});
Run Code Online (Sandbox Code Playgroud)

但是,当在AWS Lambda函数的上下文中尝试使用与上述几乎完全相同的代码时,调用该函数会导致超时:

'use strict';

const zlib = require('zlib');
const mysql = require('mysql');
const fs = require('fs');
const AWS = require('aws-sdk');
const kms = new AWS.KMS({region:'us-east-1'});

const secretPath = './encrypted-secrets';
const encryptedSecret = fs.readFileSync(secretPath);

const params = {
    CiphertextBlob: encryptedSecret
};

exports.handler = (event, context, callback) => {
    kms.decrypt(params, (err, data) => {
       if (err) {
            console.log(err, err.stack);
            return callback(err);
        } else {
            const decryptedScret = data['Plaintext'].toString();
            console.log('decrypted secret', decryptedScret);
            return callback(null, `Successfully processed ${parsed.logEvents.length} log events.`);
        }
    });
};
Run Code Online (Sandbox Code Playgroud)

超时日志:

START RequestId: start-request-id-redacted Version: $LATEST
END RequestId: end-request-id-redacted
REPORT RequestId: report-requested-id-redacted  Duration: 10002.43 ms   Billed Duration: 10000 ms   Memory Size: 128 MB Max Memory Used: 18 MB  
2016-11-13T19:22:28.774Z task-id-redacted Task timed out after 10.00 seconds
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 如果我将该调用注释掉kms.decrypt并尝试真正console.logparams或其他任何内容,则输出的值没有问题.kms.decrypt调用似乎存在某种问题,并且不会返回超出超时的实际错误.
  • 附加到调用lambda函数的角色的策略包含附加的策略AWSLambdaVPCAccessExecutionRole,以及以下附加的内联策略:

policygen-lambda_basic_execution_and_kms_decrypt-201611131221:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "sid-redacted",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:us-east-1:account-redacted:key/key-id-redacted"
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)
  • 我已经从代码中删除了任何识别信息.

zea*_*ker 34

在与AWS支持人员进行了一些彻底的对话之后,我们得到了答案:

导致超时的主要原因是由于KMS服务在配置Lambda功能的VPC中没有端点,因此缺少从Lambda函数到KMS服务的连接.

为了使VPC中的Lambda函数能够连接到除了在VPC 具有端点的Amazon S3之外的任何服务,Lambda函数必须位于至少一个,但最好是两个私有子网中/与之相关联,它们的路由表包括到NAT网关的目的地路由0.0.0.0/16.

这是不是可能有lambda函数是在公共子网中,与互联网网关.

获取VPC绑定的Lambda函数以访问KMS以及所有其他没有VPC端点的服务的步骤:

  1. 创建或记录现有的专用子网,其具有0.0.0.0/0的路由表条目到NAT网关.
    • 如果您还没有NAT网关,路由表和子网,如上所述,您必须先创建并相互关联它们.
  2. 在创建Lambda函数时将Lambda函数附加到上面的私有子网,或编辑Lambda函数以使其具有该配置.

如果您遵循这两个步骤,您应该能够调用kms.encryptLambda函数中的其他请求,这些请求需要出站/出站互联网连接,因为这些服务在您的VPC中没有端点.

可视化概述Lambda如何在VPC中工作

  • 值得注意的是AWS现在有一个KMS的接口端点,您可以在VPC中使用lambda:https://aws.amazon.com/blogs/security/how-to-connect-directly-to-aws-key-management -service从 - 亚马逊VPC逐使用-AN-AWS-privatelink端点/ (3认同)
  • 他们没有具体解释,但基于我对Lambda函数如何实例化的理解,这是由于Lambda函数在他们自己的VPC中的短暂容器中. (2认同)

Set*_*ren 6

默认情况下,EC2 实例带有自己的公共 IP,因此它们在访问任何需要访问 Internet 的服务(例如 KMS)时没有问题。

附加到您的 VPC 的 Lambda 函数没有公共 IP,因此要通过 Internet(例如 KMS)访问服务,您需要按照 zealoushacker 的描述设置 NAT。