public async doCreate()

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;
  }