"Runtime.ImportModuleError" 尝试使用层访问 AWS lambda 函数中的 npm 包
"Runtime.ImportModuleError" trying to access npm package in an AWS lambda function using layers
我想在 AWS lambda 函数中使用 npm 包 "request"。
我正在尝试按照本文中概述的步骤操作: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');
...都无济于事。
我错过了什么?
哦,我简直不敢相信只有这个!
.zip 文件的顶级目录必须按字面意思命名为“nodejs
”!我使用了不同的名称,只是在 post 的文本中将其改回 "nodejs" 以便更通用,但目录名称一直是真正的问题。
感叹
一般与里面folder/files的名字有关。如果这些文件在别处引用,它也会在那里渗透和抱怨。只要彻底检查文件夹结构,就能抓住小偷。折腾了一天才搞明白,真是个傻逼。
Accessing table data from RDS using lambda function with encrypted key (KMS) and Environment variable
第 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 函数
Node.js lambda 函数代码
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。
第五步:-设置环境变量并加密。
Lambda -> 函数 -> 配置 -> 环境变量 -> 编辑
RDS_DATABASE 文档
RDS_HOSTNAME docrds-library.c1k3kcldebmp.us-east-1.rds.amazonaws.com
RDS_PASSWORD root123
RDS_PORT3306
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 文档 table 看起来像:-
我正在使用 lambda 函数中的 sqlQuery 访问列 doc_id
var sqlQuery = `SELECT doc_id from documents`;
测试 lambda 函数后,我得到以下输出。
如果你得到SQL import Error,那么必须添加一层。
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'",
You can configure your Lambda function to use additional code and
content in the form of layers. A layer is a ZIP archive that contains
libraries, a custom runtime, or other dependencies. With layers, you
can use libraries in your function without needing to include them in
your deployment package.
To include libraries in a layer, place them in the directory structure
that corresponds to your programming language.
Node.js – nodejs/node_modules
Python – python
Ruby – ruby/gems/2.5.0
Java – java/lib
首先创建一个包含 mysql archieve 的 zip archieve。
First create a react-project
Then in terminal $project-path > npm init
Then $project-path > npm install mysql
You should see node_modules folder created.
Zip node_modules that folder and upload on layer as shown below.
然后,Goto Lambda--> Layer-->Create layer.
对我来说,导致这些问题的原因是 package.json 的一个版本仍然在旧版本的 .build 文件夹中,该文件夹也已部署。一旦我删除它,软件包就会按预期安装。
我想在 AWS lambda 函数中使用 npm 包 "request"。
我正在尝试按照本文中概述的步骤操作: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');
...都无济于事。
我错过了什么?
哦,我简直不敢相信只有这个!
.zip 文件的顶级目录必须按字面意思命名为“nodejs
”!我使用了不同的名称,只是在 post 的文本中将其改回 "nodejs" 以便更通用,但目录名称一直是真正的问题。
感叹
一般与里面folder/files的名字有关。如果这些文件在别处引用,它也会在那里渗透和抱怨。只要彻底检查文件夹结构,就能抓住小偷。折腾了一天才搞明白,真是个傻逼。
Accessing table data from RDS using lambda function with encrypted key (KMS) and Environment variable
第 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 函数
Node.js lambda 函数代码
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。
第五步:-设置环境变量并加密。
Lambda -> 函数 -> 配置 -> 环境变量 -> 编辑
RDS_DATABASE 文档
RDS_HOSTNAME docrds-library.c1k3kcldebmp.us-east-1.rds.amazonaws.com
RDS_PASSWORD root123
RDS_PORT3306
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 文档 table 看起来像:-
我正在使用 lambda 函数中的 sqlQuery 访问列 doc_id
var sqlQuery = `SELECT doc_id from documents`;
测试 lambda 函数后,我得到以下输出。
如果你得到SQL import Error,那么必须添加一层。
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'",
You can configure your Lambda function to use additional code and content in the form of layers. A layer is a ZIP archive that contains libraries, a custom runtime, or other dependencies. With layers, you can use libraries in your function without needing to include them in your deployment package.
To include libraries in a layer, place them in the directory structure that corresponds to your programming language.
Node.js – nodejs/node_modules
Python – python
Ruby – ruby/gems/2.5.0
Java – java/lib
首先创建一个包含 mysql archieve 的 zip archieve。
First create a react-project
Then in terminal $project-path > npm init
Then $project-path > npm install mysql
You should see node_modules folder created.
Zip node_modules that folder and upload on layer as shown below.
然后,Goto Lambda--> Layer-->Create layer.
对我来说,导致这些问题的原因是 package.json 的一个版本仍然在旧版本的 .build 文件夹中,该文件夹也已部署。一旦我删除它,软件包就会按预期安装。