in packages/aws-rfdk/lib/lambdas/nodejs/x509-certificate/handlers.ts [171:242]
public async doCreate(physicalId: string, resourceProperties: IX509CertificateGenerate): Promise<object> {
const resourceTable = await this.getResourceTable();
await Promise.all([
this.databasePermissionsCheck(resourceTable),
this.secretsPermissionsCheck(resourceProperties.Secret.Tags),
]);
const subject = new DistinguishedName(resourceProperties.DistinguishedName);
const passphrase = await Secret.fromArn(resourceProperties.Passphrase, this.secretsManagerClient).getValue() as string;
let certExpiry: number = resourceProperties.CertificateValidFor ? Number(resourceProperties.CertificateValidFor) : 1095;
let signingCert: Certificate | undefined;
if (resourceProperties.SigningCertificate) {
const signCert = resourceProperties.SigningCertificate;
const cert = await Secret.fromArn(signCert.Cert, this.secretsManagerClient).getValue() as string;
const key = await Secret.fromArn(signCert.Key, this.secretsManagerClient).getValue() as string;
const pass = await Secret.fromArn(signCert.Passphrase, this.secretsManagerClient).getValue() as string;
const certChain = signCert.CertChain.length > 0
? await Secret.fromArn(signCert.CertChain, this.secretsManagerClient).getValue() as string
: '';
signingCert = new Certificate(cert, key, pass, certChain);
}
const newCert = await Certificate.fromGenerated(subject, passphrase, certExpiry, signingCert);
const now = new Date(Date.now());
// timeSuffix = "<year>-<month>-<day>-<time since epoch>" -- to disambiguate secrets
// in case we do an update on the same day as a create (both old & new exist at the same time)
const timeSuffix: string = `${now.getFullYear()}-${now.getMonth()}-${now.getDate()}-${now.getTime()}`;
const kmsKey = resourceProperties.Secret.EncryptionKey ? Key.fromArn(resourceProperties.Secret.EncryptionKey) : undefined;
const returnArns: { [key: string]: string } = {};
const certComponents: Array<{ key: string, purpose: string, data: string | Buffer | undefined}> = [
{
key: 'Cert',
purpose: 'Certificate',
data: newCert.cert,
},
{
key: 'Key',
purpose: 'Private Key',
data: newCert.key,
},
{
key: 'CertChain',
purpose: 'Certificate Chain',
data: newCert.certChain,
},
];
for (const component of certComponents) {
if (component.data) {
const data = component.data;
const purpose = component.purpose;
const name = sanitizeSecretName(`${resourceProperties.Secret.NamePrefix}-X.509-${purpose}-${timeSuffix}`);
const arn = await this.createAndStoreSecret({
database: resourceTable,
name,
physicalId,
purpose,
data,
description: `X.509 ${component.purpose} for ${resourceProperties.Secret.Description}`,
tags: resourceProperties.Secret.Tags,
encryptionKey: kmsKey,
});
returnArns[component.key] = arn;
} else {
// Case for CertChain being empty. We cannot just skip it due to constraints put on us by CDK's CustomResource
returnArns[component.key] = '';
}
}
return returnArns;
}