|
1 | 1 | import * as cdk from 'aws-cdk-lib'; |
| 2 | +import * as iam from 'aws-cdk-lib/aws-iam'; |
2 | 3 | import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'; |
3 | 4 | import { Construct } from 'constructs'; |
4 | 5 | import { CloudFrontConstruct } from './constructs/cloudfront'; |
@@ -128,10 +129,51 @@ export class LocalGovDrupalStack extends cdk.Stack { |
128 | 129 | value: 'admin', |
129 | 130 | }); |
130 | 131 |
|
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 | + |
132 | 174 | 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}®ion=${cdk.Aws.REGION}`, |
| 175 | + description: 'Admin password for login', |
| 176 | + value: readSecretCR.getAttString('Password'), |
135 | 177 | }); |
136 | 178 |
|
137 | 179 | // CloudWatch Logs URL for monitoring initialization |
|
0 commit comments