如何在SAM CLI生成的TypeScript Lambda目录中放置global-bundle.pem
解决SAM CLI构建Lambda时自动包含DocDB证书的问题
方法一:自动将证书打包进构建产物
1. 直接放入函数源码目录
把global-bundle.pem放到LambdaPOCv3文件夹下(和app.ts同级),同时检查两个配置:
- 确保
LambdaPOCv3/.npmignore里没有列出global-bundle.pem,避免npm打包时排除它; - 确认
tsconfig.json的exclude规则没有排除该文件,或include规则覆盖到它。
执行sam build后,证书会被自动复制到.aws-sam/build/LambdaPOCv3目录中。
2. 通过SAM模板配置文件复制
如果证书不在函数源码目录,或需要更灵活的控制,可以在template.yaml的函数资源中添加Metadata配置,指定构建时的文件复制规则:
Resources: LambdaPOCv3Function: Type: AWS::Serverless::Function Properties: CodeUri: LambdaPOCv3/ Handler: app.handler Runtime: nodejs18.x Metadata: BuildMethod: esbuild # 根据你的实际构建工具调整,比如npm、make等 BuildProperties: CopyFiles: - Source: '../global-bundle.pem' # 证书相对于函数目录的路径 Destination: '.' # 复制到构建产物的根目录
如果使用自定义构建脚本,可在函数目录下创建buildspec.yml,添加复制步骤:
version: 0.2 phases: build: commands: - npm install - npm run build - cp ../global-bundle.pem dist/ # 假设编译产物存放在dist目录 artifacts: files: - '**/*'
方法二:无需打包证书的替代方案
1. 启动时从AWS公共存储下载证书
Lambda启动时自动从AWS官方信任存储下载证书到临时目录(/tmp),代码示例:
import axios from 'axios'; import fs from 'fs'; import { MongoClient } from 'mongodb'; const CERT_PATH = '/tmp/global-bundle.pem'; const DB_URI = '你的DocDB连接地址'; async function prepareCert() { if (!fs.existsSync(CERT_PATH)) { const certResponse = await axios.get( 'https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem', { responseType: 'stream' } ); await new Promise((resolve, reject) => { certResponse.data.pipe(fs.createWriteStream(CERT_PATH)) .on('finish', resolve) .on('error', reject); }); } } export const handler = async () => { await prepareCert(); const client = new MongoClient(DB_URI, { sslCA: fs.readFileSync(CERT_PATH), ssl: true }); // 后续数据库操作逻辑 await client.connect(); // ... };
注:/tmp目录在Lambda容器存活期间会保留,仅冷启动时会下载证书,热启动可直接复用。
2. 用Secrets Manager存储证书内容
将证书内容上传到AWS Secrets Manager,Lambda运行时读取并写入/tmp:
- 在Secrets Manager创建新密钥,值填入
global-bundle.pem的完整内容; - 给Lambda添加读取该密钥的IAM权限;
- 代码中读取密钥并写入临时文件:
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager"; import fs from 'fs'; const secretsClient = new SecretsManagerClient({ region: '你的AWS区域' }); const SECRET_NAME = 'docdb-global-bundle-cert'; const CERT_PATH = '/tmp/global-bundle.pem'; async function getCertFromSecrets() { const command = new GetSecretValueCommand({ SecretId: SECRET_NAME }); const response = await secretsClient.send(command); const certContent = response.SecretString; fs.writeFileSync(CERT_PATH, certContent); } // 在handler中先调用getCertFromSecrets,再执行数据库连接逻辑
内容的提问来源于stack exchange,提问作者yungfrankling
相关产品推荐
相关产品推荐

