Skip to content

Step by Step Setup (CDK)

Chris/0 edited this page Sep 8, 2023 · 14 revisions

Module

AWS provides the nouns of SAM (AWS::Serverless::Function, AWS::Serverless::Application, &c.) as CDK Constructs in the module aws-sam.

Construct

The construct through which to deploy the Platform Client Secret Rotator is CfnApplication, which corresponds to the SAM resource AWS::Serverless::Application. This, in turn, corresponds to the raw CloudFormation resource AWS::CloudFormation::Stack. The multi-language nature of the CDK means that any of various languages could be used, but here is an example of using that construct in TypeScript:

import * as cdk from '@aws-cdk/core';
import * as kms from '@aws-sdk/kms';
import * as sam from '@aws-cdk/aws-sam';

export class AppStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        const applicationKey = new kms.Key(this, 'appKey', {
          enableKeyRotation: true
        });
        const rotator = new sam.CfnApplication(this, 'appRotator', {
          location: {
            applicationId: 'arn:aws:serverlessrepo:us-east-1:820870426321:applications/platform-client-secret-rotator',
            semanticVersion: '2.1.1'
          },
          parameters: {
            Endpoint: `https://secretsmanager.${this.region}.${this.urlSuffix}`,
            FunctionName: `${this.stackName}-client-credentials-secret-rotator`,
            KmsKeyArn: applicationKey.keyArn
          }
        });
    }
}

The keys and values under the location key are required for all resources of type CfnApplication. The applicationId is the identifier, and should not change. The semanticVersion can change, and you should make sure that you are using the most up-to-date version.

The applicationId is specifically an opaque identifier. Even though there are a region ID and an account ID in there, they really do only identify the application. The resources which are produced run in your deployed account, in your deployed region, with your deployed permissions. If you would like to fork Cimpress-MCP/Platform-Client-Secret-Rotator, you are of course welcome to. But there's no reason to if you are only consuming it.

The keys and values under the parameters property are specific to the Platform Client Secret Rotator. The value specified for Endpoint in this example is almost always the endpoint you want to use. However, if your account has external network access particularly restricted, and you have created a service link route to AWS Secrets Manager, supply the address of that route here instead. If that doesn't mean anything to you, use the provided value. The value specified for FunctionName must be unique in an account–region combination. Using the stack name helps to enforce that. The value for KmsKeyArn is only required if the secret is encrypted with a CMK. (This is recommended.)

The parameter OverlapDuration controls how long after rotation a previous client remains valid. This defaults to P1D, which is "one day" in ISO-8601 Duration syntax. "One hour" is spelled PT1H, and so on.

Given this setup, the output of the ARN of the created rotation function is available:

rotator.getAtt('Outputs.RotationLambdaARN').toString()

…which can be used to connect the Function to a Secret and a Rotation Schedule. The official CDK documentation explains that far better than a GitHub wiki page ever could, so please consult the linked resources for more guidance.

Bootstrapping

There is an unavoidable bootstrapping step when deploying the Platform Client Secret Rotator into a service for the first time. The deployment process has no way of knowing what a client's current secret is (nor should it!), so the first rotation which occurs after deployment will necessarily fail. To take ownership of the rotation of a client secret, transfer the client secret value into AWS Secrets Manager (into the deployed secret, specifically) and instruct AWS Secrets Manager to rotate the secret immediately. It's hands-off operation from then on out.

Clone this wiki locally