You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Lambda Skill CDK构造不接受传入的cdk.SecretValue参数?

问题:AWS CDK部署栈时触发SecretValue暴露风险错误

错误信息

Resolution error: Synthing a secret value to . Using a SecretValue here risks exposing your secret. Only pass SecretValues to constructs that accept a SecretValue property, or call AWS Secrets Manager directly in your runtime code. Call 'secretValue.unsafeUnwrap()' if you understand and accept the risks..

调用栈:

Object creation stack:
  at new Intrinsic (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/aws-cdk-lib/core/lib/private/intrinsic.js:1:680)
  at new SecretValue (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/aws-cdk-lib/core/lib/secret-value.js:1:592)
  at Function.cfnDynamicReference (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/aws-cdk-lib/core/lib/secret-value.js:1:2713)
  at Function.secretsManager (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/aws-cdk-lib/core/lib/secret-value.js:1:2202)
  at HltbStack.retrieveSecrets (/Users/john/Desktop/Production/alexa skills/hltb/lib/hltb-stack.ts:55:45)
  at new HltbStack (/Users/john/Desktop/Production/alexa skills/hltb/lib/hltb-stack.ts:27:12)
  at Object.<anonymous> (/Users/john/Desktop/Production/alexa skills/hltb/bin/hltb.ts:20:1)
  at Module._compile (internal/modules/cjs/loader.js:1085:14)
  at Module.m._compile (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/ts-node/src/index.ts:1618:23)
  at Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
  at Object.require.extensions.<computed> [as .ts] (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/ts-node/src/index.ts:1621:12)
  at Module.load (internal/modules/cjs/loader.js:950:32)
  at Function.Module._load (internal/modules/cjs/loader.js:790:12)
  at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
  at phase4 (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/ts-node/src/bin.ts:649:14)
  at bootstrap (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/ts-node/src/bin.ts:95:10)
  at main (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/ts-node/src/bin.ts:55:10)
  at Object.<anonymous> (/Users/john/Desktop/Production/alexa skills/hltb/node_modules/ts-node/src/bin.ts:800:3)
  at Module._compile (internal/modules/cjs/loader.js:1085:14)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
  at Module.load (internal/modules/cjs/loader.js:950:32)
  at Function.Module._load (internal/modules/cjs/loader.js:790:12)
  at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
  at /Users/john/.nvm/versions/node/v14.20.1/lib/node_modules/npm/node_modules/libnpx/index.js:268:14

栈代码

import { Stack } from "aws-cdk-lib";
import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { Skill } from "cdk-alexa-skill";
import * as path from "path";
import { Props } from "../bin/hltb";
import * as ssm from "aws-cdk-lib/aws-ssm";

export type SkillConfig = {
  alexaVendorIdSecretValue: string;
  lwaClientIdSecretValue: string;
  lwaClientSecretSecretValue: string;
  lwaRefreshTokenSecretValue: string;
};

export class HltbStack extends Stack {
  constructor(scope: cdk.App, id: string, props: Props) {
    super(scope, id, props);

    const skillBackendLambdaFunction = new lambda.Function(this, "Function", {
      runtime: lambda.Runtime.NODEJS_16_X,
      handler: "handler.handler",
      code: lambda.Code.fromAsset(path.join(__dirname, "/../src/handlers")),
    });

    const { alexaVendorId, lwaClientId, lwaClientSecret, lwaRefreshToken } = 
      this.retrieveSecrets(props);

    const skill = new Skill(this, "hltbSkill", {
      endpointLambdaFunction: skillBackendLambdaFunction,
      skillPackagePath: "src/skill-package",
      alexaVendorId,
      lwaClientId,
      lwaClientSecret,
      lwaRefreshToken,
    });
  }

  private retrieveSecrets(props: Props): {
    alexaVendorId: string;
    lwaClientId: string;
    lwaClientSecret: cdk.SecretValue;
    lwaRefreshToken: cdk.SecretValue;
  } {
    const alexaVendorId = ssm.StringParameter.valueForStringParameter(
      this,
      props.alexaVendorIdSecretValue
    );

    const lwaClientId = ssm.StringParameter.valueForStringParameter(
      this,
      props.lwaClientIdSecretValue
    );

    const lwaClientSecret = cdk.SecretValue.secretsManager(
      props.lwaClientSecretSecretValue
    );
    const lwaRefreshToken = cdk.SecretValue.secretsManager(
      props.lwaRefreshTokenSecretValue
    );

    return {
      alexaVendorId,
      lwaClientId,
      lwaClientSecret,
      lwaRefreshToken,
    };
  }
}

Skill组件类型定义

export interface SkillProps {
    readonly endpointLambdaFunction?: lambda.IFunction;
    readonly skillPackagePath: string;
    readonly alexaVendorId: string;
    readonly lwaClientId: string;
    readonly lwaClientSecret: cdk.SecretValue;
    readonly lwaRefreshToken: cdk.SecretValue;
}

问题分析与解决方案

原因

尽管你按照SkillProps定义传入了cdk.SecretValue类型的值,但cdk-alexa-skill库的内部实现可能将这些SecretValue转换为字符串(比如构造Alexa API请求参数),触发了CDK的安全检测——CDK禁止直接将SecretValue转为字符串,避免秘密值在CloudFormation模板或部署日志中暴露。

解决方案

由于cdk-alexa-skill在部署阶段需要直接使用凭证调用Alexa管理API,无法通过CloudFormation动态引用传递,因此需要明确调用unsafeUnwrap()告知CDK你已了解风险并接受:

  1. 修改retrieveSecrets方法中获取秘密值的代码:
const lwaClientSecret = cdk.SecretValue.secretsManager(
  props.lwaClientSecretSecretValue
).unsafeUnwrap();
const lwaRefreshToken = cdk.SecretValue.secretsManager(
  props.lwaRefreshTokenSecretValue
).unsafeUnwrap();
  1. 同步修改retrieveSecrets的返回类型,将两个秘密字段改为string:
private retrieveSecrets(props: Props): {
  alexaVendorId: string;
  lwaClientId: string;
  lwaClientSecret: string;
  lwaRefreshToken: string;
}
  1. 若SkillProps严格要求SecretValue类型,需检查cdk-alexa-skill库是否有版本更新修复该兼容性问题。

内容的提问来源于stack exchange,提问作者John Nezzi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:56:10