async function createGreengrassCertAndKeys()

in source/lambda/custom-resource/index.ts [197:308]


async function createGreengrassCertAndKeys(
  props: CustomResourceTypes.CreateGreengrassCertAndKeysProperties,
  requestType: CustomResourceTypes.RequestTypes
): Promise<CustomResourceTypes.GreengrassCertificateResponse | {}> {
  if (requestType === CustomResourceTypes.RequestTypes.CREATE) {
    const iotEndpointAddress = await iotHandler.describeIoTEndpoint();
    const keysAndCertificate = await iotHandler.createKeysAndCertificate();
    const { certificateArn, certificateId, certificatePem, keyPair } = keysAndCertificate;

    /**
     * Since Lambda function allows to store temporary files in /tmp directory,
     * all files are going to be created under /tmp directory.
     */
    const tempDirectory = '/tmp';
    const certsDirectory = 'certs';
    const prefix = certificateId.slice(0, 10);
    const certificateFileName = `${prefix}-cert.pem`;
    const privateKeyFileName = `${prefix}-private.key`;
    const publicKeyFileName = `${prefix}-public.key`;
    const rootCaFileName = 'root.ca.pem';

    if (!fs.existsSync(`${tempDirectory}/${certsDirectory}`)) {
      fs.mkdirSync(`${tempDirectory}/${certsDirectory}`);
    }

    fs.writeFileSync(`${tempDirectory}/${certsDirectory}/${certificateFileName}`, certificatePem);
    fs.writeFileSync(`${tempDirectory}/${certsDirectory}/${privateKeyFileName}`, keyPair.PrivateKey);
    fs.writeFileSync(`${tempDirectory}/${certsDirectory}/${publicKeyFileName}`, keyPair.PublicKey);

    const amazonCa = await axios.get('https://www.amazontrust.com/repository/AmazonRootCA1.pem');
    fs.writeFileSync(`${tempDirectory}/${certsDirectory}/${rootCaFileName}`, amazonCa.data);

    const configFileName = 'config.json';
    const configDirectory = `config`;

    if (!fs.existsSync(`${tempDirectory}/${configDirectory}`)) {
      fs.mkdirSync(`${tempDirectory}/${configDirectory}`);
    }

    const config = {
      coreThing: {
        caPath: rootCaFileName,
        certPath: certificateFileName,
        keyPath: privateKeyFileName,
        thingArn: props.ThingArn,
        iotHost: iotEndpointAddress,
        ggHost: `greengrass-ats.iot.${AWS_REGION}.amazonaws.com`,
      },
      runtime: {
        cgroup: { useSystemd: 'yes' }
      },
      managedRespawn: false,
      crypto: {
        principals: {
          SecretsManager: {
            privateKeyPath: `file:///greengrass/certs/${privateKeyFileName}`
          },
          IoTCertificate: {
            privateKeyPath: `file:///greengrass/certs/${privateKeyFileName}`,
            certificatePath: `file:///greengrass/certs/${certificateFileName}`
          }
        },
        caPath: `file:///greengrass/certs/root.ca.pem`
      }
    };
    logger.log(LogLevel.DEBUG, `Greengrass config: ${JSON.stringify(config, null, 2)}`);
    fs.writeFileSync(`${tempDirectory}/${configDirectory}/${configFileName}`, JSON.stringify(config, null, 2));

    const setupCommands = [
      '#!/bin/bash',
      '# Prereq for running this script: download the tar file from S3 that contains your certificate and keypair, upload the tarball to your Greengrass instance',
      '# Run this file with the command `sudo ./setup.sh`',
      'cp certs/* /greengrass/certs',
      'cp config/* /greengrass/config',
      'if [[ ! -d /m2c2 && ! -d /m2c2/job ]] ; then',
      '  mkdir -p /m2c2/job',
      'fi',
      'chown -R ggc_user /m2c2/job/',
      'if [[ ! -d /var/sitewise ]] ; then',
      '  mkdir /var/sitewise',
      'fi',
      'chown ggc_user /var/sitewise',
      'chmod 700 /var/sitewise',
      '/greengrass/ggc/core/greengrassd start'
    ];
    fs.writeFileSync(`${tempDirectory}/setup.sh`, setupCommands.join('\n'));
    fs.chmodSync(`${tempDirectory}/setup.sh`, '0755');

    const tarFileName = `m2c2-greengrass-${STACK_NAME}.tar.gz`;
    await tar.c(
      {
        gzip: true,
        file: `${tempDirectory}/${tarFileName}`,
        C: tempDirectory
      },
      [certsDirectory, configDirectory, 'setup.sh']
    );

    logger.log(LogLevel.DEBUG, 'Putting certificate and setup.sh to S3');
    await s3.putObject({ Bucket: props.DestinationBucket, Key: tarFileName, Body: fs.readFileSync(`${tempDirectory}/${tarFileName}`) }).promise();
    const generatedS3URL = await s3.getSignedUrlPromise('getObject', { Bucket: props.DestinationBucket, Key: tarFileName, Expires: 7200 });
    logger.log(LogLevel.DEBUG, `Generated S3 URL: ${generatedS3URL}`);

    return {
      certificateId,
      certificateArn,
      generatedS3URL
    };
  } else {
    return {};
  }
}