I'm using aws-cdk-lib
(2.13.0). Here's a snippet of my code:
import { App, Stack } from 'aws-cdk-lib';
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
export class CognitoStack extends Stack {
constructor(scope: App) {
super(scope, 'cognito');
const secret = this.getSecret('google');
console.log({ secret });
}
public getSecret(path: string) {
const secret = Secret.fromSecretNameV2(this, `Secret${path}`, path);
console.log({ path, secret, secretArn: secret.secretArn, string: secret.secretValue.toString() });
return secret.secretValue.toJSON();
}
}
The resulting logs look like this:
{
path: 'google',
secret: <ref *1> SecretBase {
node: Node {
host: [Circular *1],
_locked: false,
_children: {},
_context: {},
_metadata: [],
_dependencies: Set(0) {},
_validations: [Array],
id: 'Secretgoogle',
scope: [CognitoStack]
},
stack: CognitoStack {
node: [Node],
_missingContext: [],
_stackDependencies: {},
templateOptions: {},
_logicalIds: [LogicalIDs],
account: '${Token[AWS.AccountId.4]}',
region: '${Token[AWS.Region.8]}',
environment: 'aws://unknown-account/unknown-region',
terminationProtection: undefined,
_stackName: 'cognito',
tags: [TagManager],
artifactId: 'cognito',
templateFile: 'cognito.template.json',
_versionReportingEnabled: true,
synthesizer: [DefaultStackSynthesizer],
[Symbol(@aws-cdk/core.DependableTrait)]: [Object]
},
env: {
account: '${Token[AWS.AccountId.4]}',
region: '${Token[AWS.Region.8]}'
},
_physicalName: undefined,
_allowCrossEnvironment: false,
physicalName: '${Token[TOKEN.332]}',
encryptionKey: undefined,
secretName: 'google',
secretArn: 'arn:${Token[AWS.Partition.7]}:secretsmanager:${Token[AWS.Region.8]}:${Token[AWS.AccountId.4]}:secret:google',
autoCreatePolicy: false,
[Symbol(@aws-cdk/core.DependableTrait)]: { dependencyRoots: [Array] }
},
secretArn: 'arn:${Token[AWS.Partition.7]}:secretsmanager:${Token[AWS.Region.8]}:${Token[AWS.AccountId.4]}:secret:google',
string: '${Token[TOKEN.333]}'
}
{ secret: '<unresolved-token>' }
The results of the npx cdk diff sandbox-cognito
look like this:
Stack sandbox-cognito
Resources
[~] AWS::Cognito::UserPoolIdentityProvider Google GoogleAF1E99FA
└─ [~] ProviderDetails
├─ [-] Removed: .client_id
└─ [-] Removed: .client_secret
Which means that it is removing the client_id/client_secret that I was able to set manually. Now that I'm trying to load the values from a secret, it is not working.
The problem is that I cannot parse the JSON (notice the <unresolved-token>
in the logs. I think that it is not yet resolved, but I'm not sure how to resolve... It's trying parse this string literal: ${Token[TOKEN.333]}
, instead of the secret value. How can I get the results of the secret string?
Import your existing secret as a SecretValue. Pass it to the clientSecret:string
prop using the .toString()
method.
// Existing secret as SecretValue. Or use Secret.fromSecretNameV2.
const secretVal = cdk.SecretValue.secretsManager('GoogleSecrets', {
jsonField: 'client-secret',
});
new cognito.UserPoolIdentityProviderGoogle(this, 'GoogleProvider', {
userPool,
// creates a dynamic reference which resolves to the actual secret value at deploy-time
clientSecret: secretVal.toString(),
clientId: 'my-id',
});
SecretValue.toString()
"resolves" to different values during the lifecycle:
When you console.log
it, you get an (useless) opaque placeholder Token value like ${Token[TOKEN.198]}
. At synth-time CDK renders a CloudFormation dynamic reference in the template:
//my-stack.template.json
{"client_secret": "{{resolve:secretsmanager:arn:aws:secretsmanager:us-east-1:123456789012:secret:GoogleSecrets:SecretString:client-secret::}}"}
At deploy-time, CloudFormation "resolves" the actual secret value from the dynamic reference.
The important takeaway is that the actual secret value is never exposed to your local environment or the template artefacts.