从 SSM 参数生成文件并包含在无服务器框架 lambda 包中
Posted
技术标签:
【中文标题】从 SSM 参数生成文件并包含在无服务器框架 lambda 包中【英文标题】:Generate files from SSM parameters and include in Serverless Framework lambda bundle 【发布时间】:2021-06-29 12:32:08 【问题描述】:我有一些 JSON 存储在 SSM 参数存储中,我想在我的无服务器框架 lambda 函数中使用它们(包含有关 Terraform 之前生成的基础设施的一些详细信息)。我可以调用 SSM 以在运行时获取数据,但 Parameter Store 的吞吐量限制非常低 (40tps by default),因此我可能会立即超过该限制,即使更高的限制仍然太低而无法执行此操作正在生产中。
更一般地说,我希望避免调用外部服务来检索此信息的开销,因为它将在自定义 lambda 授权器中使用,因此我希望它快速且尽可能不依赖任何外部依赖项。
当我执行serverless deploy
时,我正在考虑从 Parameter Store 检索 JSON 并将其烘焙到我的 lambda 包中。我很高兴在后端发生变化时必须重新部署我的后端。
我可以使用环境变量,但是maximum size of all environment variables is 4kb,所以我不能把 JSON 放在那里。
我正在使用Serverless Webpack Plugin,我认为这可能是关键,但我是 Webpack 新手,不知道从哪里开始!
【问题讨论】:
【参考方案1】:也许有更好的方法,但我设法通过写custom webpack loader 来实现它。这个答案专门针对我需要将多个 cognito 池的详细信息导出到单个文件以在自定义 lambda 授权程序中使用的情况,但该模式应该适用于任何场景,也不一定与 SSM 相关(你可以使用任何方法生成文件,因为加载器只是普通的 javascript)。它使我的 Lambda 执行时间从 ~40ms(使用 SSM)降低到 ~2ms。
模板文件和用法
首先,我创建了一个示例模板 .json 文件,其结构与我存储在 SSM 中的数据相匹配。这可能在任何地方,但我把它放在generated/cognitoConfig.json
中。这对于使用点的文档和代码辅助很有用。
"pools": [
"_note_": "This is just an example. This file gets totally replaced with the real pool config by cognitoConfigLoader on deploy",
"clientId":"example-client",
"name":"example",
"poolArn":"arn:aws:cognito-idp:eu-west-2:account-id:userpool/example-pool",
"poolEndpoint":"cognito-idp.eu-west-2.amazonaws.com/example-pool",
"poolId":"example-pool",
"poolKeysUrl":"https://cognito-idp.eu-west-2.amazonaws.com/example-pool/.well-known/jwks.json",
"region":"eu-west-2"
]
然后可以在 lambda 代码 (ES6) 中导入和使用它。例如:
import * as cognitoData from '../../generated/cognitoConfig.json';
function getPoolConfig(name)
const poolConfig = cognitoData.pools.filter(pool => pool.name === name)[0]
Webpack 加载器
我配置了一个针对此模板文件运行的自定义 webpack 加载器:
const path = require('path');
module.exports =
//...other webpack config
module:
// These execute from bottom to top
rules: [
// ...other rules (e.g. babel)
// Retrieve cognito pool information from SSM and store
test: /cognitoConfig\.json$/,
include: path.resolve(__dirname, "generated"),
loader: path.resolve(__dirname, "webpack-loaders/cognitoConfigLoader.js"),
,
]
然后我编写了一个 webpack 加载器,用于搜索所有匹配的 SSM 参数,并将内容写入 JSON 文件。无服务器 webpack 插件提供对 the underlying serverless object 的访问,因此可以访问当前的 AWS 凭证。
对于奖励积分,我还下载了签名密钥,但我没有在此处包含,因为我不想弄乱答案:
const slsw = require("serverless-webpack");
const SSMClient, GetParametersByPathCommand = require("@aws-sdk/client-ssm")
const fromIni = require("@aws-sdk/credential-provider-ini")
module.exports = function ()
const callback = this.async()
buildPoolsJson().then(
poolsJson => callback(undefined, poolsJson),
error => callback(error)
)
async function buildPoolsJson()
const poolsParameters= await loadPoolsParameters()
return JSON.stringify(
pools: poolsParameters
)
async function loadPoolsParameters()
const awsProvider = slsw.lib.serverless.service.provider
const ssmClient = new SSMClient(
credentials: fromIni( profile: awsProvider.profile ),
region: awsProvider.region,
)
const poolParamsResponse = await ssmClient.send(new GetParametersByPathCommand(
Path: "/terraform/cognito-pools",
))
return poolParamsResponse.Parameters.map(parameter =>
return JSON.parse(parameter.Value);
)
【讨论】:
以上是关于从 SSM 参数生成文件并包含在无服务器框架 lambda 包中的主要内容,如果未能解决你的问题,请参考以下文章
SSM框架——使用MyBatis Generator自动创建代码