@digitraffic/common 2023.1.18-2 → 2023.1.23-2
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/dist/aws/infra/api/integration.d.ts +2 -1
- package/dist/aws/infra/api/integration.js +3 -2
- package/dist/aws/infra/api/response.d.ts +2 -1
- package/dist/aws/infra/api/response.js +13 -7
- package/dist/aws/infra/canaries/canary-alarm.js +11 -13
- package/dist/aws/infra/canaries/canary.js +2 -4
- package/dist/aws/infra/canaries/database-checker.js +4 -1
- package/dist/aws/infra/canaries/url-canary.js +1 -0
- package/dist/aws/infra/canaries/url-checker.d.ts +2 -2
- package/dist/aws/infra/canaries/url-checker.js +24 -5
- package/dist/aws/infra/sqs-integration.d.ts +1 -3
- package/dist/aws/infra/sqs-integration.js +28 -32
- package/dist/aws/infra/sqs-queue.d.ts +0 -2
- package/dist/aws/infra/sqs-queue.js +31 -24
- package/dist/aws/infra/stack/lambda-configs.d.ts +2 -31
- package/dist/aws/infra/stack/lambda-configs.js +5 -38
- package/dist/aws/infra/stack/monitoredfunction.js +3 -1
- package/dist/aws/infra/stacks/db-stack.js +1 -1
- package/dist/aws/infra/stacks/network-stack.d.ts +2 -1
- package/dist/aws/infra/stacks/network-stack.js +4 -2
- package/dist/aws/runtime/digitraffic-integration-response.d.ts +2 -2
- package/dist/aws/runtime/digitraffic-integration-response.js +6 -4
- package/dist/aws/runtime/secrets/dbsecret.d.ts +0 -39
- package/dist/aws/runtime/secrets/dbsecret.js +1 -71
- package/dist/aws/runtime/secrets/proxy-holder.js +5 -4
- package/dist/aws/runtime/secrets/rds-holder.js +5 -4
- package/dist/aws/runtime/secrets/secret-holder.d.ts +0 -4
- package/dist/aws/runtime/secrets/secret-holder.js +6 -12
- package/dist/aws/runtime/secrets/secret.d.ts +0 -6
- package/dist/aws/runtime/secrets/secret.js +8 -17
- package/dist/database/database.d.ts +7 -0
- package/dist/database/database.js +19 -8
- package/dist/test/db-testutils.js +4 -5
- package/package.json +1 -1
- package/src/aws/infra/api/integration.ts +8 -3
- package/src/aws/infra/api/response.ts +16 -16
- package/src/aws/infra/canaries/canary-alarm.ts +26 -24
- package/src/aws/infra/canaries/canary.ts +2 -4
- package/src/aws/infra/canaries/database-checker.ts +4 -1
- package/src/aws/infra/canaries/url-canary.ts +2 -1
- package/src/aws/infra/canaries/url-checker.ts +28 -11
- package/src/aws/infra/sqs-integration.ts +51 -47
- package/src/aws/infra/sqs-queue.ts +85 -53
- package/src/aws/infra/stack/lambda-configs.ts +6 -69
- package/src/aws/infra/stack/monitoredfunction.ts +2 -1
- package/src/aws/infra/stacks/db-stack.ts +1 -1
- package/src/aws/infra/stacks/network-stack.ts +7 -3
- package/src/aws/runtime/digitraffic-integration-response.ts +16 -9
- package/src/aws/runtime/secrets/dbsecret.ts +1 -117
- package/src/aws/runtime/secrets/proxy-holder.ts +2 -5
- package/src/aws/runtime/secrets/rds-holder.ts +2 -1
- package/src/aws/runtime/secrets/secret-holder.ts +8 -20
- package/src/aws/runtime/secrets/secret.ts +17 -22
- package/src/database/database.ts +14 -3
- package/src/test/db-testutils.ts +5 -2
- package/dist/test/secret.d.ts +0 -3
- package/dist/test/secret.js +0 -25
- package/src/test/secret.ts +0 -23
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.defaultLambdaConfiguration = exports.
|
3
|
+
exports.defaultLambdaConfiguration = exports.lambdaFunctionProps = exports.databaseFunctionProps = void 0;
|
4
4
|
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
5
5
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
6
6
|
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
|
@@ -13,9 +13,9 @@ function databaseFunctionProps(stack, environment, lambdaName, simpleLambdaName,
|
|
13
13
|
return {
|
14
14
|
...lambdaFunctionProps(stack, environment, lambdaName, simpleLambdaName, config),
|
15
15
|
...{
|
16
|
-
vpc: stack.vpc
|
16
|
+
vpc: stack.vpc ?? undefined,
|
17
17
|
vpcSubnets,
|
18
|
-
securityGroup: stack.lambdaDbSg
|
18
|
+
securityGroup: stack.lambdaDbSg ?? undefined,
|
19
19
|
},
|
20
20
|
};
|
21
21
|
}
|
@@ -42,39 +42,6 @@ function getAssetCode(simpleLambdaName, isSingleLambda) {
|
|
42
42
|
: `dist/lambda/${simpleLambdaName}`;
|
43
43
|
return new aws_lambda_1.AssetCode(lambdaPath);
|
44
44
|
}
|
45
|
-
/**
|
46
|
-
* Creates a base configuration for a Lambda that uses an RDS database
|
47
|
-
* @param vpc "Private" Lambdas are associated with a VPC
|
48
|
-
* @param lambdaDbSg Security Group shared by Lambda and RDS
|
49
|
-
* @param props Database connection properties for the Lambda
|
50
|
-
* @param config Lambda configuration
|
51
|
-
*/
|
52
|
-
function dbLambdaConfiguration(vpc, lambdaDbSg, props, config) {
|
53
|
-
return {
|
54
|
-
runtime: props.runtime ?? aws_lambda_1.Runtime.NODEJS_16_X,
|
55
|
-
memorySize: props.memorySize ?? config.memorySize ?? 1024,
|
56
|
-
functionName: config.functionName,
|
57
|
-
code: config.code,
|
58
|
-
role: config.role,
|
59
|
-
handler: config.handler,
|
60
|
-
timeout: aws_cdk_lib_1.Duration.seconds(config.timeout ?? props.defaultLambdaDurationSeconds ?? 60),
|
61
|
-
environment: config.environment ?? {
|
62
|
-
DB_USER: props.dbProps?.username ?? "",
|
63
|
-
DB_PASS: props.dbProps?.password ?? "",
|
64
|
-
DB_URI: (config.readOnly
|
65
|
-
? props.dbProps?.ro_uri
|
66
|
-
: props.dbProps?.uri) ?? "",
|
67
|
-
},
|
68
|
-
logRetention: aws_logs_1.RetentionDays.ONE_YEAR,
|
69
|
-
vpc: vpc,
|
70
|
-
vpcSubnets: {
|
71
|
-
subnets: vpc.privateSubnets,
|
72
|
-
},
|
73
|
-
securityGroups: [lambdaDbSg],
|
74
|
-
reservedConcurrentExecutions: config.reservedConcurrentExecutions ?? 3,
|
75
|
-
};
|
76
|
-
}
|
77
|
-
exports.dbLambdaConfiguration = dbLambdaConfiguration;
|
78
45
|
function defaultLambdaConfiguration(config) {
|
79
46
|
const props = {
|
80
47
|
runtime: aws_lambda_1.Runtime.NODEJS_16_X,
|
@@ -86,7 +53,7 @@ function defaultLambdaConfiguration(config) {
|
|
86
53
|
reservedConcurrentExecutions: config.reservedConcurrentExecutions,
|
87
54
|
code: config.code,
|
88
55
|
role: config.role,
|
89
|
-
timeout: aws_cdk_lib_1.Duration.seconds(config.timeout
|
56
|
+
timeout: aws_cdk_lib_1.Duration.seconds(config.timeout ?? 10),
|
90
57
|
};
|
91
58
|
if (config.vpc) {
|
92
59
|
return {
|
@@ -94,7 +61,7 @@ function defaultLambdaConfiguration(config) {
|
|
94
61
|
...{
|
95
62
|
vpc: config.vpc,
|
96
63
|
vpcSubnets: {
|
97
|
-
subnets: config.vpc
|
64
|
+
subnets: config.vpc.privateSubnets,
|
98
65
|
},
|
99
66
|
},
|
100
67
|
};
|
@@ -22,7 +22,9 @@ class MonitoredFunction extends aws_lambda_1.Function {
|
|
22
22
|
static create(stack, id, functionProps, props) {
|
23
23
|
if (props === MonitoredFunction.DISABLE_ALARMS &&
|
24
24
|
stack.configuration.production) {
|
25
|
-
throw new Error(
|
25
|
+
throw new Error(
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
27
|
+
`Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`);
|
26
28
|
}
|
27
29
|
return new MonitoredFunction(stack, id, functionProps, stack.alarmTopic, stack.warningTopic, stack.configuration.production, stack.configuration.trafficType, props);
|
28
30
|
}
|
@@ -67,7 +67,7 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
67
67
|
vpc,
|
68
68
|
securityGroups: [securityGroup],
|
69
69
|
vpcSubnets: {
|
70
|
-
subnetType: aws_ec2_1.SubnetType.
|
70
|
+
subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS,
|
71
71
|
},
|
72
72
|
instanceType: configuration.dbInstanceType,
|
73
73
|
parameterGroup,
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import { Stack } from "aws-cdk-lib";
|
2
2
|
import { Construct } from "constructs";
|
3
|
-
import { Vpc } from "aws-cdk-lib/aws-ec2";
|
3
|
+
import { IVpc, Vpc } from "aws-cdk-lib/aws-ec2";
|
4
4
|
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
5
5
|
export interface NetworkConfiguration {
|
6
6
|
readonly vpcName: string;
|
7
7
|
readonly cidr: string;
|
8
8
|
}
|
9
9
|
export declare class NetworkStack extends Stack {
|
10
|
+
readonly vpc: IVpc;
|
10
11
|
constructor(scope: Construct, id: string, isc: InfraStackConfiguration, configuration: NetworkConfiguration);
|
11
12
|
createVpc(configuration: NetworkConfiguration): Vpc;
|
12
13
|
}
|
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NetworkStack = void 0;
|
4
4
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
5
5
|
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
6
|
+
const import_util_1 = require("../import-util");
|
6
7
|
class NetworkStack extends aws_cdk_lib_1.Stack {
|
7
8
|
constructor(scope, id, isc, configuration) {
|
8
9
|
super(scope, id, {
|
9
10
|
env: isc.env,
|
10
11
|
});
|
11
|
-
this.createVpc(configuration);
|
12
|
+
this.vpc = this.createVpc(configuration);
|
13
|
+
(0, import_util_1.exportValue)(this, isc.environmentName, "VPCID", this.vpc.vpcId);
|
12
14
|
}
|
13
15
|
createVpc(configuration) {
|
14
16
|
return new aws_ec2_1.Vpc(this, "DigitrafficVPC", {
|
@@ -26,7 +28,7 @@ class NetworkStack extends aws_cdk_lib_1.Stack {
|
|
26
28
|
{
|
27
29
|
name: "private",
|
28
30
|
cidrMask: 24,
|
29
|
-
subnetType: aws_ec2_1.SubnetType.
|
31
|
+
subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS,
|
30
32
|
},
|
31
33
|
],
|
32
34
|
});
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { IntegrationResponse } from "aws-cdk-lib/aws-apigateway";
|
2
2
|
import { MediaType } from "../types/mediatypes";
|
3
3
|
export declare abstract class DigitrafficIntegrationResponse {
|
4
|
-
static ok(mediaType: MediaType): IntegrationResponse;
|
4
|
+
static ok(mediaType: MediaType, sunset?: string): IntegrationResponse;
|
5
5
|
static badRequest(mediaType?: MediaType): IntegrationResponse;
|
6
6
|
static notImplemented(mediaType?: MediaType): IntegrationResponse;
|
7
|
-
static create(statusCode: string, mediaType: MediaType): IntegrationResponse;
|
7
|
+
static create(statusCode: string, mediaType: MediaType, sunset?: string): IntegrationResponse;
|
8
8
|
}
|
@@ -4,8 +4,8 @@ exports.DigitrafficIntegrationResponse = void 0;
|
|
4
4
|
const mediatypes_1 = require("../types/mediatypes");
|
5
5
|
const response_1 = require("../infra/api/response");
|
6
6
|
class DigitrafficIntegrationResponse {
|
7
|
-
static ok(mediaType) {
|
8
|
-
return this.create("200", mediaType);
|
7
|
+
static ok(mediaType, sunset) {
|
8
|
+
return this.create("200", mediaType, sunset);
|
9
9
|
}
|
10
10
|
static badRequest(mediaType) {
|
11
11
|
return this.create("400", mediaType ?? mediatypes_1.MediaType.TEXT_PLAIN);
|
@@ -13,11 +13,13 @@ class DigitrafficIntegrationResponse {
|
|
13
13
|
static notImplemented(mediaType) {
|
14
14
|
return this.create("501", mediaType ?? mediatypes_1.MediaType.TEXT_PLAIN);
|
15
15
|
}
|
16
|
-
static create(statusCode, mediaType) {
|
16
|
+
static create(statusCode, mediaType, sunset) {
|
17
17
|
return {
|
18
18
|
statusCode,
|
19
19
|
responseTemplates: {
|
20
|
-
[mediaType]:
|
20
|
+
[mediaType]: sunset
|
21
|
+
? (0, response_1.getDeprecatedDefaultLambdaResponse)(sunset)
|
22
|
+
: response_1.RESPONSE_DEFAULT_LAMBDA,
|
21
23
|
},
|
22
24
|
};
|
23
25
|
}
|
@@ -1,10 +1,4 @@
|
|
1
1
|
import { GenericSecret } from "./secret";
|
2
|
-
export interface DbSecret {
|
3
|
-
readonly username: string;
|
4
|
-
readonly password: string;
|
5
|
-
readonly host: string;
|
6
|
-
readonly ro_host: string;
|
7
|
-
}
|
8
2
|
export declare enum RdsProxySecretKey {
|
9
3
|
username = "username",
|
10
4
|
password = "password",
|
@@ -19,37 +13,4 @@ export declare enum RdsSecretKey {
|
|
19
13
|
}
|
20
14
|
export type RdsProxySecret = Record<RdsProxySecretKey, string>;
|
21
15
|
export type RdsSecret = Record<RdsSecretKey, string>;
|
22
|
-
export declare enum DatabaseEnvironmentKeys {
|
23
|
-
DB_USER = "DB_USER",
|
24
|
-
DB_PASS = "DB_PASS",
|
25
|
-
DB_URI = "DB_URI",
|
26
|
-
DB_RO_URI = "DB_RO_URI",
|
27
|
-
DB_APPLICATION = "DB_APPLICATION"
|
28
|
-
}
|
29
|
-
/**
|
30
|
-
* You can give the following options for retrieving a secret:
|
31
|
-
*
|
32
|
-
* expectedKeys: the list of keys the secret must include. If not, an error will be thrown.
|
33
|
-
* prefix: a prefix that's included in retrieved secret's keys. Only keys begining with the prefix will be included.
|
34
|
-
* The secret that is passed to the given function will not include the prefix in it's keys.
|
35
|
-
|
36
|
-
*/
|
37
|
-
export interface SecretOptions {
|
38
|
-
readonly expectedKeys?: string[];
|
39
|
-
readonly prefix?: string;
|
40
|
-
}
|
41
|
-
export type SecretToPromiseFunction<Secret, Response = void> = (secret: Secret) => Promise<Response> | void;
|
42
|
-
export type SecretFunction<Secret, Response = void> = (secretId: string, fn: SecretToPromiseFunction<Secret, Response>, options?: SecretOptions) => Promise<Response | void>;
|
43
|
-
export type EmptySecretFunction<Response = void> = SecretFunction<DbSecret, Response>;
|
44
|
-
/**
|
45
|
-
* Run the given function with secret retrieved from Secrets Manager. Also injects database-credentials into environment.
|
46
|
-
*
|
47
|
-
* @deprecated use SecretHolder & ProxyHolder
|
48
|
-
* @see SecretOptions
|
49
|
-
*
|
50
|
-
* @param {string} secretId
|
51
|
-
* @param {function} fn
|
52
|
-
* @param {SecretOptions} options
|
53
|
-
*/
|
54
|
-
export declare function withDbSecret<Secret, Response>(secretId: string, fn: SecretToPromiseFunction<Secret, Response>, options?: SecretOptions): Promise<Response | void>;
|
55
16
|
export declare function checkExpectedSecretKeys<Secret extends GenericSecret>(keys: string[], secret: Secret): void;
|
@@ -1,7 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.checkExpectedSecretKeys = exports.
|
4
|
-
const secret_1 = require("./secret");
|
3
|
+
exports.checkExpectedSecretKeys = exports.RdsSecretKey = exports.RdsProxySecretKey = void 0;
|
5
4
|
var RdsProxySecretKey;
|
6
5
|
(function (RdsProxySecretKey) {
|
7
6
|
RdsProxySecretKey["username"] = "username";
|
@@ -16,75 +15,6 @@ var RdsSecretKey;
|
|
16
15
|
RdsSecretKey["host"] = "host";
|
17
16
|
RdsSecretKey["ro_host"] = "ro_host";
|
18
17
|
})(RdsSecretKey = exports.RdsSecretKey || (exports.RdsSecretKey = {}));
|
19
|
-
var DatabaseEnvironmentKeys;
|
20
|
-
(function (DatabaseEnvironmentKeys) {
|
21
|
-
DatabaseEnvironmentKeys["DB_USER"] = "DB_USER";
|
22
|
-
DatabaseEnvironmentKeys["DB_PASS"] = "DB_PASS";
|
23
|
-
DatabaseEnvironmentKeys["DB_URI"] = "DB_URI";
|
24
|
-
DatabaseEnvironmentKeys["DB_RO_URI"] = "DB_RO_URI";
|
25
|
-
DatabaseEnvironmentKeys["DB_APPLICATION"] = "DB_APPLICATION";
|
26
|
-
})(DatabaseEnvironmentKeys = exports.DatabaseEnvironmentKeys || (exports.DatabaseEnvironmentKeys = {}));
|
27
|
-
function setDbSecret(secret) {
|
28
|
-
process.env[DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
29
|
-
process.env[DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
30
|
-
process.env[DatabaseEnvironmentKeys.DB_URI] = secret.host;
|
31
|
-
process.env[DatabaseEnvironmentKeys.DB_RO_URI] = secret.ro_host;
|
32
|
-
}
|
33
|
-
// cached at Lambda container level
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
35
|
-
let cachedSecret;
|
36
|
-
const missingSecretErrorText = "Missing or empty secretId";
|
37
|
-
/**
|
38
|
-
* Run the given function with secret retrieved from Secrets Manager. Also injects database-credentials into environment.
|
39
|
-
*
|
40
|
-
* @deprecated use SecretHolder & ProxyHolder
|
41
|
-
* @see SecretOptions
|
42
|
-
*
|
43
|
-
* @param {string} secretId
|
44
|
-
* @param {function} fn
|
45
|
-
* @param {SecretOptions} options
|
46
|
-
*/
|
47
|
-
async function withDbSecret(secretId, fn, options) {
|
48
|
-
if (!secretId) {
|
49
|
-
console.error(missingSecretErrorText);
|
50
|
-
return Promise.reject(missingSecretErrorText);
|
51
|
-
}
|
52
|
-
if (!cachedSecret) {
|
53
|
-
// if prefix is given, first set db values and then fetch secret
|
54
|
-
if (options?.prefix) {
|
55
|
-
// first set db values
|
56
|
-
await (0, secret_1.withSecret)(secretId, (fetchedSecret) => {
|
57
|
-
setDbSecret(fetchedSecret);
|
58
|
-
});
|
59
|
-
// then actual secret
|
60
|
-
await (0, secret_1.withSecretAndPrefix)(secretId, options.prefix, (fetchedSecret) => {
|
61
|
-
cachedSecret = fetchedSecret;
|
62
|
-
});
|
63
|
-
}
|
64
|
-
else {
|
65
|
-
await (0, secret_1.withSecret)(secretId, (fetchedSecret) => {
|
66
|
-
setDbSecret(fetchedSecret);
|
67
|
-
cachedSecret = fetchedSecret;
|
68
|
-
});
|
69
|
-
}
|
70
|
-
}
|
71
|
-
try {
|
72
|
-
if (options?.expectedKeys?.length) {
|
73
|
-
checkExpectedSecretKeys(options.expectedKeys, cachedSecret);
|
74
|
-
}
|
75
|
-
return fn(cachedSecret);
|
76
|
-
}
|
77
|
-
catch (error) {
|
78
|
-
console.error("method=withDbSecret Caught an error, refreshing secret", error);
|
79
|
-
// try to refetch secret in case it has changed
|
80
|
-
await (0, secret_1.withSecret)(secretId, (fetchedSecret) => {
|
81
|
-
setDbSecret(fetchedSecret);
|
82
|
-
cachedSecret = fetchedSecret;
|
83
|
-
});
|
84
|
-
return fn(cachedSecret);
|
85
|
-
}
|
86
|
-
}
|
87
|
-
exports.withDbSecret = withDbSecret;
|
88
18
|
function checkExpectedSecretKeys(keys, secret) {
|
89
19
|
const missingKeys = keys.filter((key) => !(key in secret));
|
90
20
|
if (missingKeys.length) {
|
@@ -4,6 +4,7 @@ exports.ProxyHolder = void 0;
|
|
4
4
|
const secret_holder_1 = require("./secret-holder");
|
5
5
|
const dbsecret_1 = require("./dbsecret");
|
6
6
|
const utils_1 = require("../../../utils/utils");
|
7
|
+
const database_1 = require("../../../database/database");
|
7
8
|
const RDS_PROXY_SECRET_KEYS = Object.values(dbsecret_1.RdsProxySecretKey);
|
8
9
|
/**
|
9
10
|
* Holds credentials for RDS Proxy access.
|
@@ -17,10 +18,10 @@ class ProxyHolder {
|
|
17
18
|
}
|
18
19
|
async setCredentials() {
|
19
20
|
const secret = await this.secretHolder.get();
|
20
|
-
process.env[
|
21
|
-
process.env[
|
22
|
-
process.env[
|
23
|
-
process.env[
|
21
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
22
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
23
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_URI] = secret.proxy_host;
|
24
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_RO_URI] = secret.proxy_ro_host;
|
24
25
|
}
|
25
26
|
}
|
26
27
|
exports.ProxyHolder = ProxyHolder;
|
@@ -4,6 +4,7 @@ exports.RdsHolder = void 0;
|
|
4
4
|
const secret_holder_1 = require("./secret-holder");
|
5
5
|
const dbsecret_1 = require("./dbsecret");
|
6
6
|
const utils_1 = require("../../../utils/utils");
|
7
|
+
const database_1 = require("../../../database/database");
|
7
8
|
const RDS_SECRET_KEYS = Object.values(dbsecret_1.RdsSecretKey);
|
8
9
|
/**
|
9
10
|
* Holds credentials for RDS access.
|
@@ -17,10 +18,10 @@ class RdsHolder {
|
|
17
18
|
}
|
18
19
|
async setCredentials() {
|
19
20
|
const secret = await this.secretHolder.get();
|
20
|
-
process.env[
|
21
|
-
process.env[
|
22
|
-
process.env[
|
23
|
-
process.env[
|
21
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
22
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
23
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_URI] = secret.host;
|
24
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_RO_URI] = secret.ro_host;
|
24
25
|
}
|
25
26
|
}
|
26
27
|
exports.RdsHolder = RdsHolder;
|
@@ -4,7 +4,7 @@ exports.SecretHolder = void 0;
|
|
4
4
|
const secret_1 = require("./secret");
|
5
5
|
const dbsecret_1 = require("./dbsecret");
|
6
6
|
const utils_1 = require("../../../utils/utils");
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
|
8
8
|
const NodeTtl = require("node-ttl");
|
9
9
|
const DEFAULT_PREFIX = "";
|
10
10
|
const DEFAULT_SECRET_KEY = "SECRET";
|
@@ -24,11 +24,13 @@ class SecretHolder {
|
|
24
24
|
this.secretId = secretId;
|
25
25
|
this.prefix = prefix;
|
26
26
|
this.expectedKeys = expectedKeys;
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
27
28
|
this.secretCache = new NodeTtl(configuration);
|
28
29
|
}
|
29
30
|
async initSecret() {
|
30
31
|
const secretValue = await (0, secret_1.getSecret)(this.secretId);
|
31
32
|
console.info("refreshing secret " + this.secretId);
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
32
34
|
this.secretCache.push(DEFAULT_SECRET_KEY, secretValue);
|
33
35
|
}
|
34
36
|
static create(prefix = DEFAULT_PREFIX, expectedKeys = []) {
|
@@ -55,21 +57,13 @@ class SecretHolder {
|
|
55
57
|
return parsed;
|
56
58
|
}
|
57
59
|
async getSecret() {
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
58
61
|
const secret = this.secretCache.get(DEFAULT_SECRET_KEY);
|
59
62
|
if (!secret) {
|
60
63
|
await this.initSecret();
|
61
64
|
}
|
62
|
-
|
63
|
-
|
64
|
-
/**
|
65
|
-
* @deprecated Use ProxyHolder
|
66
|
-
*/
|
67
|
-
async setDatabaseCredentials() {
|
68
|
-
const secret = await this.getSecret();
|
69
|
-
process.env[dbsecret_1.DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
70
|
-
process.env[dbsecret_1.DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
71
|
-
process.env[dbsecret_1.DatabaseEnvironmentKeys.DB_URI] = secret.host;
|
72
|
-
process.env[dbsecret_1.DatabaseEnvironmentKeys.DB_RO_URI] = secret.ro_host;
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
66
|
+
return secret ?? this.secretCache.get(DEFAULT_SECRET_KEY);
|
73
67
|
}
|
74
68
|
}
|
75
69
|
exports.SecretHolder = SecretHolder;
|
@@ -1,8 +1,2 @@
|
|
1
|
-
import { SecretToPromiseFunction } from "./dbsecret";
|
2
1
|
export type GenericSecret = Record<string, string>;
|
3
|
-
/**
|
4
|
-
@deprecated use SecretHolder & ProxyHolder
|
5
|
-
*/
|
6
|
-
export declare function withSecret<Secret, Response>(secretId: string, fn: SecretToPromiseFunction<Secret, Response>): Promise<Response | void>;
|
7
2
|
export declare function getSecret<Secret>(secretId: string, prefix?: string): Promise<Secret>;
|
8
|
-
export declare function withSecretAndPrefix<Secret, Response>(secretId: string, prefix: string, fn: SecretToPromiseFunction<Secret, Response>): Promise<Response | void>;
|
@@ -1,26 +1,21 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.getSecret = void 0;
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
5
5
|
const smClient = new aws_sdk_1.SecretsManager({
|
6
6
|
region: process.env.AWS_REGION,
|
7
7
|
});
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
async function withSecret(secretId, fn) {
|
12
|
-
return fn(await getSecret(secretId));
|
13
|
-
}
|
14
|
-
exports.withSecret = withSecret;
|
15
|
-
async function getSecret(secretId, prefix = '') {
|
16
|
-
const secretObj = await smClient.getSecretValue({
|
8
|
+
async function getSecret(secretId, prefix = "") {
|
9
|
+
const secretObj = await smClient
|
10
|
+
.getSecretValue({
|
17
11
|
SecretId: secretId,
|
18
|
-
})
|
12
|
+
})
|
13
|
+
.promise();
|
19
14
|
if (!secretObj.SecretString) {
|
20
|
-
throw new Error(
|
15
|
+
throw new Error("No secret found!");
|
21
16
|
}
|
22
17
|
const secret = JSON.parse(secretObj.SecretString);
|
23
|
-
if (prefix
|
18
|
+
if (!prefix) {
|
24
19
|
return secret;
|
25
20
|
}
|
26
21
|
return parseSecret(secret, `${prefix}.`);
|
@@ -36,8 +31,4 @@ function parseSecret(secret, prefix) {
|
|
36
31
|
}
|
37
32
|
return parsed;
|
38
33
|
}
|
39
|
-
async function withSecretAndPrefix(secretId, prefix, fn) {
|
40
|
-
return fn(await getSecret(secretId, prefix));
|
41
|
-
}
|
42
|
-
exports.withSecretAndPrefix = withSecretAndPrefix;
|
43
34
|
//# sourceMappingURL=secret.js.map
|
@@ -1,4 +1,11 @@
|
|
1
1
|
import { IDatabase, ITask } from "pg-promise";
|
2
|
+
export declare enum DatabaseEnvironmentKeys {
|
3
|
+
DB_USER = "DB_USER",
|
4
|
+
DB_PASS = "DB_PASS",
|
5
|
+
DB_URI = "DB_URI",
|
6
|
+
DB_RO_URI = "DB_RO_URI",
|
7
|
+
DB_APPLICATION = "DB_APPLICATION"
|
8
|
+
}
|
2
9
|
export type DTDatabase = IDatabase<unknown>;
|
3
10
|
export type DTTransaction = ITask<unknown>;
|
4
11
|
/**
|
@@ -1,18 +1,28 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.inDatabaseReadonly = exports.inDatabase = exports.inTransaction = exports.initDbConnection = void 0;
|
4
|
-
const dbsecret_1 = require("../aws/runtime/secrets/dbsecret");
|
3
|
+
exports.inDatabaseReadonly = exports.inDatabase = exports.inTransaction = exports.initDbConnection = exports.DatabaseEnvironmentKeys = void 0;
|
5
4
|
const utils_1 = require("../utils/utils");
|
6
5
|
const environment_1 = require("../aws/runtime/environment");
|
7
|
-
|
6
|
+
var DatabaseEnvironmentKeys;
|
7
|
+
(function (DatabaseEnvironmentKeys) {
|
8
|
+
DatabaseEnvironmentKeys["DB_USER"] = "DB_USER";
|
9
|
+
DatabaseEnvironmentKeys["DB_PASS"] = "DB_PASS";
|
10
|
+
DatabaseEnvironmentKeys["DB_URI"] = "DB_URI";
|
11
|
+
DatabaseEnvironmentKeys["DB_RO_URI"] = "DB_RO_URI";
|
12
|
+
DatabaseEnvironmentKeys["DB_APPLICATION"] = "DB_APPLICATION";
|
13
|
+
})(DatabaseEnvironmentKeys = exports.DatabaseEnvironmentKeys || (exports.DatabaseEnvironmentKeys = {}));
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
8
15
|
const pgp = require("pg-promise")();
|
9
16
|
// convert numeric types to number instead of string
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
10
18
|
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.INT8, (value) => {
|
11
19
|
return parseInt(value);
|
12
20
|
});
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
13
22
|
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.FLOAT8, (value) => {
|
14
23
|
return parseFloat(value);
|
15
24
|
});
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
16
26
|
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.NUMERIC, (value) => {
|
17
27
|
return parseFloat(value);
|
18
28
|
});
|
@@ -30,6 +40,7 @@ pgp.pg.types.setTypeParser(pgp.pg.types.builtins.NUMERIC, (value) => {
|
|
30
40
|
*/
|
31
41
|
function initDbConnection(username, password, applicationName, url, options) {
|
32
42
|
const finalUrl = `postgresql://${username}:${password}@${url}?application_name=${applicationName}`;
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
|
33
44
|
return pgp(finalUrl, options);
|
34
45
|
}
|
35
46
|
exports.initDbConnection = initDbConnection;
|
@@ -46,11 +57,11 @@ function inDatabaseReadonly(fn) {
|
|
46
57
|
}
|
47
58
|
exports.inDatabaseReadonly = inDatabaseReadonly;
|
48
59
|
async function doInDatabase(readonly, fn) {
|
49
|
-
const db_application = (0, environment_1.envValue)(
|
60
|
+
const db_application = (0, environment_1.envValue)(DatabaseEnvironmentKeys.DB_APPLICATION, "unknown-cdk-application");
|
50
61
|
const db_uri = readonly
|
51
|
-
? (0, environment_1.envValue)(
|
52
|
-
: (0, environment_1.envValue)(
|
53
|
-
const db = initDbConnection((0, utils_1.getEnvVariable)(
|
62
|
+
? (0, environment_1.envValue)(DatabaseEnvironmentKeys.DB_RO_URI)
|
63
|
+
: (0, environment_1.envValue)(DatabaseEnvironmentKeys.DB_URI);
|
64
|
+
const db = initDbConnection((0, utils_1.getEnvVariable)(DatabaseEnvironmentKeys.DB_USER), (0, utils_1.getEnvVariable)(DatabaseEnvironmentKeys.DB_PASS), db_application, db_uri);
|
54
65
|
try {
|
55
66
|
// deallocate all prepared statements to allow for connection pooling
|
56
67
|
// DISCARD instead of DEALLOCATE as it didn't always clean all prepared statements
|
@@ -62,7 +73,7 @@ async function doInDatabase(readonly, fn) {
|
|
62
73
|
throw e;
|
63
74
|
}
|
64
75
|
finally {
|
65
|
-
db.$pool.end();
|
76
|
+
await db.$pool.end();
|
66
77
|
}
|
67
78
|
}
|
68
79
|
//# sourceMappingURL=database.js.map
|
@@ -2,7 +2,6 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.dbTestBase = exports.assertCount = void 0;
|
4
4
|
const database_1 = require("../database/database");
|
5
|
-
const dbsecret_1 = require("../aws/runtime/secrets/dbsecret");
|
6
5
|
async function assertCount(db, sql, count) {
|
7
6
|
await db.one(sql).then((x) => expect(x.count).toEqual(count));
|
8
7
|
}
|
@@ -15,10 +14,10 @@ function dbTestBase(fn, truncateFn, dbUser, dbPass, dbUri) {
|
|
15
14
|
noWarnings: true, // ignore duplicate connection warning for tests
|
16
15
|
});
|
17
16
|
beforeAll(async () => {
|
18
|
-
process.env[
|
19
|
-
process.env[
|
20
|
-
process.env[
|
21
|
-
process.env[
|
17
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_USER] = dbUser;
|
18
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_PASS] = dbPass;
|
19
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_URI] = theDbUri;
|
20
|
+
process.env[database_1.DatabaseEnvironmentKeys.DB_RO_URI] = theDbUri;
|
22
21
|
await truncateFn(db);
|
23
22
|
});
|
24
23
|
afterAll(async () => {
|
package/package.json
CHANGED
@@ -17,12 +17,17 @@ interface ApiParameter {
|
|
17
17
|
export class DigitrafficIntegration {
|
18
18
|
readonly lambda: IFunction;
|
19
19
|
readonly mediaType: MediaType;
|
20
|
-
|
21
20
|
readonly parameters: ApiParameter[] = [];
|
21
|
+
readonly sunset?: string;
|
22
22
|
|
23
|
-
constructor(
|
23
|
+
constructor(
|
24
|
+
lambda: IFunction,
|
25
|
+
mediaType = MediaType.TEXT_PLAIN,
|
26
|
+
sunset?: string
|
27
|
+
) {
|
24
28
|
this.lambda = lambda;
|
25
29
|
this.mediaType = mediaType;
|
30
|
+
this.sunset = sunset;
|
26
31
|
}
|
27
32
|
|
28
33
|
addPathParameter(...names: string[]): this {
|
@@ -84,6 +89,6 @@ export class DigitrafficIntegration {
|
|
84
89
|
}
|
85
90
|
|
86
91
|
createResponses(): IntegrationResponse[] {
|
87
|
-
return [DigitrafficIntegrationResponse.ok(this.mediaType)];
|
92
|
+
return [DigitrafficIntegrationResponse.ok(this.mediaType, this.sunset)];
|
88
93
|
}
|
89
94
|
}
|