11

我想在 AWS lambda 函数中使用 npm 包“请求”。

我正在尝试遵循本文中概述的程序:https ://medium.com/@anjanava.biswas/nodejs-runtime-environment-with-aws-lambda-layers-f3914613e20e

我创建了一个这样的目录结构:

nodejs
│   package-lock.json
│   package.json
└───node_modules

我的 package.json 看起来像这样:

{
  "name": "my-package-name",
  "version": "1.0.0",
  "description": "whatever",
  "author": "My Name",
  "license": "MIT",
  "dependencies": {
    "request": "^2.88.0"
  }
}

据我从文章中可以看出,我应该对上面做的就是运行npm i,压缩目录,将它作为一个层上传,然后将该层添加到我的 lambda 函数中。

截屏

我已经完成了所有这些,但是当我尝试测试我的功能时,我得到的只是:

{
  "errorType": "Runtime.ImportModuleError",
  "errorMessage": "Error: Cannot find module 'request'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
  "trace": [
    "Runtime.ImportModuleError: Error: Cannot find module 'request'",
    "Require stack:",
    ...

...就好像该层从未添加过一样。无论是否添加图层,错误都是完全相同的。如果需要解决某种权限问题,那么文章中没有任何内容表明这一点。

我尝试了一些不同的方法,例如我的 .zip 文件是否包含顶级目录“nodejs”或仅包含其内容。我已经尝试使用这样的文件添加"main": "index.js",到我的package.json, 中:index.js

export.modules.request = require('request');

……一切都无济于事。

我错过了什么?

4

3 回答 3

18

哦,我不敢相信它只是这个!

.zip 文件的顶级目录必须从字面上命名为“ nodejs”!我使用了不同的名称,只是在这篇文章的文本中将其改回“nodejs”以更通用,但目录名称一直是真正的问题。

叹。

于 2019-12-04T20:03:00.173 回答
0

通常,它与里面的文件夹/文件的名称有关。如果这些文件被引用到其他地方,它也会在那里渗透和抱怨。只要彻底检查文件夹结构,你就能抓到小偷。我挣扎了一天才弄明白,这是一个愚蠢的错字。

于 2020-11-20T19:04:25.983 回答
-7

使用带有加密密钥 (KMS) 和环境变量的 lambda 函数从 RDS 访问表数据

第 1 步:-首先在 KMS(密钥管理服务 (KMS))中启用密钥 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

查看您的关键政策并完成!通过 KMS 创建

{
"Id": "key-consolepolicy-3",
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "Enable IAM User Permissions",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::163806924483:root"
        },
        "Action": "kms:*",
        "Resource": "*"
    },
    {
        "Sid": "Allow access for Key Administrators",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::163806924483:user/User1@gmail.com"
        },
        "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": [
                "arn:aws:iam::163806924483:user/User1@gmail.com",
                "arn:aws:iam::163806924483:user/User2@gmail.com",
                "arn:aws:iam::163806924483:user/User3@gmail.com"
            ]
        },
        "Action": [
            "kms:Encrypt",
            "kms:Decrypt",
            "kms:ReEncrypt*",
            "kms:GenerateDataKey*",
            "kms:DescribeKey"
        ],
        "Resource": "*"
    },
    {
        "Sid": "Allow attachment of persistent resources",
        "Effect": "Allow",
        "Principal": {
            "AWS": [
                "arn:aws:iam::163806924483:user/User1.dilip@gmail.com",
                "arn:aws:iam::163806924483:user/User2@gmail.com",
                "arn:aws:iam::163806924483:user/User3@gmail.com"
            ]
        },
        "Action": [
            "kms:CreateGrant",
            "kms:ListGrants",
            "kms:RevokeGrant"
        ],
        "Resource": "*",
        "Condition": {
            "Bool": {
                "kms:GrantIsForAWSResource": "true"
            }
        }
    }
]
}

在此处输入图像描述

步骤:- 2在 IAM 中为 KMS 创建一个策略,将其分配给您的每个 lambda 函数

"StringEquals": {
            "kms:EncryptionContext:LambdaFunctionName": [
                "LambdaFunction-1",
                "LambdaFunction-2",
                "LambdaFunction-3"
            ]
        }

