@digitraffic/common 2024.1.24-3 → 2024.1.30-1
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/__test__/api/handler-factory.test.d.mts +1 -0
- package/dist/__test__/api/handler-factory.test.mjs +43 -0
- package/dist/__test__/api/response.test.d.mts +1 -0
- package/dist/__test__/api/response.test.mjs +86 -0
- package/dist/__test__/imports.test.d.mts +1 -0
- package/dist/__test__/imports.test.mjs +332 -0
- package/dist/__test__/marine/id_utils.test.d.mts +1 -0
- package/dist/__test__/marine/id_utils.test.mjs +44 -0
- package/dist/__test__/promise/promise.test.d.mts +1 -0
- package/dist/__test__/promise/promise.test.mjs +130 -0
- package/dist/__test__/runtime/dt-logger.test.d.mts +1 -0
- package/dist/__test__/runtime/dt-logger.test.mjs +108 -0
- package/dist/__test__/secrets/secret-holder.test.d.mts +1 -0
- package/dist/__test__/secrets/secret-holder.test.mjs +89 -0
- package/dist/__test__/secrets/secret.test.d.mts +1 -0
- package/dist/__test__/secrets/secret.test.mjs +42 -0
- package/dist/__test__/test/httpserver.test.d.mts +1 -0
- package/dist/__test__/test/httpserver.test.mjs +154 -0
- package/dist/__test__/types/lambda-response.test.d.mts +1 -0
- package/dist/__test__/types/lambda-response.test.mjs +58 -0
- package/dist/__test__/utils/date-utils.test.d.mts +1 -0
- package/dist/__test__/utils/date-utils.test.mjs +27 -0
- package/dist/__test__/utils/geometry.test.d.mts +1 -0
- package/dist/__test__/utils/geometry.test.mjs +24 -0
- package/dist/__test__/utils/logging.test.d.mts +1 -0
- package/dist/__test__/utils/logging.test.mjs +78 -0
- package/dist/__test__/utils/utils.test.d.mts +1 -0
- package/dist/__test__/utils/utils.test.mjs +43 -0
- package/dist/aws/infra/api/handler-factory.mjs +4 -0
- package/dist/aws/infra/api/integration.d.mts +2 -2
- package/dist/aws/infra/api/integration.mjs +4 -1
- package/dist/aws/infra/api/response.d.mts +1 -1
- package/dist/aws/infra/api/responses.d.mts +1 -1
- package/dist/aws/infra/api/responses.mjs +2 -0
- package/dist/aws/infra/api/static-integration.mjs +1 -1
- package/dist/aws/infra/canaries/canary-alarm.d.mts +1 -1
- package/dist/aws/infra/canaries/canary-alarm.mjs +2 -0
- package/dist/aws/infra/canaries/canary-parameters.mjs +1 -1
- package/dist/aws/infra/canaries/canary-role.mjs +1 -0
- package/dist/aws/infra/canaries/canary.d.mts +2 -2
- package/dist/aws/infra/canaries/canary.mjs +2 -0
- package/dist/aws/infra/canaries/database-canary.d.mts +2 -2
- package/dist/aws/infra/canaries/database-canary.mjs +2 -0
- package/dist/aws/infra/canaries/database-checker.d.mts +1 -1
- package/dist/aws/infra/canaries/database-checker.mjs +7 -1
- package/dist/aws/infra/canaries/url-canary.d.mts +2 -2
- package/dist/aws/infra/canaries/url-canary.mjs +3 -0
- package/dist/aws/infra/canaries/url-checker.d.mts +1 -1
- package/dist/aws/infra/canaries/url-checker.mjs +4 -1
- package/dist/aws/infra/documentation.mjs +5 -1
- package/dist/aws/infra/import-util.d.mts +1 -1
- package/dist/aws/infra/import-util.mjs +4 -3
- package/dist/aws/infra/scheduler.mjs +2 -0
- package/dist/aws/infra/security-rule.d.mts +1 -1
- package/dist/aws/infra/security-rule.mjs +1 -0
- package/dist/aws/infra/sqs-integration.d.mts +1 -1
- package/dist/aws/infra/sqs-integration.mjs +3 -1
- package/dist/aws/infra/sqs-queue.d.mts +1 -1
- package/dist/aws/infra/sqs-queue.mjs +2 -1
- package/dist/aws/infra/stack/lambda-configs.d.mts +4 -4
- package/dist/aws/infra/stack/lambda-configs.mjs +4 -2
- package/dist/aws/infra/stack/monitoredfunction.d.mts +3 -3
- package/dist/aws/infra/stack/monitoredfunction.mjs +20 -16
- package/dist/aws/infra/stack/parameters.mjs +1 -0
- package/dist/aws/infra/stack/rest_apis.d.mts +2 -2
- package/dist/aws/infra/stack/rest_apis.mjs +6 -1
- package/dist/aws/infra/stack/stack-checking-aspect.d.mts +2 -2
- package/dist/aws/infra/stack/stack-checking-aspect.mjs +6 -1
- package/dist/aws/infra/stack/stack.d.mts +5 -5
- package/dist/aws/infra/stack/stack.mjs +9 -0
- package/dist/aws/infra/stack/subscription.mjs +4 -0
- package/dist/aws/infra/stacks/db-dns-stack.d.mts +1 -1
- package/dist/aws/infra/stacks/db-dns-stack.mjs +1 -0
- package/dist/aws/infra/stacks/db-proxy-stack.d.mts +3 -3
- package/dist/aws/infra/stacks/db-proxy-stack.mjs +4 -2
- package/dist/aws/infra/stacks/db-stack.d.mts +3 -3
- package/dist/aws/infra/stacks/db-stack.mjs +11 -7
- package/dist/aws/infra/stacks/intra-stack-configuration.d.mts +1 -1
- package/dist/aws/infra/stacks/network-stack.d.mts +2 -2
- package/dist/aws/infra/stacks/network-stack.mjs +8 -0
- package/dist/aws/infra/usage-plans.d.mts +1 -1
- package/dist/aws/infra/usage-plans.mjs +1 -0
- package/dist/aws/runtime/apikey.d.mts +2 -2
- package/dist/aws/runtime/apikey.mjs +2 -1
- package/dist/aws/runtime/digitraffic-integration-response.d.mts +1 -1
- package/dist/aws/runtime/dt-logger.mjs +6 -2
- package/dist/aws/runtime/messaging.d.mts +2 -2
- package/dist/aws/runtime/s3.d.mts +2 -2
- package/dist/aws/runtime/s3.mjs +2 -1
- package/dist/aws/runtime/secrets/dbsecret.d.mts +1 -1
- package/dist/aws/runtime/secrets/proxy-holder.mjs +1 -0
- package/dist/aws/runtime/secrets/rds-holder.mjs +1 -0
- package/dist/aws/runtime/secrets/secret-holder.d.mts +1 -1
- package/dist/aws/runtime/secrets/secret-holder.mjs +6 -1
- package/dist/aws/runtime/secrets/secret.mjs +4 -2
- package/dist/aws/types/errors.mjs +1 -0
- package/dist/aws/types/lambda-response.mjs +5 -0
- package/dist/aws/types/model-with-reference.mjs +1 -1
- package/dist/database/cached.d.mts +1 -1
- package/dist/database/database.mjs +1 -0
- package/dist/database/last-updated.d.mts +1 -1
- package/dist/test/db-testutils.d.mts +1 -1
- package/dist/test/db-testutils.mjs +1 -1
- package/dist/test/httpserver.mjs +7 -3
- package/dist/test/secrets-manager.d.mts +1 -1
- package/dist/test/secrets-manager.mjs +1 -1
- package/dist/test/testutils.mjs +1 -1
- package/dist/types/http-error.mjs +1 -0
- package/dist/types/nullable.d.mts +1 -1
- package/dist/utils/api-model.d.mts +2 -2
- package/dist/utils/api-model.mjs +1 -1
- package/dist/utils/geojson-types.d.mts +1 -1
- package/dist/utils/geojson-types.mjs +4 -2
- package/dist/utils/geometry.d.mts +1 -1
- package/dist/utils/geometry.mjs +3 -0
- package/dist/utils/retry.d.mts +2 -2
- package/dist/utils/retry.mjs +2 -2
- package/dist/utils/slack.mjs +1 -0
- package/dist/utils/utils.d.mts +2 -2
- package/package.json +11 -6
- package/src/@types/geojson-validation/index.d.mts +0 -4
- package/src/aws/infra/api/handler-factory.mts +0 -86
- package/src/aws/infra/api/integration.mts +0 -147
- package/src/aws/infra/api/response.mts +0 -165
- package/src/aws/infra/api/responses.mts +0 -127
- package/src/aws/infra/api/static-integration.mts +0 -108
- package/src/aws/infra/canaries/Synthetics.d.mts +0 -21
- package/src/aws/infra/canaries/canary-alarm.mts +0 -33
- package/src/aws/infra/canaries/canary-keys.mts +0 -3
- package/src/aws/infra/canaries/canary-parameters.mts +0 -19
- package/src/aws/infra/canaries/canary-role.mts +0 -73
- package/src/aws/infra/canaries/canary.mts +0 -44
- package/src/aws/infra/canaries/database-canary.mts +0 -98
- package/src/aws/infra/canaries/database-checker.mts +0 -163
- package/src/aws/infra/canaries/url-canary.mts +0 -98
- package/src/aws/infra/canaries/url-checker.mts +0 -388
- package/src/aws/infra/documentation.mts +0 -142
- package/src/aws/infra/import-util.mts +0 -57
- package/src/aws/infra/scheduler.mts +0 -59
- package/src/aws/infra/security-rule.mts +0 -38
- package/src/aws/infra/sqs-integration.mts +0 -106
- package/src/aws/infra/sqs-queue.mts +0 -162
- package/src/aws/infra/stack/lambda-configs.mts +0 -135
- package/src/aws/infra/stack/monitoredfunction.mts +0 -352
- package/src/aws/infra/stack/parameters.mts +0 -74
- package/src/aws/infra/stack/rest_apis.mts +0 -322
- package/src/aws/infra/stack/stack-checking-aspect.mts +0 -233
- package/src/aws/infra/stack/stack.mts +0 -144
- package/src/aws/infra/stack/subscription.mts +0 -58
- package/src/aws/infra/stacks/db-dns-stack.mts +0 -77
- package/src/aws/infra/stacks/db-proxy-stack.mts +0 -134
- package/src/aws/infra/stacks/db-stack.mts +0 -292
- package/src/aws/infra/stacks/intra-stack-configuration.mts +0 -6
- package/src/aws/infra/stacks/network-stack.mts +0 -76
- package/src/aws/infra/usage-plans.mts +0 -50
- package/src/aws/runtime/apikey.mts +0 -9
- package/src/aws/runtime/digitraffic-integration-response.mts +0 -35
- package/src/aws/runtime/dt-logger-default.mts +0 -11
- package/src/aws/runtime/dt-logger.mts +0 -184
- package/src/aws/runtime/environment.mts +0 -22
- package/src/aws/runtime/messaging.mts +0 -26
- package/src/aws/runtime/s3.mts +0 -44
- package/src/aws/runtime/secrets/dbsecret.mts +0 -31
- package/src/aws/runtime/secrets/node-ttl.d.mts +0 -12
- package/src/aws/runtime/secrets/proxy-holder.mts +0 -34
- package/src/aws/runtime/secrets/rds-holder.mts +0 -34
- package/src/aws/runtime/secrets/secret-holder.mts +0 -106
- package/src/aws/runtime/secrets/secret.mts +0 -58
- package/src/aws/types/errors.mts +0 -14
- package/src/aws/types/lambda-response.mts +0 -100
- package/src/aws/types/mediatypes.mts +0 -12
- package/src/aws/types/model-with-reference.mts +0 -8
- package/src/aws/types/proxytypes.mts +0 -27
- package/src/aws/types/tags.mts +0 -3
- package/src/database/cached.mts +0 -64
- package/src/database/database.mts +0 -107
- package/src/database/last-updated.mts +0 -103
- package/src/database/models.mts +0 -7
- package/src/index.mts +0 -2
- package/src/marine/id_utils.mts +0 -30
- package/src/marine/rtz.mts +0 -57
- package/src/test/asserter.mts +0 -58
- package/src/test/db-testutils.mts +0 -52
- package/src/test/httpserver.mts +0 -111
- package/src/test/secrets-manager.mts +0 -37
- package/src/test/testutils.mts +0 -39
- package/src/types/async-timeout-error.mts +0 -5
- package/src/types/aws-env.mts +0 -3
- package/src/types/either.mts +0 -9
- package/src/types/http-error.mts +0 -8
- package/src/types/input-error.mts +0 -2
- package/src/types/language.mts +0 -3
- package/src/types/nullable.mts +0 -21
- package/src/types/traffictype.mts +0 -8
- package/src/types/urn.mts +0 -1
- package/src/types/util-types.mts +0 -10
- package/src/types/validator.mts +0 -10
- package/src/utils/api-model.mts +0 -133
- package/src/utils/base64.mts +0 -16
- package/src/utils/date-utils.mts +0 -53
- package/src/utils/geojson-types.mts +0 -22
- package/src/utils/geometry.mts +0 -171
- package/src/utils/logging.mts +0 -75
- package/src/utils/retry.mts +0 -200
- package/src/utils/slack.mts +0 -26
- package/src/utils/utils.mts +0 -184
@@ -1,388 +0,0 @@
|
|
1
|
-
import { IncomingMessage, RequestOptions } from "http";
|
2
|
-
import { Asserter } from "../../../test/asserter.mjs";
|
3
|
-
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
|
5
|
-
import synthetics from "Synthetics";
|
6
|
-
import zlib from "zlib";
|
7
|
-
import { MediaType } from "../../types/mediatypes.mjs";
|
8
|
-
import { getApiKeyFromAPIGateway } from "../../runtime/apikey.mjs";
|
9
|
-
import { FeatureCollection } from "geojson";
|
10
|
-
import { isValidGeoJson } from "../../../utils/geometry.mjs";
|
11
|
-
import { getEnvVariable } from "../../../utils/utils.mjs";
|
12
|
-
import { ENV_API_KEY, ENV_HOSTNAME } from "./canary-keys.mjs";
|
13
|
-
import { logger } from "../../runtime/dt-logger-default.mjs";
|
14
|
-
import { logException } from "../../../utils/logging.mjs";
|
15
|
-
|
16
|
-
export const API_KEY_HEADER = "x-api-key";
|
17
|
-
|
18
|
-
const baseHeaders = {
|
19
|
-
"Digitraffic-User": "internal-digitraffic-canary",
|
20
|
-
"Accept-Encoding": "gzip",
|
21
|
-
Accept: "*/*",
|
22
|
-
} as Record<string, string>;
|
23
|
-
|
24
|
-
type CheckerFunction = (Res: IncomingMessage) => Promise<void>;
|
25
|
-
type JsonCheckerFunction<T> = (
|
26
|
-
json: T,
|
27
|
-
body: string,
|
28
|
-
message: IncomingMessage
|
29
|
-
) => Promise<void>;
|
30
|
-
|
31
|
-
export class UrlChecker {
|
32
|
-
private readonly requestOptions: RequestOptions;
|
33
|
-
|
34
|
-
constructor(hostname: string, apiKey?: string) {
|
35
|
-
const headers = { ...baseHeaders };
|
36
|
-
|
37
|
-
if (apiKey) {
|
38
|
-
headers[API_KEY_HEADER] = apiKey;
|
39
|
-
}
|
40
|
-
|
41
|
-
this.requestOptions = {
|
42
|
-
hostname,
|
43
|
-
method: "GET",
|
44
|
-
protocol: "https:",
|
45
|
-
headers,
|
46
|
-
};
|
47
|
-
|
48
|
-
synthetics.getConfiguration().disableRequestMetrics();
|
49
|
-
|
50
|
-
synthetics
|
51
|
-
.getConfiguration()
|
52
|
-
.withIncludeRequestBody(false)
|
53
|
-
.withIncludeRequestHeaders(false)
|
54
|
-
.withIncludeResponseBody(false)
|
55
|
-
.withIncludeResponseHeaders(false)
|
56
|
-
.withFailedCanaryMetric(true);
|
57
|
-
}
|
58
|
-
|
59
|
-
static create(hostname: string, apiKeyId: string): Promise<UrlChecker> {
|
60
|
-
return getApiKeyFromAPIGateway(apiKeyId).then((apiKey) => {
|
61
|
-
return new UrlChecker(hostname, apiKey.value);
|
62
|
-
});
|
63
|
-
}
|
64
|
-
|
65
|
-
static createV2(): Promise<UrlChecker> {
|
66
|
-
return this.create(
|
67
|
-
getEnvVariable(ENV_HOSTNAME),
|
68
|
-
getEnvVariable(ENV_API_KEY)
|
69
|
-
);
|
70
|
-
}
|
71
|
-
|
72
|
-
expectStatus<T>(
|
73
|
-
statusCode: number,
|
74
|
-
url: string,
|
75
|
-
callback: JsonCheckerFunction<T>
|
76
|
-
): Promise<void> {
|
77
|
-
const requestOptions = {
|
78
|
-
...this.requestOptions,
|
79
|
-
...{
|
80
|
-
path: url,
|
81
|
-
},
|
82
|
-
};
|
83
|
-
|
84
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return
|
85
|
-
return synthetics.executeHttpStep(
|
86
|
-
`Verify ${statusCode} for ${url.replace(/auth=.*/, "")}`,
|
87
|
-
requestOptions,
|
88
|
-
callback
|
89
|
-
);
|
90
|
-
}
|
91
|
-
|
92
|
-
expect200<T>(
|
93
|
-
url: string,
|
94
|
-
...callbacks: JsonCheckerFunction<T>[]
|
95
|
-
): Promise<void> {
|
96
|
-
const callback = async (
|
97
|
-
json: T,
|
98
|
-
body: string,
|
99
|
-
res: IncomingMessage
|
100
|
-
) => {
|
101
|
-
await Promise.allSettled(callbacks.map((c) => c(json, body, res)));
|
102
|
-
};
|
103
|
-
|
104
|
-
return this.expectStatus(200, url, callback);
|
105
|
-
}
|
106
|
-
|
107
|
-
expect404(url: string): Promise<void> {
|
108
|
-
const requestOptions = {
|
109
|
-
...this.requestOptions,
|
110
|
-
...{
|
111
|
-
path: url,
|
112
|
-
},
|
113
|
-
};
|
114
|
-
|
115
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return
|
116
|
-
return synthetics.executeHttpStep(
|
117
|
-
`Verify 404 for ${url}`,
|
118
|
-
requestOptions,
|
119
|
-
validateStatusCodeAndContentType(404, MediaType.TEXT_PLAIN)
|
120
|
-
);
|
121
|
-
}
|
122
|
-
|
123
|
-
expect400(url: string): Promise<void> {
|
124
|
-
const requestOptions = {
|
125
|
-
...this.requestOptions,
|
126
|
-
...{
|
127
|
-
path: url,
|
128
|
-
},
|
129
|
-
};
|
130
|
-
|
131
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return
|
132
|
-
return synthetics.executeHttpStep(
|
133
|
-
`Verify 400 for ${url}`,
|
134
|
-
requestOptions,
|
135
|
-
validateStatusCodeAndContentType(400, MediaType.TEXT_PLAIN)
|
136
|
-
);
|
137
|
-
}
|
138
|
-
|
139
|
-
expect403WithoutApiKey(url: string, mediaType?: MediaType): Promise<void> {
|
140
|
-
if (
|
141
|
-
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
142
|
-
!this.requestOptions.headers ||
|
143
|
-
!this.requestOptions.headers[API_KEY_HEADER]
|
144
|
-
) {
|
145
|
-
logger.error({
|
146
|
-
method: "UrlChecker.expect403WithoutApiKey",
|
147
|
-
message: "No Api-key defined",
|
148
|
-
});
|
149
|
-
}
|
150
|
-
|
151
|
-
const requestOptions = {
|
152
|
-
...this.requestOptions,
|
153
|
-
...{
|
154
|
-
path: url,
|
155
|
-
headers: baseHeaders,
|
156
|
-
},
|
157
|
-
};
|
158
|
-
|
159
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return
|
160
|
-
return synthetics.executeHttpStep(
|
161
|
-
`Verify 403 for ${url}`,
|
162
|
-
requestOptions,
|
163
|
-
validateStatusCodeAndContentType(
|
164
|
-
403,
|
165
|
-
mediaType ?? MediaType.APPLICATION_JSON
|
166
|
-
)
|
167
|
-
);
|
168
|
-
}
|
169
|
-
|
170
|
-
done(): string {
|
171
|
-
return "Canary successful";
|
172
|
-
}
|
173
|
-
}
|
174
|
-
|
175
|
-
async function getResponseBody(response: IncomingMessage): Promise<string> {
|
176
|
-
const body = await getBodyFromResponse(response);
|
177
|
-
|
178
|
-
if (response.headers["content-encoding"] === "gzip") {
|
179
|
-
try {
|
180
|
-
return zlib.gunzipSync(body).toString();
|
181
|
-
} catch (e) {
|
182
|
-
logException(logger, e);
|
183
|
-
}
|
184
|
-
}
|
185
|
-
|
186
|
-
return body.toString();
|
187
|
-
}
|
188
|
-
|
189
|
-
function getBodyFromResponse(response: IncomingMessage): Promise<string> {
|
190
|
-
return new Promise((resolve: (value: string) => void) => {
|
191
|
-
const buffers: Buffer[] = [];
|
192
|
-
|
193
|
-
response.on("data", (data: Buffer) => {
|
194
|
-
buffers.push(data);
|
195
|
-
});
|
196
|
-
|
197
|
-
response.on("end", () => {
|
198
|
-
resolve(Buffer.concat(buffers).toString());
|
199
|
-
});
|
200
|
-
});
|
201
|
-
}
|
202
|
-
|
203
|
-
/**
|
204
|
-
* Returns function, that validates that the status code and content-type from response are the given values
|
205
|
-
* @param statusCode
|
206
|
-
* @param contentType
|
207
|
-
*/
|
208
|
-
function validateStatusCodeAndContentType(
|
209
|
-
statusCode: number,
|
210
|
-
contentType: MediaType
|
211
|
-
): (Res: IncomingMessage) => Promise<void> {
|
212
|
-
return (res: IncomingMessage) => {
|
213
|
-
return new Promise((resolve) => {
|
214
|
-
if (res.statusCode !== statusCode) {
|
215
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
216
|
-
throw new Error(`${res.statusCode!} ${res.statusMessage!}`);
|
217
|
-
}
|
218
|
-
|
219
|
-
if (res.headers["content-type"] !== contentType) {
|
220
|
-
throw new Error(
|
221
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
222
|
-
`Wrong content-type ${res.headers["content-type"]!}`
|
223
|
-
);
|
224
|
-
}
|
225
|
-
|
226
|
-
resolve();
|
227
|
-
});
|
228
|
-
};
|
229
|
-
}
|
230
|
-
|
231
|
-
// DEPRECATED
|
232
|
-
export class ResponseChecker {
|
233
|
-
private readonly contentType;
|
234
|
-
private checkCors = true;
|
235
|
-
|
236
|
-
constructor(contentType: string) {
|
237
|
-
this.contentType = contentType;
|
238
|
-
}
|
239
|
-
|
240
|
-
static forJson(): ResponseChecker {
|
241
|
-
return new ResponseChecker(MediaType.APPLICATION_JSON);
|
242
|
-
}
|
243
|
-
|
244
|
-
static forCSV(): ResponseChecker {
|
245
|
-
return new ResponseChecker(MediaType.TEXT_CSV);
|
246
|
-
}
|
247
|
-
|
248
|
-
static forGeojson(): ResponseChecker {
|
249
|
-
return new ResponseChecker(MediaType.APPLICATION_GEOJSON);
|
250
|
-
}
|
251
|
-
|
252
|
-
static forJpeg(): ResponseChecker {
|
253
|
-
return new ResponseChecker(MediaType.IMAGE_JPEG);
|
254
|
-
}
|
255
|
-
|
256
|
-
check(): CheckerFunction {
|
257
|
-
return this.responseChecker(() => {
|
258
|
-
// no need to do anything
|
259
|
-
});
|
260
|
-
}
|
261
|
-
|
262
|
-
checkJson<T>(
|
263
|
-
fn: (json: T, body: string, res: IncomingMessage) => void
|
264
|
-
): CheckerFunction {
|
265
|
-
return this.responseChecker((body: string, res: IncomingMessage) => {
|
266
|
-
fn(JSON.parse(body) as unknown as T, body, res);
|
267
|
-
});
|
268
|
-
}
|
269
|
-
|
270
|
-
responseChecker(
|
271
|
-
fn: (body: string, res: IncomingMessage) => void
|
272
|
-
): CheckerFunction {
|
273
|
-
return async (res: IncomingMessage): Promise<void> => {
|
274
|
-
if (!res.statusCode) {
|
275
|
-
throw new Error("statusCode missing");
|
276
|
-
}
|
277
|
-
|
278
|
-
if (res.statusCode < 200 || res.statusCode > 299) {
|
279
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
280
|
-
throw new Error(`${res.statusCode} ${res.statusMessage!}`);
|
281
|
-
}
|
282
|
-
|
283
|
-
if (this.checkCors && !res.headers["access-control-allow-origin"]) {
|
284
|
-
throw new Error("CORS missing");
|
285
|
-
}
|
286
|
-
|
287
|
-
if (res.headers["content-type"] !== this.contentType) {
|
288
|
-
throw new Error(
|
289
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
290
|
-
`Wrong content-type ${res.headers["content-type"]!}`
|
291
|
-
);
|
292
|
-
}
|
293
|
-
|
294
|
-
const body = await getResponseBody(res);
|
295
|
-
|
296
|
-
fn(body, res);
|
297
|
-
};
|
298
|
-
}
|
299
|
-
}
|
300
|
-
|
301
|
-
export class ContentChecker {
|
302
|
-
static checkJson<T>(
|
303
|
-
fn: (json: T, body: string, res: IncomingMessage) => void
|
304
|
-
): CheckerFunction {
|
305
|
-
return async (res: IncomingMessage): Promise<void> => {
|
306
|
-
const body = await getResponseBody(res);
|
307
|
-
|
308
|
-
fn(JSON.parse(body) as unknown as T, body, res);
|
309
|
-
};
|
310
|
-
}
|
311
|
-
|
312
|
-
static checkResponse(
|
313
|
-
fn: (body: string, res: IncomingMessage) => void
|
314
|
-
): CheckerFunction {
|
315
|
-
return async (res: IncomingMessage): Promise<void> => {
|
316
|
-
const body = await getResponseBody(res);
|
317
|
-
|
318
|
-
fn(body, res);
|
319
|
-
};
|
320
|
-
}
|
321
|
-
}
|
322
|
-
|
323
|
-
export class ContentTypeChecker {
|
324
|
-
static checkContentType(contentType: MediaType): CheckerFunction {
|
325
|
-
return (res: IncomingMessage) => {
|
326
|
-
if (!res.statusCode) {
|
327
|
-
throw new Error("statusCode missing");
|
328
|
-
}
|
329
|
-
|
330
|
-
if (res.statusCode < 200 || res.statusCode > 299) {
|
331
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
332
|
-
throw new Error(`${res.statusCode} ${res.statusMessage!}`);
|
333
|
-
}
|
334
|
-
|
335
|
-
if (!res.headers["access-control-allow-origin"]) {
|
336
|
-
throw new Error("CORS missing");
|
337
|
-
}
|
338
|
-
|
339
|
-
if (res.headers["content-type"] !== contentType) {
|
340
|
-
throw new Error(
|
341
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
342
|
-
`Wrong content-type ${res.headers["content-type"]!}`
|
343
|
-
);
|
344
|
-
}
|
345
|
-
|
346
|
-
return Promise.resolve();
|
347
|
-
};
|
348
|
-
}
|
349
|
-
}
|
350
|
-
|
351
|
-
export class GeoJsonChecker {
|
352
|
-
static validFeatureCollection(
|
353
|
-
fn?: (json: FeatureCollection) => void
|
354
|
-
): CheckerFunction {
|
355
|
-
return ResponseChecker.forGeojson().checkJson(
|
356
|
-
(json: FeatureCollection) => {
|
357
|
-
Asserter.assertEquals(json.type, "FeatureCollection");
|
358
|
-
Asserter.assertTrue(isValidGeoJson(json));
|
359
|
-
|
360
|
-
if (fn) {
|
361
|
-
fn(json);
|
362
|
-
}
|
363
|
-
}
|
364
|
-
);
|
365
|
-
}
|
366
|
-
}
|
367
|
-
|
368
|
-
export class HeaderChecker {
|
369
|
-
static checkHeaderExists(headerName: string): CheckerFunction {
|
370
|
-
return (res: IncomingMessage) => {
|
371
|
-
if (!res.headers[headerName]) {
|
372
|
-
throw new Error("Missing header: " + headerName);
|
373
|
-
}
|
374
|
-
|
375
|
-
return Promise.resolve();
|
376
|
-
};
|
377
|
-
}
|
378
|
-
|
379
|
-
static checkHeaderMissing(headerName: string): CheckerFunction {
|
380
|
-
return (res: IncomingMessage) => {
|
381
|
-
if (res.headers[headerName]) {
|
382
|
-
throw new Error("Header should not exist: " + headerName);
|
383
|
-
}
|
384
|
-
|
385
|
-
return Promise.resolve();
|
386
|
-
};
|
387
|
-
}
|
388
|
-
}
|
@@ -1,142 +0,0 @@
|
|
1
|
-
import { Construct } from "constructs";
|
2
|
-
import { CfnDocumentationPart, Resource } from "aws-cdk-lib/aws-apigateway";
|
3
|
-
|
4
|
-
// Documentation parts are objects that describe an API Gateway API or parts of an API
|
5
|
-
// https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-documenting-api.html
|
6
|
-
|
7
|
-
/**
|
8
|
-
* Add description to a query parameter
|
9
|
-
* @param name query parameter name
|
10
|
-
* @param description query parameter description
|
11
|
-
* @param resource REST API resource
|
12
|
-
* @param stack CloudFormation stack
|
13
|
-
*
|
14
|
-
* @deprecated Use DigitrafficRestApi.documentResource
|
15
|
-
*/
|
16
|
-
export function addQueryParameterDescription(
|
17
|
-
name: string,
|
18
|
-
description: string,
|
19
|
-
resource: Resource,
|
20
|
-
stack: Construct
|
21
|
-
) {
|
22
|
-
new CfnDocumentationPart(stack, `${name}Documentation`, {
|
23
|
-
restApiId: resource.api.restApiId,
|
24
|
-
location: {
|
25
|
-
type: "QUERY_PARAMETER",
|
26
|
-
name,
|
27
|
-
path: resource.path,
|
28
|
-
},
|
29
|
-
properties: JSON.stringify({ description }),
|
30
|
-
});
|
31
|
-
}
|
32
|
-
|
33
|
-
/**
|
34
|
-
* Add a documentation part to a method
|
35
|
-
* @param methodDescription
|
36
|
-
* @param documentationProperties
|
37
|
-
* @param resource REST API resource
|
38
|
-
* @param stack CloudFormation stack
|
39
|
-
*/
|
40
|
-
export function addDocumentation(
|
41
|
-
methodDescription: string,
|
42
|
-
documentationProperties: object,
|
43
|
-
resource: Resource,
|
44
|
-
stack: Construct
|
45
|
-
) {
|
46
|
-
new CfnDocumentationPart(stack, `${methodDescription}Documentation`, {
|
47
|
-
restApiId: resource.api.restApiId,
|
48
|
-
location: {
|
49
|
-
type: "METHOD",
|
50
|
-
path: resource.path,
|
51
|
-
},
|
52
|
-
properties: JSON.stringify(documentationProperties),
|
53
|
-
});
|
54
|
-
}
|
55
|
-
|
56
|
-
/**
|
57
|
-
* Adds OpenAPI tags to an API method
|
58
|
-
* @param methodDescription Description of API method
|
59
|
-
* @param tags OpenAPI tags
|
60
|
-
* @param resource REST API resource
|
61
|
-
* @param stack CloudFormation stack
|
62
|
-
*/
|
63
|
-
export function addTags(
|
64
|
-
methodDescription: string,
|
65
|
-
tags: string[],
|
66
|
-
resource: Resource,
|
67
|
-
stack: Construct
|
68
|
-
) {
|
69
|
-
addDocumentation(methodDescription, { tags }, resource, stack);
|
70
|
-
}
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Adds OpenAPI tags and a method summary to an API method
|
74
|
-
*
|
75
|
-
* @deprecated Use DigitrafficRestApi.documentResource
|
76
|
-
*
|
77
|
-
* @param methodDescription Description of API method
|
78
|
-
* @param tags OpenAPI tags
|
79
|
-
* @param summary OpenAPI summary
|
80
|
-
* @param resource REST API resource
|
81
|
-
* @param stack CloudFormation stack
|
82
|
-
*/
|
83
|
-
export function addTagsAndSummary(
|
84
|
-
methodDescription: string,
|
85
|
-
tags: string[],
|
86
|
-
summary: string,
|
87
|
-
resource: Resource,
|
88
|
-
stack: Construct
|
89
|
-
) {
|
90
|
-
addDocumentation(methodDescription, { tags, summary }, resource, stack);
|
91
|
-
}
|
92
|
-
|
93
|
-
export interface DocumentationProperties {
|
94
|
-
description?: string;
|
95
|
-
tags?: string[];
|
96
|
-
summary?: string;
|
97
|
-
deprecated?: boolean;
|
98
|
-
}
|
99
|
-
|
100
|
-
export class DocumentationPart {
|
101
|
-
readonly parameterName: string;
|
102
|
-
readonly type: string;
|
103
|
-
readonly documentationProperties: DocumentationProperties;
|
104
|
-
|
105
|
-
private constructor(
|
106
|
-
parameterName: string,
|
107
|
-
documentationProperties: DocumentationProperties,
|
108
|
-
type: string
|
109
|
-
) {
|
110
|
-
this.parameterName = parameterName;
|
111
|
-
this.documentationProperties = documentationProperties;
|
112
|
-
this.type = type;
|
113
|
-
}
|
114
|
-
|
115
|
-
deprecated(note: string): this {
|
116
|
-
// deprecated is not supported ATM: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html
|
117
|
-
this.documentationProperties.deprecated = true;
|
118
|
-
this.documentationProperties.summary += ". " + note;
|
119
|
-
|
120
|
-
return this;
|
121
|
-
}
|
122
|
-
|
123
|
-
static queryParameter(parameterName: string, description: string) {
|
124
|
-
return new DocumentationPart(
|
125
|
-
parameterName,
|
126
|
-
{ description },
|
127
|
-
"QUERY_PARAMETER"
|
128
|
-
);
|
129
|
-
}
|
130
|
-
|
131
|
-
static pathParameter(parameterName: string, description: string) {
|
132
|
-
return new DocumentationPart(
|
133
|
-
parameterName,
|
134
|
-
{ description },
|
135
|
-
"PATH_PARAMETER"
|
136
|
-
);
|
137
|
-
}
|
138
|
-
|
139
|
-
static method(tags: string[], name: string, summary: string) {
|
140
|
-
return new DocumentationPart(name, { tags, summary }, "METHOD");
|
141
|
-
}
|
142
|
-
}
|
@@ -1,57 +0,0 @@
|
|
1
|
-
import { IVpc, Vpc } from "aws-cdk-lib/aws-ec2";
|
2
|
-
import { CfnOutput, Fn, Stack } from "aws-cdk-lib";
|
3
|
-
import { Construct } from "constructs";
|
4
|
-
|
5
|
-
export class OldStackImports {
|
6
|
-
public static AURORAINSTANCE_SG_IMPORT_NAME = "AuroraSG";
|
7
|
-
public static RDSPROXY_SG_IMPORT_NAME = "RDSProxySG";
|
8
|
-
}
|
9
|
-
|
10
|
-
/**
|
11
|
-
* Import VPC from other stack outputs
|
12
|
-
*/
|
13
|
-
export function importVpc(scope: Construct, environmentName: string): IVpc {
|
14
|
-
const vpcId = importValue(environmentName, "VPCID");
|
15
|
-
const privateSubnetIds = [
|
16
|
-
importValue(environmentName, "digitrafficprivateASubnet"),
|
17
|
-
importValue(environmentName, "digitrafficprivateBSubnet"),
|
18
|
-
];
|
19
|
-
const availabilityZones = ["euw1-az1", "euw1-az2"];
|
20
|
-
|
21
|
-
// VPC reference construction requires vpcId and availability zones
|
22
|
-
// private subnets are used in Lambda configuration
|
23
|
-
return Vpc.fromVpcAttributes(scope, "vpc", {
|
24
|
-
vpcId,
|
25
|
-
privateSubnetIds,
|
26
|
-
availabilityZones,
|
27
|
-
});
|
28
|
-
}
|
29
|
-
|
30
|
-
/**
|
31
|
-
* Import value from other stack output. Stack outputs are named with
|
32
|
-
* digitraffic-${environmentName}-${name} pattern and this function takes care of it
|
33
|
-
*/
|
34
|
-
export function importValue(environmentName: string, name: string): string {
|
35
|
-
return Fn.importValue(outputName(environmentName, name));
|
36
|
-
}
|
37
|
-
|
38
|
-
/**
|
39
|
-
* Export value as stack output. Use same naming pattern as importValue.
|
40
|
-
*/
|
41
|
-
export function exportValue(
|
42
|
-
stack: Stack,
|
43
|
-
environmentName: string,
|
44
|
-
name: string,
|
45
|
-
value: string
|
46
|
-
) {
|
47
|
-
const exportName = outputName(environmentName, name);
|
48
|
-
|
49
|
-
new CfnOutput(stack, exportName, {
|
50
|
-
exportName,
|
51
|
-
value,
|
52
|
-
});
|
53
|
-
}
|
54
|
-
|
55
|
-
export function outputName(environmentName: string, name: string): string {
|
56
|
-
return `digitraffic-${environmentName}-${name}`;
|
57
|
-
}
|
@@ -1,59 +0,0 @@
|
|
1
|
-
import { Rule, Schedule } from "aws-cdk-lib/aws-events";
|
2
|
-
import { Duration } from "aws-cdk-lib";
|
3
|
-
import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
|
4
|
-
import { Function as AWSFunction } from "aws-cdk-lib/aws-lambda";
|
5
|
-
import { Construct } from "constructs";
|
6
|
-
|
7
|
-
export class Scheduler extends Rule {
|
8
|
-
constructor(
|
9
|
-
stack: Construct,
|
10
|
-
ruleName: string,
|
11
|
-
schedule: Schedule,
|
12
|
-
lambda?: AWSFunction
|
13
|
-
) {
|
14
|
-
super(stack, ruleName, { ruleName, schedule });
|
15
|
-
|
16
|
-
if (lambda) {
|
17
|
-
this.addTarget(new LambdaFunction(lambda));
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
static everyMinute(
|
22
|
-
stack: Construct,
|
23
|
-
ruleName: string,
|
24
|
-
lambda?: AWSFunction
|
25
|
-
) {
|
26
|
-
return Scheduler.every(stack, ruleName, Duration.minutes(1), lambda);
|
27
|
-
}
|
28
|
-
|
29
|
-
static everyMinutes(
|
30
|
-
stack: Construct,
|
31
|
-
ruleName: string,
|
32
|
-
minutes: number,
|
33
|
-
lambda?: AWSFunction
|
34
|
-
) {
|
35
|
-
return Scheduler.every(
|
36
|
-
stack,
|
37
|
-
ruleName,
|
38
|
-
Duration.minutes(minutes),
|
39
|
-
lambda
|
40
|
-
);
|
41
|
-
}
|
42
|
-
|
43
|
-
static everyHour(stack: Construct, ruleName: string, lambda?: AWSFunction) {
|
44
|
-
return Scheduler.every(stack, ruleName, Duration.hours(1), lambda);
|
45
|
-
}
|
46
|
-
|
47
|
-
static everyDay(stack: Construct, ruleName: string, lambda?: AWSFunction) {
|
48
|
-
return Scheduler.every(stack, ruleName, Duration.days(1), lambda);
|
49
|
-
}
|
50
|
-
|
51
|
-
static every(
|
52
|
-
stack: Construct,
|
53
|
-
ruleName: string,
|
54
|
-
duration: Duration,
|
55
|
-
lambda?: AWSFunction
|
56
|
-
) {
|
57
|
-
return new Scheduler(stack, ruleName, Schedule.rate(duration), lambda);
|
58
|
-
}
|
59
|
-
}
|
@@ -1,38 +0,0 @@
|
|
1
|
-
import {Construct} from "constructs";
|
2
|
-
import {Rule} from "aws-cdk-lib/aws-events";
|
3
|
-
import {ITopic} from "aws-cdk-lib/aws-sns";
|
4
|
-
import {SnsTopic} from "aws-cdk-lib/aws-events-targets";
|
5
|
-
|
6
|
-
/**
|
7
|
-
* Automatic rule for Security Hub. Send notification to given topic if the following conditions apply:
|
8
|
-
* * There is a finding with a status of NEW
|
9
|
-
* * It has severity of HIGH or CRITICAL
|
10
|
-
* * It is in a FAILED state
|
11
|
-
*/
|
12
|
-
export class DigitrafficSecurityRule extends Rule {
|
13
|
-
constructor(scope: Construct, topic: ITopic) {
|
14
|
-
const ruleName = 'SecurityHubRule';
|
15
|
-
super(scope, ruleName, {
|
16
|
-
ruleName,
|
17
|
-
eventPattern: {
|
18
|
-
source: ['aws.securityhub'],
|
19
|
-
detailType: ["Security Hub Findings - Imported"],
|
20
|
-
detail: {
|
21
|
-
findings: {
|
22
|
-
"Compliance": {
|
23
|
-
"Status": ["FAILED"],
|
24
|
-
},
|
25
|
-
"Workflow": {
|
26
|
-
"Status": ["NEW"],
|
27
|
-
},
|
28
|
-
"Severity": {
|
29
|
-
"Label": ["HIGH", "CRITICAL"],
|
30
|
-
},
|
31
|
-
},
|
32
|
-
},
|
33
|
-
},
|
34
|
-
});
|
35
|
-
|
36
|
-
this.addTarget(new SnsTopic(topic));
|
37
|
-
}
|
38
|
-
}
|