@byaga/cdk-patterns 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.fleet/run.json +11 -0
- package/lib/ApiCertificate.d.ts +2 -2
- package/lib/ApiCertificate.js +4 -5
- package/lib/CognitoApiGatewayAuthorizer.d.ts +19 -0
- package/lib/CognitoApiGatewayAuthorizer.js +24 -0
- package/lib/DeployStack.d.ts +20 -0
- package/lib/DeployStack.js +48 -0
- package/lib/DynamoDbTable.d.ts +12 -0
- package/lib/DynamoDbTable.js +34 -0
- package/lib/FunctionIntegration.d.ts +21 -0
- package/lib/FunctionIntegration.js +61 -0
- package/lib/ICorsConfig.d.ts +5 -0
- package/lib/ICorsConfig.js +2 -0
- package/lib/NodeJsLambda.d.ts +13 -0
- package/lib/NodeJsLambda.js +28 -0
- package/lib/Output.d.ts +5 -0
- package/lib/Output.js +13 -0
- package/lib/RestApi.d.ts +28 -0
- package/lib/RestApi.js +142 -0
- package/lib/Role.d.ts +2 -2
- package/lib/Role.js +2 -5
- package/lib/SsmParameter.d.ts +18 -0
- package/lib/SsmParameter.js +40 -0
- package/lib/StaticWebSite.d.ts +12 -0
- package/lib/StaticWebSite.js +107 -0
- package/lib/index.d.ts +7 -1
- package/lib/index.js +15 -3
- package/lib/methods/apply-honeycomb-to-lambda.d.ts +3 -0
- package/lib/methods/apply-honeycomb-to-lambda.js +22 -0
- package/lib/methods/build-node-source.d.ts +13 -0
- package/lib/methods/build-node-source.js +105 -0
- package/lib/methods/duration.d.ts +8 -0
- package/lib/methods/duration.js +22 -0
- package/lib/methods/empty-directory.d.ts +2 -0
- package/lib/methods/empty-directory.js +47 -0
- package/lib/methods/generate-hash.d.ts +15 -0
- package/lib/methods/generate-hash.js +59 -0
- package/lib/methods/get-source-directory.d.ts +4 -0
- package/lib/methods/get-source-directory.js +37 -0
- package/lib/methods/walk-directory.d.ts +14 -0
- package/lib/methods/walk-directory.js +48 -0
- package/package.json +4 -2
- package/src/ApiCertificate.ts +6 -6
- package/src/CognitoApiGatewayAuthorizer.ts +25 -0
- package/src/{IDeployStack.ts → DeployStack.ts} +4 -4
- package/src/DynamoDbTable.ts +40 -0
- package/src/FunctionIntegration.ts +83 -0
- package/src/ICorsConfig.ts +5 -0
- package/src/NodeJsLambda.ts +31 -0
- package/src/Output.ts +11 -0
- package/src/RestApi.ts +178 -0
- package/src/Role.ts +5 -7
- package/src/SsmParameter.ts +47 -0
- package/src/StaticWebSite.ts +99 -0
- package/src/index.ts +7 -1
- package/src/methods/apply-honeycomb-to-lambda.ts +22 -0
- package/src/methods/build-node-source.ts +97 -0
- package/src/methods/duration.ts +24 -0
- package/src/methods/empty-directory.ts +19 -0
- package/src/methods/generate-hash.ts +49 -0
- package/src/methods/get-source-directory.ts +11 -0
- package/src/methods/walk-directory.ts +30 -0
package/.fleet/run.json
ADDED
package/lib/ApiCertificate.d.ts
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
import { Certificate } from "aws-cdk-lib/aws-certificatemanager";
|
2
2
|
import { IHostedZone } from "aws-cdk-lib/aws-route53";
|
3
|
-
import
|
3
|
+
import DeployStack from "./DeployStack";
|
4
4
|
import IDomainConfig from "./IDomainConfig";
|
5
5
|
export declare class ApiCertificate extends Certificate {
|
6
6
|
hostedZone: IHostedZone;
|
7
7
|
domain: string;
|
8
|
-
constructor(stack:
|
8
|
+
constructor(stack: DeployStack, id: string, domain: IDomainConfig);
|
9
9
|
}
|
10
10
|
export default ApiCertificate;
|
package/lib/ApiCertificate.js
CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ApiCertificate = void 0;
|
4
4
|
const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
|
5
5
|
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
|
6
|
-
const
|
6
|
+
const Output_1 = require("./Output");
|
7
7
|
class ApiCertificate extends aws_certificatemanager_1.Certificate {
|
8
8
|
hostedZone;
|
9
9
|
domain;
|
@@ -12,19 +12,18 @@ class ApiCertificate extends aws_certificatemanager_1.Certificate {
|
|
12
12
|
if (domain.subdomain)
|
13
13
|
certDomain.splice(0, 0, domain.subdomain);
|
14
14
|
const domainName = certDomain.join('.');
|
15
|
+
console.log('Getting Hosted Zone', domain.hostedZone.name);
|
15
16
|
const hostedZone = aws_route53_1.HostedZone.fromHostedZoneAttributes(stack, stack.genId(id, 'hosted-zone'), {
|
16
17
|
hostedZoneId: domain.hostedZone.id,
|
17
18
|
zoneName: domain.hostedZone.name
|
18
19
|
});
|
20
|
+
console.log('Defining Certificate For', domainName);
|
19
21
|
super(stack, stack.genId(id), {
|
20
22
|
domainName,
|
21
23
|
validation: aws_certificatemanager_1.CertificateValidation.fromDns(hostedZone)
|
22
24
|
});
|
23
25
|
this.domain = domainName;
|
24
|
-
new
|
25
|
-
value: this.certificateArn,
|
26
|
-
exportName: stack.genName(id)
|
27
|
-
});
|
26
|
+
new Output_1.Output(stack, id, this.certificateArn);
|
28
27
|
this.hostedZone = hostedZone;
|
29
28
|
}
|
30
29
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { Construct } from 'constructs';
|
2
|
+
import { CfnAuthorizer, IAuthorizer } from 'aws-cdk-lib/aws-apigateway';
|
3
|
+
import { CfnAuthorizerProps } from 'aws-cdk-lib/aws-apigateway/lib/apigateway.generated';
|
4
|
+
/**
|
5
|
+
* Custom construct that implements a Cognito based API Gateway Authorizer.
|
6
|
+
*
|
7
|
+
* @see https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_author
|
8
|
+
*
|
9
|
+
* @see https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.CfnAuthorizer.html
|
10
|
+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-authorizer.html
|
11
|
+
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html
|
12
|
+
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html
|
13
|
+
*
|
14
|
+
* @see https://github.com/aws/aws-cdk/issues/5618#issuecomment-666922559
|
15
|
+
*/
|
16
|
+
export declare class CognitoApiGatewayAuthorizer extends CfnAuthorizer implements IAuthorizer {
|
17
|
+
readonly authorizerId: string;
|
18
|
+
constructor(scope: Construct, id: string, props: CfnAuthorizerProps);
|
19
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.CognitoApiGatewayAuthorizer = void 0;
|
4
|
+
const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
|
5
|
+
/**
|
6
|
+
* Custom construct that implements a Cognito based API Gateway Authorizer.
|
7
|
+
*
|
8
|
+
* @see https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_author
|
9
|
+
*
|
10
|
+
* @see https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.CfnAuthorizer.html
|
11
|
+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-authorizer.html
|
12
|
+
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html
|
13
|
+
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html
|
14
|
+
*
|
15
|
+
* @see https://github.com/aws/aws-cdk/issues/5618#issuecomment-666922559
|
16
|
+
*/
|
17
|
+
class CognitoApiGatewayAuthorizer extends aws_apigateway_1.CfnAuthorizer {
|
18
|
+
authorizerId;
|
19
|
+
constructor(scope, id, props) {
|
20
|
+
super(scope, id, props);
|
21
|
+
this.authorizerId = this.ref;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
exports.CognitoApiGatewayAuthorizer = CognitoApiGatewayAuthorizer;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Stack } from 'aws-cdk-lib';
|
2
|
+
import IStackArguments from './IStackArguments';
|
3
|
+
import { IConstruct } from "constructs";
|
4
|
+
export declare class DeployStack extends Stack {
|
5
|
+
registry: {
|
6
|
+
[t: string]: {
|
7
|
+
[n: string]: any;
|
8
|
+
};
|
9
|
+
};
|
10
|
+
stage: string;
|
11
|
+
name: string;
|
12
|
+
genName(...name: string[]): string;
|
13
|
+
genId(...name: string[]): string;
|
14
|
+
static genStackResourceName(stackName: string, resource: string, stage?: string): string;
|
15
|
+
static genStackResourceId(stackName: string, resource: string, stage?: string): string;
|
16
|
+
constructor(scope: IConstruct, props: IStackArguments);
|
17
|
+
get(type: string, name: string): any;
|
18
|
+
set(type: string, name: string, instance: any): any;
|
19
|
+
}
|
20
|
+
export default DeployStack;
|
@@ -0,0 +1,48 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.DeployStack = void 0;
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
5
|
+
class DeployStack extends aws_cdk_lib_1.Stack {
|
6
|
+
registry = {};
|
7
|
+
stage;
|
8
|
+
name;
|
9
|
+
genName(...name) {
|
10
|
+
return DeployStack.genStackResourceName(this.name, this.stage, name.filter(n => !!n).join('-'));
|
11
|
+
}
|
12
|
+
genId(...name) {
|
13
|
+
return DeployStack.genStackResourceId(this.name, this.stage, name.filter(n => !!n).join('-'));
|
14
|
+
}
|
15
|
+
static genStackResourceName(stackName, resource, stage = 'develop') {
|
16
|
+
let name = stackName[0].toLowerCase() + stackName.substr(1);
|
17
|
+
name = name.replace(/[A-Z]/g, v => '-' + v.toLowerCase());
|
18
|
+
return `${name}-${resource}-${stage}`.toLowerCase();
|
19
|
+
}
|
20
|
+
static genStackResourceId(stackName, resource, stage = 'develop') {
|
21
|
+
const constructName = `${stackName}-${resource}-${stage}`;
|
22
|
+
return constructName[0].toUpperCase() + constructName.substr(1).replace(/-./g, v => (v[1] || '').toUpperCase());
|
23
|
+
}
|
24
|
+
constructor(scope, props) {
|
25
|
+
const options = (props || {});
|
26
|
+
const { stage = 'develop' } = options;
|
27
|
+
super(scope, props.stackName + '-' + stage, {
|
28
|
+
...props,
|
29
|
+
stackName: props.stackName + '-' + stage
|
30
|
+
});
|
31
|
+
const stack = this;
|
32
|
+
stack.name = props.stackName || '';
|
33
|
+
stack.stage = stage;
|
34
|
+
stack.tags.setTag('Stage', stage);
|
35
|
+
stack.tags.setTag('Stack', this.genName('ui-stack'));
|
36
|
+
}
|
37
|
+
get(type, name) {
|
38
|
+
const items = this.registry[type];
|
39
|
+
return (items && items[name]) || null;
|
40
|
+
}
|
41
|
+
set(type, name, instance) {
|
42
|
+
this.registry[type] = this.registry[type] || {};
|
43
|
+
this.registry[type][name] = instance;
|
44
|
+
return instance;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
exports.DeployStack = DeployStack;
|
48
|
+
exports.default = DeployStack;
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { Table } from 'aws-cdk-lib/aws-dynamodb';
|
2
|
+
import { Policy } from "aws-cdk-lib/aws-iam";
|
3
|
+
import { DeployStack } from "./DeployStack";
|
4
|
+
interface DynamoDbTableConfig {
|
5
|
+
partitionKey: string;
|
6
|
+
sortKey?: string;
|
7
|
+
}
|
8
|
+
export declare class DynamoDbTable extends Table {
|
9
|
+
getPolicy: Policy;
|
10
|
+
constructor(stack: DeployStack, id: string, props: DynamoDbTableConfig);
|
11
|
+
}
|
12
|
+
export {};
|
@@ -0,0 +1,34 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.DynamoDbTable = void 0;
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
5
|
+
const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
|
6
|
+
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
7
|
+
class DynamoDbTable extends aws_dynamodb_1.Table {
|
8
|
+
getPolicy;
|
9
|
+
constructor(stack, id, props) {
|
10
|
+
console.log('Creating DynamoDb Table', stack.genName(id, 'data-table'));
|
11
|
+
super(stack, stack.genId(id, 'data-table'), {
|
12
|
+
tableName: stack.genName(id, 'data-table'),
|
13
|
+
partitionKey: { name: props.partitionKey, type: aws_dynamodb_1.AttributeType.STRING },
|
14
|
+
sortKey: props.sortKey ? { name: props.sortKey, type: aws_dynamodb_1.AttributeType.STRING } : undefined,
|
15
|
+
billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
|
16
|
+
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY
|
17
|
+
});
|
18
|
+
stack.set('dynamo', id, this);
|
19
|
+
new aws_cdk_lib_1.CfnOutput(stack, stack.genId(id, 'table'), {
|
20
|
+
value: this.tableName,
|
21
|
+
exportName: stack.genName(id, 'table')
|
22
|
+
});
|
23
|
+
this.getPolicy = new aws_iam_1.Policy(stack, stack.genId(id, 'get-policy'), {
|
24
|
+
statements: [
|
25
|
+
new aws_iam_1.PolicyStatement({
|
26
|
+
actions: ['dynamodb:GetItem'],
|
27
|
+
effect: aws_iam_1.Effect.ALLOW,
|
28
|
+
resources: [this.tableArn]
|
29
|
+
})
|
30
|
+
]
|
31
|
+
});
|
32
|
+
}
|
33
|
+
}
|
34
|
+
exports.DynamoDbTable = DynamoDbTable;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { DeployStack } from "./DeployStack";
|
2
|
+
import { Function, FunctionProps } from "aws-cdk-lib/aws-lambda";
|
3
|
+
import { JsonSchema, MethodOptions } from "aws-cdk-lib/aws-apigateway";
|
4
|
+
import { Duration } from "aws-cdk-lib";
|
5
|
+
import { RestApi } from "./RestApi";
|
6
|
+
interface AddToApiOptions {
|
7
|
+
requestSchema?: JsonSchema;
|
8
|
+
methodOptions?: MethodOptions;
|
9
|
+
}
|
10
|
+
export interface FunctionIntegrationProps {
|
11
|
+
funcProps: FunctionProps;
|
12
|
+
timeout?: Duration;
|
13
|
+
memory?: number;
|
14
|
+
}
|
15
|
+
export declare class FunctionIntegration extends Function {
|
16
|
+
stack: DeployStack;
|
17
|
+
name: string;
|
18
|
+
constructor(stack: DeployStack, id: string, options: FunctionIntegrationProps);
|
19
|
+
attach(api: RestApi, httpMethod: string, path: string, props: AddToApiOptions): void;
|
20
|
+
}
|
21
|
+
export {};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.FunctionIntegration = void 0;
|
4
|
+
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
5
|
+
const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
|
6
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
7
|
+
const apply_honeycomb_to_lambda_1 = require("./methods/apply-honeycomb-to-lambda");
|
8
|
+
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
|
9
|
+
class FunctionIntegration extends aws_lambda_1.Function {
|
10
|
+
stack;
|
11
|
+
name;
|
12
|
+
constructor(stack, id, options) {
|
13
|
+
const props = (0, apply_honeycomb_to_lambda_1.applyHoneycombToLambda)(stack, {
|
14
|
+
functionName: stack.genName(id),
|
15
|
+
memorySize: options.memory || 256,
|
16
|
+
timeout: options.timeout || aws_cdk_lib_1.Duration.seconds(16),
|
17
|
+
logRetention: aws_logs_1.RetentionDays.ONE_WEEK,
|
18
|
+
...options.funcProps
|
19
|
+
});
|
20
|
+
super(stack, stack.genId(id, 'lambda'), props);
|
21
|
+
this.stack = stack;
|
22
|
+
this.name = id;
|
23
|
+
stack.set('lambda', id, this);
|
24
|
+
new aws_cdk_lib_1.CfnOutput(stack, stack.genId(id, 'function-name'), {
|
25
|
+
value: this.functionName,
|
26
|
+
exportName: stack.genName(id, 'function-name')
|
27
|
+
});
|
28
|
+
}
|
29
|
+
attach(api, httpMethod, path, props) {
|
30
|
+
const resource = api.path(path);
|
31
|
+
const integration = new aws_apigateway_1.LambdaIntegration(this, {
|
32
|
+
requestTemplates: {
|
33
|
+
'application/json': '{ "statusCode": "200" }'
|
34
|
+
}
|
35
|
+
});
|
36
|
+
let options = props?.methodOptions || {};
|
37
|
+
const schema = props?.requestSchema;
|
38
|
+
if (schema)
|
39
|
+
options = applySchema(this.stack, this.name, schema, options, resource);
|
40
|
+
const method = resource.addMethod(httpMethod, integration, options);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
exports.FunctionIntegration = FunctionIntegration;
|
44
|
+
function applySchema(stack, name, schema, options, path) {
|
45
|
+
return {
|
46
|
+
...options,
|
47
|
+
requestValidator: new aws_apigateway_1.RequestValidator(stack, stack.genId(name, 'validator'), {
|
48
|
+
restApi: path.api,
|
49
|
+
requestValidatorName: stack.genName(name, 'validator'),
|
50
|
+
validateRequestBody: true
|
51
|
+
}),
|
52
|
+
requestModels: {
|
53
|
+
'application/json': new aws_apigateway_1.Model(stack, stack.genId(name, 'model'), {
|
54
|
+
schema: schema,
|
55
|
+
contentType: 'application/json',
|
56
|
+
restApi: path.api,
|
57
|
+
modelName: stack.genId(name, 'model')
|
58
|
+
})
|
59
|
+
}
|
60
|
+
};
|
61
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { FunctionOptions } from "aws-cdk-lib/aws-lambda";
|
2
|
+
import { DeployStack } from "./DeployStack";
|
3
|
+
import { FunctionIntegration } from "./FunctionIntegration";
|
4
|
+
import { Duration } from "aws-cdk-lib";
|
5
|
+
interface NodeFunctionProps {
|
6
|
+
funcProps?: FunctionOptions;
|
7
|
+
timeout?: Duration;
|
8
|
+
memory?: number;
|
9
|
+
}
|
10
|
+
export declare class NodeJsLambda extends FunctionIntegration {
|
11
|
+
constructor(stack: DeployStack, id: string, options?: NodeFunctionProps);
|
12
|
+
}
|
13
|
+
export {};
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.NodeJsLambda = void 0;
|
7
|
+
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
8
|
+
const FunctionIntegration_1 = require("./FunctionIntegration");
|
9
|
+
const build_node_source_1 = require("./methods/build-node-source");
|
10
|
+
const duration_1 = __importDefault(require("./methods/duration"));
|
11
|
+
class NodeJsLambda extends FunctionIntegration_1.FunctionIntegration {
|
12
|
+
constructor(stack, id, options) {
|
13
|
+
console.log('Defining Node Lambda', id);
|
14
|
+
const done = (0, duration_1.default)();
|
15
|
+
const { buildDir } = (0, build_node_source_1.buildNodeSource)('lambda', id);
|
16
|
+
console.log('Total Build Duration (ms)', done());
|
17
|
+
super(stack, id, {
|
18
|
+
...options,
|
19
|
+
funcProps: {
|
20
|
+
...options?.funcProps,
|
21
|
+
code: aws_lambda_1.Code.fromAsset(buildDir),
|
22
|
+
handler: `${id}.handler`,
|
23
|
+
runtime: aws_lambda_1.Runtime.NODEJS_18_X
|
24
|
+
}
|
25
|
+
});
|
26
|
+
}
|
27
|
+
}
|
28
|
+
exports.NodeJsLambda = NodeJsLambda;
|
package/lib/Output.d.ts
ADDED
package/lib/Output.js
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.Output = void 0;
|
4
|
+
const core_1 = require("aws-cdk-lib/core");
|
5
|
+
class Output extends core_1.CfnOutput {
|
6
|
+
constructor(stack, name, value) {
|
7
|
+
super(stack, stack.genId(name, 'output'), {
|
8
|
+
value,
|
9
|
+
exportName: stack.genName(name)
|
10
|
+
});
|
11
|
+
}
|
12
|
+
}
|
13
|
+
exports.Output = Output;
|
package/lib/RestApi.d.ts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
import { RestApi as RestApiBase, IDomainName, IResource } from "aws-cdk-lib/aws-apigateway";
|
2
|
+
import { DeployStack } from "./DeployStack";
|
3
|
+
import { ICorsConfig } from "./ICorsConfig";
|
4
|
+
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
5
|
+
interface IRestApiConfig {
|
6
|
+
cors?: ICorsConfig;
|
7
|
+
allowCredentials: boolean;
|
8
|
+
}
|
9
|
+
interface IBasePathMappingConfig {
|
10
|
+
domain?: IDomainName;
|
11
|
+
domainName?: string;
|
12
|
+
hostedZoneId?: string;
|
13
|
+
}
|
14
|
+
interface IResourceNode {
|
15
|
+
children: {
|
16
|
+
[key: string]: IResourceNode;
|
17
|
+
};
|
18
|
+
node: IResource;
|
19
|
+
}
|
20
|
+
export declare class RestApi extends RestApiBase {
|
21
|
+
_id: string;
|
22
|
+
_tree: IResourceNode;
|
23
|
+
constructor(stack: DeployStack, id: string, props: IRestApiConfig);
|
24
|
+
addBasePathMapping(stack: DeployStack, config: IBasePathMappingConfig): void;
|
25
|
+
addAuthorizedRole(stack: DeployStack, roleArn: string): PolicyStatement;
|
26
|
+
path(uri: string): IResource;
|
27
|
+
}
|
28
|
+
export {};
|
package/lib/RestApi.js
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.RestApi = void 0;
|
4
|
+
const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
|
5
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
6
|
+
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
7
|
+
const DEFAULT_EXPOSE_HEADERS = ['Date'];
|
8
|
+
class RestApi extends aws_apigateway_1.RestApi {
|
9
|
+
_id;
|
10
|
+
_tree;
|
11
|
+
constructor(stack, id, props) {
|
12
|
+
const { stage } = stack;
|
13
|
+
console.log('Defining Rest API', stack.genId(id, 'api'));
|
14
|
+
const cors = props.cors || {};
|
15
|
+
const allowOrigins = Array.isArray(cors.allowOrigin) ? cors.allowOrigin : [cors.allowOrigin || '*'];
|
16
|
+
super(stack, stack.genId(id, 'api'), {
|
17
|
+
restApiName: stack.genName('api'),
|
18
|
+
deploy: true,
|
19
|
+
deployOptions: {
|
20
|
+
stageName: stage,
|
21
|
+
tracingEnabled: true
|
22
|
+
},
|
23
|
+
minCompressionSize: aws_cdk_lib_1.Size.bytes(1000),
|
24
|
+
endpointConfiguration: {
|
25
|
+
types: [aws_apigateway_1.EndpointType.EDGE]
|
26
|
+
},
|
27
|
+
defaultCorsPreflightOptions: {
|
28
|
+
allowHeaders: ['*'],
|
29
|
+
allowMethods: ['*'],
|
30
|
+
allowCredentials: props.allowCredentials,
|
31
|
+
allowOrigins,
|
32
|
+
maxAge: aws_cdk_lib_1.Duration.seconds(cors.maxAge || 86400),
|
33
|
+
exposeHeaders: cors.exposeHeaders || DEFAULT_EXPOSE_HEADERS
|
34
|
+
}
|
35
|
+
});
|
36
|
+
this._id = id;
|
37
|
+
// APIs MUST have at least one endpoint, so this will give it one
|
38
|
+
console.log('Adding health endpoint', '/health');
|
39
|
+
const health = this.root.addResource('health');
|
40
|
+
health.addMethod("GET", new aws_apigateway_1.MockIntegration({
|
41
|
+
requestTemplates: {
|
42
|
+
"application/json": "{\"statusCode\": 200}"
|
43
|
+
},
|
44
|
+
integrationResponses: [{
|
45
|
+
statusCode: '200',
|
46
|
+
contentHandling: aws_apigateway_1.ContentHandling.CONVERT_TO_TEXT,
|
47
|
+
responseTemplates: {
|
48
|
+
'application/json': `
|
49
|
+
## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
|
50
|
+
## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
|
51
|
+
#set($allParams = $input.params())
|
52
|
+
{
|
53
|
+
"body-json" : $input.json('$'),
|
54
|
+
"params" : {
|
55
|
+
#foreach($type in $allParams.keySet())
|
56
|
+
#set($params = $allParams.get($type))
|
57
|
+
"$type" : {
|
58
|
+
#foreach($paramName in $params.keySet())
|
59
|
+
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
|
60
|
+
#if($foreach.hasNext),#end
|
61
|
+
#end
|
62
|
+
}
|
63
|
+
#if($foreach.hasNext),#end
|
64
|
+
#end
|
65
|
+
},
|
66
|
+
"stage-variables" : {
|
67
|
+
#foreach($key in $stageVariables.keySet())
|
68
|
+
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
|
69
|
+
#if($foreach.hasNext),#end
|
70
|
+
#end
|
71
|
+
},
|
72
|
+
"context" : {
|
73
|
+
"account-id" : "$context.identity.accountId",
|
74
|
+
"api-id" : "$context.apiId",
|
75
|
+
"api-key" : "$context.identity.apiKey",
|
76
|
+
"authorizer-principal-id" : "$context.authorizer.principalId",
|
77
|
+
"caller" : "$context.identity.caller",
|
78
|
+
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
|
79
|
+
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
|
80
|
+
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
|
81
|
+
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
|
82
|
+
"http-method" : "$context.httpMethod",
|
83
|
+
"stage" : "$context.stage",
|
84
|
+
"source-ip" : "$context.identity.sourceIp",
|
85
|
+
"user" : "$context.identity.user",
|
86
|
+
"user-agent" : "$context.identity.userAgent",
|
87
|
+
"user-arn" : "$context.identity.userArn",
|
88
|
+
"request-id" : "$context.requestId",
|
89
|
+
"resource-id" : "$context.resourceId",
|
90
|
+
"resource-path" : "$context.resourcePath"
|
91
|
+
}
|
92
|
+
}`
|
93
|
+
}
|
94
|
+
}]
|
95
|
+
}), {
|
96
|
+
methodResponses: [{ statusCode: "200" }]
|
97
|
+
});
|
98
|
+
this._tree = { node: this.root, children: {} };
|
99
|
+
}
|
100
|
+
addBasePathMapping(stack, config) {
|
101
|
+
let domain = config.domain;
|
102
|
+
if (!domain && config.domainName && config.hostedZoneId) {
|
103
|
+
domain = aws_apigateway_1.DomainName.fromDomainNameAttributes(stack, stack.genName('domain-name'), {
|
104
|
+
domainName: config.domainName,
|
105
|
+
domainNameAliasHostedZoneId: config.hostedZoneId,
|
106
|
+
domainNameAliasTarget: this.restApiRootResourceId
|
107
|
+
});
|
108
|
+
}
|
109
|
+
if (!domain)
|
110
|
+
throw new Error('Missing Domain Configuration For Base Path Mapping');
|
111
|
+
new aws_apigateway_1.BasePathMapping(stack, stack.genId(this._id, 'base-path-mapping'), {
|
112
|
+
domainName: domain,
|
113
|
+
stage: this.deploymentStage,
|
114
|
+
restApi: this,
|
115
|
+
basePath: this._id
|
116
|
+
});
|
117
|
+
}
|
118
|
+
addAuthorizedRole(stack, roleArn) {
|
119
|
+
const policyStatement = new aws_iam_1.PolicyStatement({
|
120
|
+
effect: aws_iam_1.Effect.ALLOW,
|
121
|
+
actions: ['execute-api:Invoke']
|
122
|
+
});
|
123
|
+
const authRole = aws_iam_1.Role.fromRoleArn(stack, stack.genId('authenticated-role'), roleArn);
|
124
|
+
authRole.attachInlinePolicy(new aws_iam_1.Policy(stack, stack.genId('api-access-policy'), {
|
125
|
+
statements: [policyStatement]
|
126
|
+
}));
|
127
|
+
return policyStatement;
|
128
|
+
}
|
129
|
+
path(uri) {
|
130
|
+
const { node } = uri.split('/').reduce((resource, path) => {
|
131
|
+
if (!resource.children[path]) {
|
132
|
+
resource.children[path] = {
|
133
|
+
children: {},
|
134
|
+
node: resource.node.addResource(path)
|
135
|
+
};
|
136
|
+
}
|
137
|
+
return resource.children[path];
|
138
|
+
}, this._tree);
|
139
|
+
return node;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
exports.RestApi = RestApi;
|
package/lib/Role.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { IPrincipal, Role as CdkRole } from "aws-cdk-lib/aws-iam";
|
2
2
|
import { Duration } from "aws-cdk-lib";
|
3
|
-
import {
|
3
|
+
import { DeployStack } from "./DeployStack";
|
4
4
|
import { IManagedPolicy } from "aws-cdk-lib/aws-iam/lib/managed-policy";
|
5
5
|
import { PolicyDocument } from "aws-cdk-lib/aws-iam/lib/policy-document";
|
6
6
|
interface IRoleProps {
|
@@ -134,6 +134,6 @@ interface IRoleProps {
|
|
134
134
|
readonly description?: string;
|
135
135
|
}
|
136
136
|
export declare class Role extends CdkRole {
|
137
|
-
constructor(stack:
|
137
|
+
constructor(stack: DeployStack, id: string, props: IRoleProps);
|
138
138
|
}
|
139
139
|
export {};
|
package/lib/Role.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.Role = void 0;
|
4
4
|
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
5
|
-
const
|
5
|
+
const Output_1 = require("./Output");
|
6
6
|
class Role extends aws_iam_1.Role {
|
7
7
|
constructor(stack, id, props) {
|
8
8
|
console.log('Defining Role', stack.genId(id));
|
@@ -21,10 +21,7 @@ class Role extends aws_iam_1.Role {
|
|
21
21
|
roleName: stack.genName(props.roleName || id),
|
22
22
|
assumedBy: props.assumedBy
|
23
23
|
});
|
24
|
-
new
|
25
|
-
value: this.roleArn,
|
26
|
-
exportName: stack.genName(id, 'arn')
|
27
|
-
});
|
24
|
+
new Output_1.Output(stack, `${id}-arn`, this.roleArn);
|
28
25
|
}
|
29
26
|
}
|
30
27
|
exports.Role = Role;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { DeployStack } from "./DeployStack";
|
2
|
+
import { IStringParameter } from "aws-cdk-lib/aws-ssm";
|
3
|
+
import { IGrantable } from "aws-cdk-lib/aws-iam";
|
4
|
+
import { IKey } from "aws-cdk-lib/aws-kms";
|
5
|
+
interface SsmParameterOptions {
|
6
|
+
decryptWithKey?: IKey;
|
7
|
+
}
|
8
|
+
export declare class SsmParameter {
|
9
|
+
parameterName: string;
|
10
|
+
parameterArn: string;
|
11
|
+
decryptWithKey?: IKey;
|
12
|
+
_stack: DeployStack;
|
13
|
+
constructor(stack: DeployStack, name: string, options?: SsmParameterOptions);
|
14
|
+
grantRead(grantee: IGrantable): void;
|
15
|
+
get stringValue(): string;
|
16
|
+
getParameter(): IStringParameter;
|
17
|
+
}
|
18
|
+
export {};
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.SsmParameter = void 0;
|
4
|
+
const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
|
5
|
+
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
6
|
+
const paramCache = {};
|
7
|
+
class SsmParameter {
|
8
|
+
parameterName;
|
9
|
+
parameterArn;
|
10
|
+
decryptWithKey;
|
11
|
+
_stack;
|
12
|
+
constructor(stack, name, options) {
|
13
|
+
if (name[0] !== '/')
|
14
|
+
name = '/' + name;
|
15
|
+
this.parameterName = `/${stack.name}${name}`;
|
16
|
+
this.parameterArn = `arn:aws:ssm:${stack.region}:${stack.account}:parameter${this.parameterName}`;
|
17
|
+
this._stack = stack;
|
18
|
+
this.decryptWithKey = options?.decryptWithKey;
|
19
|
+
}
|
20
|
+
grantRead(grantee) {
|
21
|
+
grantee.grantPrincipal.addToPrincipalPolicy(new aws_iam_1.PolicyStatement({
|
22
|
+
effect: aws_iam_1.Effect.ALLOW,
|
23
|
+
actions: ['ssm:GetParameter'],
|
24
|
+
resources: [this.parameterArn]
|
25
|
+
}));
|
26
|
+
if (this.decryptWithKey) {
|
27
|
+
this.decryptWithKey.grantDecrypt(grantee);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
get stringValue() {
|
31
|
+
return this.getParameter().stringValue;
|
32
|
+
}
|
33
|
+
getParameter() {
|
34
|
+
if (!paramCache[this.parameterArn]) {
|
35
|
+
paramCache[this.parameterArn] = aws_ssm_1.StringParameter.fromStringParameterName(this._stack, this._stack.genId(this.parameterName.substring(1).replace('/', '_')), this.parameterName);
|
36
|
+
}
|
37
|
+
return paramCache[this.parameterArn];
|
38
|
+
}
|
39
|
+
}
|
40
|
+
exports.SsmParameter = SsmParameter;
|