在此处输入图像描述

第 3 步:-将在第 2 步中创建的策略分配给您的默认 lambda 角色(需要创建第一个 Lambda 以获得默认 lambda 角色) 在此处输入图像描述

第 4 步:- 创建 lambda 函数

lambda 函数的Node.js代码

const mysql = require('mysql');
const aws = require("aws-sdk");


const functionName = process.env.AWS_LAMBDA_FUNCTION_NAME;
let res;
let response={};
exports.handler = async(event) => {
reset_globals();

// load env variables
const rds_user = await kms_decrypt(process.env.RDS_USERNAME);
const rds_pwd = await kms_decrypt(process.env.RDS_PASSWORD)

// setup rds connection
var db_connection = await mysql.createConnection({
    host: process.env.RDS_HOSTNAME,
    user: rds_user,
    password: rds_pwd,
    port: process.env.RDS_PORT,
    database: process.env.RDS_DATABASE
});

var sqlQuery = `SELECT doc_id from documents`;
await getValues(db_connection,sqlQuery);

}

async function getValues(db_connection,sql) {
await new Promise((resolve, reject) => {
    db_connection.query(sql, function (err, result) {
        if (err) {
            response = {statusCode: 500, body:{message:"Database Connection Failed", 
             error: err}};
            console.log(response);
            resolve();
        }
        else {
           
            console.log("Number of records retrieved: " + JSON.stringify(result));
            res = result;
           
            resolve();
        }
    });
    });
}

async function kms_decrypt(encrypted) {
const kms = new aws.KMS();
const req = { CiphertextBlob: Buffer.from(encrypted, 'base64'), EncryptionContext: { 
LambdaFunctionName: functionName } };
const decrypted = await kms.decrypt(req).promise();
let cred = decrypted.Plaintext.toString('ascii');
return cred;
}


function reset_globals() {
res = (function () { return; })();
response = {};
}

现在你应该在 Lambda 中看到 KMS。 在此处输入图像描述

第 5 步:-设置环境变量并加密。

Lambda -> 函数 -> 配置 -> 环境变量 -> 编辑

RDS_DATABASE 文档

RDS_HOSTNAME docrds-library.c1k3kcldebmp.us-east-1.rds.amazonaws.com

RDS_PASSWORD root123

RDS_PORT 3306

RDS_USERNAME 管理员

在此处输入图像描述

在 Lambda 函数中解密加密的环境变量,使用下面的代码

function kms_decrypt(encrypted) {
const kms = new aws.KMS();
const req = { CiphertextBlob: Buffer.from(encrypted, 'base64'), EncryptionContext: { 
LambdaFunctionName: functionName } };
const decrypted = await kms.decrypt(req).promise();
let cred = decrypted.Plaintext.toString('ascii');
return cred;
}

我的 RDS 文档表如下所示:-

在此处输入图像描述

我在 lambda 函数中使用 sqlQuery 访问列 doc_id

var sqlQuery = `SELECT doc_id from documents`;

测试 lambda 函数后,我得到以下输出。

在此处输入图像描述

如果你得到 SQL 导入错误,那么必须添加一个层。

在此处输入图像描述

errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'mysql'\nRequire stack:\n- 
/var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
 "trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'mysql'",

您可以配置您的 Lambda 函数以使用层形式的其他代码和内容。层是包含库、自定义运行时或其他依赖项的 ZIP 存档。通过层,您可以在函数中使用库,而无需将它们包含在部署包中。

要将库包含在层中,请将它们放在与您的编程语言对应的目录结构中。

Node.js – nodejs/node_modules

蟒蛇——蟒蛇

红宝石 - 红宝石/宝石/2.5.0

Java – java/lib

首先创建一个包含 mysql 归档的 zip 归档。

首先创建一个反应项目

然后在终端 $project-path > npm init

然后 $project-path > npm install mysql

您应该会看到创建的 node_modules 文件夹。

压缩 node_modules 该文件夹并上传到图层,如下所示。

然后,转到 Lambda--> 层--> 创建层。

在此处输入图像描述 在此处输入图像描述

在此处输入图像描述 在此处输入图像描述

于 2021-04-07T03:09:52.173 回答