CDK: How to get apigateway key value (ie x-api-key: *20 Chars*)

Viewed 3368

I'm unable to find out how to get the api key out of an apigateway key. I can get its ID and its ARN but not the value. I know you can specify the value when creating the key, but not how to retrieve it once created--short of logging into the AWS GUI and finding it that way.

I've looked at the documentation for aws-apigateway.ApiKey and couldn't find any way to get the value. https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.ApiKey.html I've also looked at kms keys since you can get their value, but I don't know if it's usable in the context of an API Gateway usage plan (not included in code below).

Failing the ability to get the value, is there a way to generate a value that won't change, or will persist? I'm using an ephemeral Jenkins node to run the CDK.

    const apiGateway  = require('@aws-cdk/aws-apigateway');
...
    const apiKey = new apiGateway.ApiKey(this, 'api-key', {
      apiKeyName: 'my-api-key',
    });
...
    new cdk.CfnOutput(this, 'x-api-key-apiKey_id', {
      value: apiKey.keyId
      });
    new cdk.CfnOutput(this, 'x-api-key-apiKey_keyArn', {
      value: apiKey.keyArn
      });
3 Answers

We can't retrieve the auto generated key via cdk/cloudformation without a custom resource. But we can generate the key , store it in a secret manager or an ssm secret and use that to create api key.

const secret = new secretsmanager.Secret(this, 'Secret', {
    generateSecretString: {
        generateStringKey: 'api_key',
        secretStringTemplate: JSON.stringify({ username: 'web_user' }),
        excludeCharacters: ' %+~`#$&*()|[]{}:;<>?!\'/@"\\',
    },
});
this.restApi.addApiKey('ApiKey', {
    apiKeyName: `web-app-key`,
    value: secret.secretValueFromJson('api_key').toString(),
});

The accepted answer is perhaps not the best way to go about this. It can be solved without creating an extra secret using aws-cdk's custom resources.

Here is a snippet that will get you the value of an api key. The value of this key is generated randomly by the api gateway.

import * as iam from "@aws-cdk/aws-iam";
import { RetentionDays } from "@aws-cdk/aws-logs";
import * as cdk from "@aws-cdk/core";
import {
  AwsCustomResource,
  AwsCustomResourcePolicy,
  AwsSdkCall,
  PhysicalResourceId,
} from "@aws-cdk/custom-resources";
import { IApiKey } from "@aws-cdk/aws-apigateway";

export interface GetApiKeyCrProps {
  apiKey: IApiKey;
}

export class GetApiKeyCr extends cdk.Construct {
  apikeyValue: string;

  constructor(scope: cdk.Construct, id: string, props: GetApiKeyCrProps) {
    super(scope, id);

    const apiKey: AwsSdkCall = {
      service: "APIGateway",
      action: "getApiKey",
      parameters: {
        apiKey: props.apiKey.keyId,
        includeValue: true,
      },
      physicalResourceId: PhysicalResourceId.of(`APIKey:${props.apiKey.keyId}`),
    };

    const apiKeyCr = new AwsCustomResource(this, "api-key-cr", {
      policy: AwsCustomResourcePolicy.fromStatements([
        new iam.PolicyStatement({
          effect: iam.Effect.ALLOW,
          resources: [props.apiKey.keyArn],
          actions: ["apigateway:GET"],
        }),
      ]),
      logRetention: RetentionDays.ONE_DAY,
      onCreate: apiKey,
      onUpdate: apiKey,
    });

    apiKeyCr.node.addDependency(props.apiKey);
    this.apikeyValue = apiKeyCr.getResponseField("value");
  }
}
Related