@makemydeal/cdk-lambda-stack
This package contains stacks for creating lambdas. These stacks take in as configuration the location of the build artifacts for the lambda, the name of the lambda, etc. The stacks give you the following options:
Stacks
Stack | Description |
---|---|
LambdaStack | Create Lambdas without hooks to RestAPI, SNS or anything else. This is the base stack for the other implementations |
RestApiLambdaStack | Create Lambdas and associate them with APIGateway for RestAPI calls. You have the option to pass in an already configured Custom Domain to associate API Gateway with |
SnsLambdaStack | Create or use an existing SNS Topic and create lambdas as subscribers to that topic. |
SqsLambdaStack | Create or use an existing SQS Queue and create lambdas as event sources for the queue. |
NOTE RestApiLambdaStack, SnsLambdaStack and SqsLambdaStack all extend LambdaStack.
LambdaStack Properties
A LambdaStack will add Lambdas to your environment. It will not associate them to RestAPI, SNS or anything else. This stack is the base for the other stacks, and can even serve as the base for your own stack.
When defining a LambdaStack, you provide the following properties.
| Property | Required | Type | Description
| --- | --- | ---
| applicationName | Yes | string | Name of the application and used as a prefix for all lambda names
| splunkForwarder | No | LambdaStackSplunkForwarderProps | If you wish to define a splunk forwarder, you can specify this object, see the definition of the object below
| definition | Yes | LambdaDefinition | The definition of each lambda you wish to deploy. LambdaDefinition is well documented in the interface itself which should reflect what each property is for.
| includeNewRelicExtension | No | boolean | Should the NewRelic Lambda Extension be added (default: true)
LambdaStackSplunkForwarderProps
| Property | Required | Type | Description | --- | --- | --- | option | No | LambdaStackSplunkForwarderProps | Option to use to get the ARN for the splunk forwarder (see below). By Default, USE_DEFAULT is the option selected | value | No | string | For USE_CUSTOM_ARN or USE_PARAMETER_STORE, the value you want to specify is placed here.
LambdaStackPropsSplunkForwarderOptions
Property | Description |
---|---|
USE_DEFAULT* | Use the default SplunkForwarder defined which will forward to cai-mmd* indexes |
USE_CUSTOM_ARN | Specify a custom ARN for the splunk forwarder |
USE_PARAMETER_STORE | Specify the key for the parameter store that contains the ARN for the forwarder |
NONE | Do not attach a splunk forwarder |
LambdaVersionDefinition
Property | Description |
---|---|
description | Optional Description of the version. Useful for the package.json version |
removalPolicy | What should we do with the version once CloudFormation no longer manages it? Default is to retain. |
LambdaAliasDefinition
Property | Description |
---|---|
description | Optional Description of the alias |
aliasName | Name of the alias. Default is "live" |
removalPolicy | What should we do with the alias once CloudFormation no longer manages it? Default is to retain. |
provisionedConcurrency | Optional definition for provisioned concurrency |
LambdaProvisionedConcurrency
Property | Description |
---|---|
executions | number of instances to have warm |
minCapacity | minimum capacity when auto scaling (optional) |
maxCapacity | maximum capacity when auto scaling (required) |
utilizationTarget | When to scale (0.5 means 50%) |
RestApiLambdaStack Properties
RestApiLambdaStack extends LambdaStack to allow for creation of an API Gateway and adding the Lambdas as endpoints. It also allows creation of lambdas for Custom Authorizers as well. Below are the properties to pass when constructing the class. These properties are an extension of the properties defined for the LambdaStack above. This section will define the additional properties.
Property | Required | Type | Description |
---|---|---|---|
enableCrossOrigin | Yes | boolean | Should Cross Origin support be enabled. Currently this supports only * support, and does not allow for specifying a domain. Default is false
|
definition | Yes | RestApiLambdaDefinition | Definition of each lambda for the account. This interface is well documented in code and will define eveything you need and can do when using the interface via intellisense. The RestApiEndpoint interface will be defined below for more detail about setting up the endpoint |
basePath | No | string | If you are using a custom domain, you can set up a basePath which serves as a virtual folder for your API. You can use this to define the business domain that this API is serving |
stage | No | string | The name of the stage you wish to set up with this API. Default is api
|
domainName | No | string | For REGIONAL and EDGE endpoints, this is the name of the custom domain you wish to set up. This can be retrieved from SSM, imported from a stack variable on another stack or simply hard coded. |
endpointType | No | EndpointType | The endpoint type as defined by AWS. Default is REGIONAL . You can look uop their meaning in AWS docs on EndpointType
|
createSecondaryPrivateApiGateway | No | boolean | When set, it will create a second API gateway which will be a Private API gateway using the same lambdas and same endpoint definitions. |
privateEndpoint | No | RestApiLambdaStackPrivateEndpointProps | If you wish to set this up as a private endpoint, and specify endpointType = PRIVATE then these are settings you also need to provide to set it up. |
models | No | RestApiModelOptions | Models used to validate the request coming in |
customAuthorizers | No | RestApiCustomAuthorizers[] | Set of Custom Authorizers that you would like to define in this API Gateway to be used on your endpoints. |
existingDefinition | No | RestApiLambdaExistingDefinition[] | Set of existing lambdas you would like to add endpoints for. This means the lambda is not created in this stack, but an endpoint on api gateway is created |
mockDefinition | No | RestApiMockDefinition[] | Set of API Gateway Mock Endpoints you wish to create. These will respond with JSON, for example, on a certain endpoint but not be a proxy to Lambda. |
httpProxyDefinition | No | RestApiHttpProxyDefinition[] | Set of HTTP Proxies to add to API Gateway |
MockDefinitions
MockDefinitions allow you to have API Gateway return a response to an endpoint that is static. You can supply the JSON of your choice if you wish. This can be useful for any mocking you wish to do, and the template can consiste of some variables from API Gateway. Please refer to this document about that information: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html#mapping-response-parameters
HttpProxyDefinitions
HttpProxyDefinitions allow you to proxy requests right to other HTTP resources, bypassing the need for a lambda to call those endpoints. If your intention is to just pass requests through, this could be a cost saving alternative.
Application Version
One common use-case would be to return the version of the application. Since this is a pretty standard item, we've added a helper function to create this mock integration.
mockDefinitionCreateVersion
will take in 3 parameters:
| Parameter | Default | Description
| --- | ---
| appVersion | | The version of the application being deployed.
| httpMethod | 'GET' | The Http Method / Verb to use for this mock
| path | /echo | The route to use for this mock
RestApiLambdaStackPrivateEndpointProps
Property | Required | Type | Description |
---|---|---|---|
vpcEndpointId | No | string | The VPC EndpointId you wish to use. This MUST BE concrete if it is specified. This means it cannot be read from SSM directly. Our tooling has the ability to read from SSM for each CodeBuild and passes it back to the app synthizer so you can pass a concrete value back |
privateDnsEnabled | No | boolean | Setup Private DNS for this VPCE. There can only be one endpoint with this turned on per VPC |
port | No | number | Default is 443
|
region | No | string | Region name, the default is the current region we are running under |
RestApiModelOptions
This extends the AWS CDK ModelOptions
by requiring the modelName be entered. We use the modelName later when assigning the model to the given endpoint.
RestApiCustomAuthorizers
Property | Required | Type | Description |
---|---|---|---|
sourceType | Yes | string |
EXISTING_ARN to pass in an ARN or LAMBDA_DEFINITION to reference a lambda (by the name assigned in the definition array) as the authorizer |
sourceValue | Yes | string | The ARN or Lambda Name based on your selection in sourceType
|
type | No | string | The type of authorizer TOKEN or REQUEST . The default is TOKEN
|
settings | No | RestApiCustomAuthorizersToken or RestApiCustomAuthorizersRequest | The properties needed for the given type of authorizer selected |
name | Yes | string | The name of the authorizer. This will be used when adding it to the API Gateway and will also be used when referencing it in the endpoint definition. |
cacheTtl | No | Duration | How long to cache the result. Default is Duration.minutes(5)
|
RestApiCustomAuthorizersToken
Property | Required | Type | Description |
---|---|---|---|
identitySource | No | string | The identity source (where is the token). By Default, IdentitySource.headers('Authorization')
|
validationRegex | No | string | RegEx to validate the token |
RestApiCustomAuthorizersRequest
Property | Required | Type | Description |
---|---|---|---|
identitySources | Yes | string[] | 1 or more IdentitySources to specify the keys to cache by when caching the result |
LambdaCreateAliasStack
A LambdaCreateAliasStack will add a new alias to an existing lambda function. It will find an existing alias and point the new alias to that function version. This can be useful for blue/green deployment so you can move a "live" alias to a "Dark" existing alias.
When defining a LambdaCreateAliasStack, you provide the following properties.
| Property | Required | Type | Description
| --- | --- | ---
| applicationName | Yes | string | Name of the application and used as a prefix for all lambda names
| alias | Yes | LambdaAliasDefinition | This will define the alias you wish to create
| aliasToFind | Yes | LambdaCreateAliasAliasToFindProps | The alias to find and the method on how to find it
| definition | Yes | LambdaDefinition | The definition of all the lambdas you wish to add a new alias to. This leverages the same interface used to create the alias to make it easier.
Managers
Managers are used to have a consolidated object that will control the CICD and Build process. This allows the same object to be passed to the CICD and APP setups. They allow for custom actions to be run during the IAC Setup, the Environment Setup, and when creating the stack. These managers will be passed to the CICD process.
Each stack above has a corresponding manager:
- LambdaStackManager
- RestApiLambdaStackManager
- SnsLambdaStackManager
- SqsLambdaStackManager
- LambdaCreateAliasStackManager
Usage
import { ParameterType, StringParameter } from '@aws-cdk/aws-ssm';
import { Construct } from '@aws-cdk/core';
import {
RestApiCreateStackProps,
RestApiLambdaStack,
RestApiLambdaStackManager,
RestApiLambdaStackManagerProps
} from '@makemydeal/cdk-lambda-stack';
import { isPrivateApi } from './utils';
export class DealerRestApiLambdaManager extends RestApiLambdaStackManager {
public CreateStack(scope: Construct, props: RestApiCreateStackProps): RestApiLambdaStack {
const stack = super.CreateStack(scope, props) as RestApiLambdaStack;
const { environmentName } = props;
// add storage of the restApi and stage to parameter store
new StringParameter(stack, `${stack.instanceName}-parameter-restapiid`, {
parameterName: `/dr/${environmentName}/services/dealer/lambda/restApiId`,
stringValue: stack.ApiGateway.restApiId,
type: ParameterType.STRING
});
return stack;
}
}
NewRelic Lambda Extension Support
By Default, each lambda will be instrumented with NewRelic's Lambda Extension. This will send more detailed information to NewRelic about the lambda. If you do not wish to do this, in each lambda definition, there is a includeNewRelicExtension
setting. Setting this to false
will not install the layer for the particular lambda.
NewRelic Prerequisites
In order for the NewRelic extension to work, there are a few prerequisites. These are outlined below:
- A Role with Trust Relationship setup to account
754728514883
. This is NewRelic's account. This Role should be setup by CBO in our account and have the following:ReadOnlyAccess
AWS Managed Policy and
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"budgets:ViewBudget"
],
"Resource": "*"
}
]
}
In our L1 accounts, this role is called SvcNewRelicInfrastructure-Integrations
- A SecretsManager Token with
NEW_RELIC_LICENSE_KEY
setup. It will have aLicenseKey
value setup to our key on NewRelic. NewRelic's Lambda CLInewrelic-lambda
will assist in setting this up, but because of ALKS, we cannot use the CLI out of the box. This repo https://ghe.coxautoinc.com/DigitalRetailing/newrelic-lambda-cli has been setup as a fork of NewRelic's repo. It has adjustments to https://ghe.coxautoinc.com/DigitalRetailing/newrelic-lambda-cli/blob/master/newrelic_lambda_cli/templates/license-key-secret.yaml and https://ghe.coxautoinc.com/DigitalRetailing/newrelic-lambda-cli/blob/master/newrelic_lambda_cli/integrations.py that will use the role setup in the bullet above and give the right permissions for theNEW_RELIC_LICENSE_KEY
secret to be created.
Here is the command once you've installed the newrelic-lambda and placed our files on top of theirs to apply to the account. This has been done for awsdrst
and awsdrstnp
newrelic-lambda integrations install --nr-account-id 1840109 --linked-account-name awsdrstnp --nr-api-key <nr userapikey> --enable-license-key-secret --role-name acct-managed/cai-dr-lambda-execution-role
-
newrelic-log-ingestion
will also be created by the process above. -
cai-dr-lambda-execution-role
(lambda execution role) needs the following policy so it can read secrets:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": [
"arn:aws:secretsmanager:us-east-1:<accountId>:secret:*"
]
}
]
}
- SSM Parameter Store needs to be setup with
/dr/global/services/newrelic/*
as defined in the "Parameter Store Dependencies" section below. This has been done forawsdrst
andawsdrstnp
Parameter Store Dependencies
Key | Construct | Description |
---|---|---|
/dr/global/services/splunk-forwarder/dr | LambdaStack | DR Lambda used to forward logs to splunk |
/dr/global/services/newrelic/environmentVariables/NEW_RELIC_ACCOUNT_ID' | LambdaStack | NewRelic Account ID |
/dr/global/services/newrelic/environmentVariables/NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS | LambdaStack | NewRelic flag for sending function logs |
/dr/global/services/newrelic/environmentVariables/NEW_RELIC_LAMBDA_EXTENSION_ENABLED | NewRelic flag to enable the extension | |
/dr/global/services/newrelic/extensions/{runtime} | LambdaStack | NewRelic Lambda Extension Layer ARN. {runtime} is the name of the runtime, for instance, nodejs14.x . We have setup Node 10, 12 and 14. |
/dr/global/services/newrelic/handler | LambdaStack | NewRelic Extension Handler. NR uses this as the handler function which proxies to our actual handler. |
/dr/global/services/pipeline-tools/create-or-update-alias/lambda-arn | LambdaMoveAliasToVersionManager | Find the lambda to use to move an alias |