将敏感值作为环境变量传递到 aws-cdk 自定义资源中是否安全

Is it safe to pass sensitive values as environment variables into an aws-cdk custom resource

我想在通过自定义资源初始化 cdk 堆栈时将初始管理员用户保存到我的 dynamodb table,但我不确定为该用户安全传递值的最佳方式。我的代码现在使用 dotEnv 并将值作为环境变量传递:

import * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
import * as dynamodb from "@aws-cdk/aws-dynamodb";
import * as customResource from "@aws-cdk/custom-resources";

require("dotenv").config();

export class CDKBackend extends cdk.Construct {
    public readonly handler: lambda.Function;
    constructor(scope: cdk.Construct, id: string) {
        super(scope, id);

        const tableName = "CDKBackendTable";

        // not shown here but also:
        // creates a dynamodb table for tableName and a seedData lambda with access to it
        // also some lambdas for CRUD operations and an apiGateway.RestApi for them

        const seedDataProvider = new customResource.Provider(this, "seedDataProvider", {
            onEventHandler: seedDataLambda
        });

        new cdk.CustomResource(this, "SeedDataResource", {
            serviceToken: seedDataProvider.serviceToken,
            properties: {
                tableName,
                user: process.env.ADMIN,
                password: process.env.ADMINPASSWORD,
                salt: process.env.SALT
            }
        });
    }
}

此代码有效,但以这种方式通过 ADMIN、ADMINPASSWORD 和 SALT 是否安全?这种方法与从 AWS secrets manager 访问这些值之间的安全差异是什么?我还计划在为所有新用户生成 passwordDigest 值时使用该 SALT 值,而不仅仅是这个管理员用户。

properties 值将在部署时进行评估。因此,它们将成为 CloudFormation 模板的一部分。可以在 AWS Web 控制台中查看 CloudFormation 模板。因此,从安全角度来看,以这种方式传递秘密是值得怀疑的。

克服此问题的一种方法是使用 AWS Secrets Manager. aws-cdk 与 Secrets Manager 很好地集成来存储机密。创建秘密后,您可以通过以下方式导入它:

const mySecretFromName = secretsmanager.Secret.fromSecretNameV2(stack, 'SecretFromName', 'MySecret')

很遗憾,不支持解析CloudFormation dynamic references in AWS Custom Resources. You can resolve the secret yourself though inside your lambda (seedDataLambda). The SqlRun repository提供了示例。

请记住为自定义资源 lambda (seedLambda) 授予对秘密的访问权限,例如

secret.grantRead(seedDataProvider.executionRole)