Skip to main content
 首页 » 编程设计

amazon-web-services之尝试使用 KMS 在 Lambda 函数中解密密文会导致超时

2024年12月31日10lidabo

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

$ aws kms decrypt --ciphertext-blob fileb://encrypted-secrets --output text --query Plaintext --region us-east-1 | base64 --decode > decryped-secrets 

当尝试从 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); 
  } 
}); 

但是,当尝试在 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.`); 
        } 
    }); 
}; 

超时日志:
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 

备注:
  • 如果我注释掉对 kms.decrypt 的调用并尝试 console.log params或其他任何东西,这些值都可以毫无问题地输出。 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" 
                ] 
            } 
        ] 
    } 
    
  • 我已经编辑了代码中的任何识别信息。
  • 请您参考如下方法:

    在与非常有帮助的 AWS 支持人员进行了深入交谈后,我们得到了答案:

    出现超时的主要原因是缺少从 Lambda 函数内部到 KMS 服务的连接,因为 KMS 服务在配置 Lambda 函数的 VPC 中没有终端节点。

    为了让 VPC 中的 Lambda 函数连接到除 Amazon S3 之外的任何服务,该服务在 VPC 中确实有一个终端节点,Lambda 函数必须位于/关联至少一个,但最好是两个私有(private)子网,具有他们的路由表包括到 NAT 网关的目标路由 0.0.0.0/16。

    无法让 Lambda 函数位于具有 Internet 网关的公共(public)子网中。

    获取 VPC 绑定(bind)的 Lambda 函数以访问 KMS 和所有其他没有 VPC 终端节点的服务的步骤:

  • 创建或记下现有的私有(private)子网,该子网具有 0.0.0.0/0 到 NAT 网关的路由表条目。
  • 如果您还没有 NAT 网关、路由表和子网,如上所述,您必须首先适本地创建它们并将它们相互关联。
  • 在创建 Lambda 函数时将 Lambda 函数附加到上面的私有(private)子网,或编辑 Lambda 函数以具有该配置。

  • 如果您遵循这两个步骤,您应该能够调用 kms.encrypt以及来自您的 Lambda 函数中的其他请求,这些请求需要出站/出站 Internet 连接,因为这些服务在您的 VPC 中没有终端节点。