この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
今回は Secrets Manager のスタックを実装していきます。
前回の記事はこちら。
実装
追加するファイルは以下の通り。
├── lib
│ ├── resource
│ │ └── secret.ts
│ └── stack
│ └── secrets-manager-stack.ts
├── test
│ └── stack
│ └── secrets-manager-stack.test.ts
Secrets Manager のスタッククラスの実装はこちら。
lib/stack/secrets-manager-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Secret } from '../resource/secret';
export class SecretsManagerStack extends Stack {
public readonly secret: Secret;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
this.secret = new Secret(this);
}
}
自前の Secret
クラスのインスタンスを生成しています。他のリソースとの依存関係はないため、コンストラクタにスタックオブジェクトのパラメーターはありません。
以下が Secret
クラスの実装です。
以前からの変更も特になし。
lib/resource/secret.ts
import { CfnSecret } from "aws-cdk-lib/aws-secretsmanager";
import { Construct } from "constructs";
import { BaseResource } from "./abstract/base-resouce";
export const OSecretKey = {
MasterUsername: 'MasterUsername',
MasterUserPassword: 'MasterUserPassword'
} as const;
type SecretKey = typeof OSecretKey[keyof typeof OSecretKey];
interface ResourceInfo {
readonly id: string;
readonly description: string;
readonly generateSecretString: CfnSecret.GenerateSecretStringProperty;
readonly resourceName: string;
readonly assign: (secret: CfnSecret) => void;
}
export class Secret extends BaseResource {
public readonly rdsCluster: CfnSecret;
private static readonly rdsClusterMasterUsername = 'admin';
private readonly resources: ResourceInfo[] = [{
id: 'SecretRdsCluster',
description: 'for RDS cluster',
generateSecretString: {
excludeCharacters: '"@/\\\'',
generateStringKey: OSecretKey.MasterUserPassword,
passwordLength: 16,
secretStringTemplate: `{"${OSecretKey.MasterUsername}": "${Secret.rdsClusterMasterUsername}"}`
},
resourceName: 'secret-rds-cluster',
assign: secret => (this.rdsCluster as CfnSecret) = secret
}];
constructor(scope: Construct) {
super();
for (const resourceInfo of this.resources) {
const secret = this.createSecret(scope, resourceInfo);
resourceInfo.assign(secret);
}
}
public static getDynamicReference(secret: CfnSecret, secretKey: SecretKey): string {
return `{{resolve:secretsmanager:${secret.ref}:SecretString:${secretKey}}}`;
}
private createSecret(scope: Construct, resourceInfo: ResourceInfo): CfnSecret {
const secret = new CfnSecret(scope, resourceInfo.id, {
description: resourceInfo.description,
generateSecretString: resourceInfo.generateSecretString,
name: this.createResourceName(scope, resourceInfo.resourceName)
});
return secret;
}
}
メインのスタッククラスの実装はこちら。
lib/devio-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Ec2Stack } from './stack/ec2-stack';
import { IamStack } from './stack/iam-stack';
import { SecretsManagerStack } from './stack/secrets-manager-stack';
import { VpcStack } from './stack/vpc-stack';
export class DevioStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// VPC Stack
const vpcStack = new VpcStack(scope, 'VpcStack', {
stackName: this.createStackName(scope, 'vpc')
});
// IAM Stack
const iamStack = new IamStack(scope, 'IamStack', {
stackName: this.createStackName(scope, 'iam')
});
// EC2 Stack
new Ec2Stack(scope, 'Ec2Stack', vpcStack, iamStack, {
stackName: this.createStackName(scope, 'ec2')
});
// Secrets Manager Stack
new SecretsManagerStack(scope, 'SecretsManagerStack', {
stackName: this.createStackName(scope, 'secrets-manager')
});
}
private createStackName(scope: Construct, originalName: string): string {
const systemName = scope.node.tryGetContext('systemName');
const envType = scope.node.tryGetContext('envType');
const stackNamePrefix = `${systemName}-${envType}-stack-`;
return `${stackNamePrefix}${originalName}`;
}
}
ハイライト部分を追記しています。
テスト
テストコードはこちら。
test/stack/secrets-manager-stack.test.ts
import { App } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { SecretsManagerStack } from '../../lib/stack/secrets-manager-stack';
test('Secrets Manager Stack', () => {
const app = new App({
context: {
'systemName': 'devio',
'envType': 'stg'
}
});
const secretsManagerStack = new SecretsManagerStack(app, 'SecretsManagerStack');
const template = Template.fromStack(secretsManagerStack);
template.resourceCountIs('AWS::SecretsManager::Secret', 1);
template.hasResourceProperties('AWS::SecretsManager::Secret', {
Description: 'for RDS cluster',
GenerateSecretString: {
ExcludeCharacters: '"@/\\\'',
GenerateStringKey: 'MasterUserPassword',
PasswordLength: 16,
SecretStringTemplate: '{"MasterUsername": "admin"}'
},
Name: 'devio-stg-secret-rds-cluster'
});
});
GitHub
今回のソースコードは コチラ です。
おわりに
スタック分割リファクタイングもいよいよ終盤です。残るは RDS スタックのみ。次回、最終回です。