@digitraffic/common 2022.10.25-1 → 2022.10.31-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.
Files changed (283) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +4 -0
  3. package/.eslintrc.json +27 -0
  4. package/.github/CODEOWNERS +2 -0
  5. package/.github/workflows/build.yml +36 -0
  6. package/.github/workflows/eslint.yml +38 -0
  7. package/.github/workflows/mirror.yml +15 -0
  8. package/.gitignore +29 -0
  9. package/.husky/pre-commit +4 -0
  10. package/.prettierrc.json +10 -0
  11. package/dist/aws/infra/api/integration.js +52 -0
  12. package/dist/aws/infra/api/response.js +61 -0
  13. package/dist/aws/infra/api/responses.js +82 -0
  14. package/dist/aws/infra/api/static-integration.js +54 -0
  15. package/dist/aws/infra/canaries/canary-alarm.js +26 -0
  16. package/dist/aws/infra/canaries/canary-keys.js +7 -0
  17. package/dist/aws/infra/canaries/canary-parameters.js +3 -0
  18. package/dist/aws/infra/canaries/canary-role.js +46 -0
  19. package/dist/aws/infra/canaries/canary.js +32 -0
  20. package/dist/aws/infra/canaries/database-canary.js +70 -0
  21. package/dist/aws/infra/canaries/database-checker.js +103 -0
  22. package/dist/aws/infra/canaries/url-canary.js +47 -0
  23. package/dist/aws/infra/canaries/url-checker.js +252 -0
  24. package/dist/aws/infra/documentation.js +95 -0
  25. package/dist/aws/infra/scheduler.js +31 -0
  26. package/dist/aws/infra/security-rule.js +39 -0
  27. package/dist/aws/infra/sqs-integration.js +93 -0
  28. package/dist/aws/infra/sqs-queue.js +130 -0
  29. package/dist/aws/infra/stack/lambda-configs.js +105 -0
  30. package/dist/aws/infra/stack/monitoredfunction.js +143 -0
  31. package/dist/aws/infra/stack/rest_apis.js +185 -0
  32. package/dist/aws/infra/stack/stack-checking-aspect.js +174 -0
  33. package/dist/aws/infra/stack/stack.js +67 -0
  34. package/dist/aws/infra/stack/subscription.js +42 -0
  35. package/dist/aws/infra/usage-plans.js +42 -0
  36. package/dist/aws/runtime/apikey.js +13 -0
  37. package/dist/aws/runtime/digitraffic-integration-response.js +26 -0
  38. package/dist/aws/runtime/environment.js +12 -0
  39. package/dist/aws/runtime/messaging.js +31 -0
  40. package/dist/aws/runtime/s3.js +30 -0
  41. package/dist/aws/runtime/secrets/dbsecret.js +96 -0
  42. package/dist/aws/runtime/secrets/proxy-holder.js +27 -0
  43. package/dist/aws/runtime/secrets/rds-holder.js +27 -0
  44. package/dist/aws/runtime/secrets/secret-holder.js +76 -0
  45. package/dist/aws/runtime/secrets/secret.js +43 -0
  46. package/dist/aws/types/errors.js +16 -0
  47. package/dist/aws/types/lambda-response.js +33 -0
  48. package/dist/aws/types/mediatypes.js +16 -0
  49. package/dist/aws/types/model-with-reference.js +3 -0
  50. package/dist/aws/types/proxytypes.js +3 -0
  51. package/dist/aws/types/tags.js +7 -0
  52. package/dist/database/cached.js +32 -0
  53. package/dist/database/database.js +70 -0
  54. package/dist/database/last-updated.js +54 -0
  55. package/dist/database/models.js +3 -0
  56. package/dist/marine/id_utils.js +33 -0
  57. package/dist/marine/rtz.js +3 -0
  58. package/dist/test/asserter.js +45 -0
  59. package/dist/test/db-testutils.js +31 -0
  60. package/dist/test/httpserver.js +74 -0
  61. package/dist/test/secret.js +25 -0
  62. package/dist/test/secrets-manager.js +59 -0
  63. package/dist/test/testutils.js +44 -0
  64. package/dist/types/either.js +3 -0
  65. package/dist/types/input-error.js +7 -0
  66. package/dist/types/language.js +10 -0
  67. package/dist/types/traffictype.js +13 -0
  68. package/dist/types/validator.js +14 -0
  69. package/dist/utils/api-model.js +129 -0
  70. package/dist/utils/base64.js +21 -0
  71. package/dist/utils/date-utils.js +34 -0
  72. package/dist/utils/geojson-types.js +18 -0
  73. package/dist/utils/geometry.js +164 -0
  74. package/dist/utils/retry.js +50 -0
  75. package/dist/utils/slack.js +25 -0
  76. package/dist/utils/utils.js +75 -0
  77. package/jest.config.js +15 -0
  78. package/package.json +15 -13
  79. package/src/@types/geojson-validation/index.d.ts +4 -0
  80. package/src/aws/infra/api/integration.ts +73 -0
  81. package/src/aws/infra/api/response.ts +67 -0
  82. package/src/aws/infra/api/responses.ts +124 -0
  83. package/src/aws/infra/api/static-integration.ts +62 -0
  84. package/src/aws/infra/canaries/canary-alarm.ts +31 -0
  85. package/src/aws/infra/canaries/canary-keys.ts +3 -0
  86. package/{aws/infra/canaries/canary-parameters.d.ts → src/aws/infra/canaries/canary-parameters.ts} +7 -6
  87. package/src/aws/infra/canaries/canary-role.ts +47 -0
  88. package/src/aws/infra/canaries/canary.ts +46 -0
  89. package/src/aws/infra/canaries/database-canary.ts +98 -0
  90. package/src/aws/infra/canaries/database-checker.ts +155 -0
  91. package/src/aws/infra/canaries/url-canary.ts +74 -0
  92. package/src/aws/infra/canaries/url-checker.ts +366 -0
  93. package/src/aws/infra/documentation.ts +124 -0
  94. package/src/aws/infra/scheduler.ts +59 -0
  95. package/src/aws/infra/security-rule.ts +38 -0
  96. package/src/aws/infra/sqs-integration.ts +102 -0
  97. package/src/aws/infra/sqs-queue.ts +148 -0
  98. package/src/aws/infra/stack/lambda-configs.ts +207 -0
  99. package/src/aws/infra/stack/monitoredfunction.ts +342 -0
  100. package/src/aws/infra/stack/rest_apis.ts +223 -0
  101. package/src/aws/infra/stack/stack-checking-aspect.ts +279 -0
  102. package/src/aws/infra/stack/stack.ts +145 -0
  103. package/src/aws/infra/stack/subscription.ts +58 -0
  104. package/src/aws/infra/usage-plans.ts +41 -0
  105. package/src/aws/runtime/apikey.ts +9 -0
  106. package/src/aws/runtime/digitraffic-integration-response.ts +28 -0
  107. package/src/aws/runtime/environment.ts +9 -0
  108. package/src/aws/runtime/messaging.ts +26 -0
  109. package/src/aws/runtime/s3.ts +44 -0
  110. package/src/aws/runtime/secrets/dbsecret.ts +116 -0
  111. package/src/aws/runtime/secrets/proxy-holder.ts +37 -0
  112. package/src/aws/runtime/secrets/rds-holder.ts +33 -0
  113. package/src/aws/runtime/secrets/secret-holder.ts +116 -0
  114. package/src/aws/runtime/secrets/secret.ts +50 -0
  115. package/src/aws/types/errors.ts +14 -0
  116. package/src/aws/types/lambda-response.ts +43 -0
  117. package/{aws/types/mediatypes.d.ts → src/aws/types/mediatypes.ts} +4 -3
  118. package/{aws/types/model-with-reference.d.ts → src/aws/types/model-with-reference.ts} +2 -1
  119. package/src/aws/types/proxytypes.ts +27 -0
  120. package/src/aws/types/tags.ts +3 -0
  121. package/src/database/cached.ts +35 -0
  122. package/src/database/database.ts +96 -0
  123. package/src/database/last-updated.ts +59 -0
  124. package/{database/models.d.ts → src/database/models.ts} +1 -0
  125. package/src/marine/id_utils.ts +30 -0
  126. package/src/marine/rtz.ts +57 -0
  127. package/src/test/asserter.ts +48 -0
  128. package/src/test/db-testutils.ts +44 -0
  129. package/src/test/httpserver.ts +96 -0
  130. package/src/test/secret.ts +23 -0
  131. package/src/test/secrets-manager.ts +34 -0
  132. package/src/test/testutils.ts +39 -0
  133. package/src/types/either.ts +3 -0
  134. package/src/types/input-error.ts +2 -0
  135. package/src/types/language.ts +3 -0
  136. package/src/types/traffictype.ts +8 -0
  137. package/src/types/validator.ts +10 -0
  138. package/src/utils/api-model.ts +133 -0
  139. package/src/utils/base64.ts +16 -0
  140. package/src/utils/date-utils.ts +30 -0
  141. package/src/utils/geojson-types.ts +22 -0
  142. package/src/utils/geometry.ts +164 -0
  143. package/src/utils/retry.ts +49 -0
  144. package/src/utils/slack.ts +22 -0
  145. package/src/utils/utils.ts +105 -0
  146. package/test/marine/id_utils.test.ts +57 -0
  147. package/test/promise/promise.test.ts +143 -0
  148. package/test/secrets/dbsecret.test.ts +59 -0
  149. package/test/secrets/secret-holder.test.ts +143 -0
  150. package/test/secrets/secret.test.ts +49 -0
  151. package/test/test/httpserver.test.ts +128 -0
  152. package/test/utils/date-utils.test.ts +28 -0
  153. package/test/utils/geometry.test.ts +29 -0
  154. package/test/utils/utils.test.ts +64 -0
  155. package/tsconfig.eslint.json +4 -0
  156. package/tsconfig.json +22 -0
  157. package/yarn.lock +4060 -0
  158. package/aws/infra/api/integration.d.ts +0 -21
  159. package/aws/infra/api/integration.js +0 -52
  160. package/aws/infra/api/response.d.ts +0 -22
  161. package/aws/infra/api/response.js +0 -61
  162. package/aws/infra/api/responses.d.ts +0 -39
  163. package/aws/infra/api/responses.js +0 -79
  164. package/aws/infra/api/static-integration.d.ts +0 -15
  165. package/aws/infra/api/static-integration.js +0 -54
  166. package/aws/infra/canaries/canary-alarm.d.ts +0 -6
  167. package/aws/infra/canaries/canary-alarm.js +0 -26
  168. package/aws/infra/canaries/canary-parameters.js +0 -3
  169. package/aws/infra/canaries/canary-role.d.ts +0 -6
  170. package/aws/infra/canaries/canary-role.js +0 -46
  171. package/aws/infra/canaries/canary.d.ts +0 -8
  172. package/aws/infra/canaries/canary.js +0 -32
  173. package/aws/infra/canaries/database-canary.d.ts +0 -18
  174. package/aws/infra/canaries/database-canary.js +0 -55
  175. package/aws/infra/canaries/database-checker.d.ts +0 -21
  176. package/aws/infra/canaries/database-checker.js +0 -109
  177. package/aws/infra/canaries/url-canary.d.ts +0 -19
  178. package/aws/infra/canaries/url-canary.js +0 -46
  179. package/aws/infra/canaries/url-checker.d.ts +0 -46
  180. package/aws/infra/canaries/url-checker.js +0 -238
  181. package/aws/infra/documentation.d.ts +0 -56
  182. package/aws/infra/documentation.js +0 -95
  183. package/aws/infra/scheduler.d.ts +0 -12
  184. package/aws/infra/scheduler.js +0 -31
  185. package/aws/infra/security-rule.d.ts +0 -12
  186. package/aws/infra/security-rule.js +0 -39
  187. package/aws/infra/sqs-integration.d.ts +0 -7
  188. package/aws/infra/sqs-integration.js +0 -93
  189. package/aws/infra/sqs-queue.d.ts +0 -16
  190. package/aws/infra/sqs-queue.js +0 -130
  191. package/aws/infra/stack/lambda-configs.d.ts +0 -72
  192. package/aws/infra/stack/lambda-configs.js +0 -93
  193. package/aws/infra/stack/monitoredfunction.d.ts +0 -84
  194. package/aws/infra/stack/monitoredfunction.js +0 -135
  195. package/aws/infra/stack/rest_apis.d.ts +0 -41
  196. package/aws/infra/stack/rest_apis.js +0 -185
  197. package/aws/infra/stack/stack-checking-aspect.d.ts +0 -21
  198. package/aws/infra/stack/stack-checking-aspect.js +0 -174
  199. package/aws/infra/stack/stack.d.ts +0 -44
  200. package/aws/infra/stack/stack.js +0 -60
  201. package/aws/infra/stack/subscription.d.ts +0 -17
  202. package/aws/infra/stack/subscription.js +0 -41
  203. package/aws/infra/usage-plans.d.ts +0 -15
  204. package/aws/infra/usage-plans.js +0 -42
  205. package/aws/runtime/apikey.d.ts +0 -2
  206. package/aws/runtime/apikey.js +0 -13
  207. package/aws/runtime/digitraffic-integration-response.d.ts +0 -8
  208. package/aws/runtime/digitraffic-integration-response.js +0 -26
  209. package/aws/runtime/environment.d.ts +0 -1
  210. package/aws/runtime/environment.js +0 -12
  211. package/aws/runtime/messaging.d.ts +0 -10
  212. package/aws/runtime/messaging.js +0 -31
  213. package/aws/runtime/s3.d.ts +0 -2
  214. package/aws/runtime/s3.js +0 -30
  215. package/aws/runtime/secrets/dbsecret.d.ts +0 -54
  216. package/aws/runtime/secrets/dbsecret.js +0 -96
  217. package/aws/runtime/secrets/proxy-holder.d.ts +0 -9
  218. package/aws/runtime/secrets/proxy-holder.js +0 -26
  219. package/aws/runtime/secrets/rds-holder.d.ts +0 -9
  220. package/aws/runtime/secrets/rds-holder.js +0 -26
  221. package/aws/runtime/secrets/secret-holder.d.ts +0 -26
  222. package/aws/runtime/secrets/secret-holder.js +0 -73
  223. package/aws/runtime/secrets/secret.d.ts +0 -8
  224. package/aws/runtime/secrets/secret.js +0 -43
  225. package/aws/types/errors.d.ts +0 -4
  226. package/aws/types/errors.js +0 -9
  227. package/aws/types/lambda-response.d.ts +0 -12
  228. package/aws/types/lambda-response.js +0 -28
  229. package/aws/types/mediatypes.js +0 -15
  230. package/aws/types/model-with-reference.js +0 -3
  231. package/aws/types/proxytypes.d.ts +0 -26
  232. package/aws/types/proxytypes.js +0 -3
  233. package/aws/types/tags.d.ts +0 -2
  234. package/aws/types/tags.js +0 -7
  235. package/database/cached.d.ts +0 -7
  236. package/database/cached.js +0 -32
  237. package/database/database.d.ts +0 -19
  238. package/database/database.js +0 -62
  239. package/database/last-updated.d.ts +0 -16
  240. package/database/last-updated.js +0 -54
  241. package/database/models.js +0 -3
  242. package/index.d.ts +0 -1
  243. package/index.js +0 -18
  244. package/marine/id_utils.d.ts +0 -3
  245. package/marine/id_utils.js +0 -33
  246. package/marine/rtz.d.ts +0 -48
  247. package/marine/rtz.js +0 -3
  248. package/test/asserter.d.ts +0 -11
  249. package/test/asserter.js +0 -45
  250. package/test/db-testutils.d.ts +0 -2
  251. package/test/db-testutils.js +0 -31
  252. package/test/httpserver.d.ts +0 -18
  253. package/test/httpserver.js +0 -67
  254. package/test/secret.d.ts +0 -3
  255. package/test/secret.js +0 -25
  256. package/test/secrets-manager.d.ts +0 -9
  257. package/test/secrets-manager.js +0 -59
  258. package/test/testutils.d.ts +0 -12
  259. package/test/testutils.js +0 -44
  260. package/types/input-error.d.ts +0 -2
  261. package/types/input-error.js +0 -7
  262. package/types/language.d.ts +0 -5
  263. package/types/language.js +0 -10
  264. package/types/traffictype.d.ts +0 -8
  265. package/types/traffictype.js +0 -13
  266. package/types/validator.d.ts +0 -4
  267. package/types/validator.js +0 -14
  268. package/utils/api-model.d.ts +0 -87
  269. package/utils/api-model.js +0 -129
  270. package/utils/base64.d.ts +0 -12
  271. package/utils/base64.js +0 -21
  272. package/utils/date-utils.d.ts +0 -17
  273. package/utils/date-utils.js +0 -34
  274. package/utils/geojson-types.d.ts +0 -14
  275. package/utils/geojson-types.js +0 -18
  276. package/utils/geometry.d.ts +0 -36
  277. package/utils/geometry.js +0 -140
  278. package/utils/retry.d.ts +0 -13
  279. package/utils/retry.js +0 -50
  280. package/utils/slack.d.ts +0 -5
  281. package/utils/slack.js +0 -25
  282. package/utils/utils.d.ts +0 -30
  283. package/utils/utils.js +0 -64
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseChecker = void 0;
4
+ const database_1 = require("../../../database/database");
5
+ const proxy_holder_1 = require("../../runtime/secrets/proxy-holder");
6
+ const rds_holder_1 = require("../../runtime/secrets/rds-holder");
7
+ const utils_1 = require("../../../utils/utils");
8
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
9
+ const synthetics = require("Synthetics");
10
+ class DatabaseCheck {
11
+ constructor(name, sql) {
12
+ this.name = name;
13
+ this.sql = sql;
14
+ this.failed = false;
15
+ }
16
+ }
17
+ class CountDatabaseCheck extends DatabaseCheck {
18
+ constructor(name, sql, minCount, maxCount) {
19
+ super(name, sql);
20
+ if (minCount == null && maxCount == null) {
21
+ throw new Error("no max or min given!");
22
+ }
23
+ this.minCount = minCount;
24
+ this.maxCount = maxCount;
25
+ }
26
+ check(value) {
27
+ if (!value) {
28
+ this.failed = true;
29
+ throw new Error("no return value");
30
+ }
31
+ else {
32
+ if ("count" in value) {
33
+ if (this.minCount && value.count < this.minCount) {
34
+ this.failed = true;
35
+ throw new Error(`count was ${value.count}, minimum is ${this.minCount}`);
36
+ }
37
+ if (this.maxCount && value.count > this.maxCount) {
38
+ this.failed = true;
39
+ throw new Error(`count was ${value.count}, max is ${this.maxCount}`);
40
+ }
41
+ }
42
+ else {
43
+ this.failed = true;
44
+ console.info("received " + JSON.stringify(value));
45
+ throw new Error("no count available");
46
+ }
47
+ }
48
+ }
49
+ }
50
+ const stepConfig = {
51
+ continueOnStepFailure: true,
52
+ screenshotOnStepStart: false,
53
+ screenshotOnStepSuccess: false,
54
+ screenshotOnStepFailure: false,
55
+ };
56
+ class DatabaseChecker {
57
+ constructor(credentialsFunction) {
58
+ this.credentialsFunction = credentialsFunction;
59
+ this.checks = [];
60
+ synthetics.getConfiguration().disableRequestMetrics();
61
+ synthetics.getConfiguration().withFailedCanaryMetric(true);
62
+ }
63
+ static createForProxy() {
64
+ return new DatabaseChecker(() => new proxy_holder_1.ProxyHolder((0, utils_1.getEnvVariable)("SECRET_ID")).setCredentials());
65
+ }
66
+ static createForRds() {
67
+ return new DatabaseChecker(() => new rds_holder_1.RdsHolder((0, utils_1.getEnvVariable)("SECRET_ID")).setCredentials());
68
+ }
69
+ one(name, sql) {
70
+ this.checks.push(new CountDatabaseCheck(name, sql, 1, 1));
71
+ return this;
72
+ }
73
+ empty(name, sql) {
74
+ this.checks.push(new CountDatabaseCheck(name, sql, null, 0));
75
+ return this;
76
+ }
77
+ notEmpty(name, sql) {
78
+ this.checks.push(new CountDatabaseCheck(name, sql, 1, null));
79
+ return this;
80
+ }
81
+ async expect() {
82
+ if (!this.checks.length) {
83
+ throw new Error("No checks");
84
+ }
85
+ await this.credentialsFunction();
86
+ await (0, database_1.inDatabaseReadonly)(async (db) => {
87
+ for (const check of this.checks) {
88
+ console.info("canary checking sql " + check.sql);
89
+ const value = await db.oneOrNone(check.sql);
90
+ const checkFunction = () => {
91
+ check.check(value);
92
+ };
93
+ synthetics.executeStep(check.name, checkFunction, stepConfig);
94
+ }
95
+ });
96
+ if (this.checks.some((check) => check.failed)) {
97
+ throw new Error("Failed");
98
+ }
99
+ return "OK";
100
+ }
101
+ }
102
+ exports.DatabaseChecker = DatabaseChecker;
103
+ //# sourceMappingURL=database-checker.js.map
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UrlCanary = void 0;
4
+ const canary_1 = require("./canary");
5
+ const canary_keys_1 = require("./canary-keys");
6
+ class UrlCanary extends canary_1.DigitrafficCanary {
7
+ constructor(stack, role, params, secret) {
8
+ const canaryName = `${params.name}-url`;
9
+ const environmentVariables = {};
10
+ environmentVariables[canary_keys_1.ENV_HOSTNAME] = params.hostname;
11
+ if (params.secret) {
12
+ environmentVariables[canary_keys_1.ENV_SECRET] = params.secret;
13
+ }
14
+ if (params.apiKeyId) {
15
+ environmentVariables[canary_keys_1.ENV_API_KEY] = params.apiKeyId;
16
+ }
17
+ if (secret) {
18
+ secret.grantRead(role);
19
+ }
20
+ // the handler code is defined at the actual project using this
21
+ super(stack, canaryName, role, params, environmentVariables);
22
+ }
23
+ static create(stack, role, publicApi, params) {
24
+ return new UrlCanary(stack, role, {
25
+ ...{
26
+ handler: `${params.name}.handler`,
27
+ hostname: publicApi.hostname(),
28
+ apiKeyId: this.getApiKey(publicApi),
29
+ },
30
+ ...params,
31
+ });
32
+ }
33
+ static getApiKey(publicApi) {
34
+ const apiKeys = publicApi.apiKeyIds;
35
+ if (apiKeys.length > 1) {
36
+ console.info("rest api has more than one api key");
37
+ }
38
+ if (apiKeys.length === 0) {
39
+ console.info("rest api has no api keys");
40
+ return undefined;
41
+ }
42
+ // always use first api key
43
+ return publicApi.apiKeyIds[0];
44
+ }
45
+ }
46
+ exports.UrlCanary = UrlCanary;
47
+ //# sourceMappingURL=url-canary.js.map
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HeaderChecker = exports.GeoJsonChecker = exports.ContentTypeChecker = exports.ContentChecker = exports.ResponseChecker = exports.UrlChecker = exports.API_KEY_HEADER = void 0;
4
+ const asserter_1 = require("../../../test/asserter");
5
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
6
+ const synthetics = require("Synthetics");
7
+ const zlib = require("zlib");
8
+ const mediatypes_1 = require("../../types/mediatypes");
9
+ const apikey_1 = require("../../runtime/apikey");
10
+ const geometry_1 = require("../../../utils/geometry");
11
+ const utils_1 = require("../../../utils/utils");
12
+ const canary_keys_1 = require("./canary-keys");
13
+ exports.API_KEY_HEADER = "x-api-key";
14
+ const baseHeaders = {
15
+ "Digitraffic-User": "internal-digitraffic-canary",
16
+ "Accept-Encoding": "gzip",
17
+ Accept: "*/*",
18
+ };
19
+ class UrlChecker {
20
+ constructor(hostname, apiKey) {
21
+ const headers = { ...baseHeaders };
22
+ if (apiKey) {
23
+ headers[exports.API_KEY_HEADER] = apiKey;
24
+ }
25
+ this.requestOptions = {
26
+ hostname,
27
+ method: "GET",
28
+ protocol: "https:",
29
+ headers,
30
+ };
31
+ synthetics.getConfiguration().disableRequestMetrics();
32
+ synthetics
33
+ .getConfiguration()
34
+ .withIncludeRequestBody(false)
35
+ .withIncludeRequestHeaders(false)
36
+ .withIncludeResponseBody(false)
37
+ .withIncludeResponseHeaders(false)
38
+ .withFailedCanaryMetric(true);
39
+ }
40
+ static create(hostname, apiKeyId) {
41
+ return (0, apikey_1.getApiKeyFromAPIGateway)(apiKeyId).then((apiKey) => {
42
+ return new UrlChecker(hostname, apiKey.value);
43
+ });
44
+ }
45
+ static createV2() {
46
+ return this.create((0, utils_1.getEnvVariable)(canary_keys_1.ENV_HOSTNAME), (0, utils_1.getEnvVariable)(canary_keys_1.ENV_API_KEY));
47
+ }
48
+ expectStatus(statusCode, url, callback) {
49
+ const requestOptions = {
50
+ ...this.requestOptions,
51
+ ...{
52
+ path: url,
53
+ },
54
+ };
55
+ return synthetics.executeHttpStep(`Verify ${statusCode} for ${url.replace(/auth=.*/, "")}`, requestOptions, callback);
56
+ }
57
+ expect200(url, ...callbacks) {
58
+ const callback = async (json, body, res) => {
59
+ await Promise.allSettled(callbacks.map((c) => c(json, body, res)));
60
+ };
61
+ return this.expectStatus(200, url, callback);
62
+ }
63
+ expect404(url) {
64
+ const requestOptions = {
65
+ ...this.requestOptions,
66
+ ...{
67
+ path: url,
68
+ },
69
+ };
70
+ return synthetics.executeHttpStep(`Verify 404 for ${url}`, requestOptions, validateStatusCodeAndContentType(404, mediatypes_1.MediaType.TEXT_PLAIN));
71
+ }
72
+ expect400(url) {
73
+ const requestOptions = {
74
+ ...this.requestOptions,
75
+ ...{
76
+ path: url,
77
+ },
78
+ };
79
+ return synthetics.executeHttpStep(`Verify 400 for ${url}`, requestOptions, validateStatusCodeAndContentType(400, mediatypes_1.MediaType.TEXT_PLAIN));
80
+ }
81
+ expect403WithoutApiKey(url, mediaType) {
82
+ if (!this.requestOptions.headers ||
83
+ !this.requestOptions.headers[exports.API_KEY_HEADER]) {
84
+ console.error("No api key defined");
85
+ }
86
+ const requestOptions = {
87
+ ...this.requestOptions,
88
+ ...{
89
+ path: url,
90
+ headers: baseHeaders,
91
+ },
92
+ };
93
+ return synthetics.executeHttpStep(`Verify 403 for ${url}`, requestOptions, validateStatusCodeAndContentType(403, mediaType || mediatypes_1.MediaType.APPLICATION_JSON));
94
+ }
95
+ done() {
96
+ return "Canary successful";
97
+ }
98
+ }
99
+ exports.UrlChecker = UrlChecker;
100
+ async function getResponseBody(response) {
101
+ const body = await getBodyFromResponse(response);
102
+ if (response.headers["content-encoding"] === "gzip") {
103
+ try {
104
+ return zlib.gunzipSync(body).toString();
105
+ }
106
+ catch (e) {
107
+ console.info("error " + JSON.stringify(e));
108
+ }
109
+ }
110
+ return body.toString();
111
+ }
112
+ function getBodyFromResponse(response) {
113
+ return new Promise((resolve) => {
114
+ const buffers = [];
115
+ response.on("data", (data) => {
116
+ buffers.push(data);
117
+ });
118
+ response.on("end", () => {
119
+ resolve(Buffer.concat(buffers).toString());
120
+ });
121
+ });
122
+ }
123
+ /**
124
+ * Returns function, that validates that the status code and content-type from response are the given values
125
+ * @param statusCode
126
+ * @param contentType
127
+ */
128
+ function validateStatusCodeAndContentType(statusCode, contentType) {
129
+ return (res) => {
130
+ return new Promise((resolve) => {
131
+ if (res.statusCode !== statusCode) {
132
+ throw new Error(`${res.statusCode} ${res.statusMessage}`);
133
+ }
134
+ if (res.headers["content-type"] !== contentType) {
135
+ throw new Error("Wrong content-type " + res.headers["content-type"]);
136
+ }
137
+ resolve();
138
+ });
139
+ };
140
+ }
141
+ // DEPRECATED
142
+ class ResponseChecker {
143
+ constructor(contentType) {
144
+ this.checkCors = true;
145
+ this.contentType = contentType;
146
+ }
147
+ static forJson() {
148
+ return new ResponseChecker(mediatypes_1.MediaType.APPLICATION_JSON);
149
+ }
150
+ static forCSV() {
151
+ return new ResponseChecker(mediatypes_1.MediaType.TEXT_CSV);
152
+ }
153
+ static forGeojson() {
154
+ return new ResponseChecker(mediatypes_1.MediaType.APPLICATION_GEOJSON);
155
+ }
156
+ static forJpeg() {
157
+ return new ResponseChecker(mediatypes_1.MediaType.IMAGE_JPEG);
158
+ }
159
+ check() {
160
+ return this.responseChecker(() => {
161
+ // no need to do anything
162
+ });
163
+ }
164
+ checkJson(fn) {
165
+ return this.responseChecker((body, res) => {
166
+ fn(JSON.parse(body), body, res);
167
+ });
168
+ }
169
+ responseChecker(fn) {
170
+ return async (res) => {
171
+ if (!res.statusCode) {
172
+ throw new Error("statusCode missing");
173
+ }
174
+ if (res.statusCode < 200 || res.statusCode > 299) {
175
+ throw new Error(`${res.statusCode} ${res.statusMessage}`);
176
+ }
177
+ if (this.checkCors && !res.headers["access-control-allow-origin"]) {
178
+ throw new Error("CORS missing");
179
+ }
180
+ if (res.headers["content-type"] !== this.contentType) {
181
+ throw new Error("Wrong content-type " + res.headers["content-type"]);
182
+ }
183
+ const body = await getResponseBody(res);
184
+ fn(body, res);
185
+ };
186
+ }
187
+ }
188
+ exports.ResponseChecker = ResponseChecker;
189
+ class ContentChecker {
190
+ static checkJson(fn) {
191
+ return async (res) => {
192
+ const body = await getResponseBody(res);
193
+ fn(JSON.parse(body), body, res);
194
+ };
195
+ }
196
+ static checkResponse(fn) {
197
+ return async (res) => {
198
+ const body = await getResponseBody(res);
199
+ fn(body, res);
200
+ };
201
+ }
202
+ }
203
+ exports.ContentChecker = ContentChecker;
204
+ class ContentTypeChecker {
205
+ static checkContentType(contentType) {
206
+ return (res) => {
207
+ if (!res.statusCode) {
208
+ throw new Error("statusCode missing");
209
+ }
210
+ if (res.statusCode < 200 || res.statusCode > 299) {
211
+ throw new Error(`${res.statusCode} ${res.statusMessage}`);
212
+ }
213
+ if (!res.headers["access-control-allow-origin"]) {
214
+ throw new Error("CORS missing");
215
+ }
216
+ if (res.headers["content-type"] !== contentType) {
217
+ throw new Error("Wrong content-type " + res.headers["content-type"]);
218
+ }
219
+ };
220
+ }
221
+ }
222
+ exports.ContentTypeChecker = ContentTypeChecker;
223
+ class GeoJsonChecker {
224
+ static validFeatureCollection(fn) {
225
+ return ResponseChecker.forGeojson().checkJson((json) => {
226
+ asserter_1.Asserter.assertEquals(json.type, "FeatureCollection");
227
+ asserter_1.Asserter.assertTrue((0, geometry_1.isValidGeoJson)(json));
228
+ if (fn) {
229
+ fn(json);
230
+ }
231
+ });
232
+ }
233
+ }
234
+ exports.GeoJsonChecker = GeoJsonChecker;
235
+ class HeaderChecker {
236
+ static checkHeaderExists(headerName) {
237
+ return (res) => {
238
+ if (!res.headers[headerName]) {
239
+ throw new Error("Missing header: " + headerName);
240
+ }
241
+ };
242
+ }
243
+ static checkHeaderMissing(headerName) {
244
+ return (res) => {
245
+ if (res.headers[headerName]) {
246
+ throw new Error("Header should not exist: " + headerName);
247
+ }
248
+ };
249
+ }
250
+ }
251
+ exports.HeaderChecker = HeaderChecker;
252
+ //# sourceMappingURL=url-checker.js.map
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DocumentationPart = exports.addTagsAndSummary = exports.addTags = exports.addDocumentation = exports.addQueryParameterDescription = void 0;
4
+ const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
5
+ // Documentation parts are objects that describe an API Gateway API or parts of an API
6
+ // https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-documenting-api.html
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
+ function addQueryParameterDescription(name, description, resource, stack) {
17
+ new aws_apigateway_1.CfnDocumentationPart(stack, `${name}Documentation`, {
18
+ restApiId: resource.api.restApiId,
19
+ location: {
20
+ type: 'QUERY_PARAMETER',
21
+ name,
22
+ path: resource.path,
23
+ },
24
+ properties: JSON.stringify({ description }),
25
+ });
26
+ }
27
+ exports.addQueryParameterDescription = addQueryParameterDescription;
28
+ /**
29
+ * Add a documentation part to a method
30
+ * @param methodDescription
31
+ * @param documentationProperties
32
+ * @param resource REST API resource
33
+ * @param stack CloudFormation stack
34
+ */
35
+ function addDocumentation(methodDescription, documentationProperties, resource, stack) {
36
+ new aws_apigateway_1.CfnDocumentationPart(stack, `${methodDescription}Documentation`, {
37
+ restApiId: resource.api.restApiId,
38
+ location: {
39
+ type: 'METHOD',
40
+ path: resource.path,
41
+ },
42
+ properties: JSON.stringify(documentationProperties),
43
+ });
44
+ }
45
+ exports.addDocumentation = addDocumentation;
46
+ /**
47
+ * Adds OpenAPI tags to an API method
48
+ * @param methodDescription Description of API method
49
+ * @param tags OpenAPI tags
50
+ * @param resource REST API resource
51
+ * @param stack CloudFormation stack
52
+ */
53
+ function addTags(methodDescription, tags, resource, stack) {
54
+ addDocumentation(methodDescription, { tags }, resource, stack);
55
+ }
56
+ exports.addTags = addTags;
57
+ /**
58
+ * Adds OpenAPI tags and a method summary to an API method
59
+ *
60
+ * @deprecated Use DigitrafficRestApi.documentResource
61
+ *
62
+ * @param methodDescription Description of API method
63
+ * @param tags OpenAPI tags
64
+ * @param summary OpenAPI summary
65
+ * @param resource REST API resource
66
+ * @param stack CloudFormation stack
67
+ */
68
+ function addTagsAndSummary(methodDescription, tags, summary, resource, stack) {
69
+ addDocumentation(methodDescription, { tags, summary }, resource, stack);
70
+ }
71
+ exports.addTagsAndSummary = addTagsAndSummary;
72
+ class DocumentationPart {
73
+ constructor(parameterName, documentationProperties, type) {
74
+ this.parameterName = parameterName;
75
+ this.documentationProperties = documentationProperties;
76
+ this.type = type;
77
+ }
78
+ deprecated(note) {
79
+ // deprecated is not supported ATM: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html
80
+ this.documentationProperties.deprecated = true;
81
+ this.documentationProperties.summary += '. ' + note;
82
+ return this;
83
+ }
84
+ static queryParameter(parameterName, description) {
85
+ return new DocumentationPart(parameterName, { description }, "QUERY_PARAMETER");
86
+ }
87
+ static pathParameter(parameterName, description) {
88
+ return new DocumentationPart(parameterName, { description }, "PATH_PARAMETER");
89
+ }
90
+ static method(tags, name, summary) {
91
+ return new DocumentationPart(name, { tags, summary }, "METHOD");
92
+ }
93
+ }
94
+ exports.DocumentationPart = DocumentationPart;
95
+ //# sourceMappingURL=documentation.js.map
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Scheduler = void 0;
4
+ const aws_events_1 = require("aws-cdk-lib/aws-events");
5
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
6
+ const aws_events_targets_1 = require("aws-cdk-lib/aws-events-targets");
7
+ class Scheduler extends aws_events_1.Rule {
8
+ constructor(stack, ruleName, schedule, lambda) {
9
+ super(stack, ruleName, { ruleName, schedule });
10
+ if (lambda) {
11
+ this.addTarget(new aws_events_targets_1.LambdaFunction(lambda));
12
+ }
13
+ }
14
+ static everyMinute(stack, ruleName, lambda) {
15
+ return Scheduler.every(stack, ruleName, aws_cdk_lib_1.Duration.minutes(1), lambda);
16
+ }
17
+ static everyMinutes(stack, ruleName, minutes, lambda) {
18
+ return Scheduler.every(stack, ruleName, aws_cdk_lib_1.Duration.minutes(minutes), lambda);
19
+ }
20
+ static everyHour(stack, ruleName, lambda) {
21
+ return Scheduler.every(stack, ruleName, aws_cdk_lib_1.Duration.hours(1), lambda);
22
+ }
23
+ static everyDay(stack, ruleName, lambda) {
24
+ return Scheduler.every(stack, ruleName, aws_cdk_lib_1.Duration.days(1), lambda);
25
+ }
26
+ static every(stack, ruleName, duration, lambda) {
27
+ return new Scheduler(stack, ruleName, aws_events_1.Schedule.rate(duration), lambda);
28
+ }
29
+ }
30
+ exports.Scheduler = Scheduler;
31
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DigitrafficSecurityRule = void 0;
4
+ const aws_events_1 = require("aws-cdk-lib/aws-events");
5
+ const aws_events_targets_1 = require("aws-cdk-lib/aws-events-targets");
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
+ class DigitrafficSecurityRule extends aws_events_1.Rule {
13
+ constructor(scope, topic) {
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
+ this.addTarget(new aws_events_targets_1.SnsTopic(topic));
36
+ }
37
+ }
38
+ exports.DigitrafficSecurityRule = DigitrafficSecurityRule;
39
+ //# sourceMappingURL=security-rule.js.map
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.attachQueueToApiGatewayResource = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
6
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
7
+ function attachQueueToApiGatewayResource(stack, queue, resource, requestValidator, resourceName, apiKeyRequired, requestModels) {
8
+ // role for API Gateway
9
+ const apiGwRole = new aws_iam_1.Role(stack, `${resourceName}APIGatewayToSQSRole`, {
10
+ assumedBy: new aws_iam_1.ServicePrincipal('apigateway.amazonaws.com'),
11
+ });
12
+ // grants API Gateway the right to send SQS messages
13
+ apiGwRole.addToPolicy(new aws_iam_1.PolicyStatement({
14
+ resources: [
15
+ queue.queueArn,
16
+ ],
17
+ actions: [
18
+ 'sqs:SendMessage',
19
+ ],
20
+ }));
21
+ // grants API Gateway the right write CloudWatch Logs
22
+ apiGwRole.addToPolicy(new aws_iam_1.PolicyStatement({
23
+ resources: [
24
+ '*',
25
+ ],
26
+ actions: [
27
+ 'logs:CreateLogGroup',
28
+ 'logs:CreateLogStream',
29
+ 'logs:DescribeLogGroups',
30
+ 'logs:DescribeLogStreams',
31
+ 'logs:PutLogEvents',
32
+ 'logs:GetLogEvents',
33
+ 'logs:FilterLogEvents',
34
+ ],
35
+ }));
36
+ // create an integration between API Gateway and an SQS queue
37
+ const fifoMessageGroupId = queue.fifo ? '&MessageGroupId=AlwaysSameFifoGroup' : '';
38
+ const sqsIntegration = new aws_apigateway_1.AwsIntegration({
39
+ service: 'sqs',
40
+ integrationHttpMethod: 'POST',
41
+ options: {
42
+ passthroughBehavior: aws_apigateway_1.PassthroughBehavior.NEVER,
43
+ credentialsRole: apiGwRole,
44
+ requestParameters: {
45
+ // SQS requires the Content-Type of the HTTP request to be application/x-www-form-urlencoded
46
+ 'integration.request.header.Content-Type': "'application/x-www-form-urlencoded'",
47
+ },
48
+ requestTemplates: {
49
+ // map the JSON request to a form parameter, FIFO needs also MessageGroupId
50
+ // https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html
51
+ 'application/json': `Action=SendMessage${fifoMessageGroupId}&MessageBody=$util.urlEncode($input.body)`,
52
+ },
53
+ // these are required by SQS
54
+ integrationResponses: [
55
+ {
56
+ statusCode: '200',
57
+ responseTemplates: {
58
+ 'text/html': 'Success',
59
+ },
60
+ },
61
+ {
62
+ statusCode: '500',
63
+ responseTemplates: {
64
+ 'text/html': 'Error',
65
+ },
66
+ selectionPattern: '500',
67
+ },
68
+ ],
69
+ },
70
+ path: `${aws_cdk_lib_1.Aws.ACCOUNT_ID}/${queue.queueName}`,
71
+ });
72
+ resource.addMethod('POST', sqsIntegration, {
73
+ requestValidator,
74
+ apiKeyRequired,
75
+ requestModels: requestModels ?? {},
76
+ methodResponses: [
77
+ {
78
+ statusCode: '200',
79
+ responseParameters: {
80
+ 'method.response.header.Content-Type': true,
81
+ },
82
+ },
83
+ {
84
+ statusCode: '500',
85
+ responseParameters: {
86
+ 'method.response.header.Content-Type': true,
87
+ },
88
+ },
89
+ ],
90
+ });
91
+ }
92
+ exports.attachQueueToApiGatewayResource = attachQueueToApiGatewayResource;
93
+ //# sourceMappingURL=sqs-integration.js.map