Skip to content

Commit 527b06e

Browse files
authored
Merge pull request #110 from co-cddo/fix/drupal-admin-password-output
fix: show admin password as plain text in CloudFormation Outputs
2 parents 533fe8b + 4e9e401 commit 527b06e

2 files changed

Lines changed: 1363 additions & 2098 deletions

File tree

cloudformation/scenarios/localgov-drupal/cdk/lib/localgov-drupal-stack.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as cdk from 'aws-cdk-lib';
2+
import * as iam from 'aws-cdk-lib/aws-iam';
23
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
34
import { Construct } from 'constructs';
45
import { CloudFrontConstruct } from './constructs/cloudfront';
@@ -128,10 +129,51 @@ export class LocalGovDrupalStack extends cdk.Stack {
128129
value: 'admin',
129130
});
130131

131-
// Admin password — link to Secrets Manager console to retrieve the value
132+
// Custom Resource to resolve admin password for display in Outputs
133+
const readSecretRole = new iam.Role(this, 'ReadSecretRole', {
134+
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
135+
managedPolicies: [
136+
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
137+
],
138+
});
139+
readSecretRole.addToPolicy(new iam.PolicyStatement({
140+
actions: ['secretsmanager:GetSecretValue'],
141+
resources: [adminSecret.secretArn],
142+
}));
143+
144+
const readSecretFn = new cdk.aws_lambda.Function(this, 'ReadSecretFn', {
145+
runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
146+
handler: 'index.handler',
147+
role: readSecretRole,
148+
timeout: cdk.Duration.seconds(30),
149+
code: cdk.aws_lambda.Code.fromInline(`
150+
const{SecretsManagerClient,GetSecretValueCommand}=require("@aws-sdk/client-secrets-manager");
151+
const r=require("https");
152+
exports.handler=async(e)=>{
153+
const rp={Status:"SUCCESS",PhysicalResourceId:e.LogicalResourceId,StackId:e.StackId,RequestId:e.RequestId,LogicalResourceId:e.LogicalResourceId,Data:{}};
154+
if(e.RequestType==="Delete"){await send(e.ResponseURL,rp);return}
155+
try{
156+
const sm=new SecretsManagerClient();
157+
const sv=await sm.send(new GetSecretValueCommand({SecretId:e.ResourceProperties.SecretArn}));
158+
rp.Data={Password:sv.SecretString};
159+
await send(e.ResponseURL,rp);
160+
}catch(err){rp.Status="FAILED";rp.Reason=err.message;await send(e.ResponseURL,rp)}
161+
};
162+
function send(u,d){return new Promise((ok,fail)=>{const b=JSON.stringify(d);const o=new URL(u);const opts={hostname:o.hostname,port:443,path:o.pathname+o.search,method:"PUT",headers:{"Content-Type":"","Content-Length":b.length}};const req=r.request(opts,ok);req.on("error",fail);req.write(b);req.end()})}
163+
`),
164+
});
165+
166+
const readSecretCR = new cdk.CustomResource(this, 'ReadSecretCR', {
167+
serviceToken: readSecretFn.functionArn,
168+
properties: {
169+
SecretArn: adminSecret.secretArn,
170+
},
171+
});
172+
readSecretCR.node.addDependency(readSecretRole);
173+
132174
new cdk.CfnOutput(this, 'AdminPassword', {
133-
description: 'Drupal admin password (retrieve from Secrets Manager)',
134-
value: `https://console.aws.amazon.com/secretsmanager/secret?name=${adminSecret.secretName}&region=${cdk.Aws.REGION}`,
175+
description: 'Admin password for login',
176+
value: readSecretCR.getAttString('Password'),
135177
});
136178

137179
// CloudWatch Logs URL for monitoring initialization

0 commit comments

Comments
 (0)