@digitraffic/common 2022.10.25-1 → 2022.10.28-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.
Files changed (332) hide show
  1. package/{aws → dist/aws}/infra/api/integration.d.ts +0 -0
  2. package/dist/aws/infra/api/integration.js +52 -0
  3. package/dist/aws/infra/api/integration.js.map +1 -0
  4. package/{aws → dist/aws}/infra/api/response.d.ts +0 -0
  5. package/dist/aws/infra/api/response.js +61 -0
  6. package/dist/aws/infra/api/response.js.map +1 -0
  7. package/{aws → dist/aws}/infra/api/responses.d.ts +3 -3
  8. package/dist/aws/infra/api/responses.js +82 -0
  9. package/dist/aws/infra/api/responses.js.map +1 -0
  10. package/{aws → dist/aws}/infra/api/static-integration.d.ts +0 -0
  11. package/dist/aws/infra/api/static-integration.js +54 -0
  12. package/dist/aws/infra/api/static-integration.js.map +1 -0
  13. package/{aws → dist/aws}/infra/canaries/canary-alarm.d.ts +0 -0
  14. package/dist/aws/infra/canaries/canary-alarm.js +26 -0
  15. package/dist/aws/infra/canaries/canary-alarm.js.map +1 -0
  16. package/dist/aws/infra/canaries/canary-keys.d.ts +3 -0
  17. package/dist/aws/infra/canaries/canary-keys.js +7 -0
  18. package/dist/aws/infra/canaries/canary-keys.js.map +1 -0
  19. package/{aws → dist/aws}/infra/canaries/canary-parameters.d.ts +0 -0
  20. package/dist/aws/infra/canaries/canary-parameters.js +3 -0
  21. package/dist/aws/infra/canaries/canary-parameters.js.map +1 -0
  22. package/{aws → dist/aws}/infra/canaries/canary-role.d.ts +0 -0
  23. package/dist/aws/infra/canaries/canary-role.js +46 -0
  24. package/dist/aws/infra/canaries/canary-role.js.map +1 -0
  25. package/{aws → dist/aws}/infra/canaries/canary.d.ts +0 -0
  26. package/dist/aws/infra/canaries/canary.js +32 -0
  27. package/dist/aws/infra/canaries/canary.js.map +1 -0
  28. package/{aws → dist/aws}/infra/canaries/database-canary.d.ts +0 -0
  29. package/dist/aws/infra/canaries/database-canary.js +70 -0
  30. package/dist/aws/infra/canaries/database-canary.js.map +1 -0
  31. package/{aws → dist/aws}/infra/canaries/database-checker.d.ts +2 -2
  32. package/dist/aws/infra/canaries/database-checker.js +103 -0
  33. package/dist/aws/infra/canaries/database-checker.js.map +1 -0
  34. package/{aws → dist/aws}/infra/canaries/url-canary.d.ts +0 -3
  35. package/dist/aws/infra/canaries/url-canary.js +47 -0
  36. package/dist/aws/infra/canaries/url-canary.js.map +1 -0
  37. package/{aws → dist/aws}/infra/canaries/url-checker.d.ts +0 -0
  38. package/dist/aws/infra/canaries/url-checker.js +252 -0
  39. package/dist/aws/infra/canaries/url-checker.js.map +1 -0
  40. package/{aws → dist/aws}/infra/documentation.d.ts +0 -0
  41. package/dist/aws/infra/documentation.js +95 -0
  42. package/dist/aws/infra/documentation.js.map +1 -0
  43. package/{aws → dist/aws}/infra/scheduler.d.ts +7 -7
  44. package/dist/aws/infra/scheduler.js +31 -0
  45. package/dist/aws/infra/scheduler.js.map +1 -0
  46. package/{aws → dist/aws}/infra/security-rule.d.ts +0 -0
  47. package/dist/aws/infra/security-rule.js +39 -0
  48. package/dist/aws/infra/security-rule.js.map +1 -0
  49. package/{aws → dist/aws}/infra/sqs-integration.d.ts +0 -0
  50. package/dist/aws/infra/sqs-integration.js +93 -0
  51. package/dist/aws/infra/sqs-integration.js.map +1 -0
  52. package/{aws → dist/aws}/infra/sqs-queue.d.ts +0 -0
  53. package/dist/aws/infra/sqs-queue.js +130 -0
  54. package/dist/aws/infra/sqs-queue.js.map +1 -0
  55. package/{aws → dist/aws}/infra/stack/lambda-configs.d.ts +5 -5
  56. package/dist/aws/infra/stack/lambda-configs.js +105 -0
  57. package/dist/aws/infra/stack/lambda-configs.js.map +1 -0
  58. package/{aws → dist/aws}/infra/stack/monitoredfunction.d.ts +1 -1
  59. package/dist/aws/infra/stack/monitoredfunction.js +143 -0
  60. package/dist/aws/infra/stack/monitoredfunction.js.map +1 -0
  61. package/{aws → dist/aws}/infra/stack/rest_apis.d.ts +0 -0
  62. package/dist/aws/infra/stack/rest_apis.js +185 -0
  63. package/dist/aws/infra/stack/rest_apis.js.map +1 -0
  64. package/{aws → dist/aws}/infra/stack/stack-checking-aspect.d.ts +0 -0
  65. package/dist/aws/infra/stack/stack-checking-aspect.js +174 -0
  66. package/dist/aws/infra/stack/stack-checking-aspect.js.map +1 -0
  67. package/{aws → dist/aws}/infra/stack/stack.d.ts +5 -4
  68. package/dist/aws/infra/stack/stack.js +67 -0
  69. package/dist/aws/infra/stack/stack.js.map +1 -0
  70. package/{aws → dist/aws}/infra/stack/subscription.d.ts +3 -3
  71. package/dist/aws/infra/stack/subscription.js +42 -0
  72. package/dist/aws/infra/stack/subscription.js.map +1 -0
  73. package/{aws → dist/aws}/infra/usage-plans.d.ts +0 -0
  74. package/dist/aws/infra/usage-plans.js +42 -0
  75. package/dist/aws/infra/usage-plans.js.map +1 -0
  76. package/{aws → dist/aws}/runtime/apikey.d.ts +0 -0
  77. package/dist/aws/runtime/apikey.js +13 -0
  78. package/dist/aws/runtime/apikey.js.map +1 -0
  79. package/{aws → dist/aws}/runtime/digitraffic-integration-response.d.ts +0 -0
  80. package/dist/aws/runtime/digitraffic-integration-response.js +26 -0
  81. package/dist/aws/runtime/digitraffic-integration-response.js.map +1 -0
  82. package/{aws → dist/aws}/runtime/environment.d.ts +0 -0
  83. package/dist/aws/runtime/environment.js +12 -0
  84. package/dist/aws/runtime/environment.js.map +1 -0
  85. package/{aws → dist/aws}/runtime/messaging.d.ts +0 -0
  86. package/dist/aws/runtime/messaging.js +31 -0
  87. package/dist/aws/runtime/messaging.js.map +1 -0
  88. package/{aws → dist/aws}/runtime/s3.d.ts +0 -0
  89. package/dist/aws/runtime/s3.js +30 -0
  90. package/dist/aws/runtime/s3.js.map +1 -0
  91. package/{aws → dist/aws}/runtime/secrets/dbsecret.d.ts +0 -0
  92. package/dist/aws/runtime/secrets/dbsecret.js +96 -0
  93. package/dist/aws/runtime/secrets/dbsecret.js.map +1 -0
  94. package/{aws → dist/aws}/runtime/secrets/proxy-holder.d.ts +0 -0
  95. package/dist/aws/runtime/secrets/proxy-holder.js +27 -0
  96. package/dist/aws/runtime/secrets/proxy-holder.js.map +1 -0
  97. package/{aws → dist/aws}/runtime/secrets/rds-holder.d.ts +0 -0
  98. package/dist/aws/runtime/secrets/rds-holder.js +27 -0
  99. package/dist/aws/runtime/secrets/rds-holder.js.map +1 -0
  100. package/{aws → dist/aws}/runtime/secrets/secret-holder.d.ts +0 -0
  101. package/dist/aws/runtime/secrets/secret-holder.js +76 -0
  102. package/dist/aws/runtime/secrets/secret-holder.js.map +1 -0
  103. package/{aws → dist/aws}/runtime/secrets/secret.d.ts +0 -0
  104. package/dist/aws/runtime/secrets/secret.js +43 -0
  105. package/dist/aws/runtime/secrets/secret.js.map +1 -0
  106. package/{aws → dist/aws}/types/errors.d.ts +4 -0
  107. package/dist/aws/types/errors.js +16 -0
  108. package/dist/aws/types/errors.js.map +1 -0
  109. package/{aws → dist/aws}/types/lambda-response.d.ts +4 -3
  110. package/dist/aws/types/lambda-response.js +33 -0
  111. package/dist/aws/types/lambda-response.js.map +1 -0
  112. package/{aws → dist/aws}/types/mediatypes.d.ts +1 -1
  113. package/dist/aws/types/mediatypes.js +16 -0
  114. package/dist/aws/types/mediatypes.js.map +1 -0
  115. package/{aws → dist/aws}/types/model-with-reference.d.ts +0 -0
  116. package/dist/aws/types/model-with-reference.js +3 -0
  117. package/dist/aws/types/model-with-reference.js.map +1 -0
  118. package/{aws → dist/aws}/types/proxytypes.d.ts +0 -0
  119. package/dist/aws/types/proxytypes.js +3 -0
  120. package/dist/aws/types/proxytypes.js.map +1 -0
  121. package/{aws → dist/aws}/types/tags.d.ts +0 -0
  122. package/dist/aws/types/tags.js +7 -0
  123. package/dist/aws/types/tags.js.map +1 -0
  124. package/{database → dist/database}/cached.d.ts +0 -0
  125. package/dist/database/cached.js +32 -0
  126. package/dist/database/cached.js.map +1 -0
  127. package/{database → dist/database}/database.d.ts +0 -0
  128. package/dist/database/database.js +70 -0
  129. package/dist/database/database.js.map +1 -0
  130. package/{database → dist/database}/last-updated.d.ts +0 -0
  131. package/dist/database/last-updated.js +54 -0
  132. package/dist/database/last-updated.js.map +1 -0
  133. package/{database → dist/database}/models.d.ts +0 -0
  134. package/dist/database/models.js +3 -0
  135. package/dist/database/models.js.map +1 -0
  136. package/{marine → dist/marine}/id_utils.d.ts +0 -0
  137. package/dist/marine/id_utils.js +33 -0
  138. package/dist/marine/id_utils.js.map +1 -0
  139. package/{marine → dist/marine}/rtz.d.ts +0 -0
  140. package/dist/marine/rtz.js +3 -0
  141. package/dist/marine/rtz.js.map +1 -0
  142. package/{test → dist/test}/asserter.d.ts +0 -0
  143. package/dist/test/asserter.js +45 -0
  144. package/dist/test/asserter.js.map +1 -0
  145. package/{test → dist/test}/db-testutils.d.ts +0 -0
  146. package/dist/test/db-testutils.js +31 -0
  147. package/dist/test/db-testutils.js.map +1 -0
  148. package/{test → dist/test}/httpserver.d.ts +2 -1
  149. package/dist/test/httpserver.js +74 -0
  150. package/dist/test/httpserver.js.map +1 -0
  151. package/{test → dist/test}/secret.d.ts +0 -0
  152. package/dist/test/secret.js +25 -0
  153. package/dist/test/secret.js.map +1 -0
  154. package/{test → dist/test}/secrets-manager.d.ts +0 -0
  155. package/dist/test/secrets-manager.js +59 -0
  156. package/dist/test/secrets-manager.js.map +1 -0
  157. package/{test → dist/test}/testutils.d.ts +0 -0
  158. package/dist/test/testutils.js +44 -0
  159. package/dist/test/testutils.js.map +1 -0
  160. package/dist/types/either.d.ts +9 -0
  161. package/dist/types/either.js +3 -0
  162. package/dist/types/either.js.map +1 -0
  163. package/{types → dist/types}/input-error.d.ts +0 -0
  164. package/dist/types/input-error.js +7 -0
  165. package/dist/types/input-error.js.map +1 -0
  166. package/{types → dist/types}/language.d.ts +0 -0
  167. package/dist/types/language.js +10 -0
  168. package/dist/types/language.js.map +1 -0
  169. package/{types → dist/types}/traffictype.d.ts +0 -0
  170. package/dist/types/traffictype.js +13 -0
  171. package/dist/types/traffictype.js.map +1 -0
  172. package/{types → dist/types}/validator.d.ts +0 -0
  173. package/dist/types/validator.js +14 -0
  174. package/dist/types/validator.js.map +1 -0
  175. package/{utils → dist/utils}/api-model.d.ts +0 -0
  176. package/dist/utils/api-model.js +129 -0
  177. package/dist/utils/api-model.js.map +1 -0
  178. package/{utils → dist/utils}/base64.d.ts +0 -0
  179. package/dist/utils/base64.js +21 -0
  180. package/dist/utils/base64.js.map +1 -0
  181. package/{utils → dist/utils}/date-utils.d.ts +0 -0
  182. package/dist/utils/date-utils.js +34 -0
  183. package/dist/utils/date-utils.js.map +1 -0
  184. package/{utils → dist/utils}/geojson-types.d.ts +0 -0
  185. package/dist/utils/geojson-types.js +18 -0
  186. package/dist/utils/geojson-types.js.map +1 -0
  187. package/{utils → dist/utils}/geometry.d.ts +0 -0
  188. package/dist/utils/geometry.js +164 -0
  189. package/dist/utils/geometry.js.map +1 -0
  190. package/{utils → dist/utils}/retry.d.ts +0 -0
  191. package/dist/utils/retry.js +50 -0
  192. package/dist/utils/retry.js.map +1 -0
  193. package/{utils → dist/utils}/slack.d.ts +0 -0
  194. package/dist/utils/slack.js +25 -0
  195. package/dist/utils/slack.js.map +1 -0
  196. package/{utils → dist/utils}/utils.d.ts +16 -0
  197. package/dist/utils/utils.js +75 -0
  198. package/dist/utils/utils.js.map +1 -0
  199. package/package.json +12 -10
  200. package/src/@types/geojson-validation/index.d.ts +4 -0
  201. package/src/aws/infra/api/integration.ts +73 -0
  202. package/src/aws/infra/api/response.ts +67 -0
  203. package/src/aws/infra/api/responses.ts +124 -0
  204. package/src/aws/infra/api/static-integration.ts +62 -0
  205. package/src/aws/infra/canaries/canary-alarm.ts +31 -0
  206. package/src/aws/infra/canaries/canary-keys.ts +3 -0
  207. package/src/aws/infra/canaries/canary-parameters.ts +19 -0
  208. package/src/aws/infra/canaries/canary-role.ts +47 -0
  209. package/src/aws/infra/canaries/canary.ts +46 -0
  210. package/src/aws/infra/canaries/database-canary.ts +98 -0
  211. package/src/aws/infra/canaries/database-checker.ts +155 -0
  212. package/src/aws/infra/canaries/url-canary.ts +74 -0
  213. package/src/aws/infra/canaries/url-checker.ts +366 -0
  214. package/src/aws/infra/documentation.ts +124 -0
  215. package/src/aws/infra/scheduler.ts +59 -0
  216. package/src/aws/infra/security-rule.ts +38 -0
  217. package/src/aws/infra/sqs-integration.ts +102 -0
  218. package/src/aws/infra/sqs-queue.ts +148 -0
  219. package/src/aws/infra/stack/lambda-configs.ts +207 -0
  220. package/src/aws/infra/stack/monitoredfunction.ts +342 -0
  221. package/src/aws/infra/stack/rest_apis.ts +223 -0
  222. package/src/aws/infra/stack/stack-checking-aspect.ts +279 -0
  223. package/src/aws/infra/stack/stack.ts +145 -0
  224. package/src/aws/infra/stack/subscription.ts +58 -0
  225. package/src/aws/infra/usage-plans.ts +41 -0
  226. package/src/aws/runtime/apikey.ts +9 -0
  227. package/src/aws/runtime/digitraffic-integration-response.ts +28 -0
  228. package/src/aws/runtime/environment.ts +9 -0
  229. package/src/aws/runtime/messaging.ts +26 -0
  230. package/src/aws/runtime/s3.ts +44 -0
  231. package/src/aws/runtime/secrets/dbsecret.ts +116 -0
  232. package/src/aws/runtime/secrets/proxy-holder.ts +37 -0
  233. package/src/aws/runtime/secrets/rds-holder.ts +33 -0
  234. package/src/aws/runtime/secrets/secret-holder.ts +116 -0
  235. package/src/aws/runtime/secrets/secret.ts +50 -0
  236. package/src/aws/types/errors.ts +14 -0
  237. package/src/aws/types/lambda-response.ts +43 -0
  238. package/src/aws/types/mediatypes.ts +11 -0
  239. package/src/aws/types/model-with-reference.ts +8 -0
  240. package/src/aws/types/proxytypes.ts +27 -0
  241. package/src/aws/types/tags.ts +3 -0
  242. package/src/database/cached.ts +35 -0
  243. package/src/database/database.ts +96 -0
  244. package/src/database/last-updated.ts +59 -0
  245. package/src/database/models.ts +7 -0
  246. package/src/marine/id_utils.ts +30 -0
  247. package/src/marine/rtz.ts +57 -0
  248. package/src/test/asserter.ts +48 -0
  249. package/src/test/db-testutils.ts +44 -0
  250. package/src/test/httpserver.ts +96 -0
  251. package/src/test/secret.ts +23 -0
  252. package/src/test/secrets-manager.ts +34 -0
  253. package/src/test/testutils.ts +39 -0
  254. package/src/types/either.ts +3 -0
  255. package/src/types/input-error.ts +2 -0
  256. package/src/types/language.ts +3 -0
  257. package/src/types/traffictype.ts +8 -0
  258. package/src/types/validator.ts +10 -0
  259. package/src/utils/api-model.ts +133 -0
  260. package/src/utils/base64.ts +16 -0
  261. package/src/utils/date-utils.ts +30 -0
  262. package/src/utils/geojson-types.ts +22 -0
  263. package/src/utils/geometry.ts +164 -0
  264. package/src/utils/retry.ts +49 -0
  265. package/src/utils/slack.ts +22 -0
  266. package/src/utils/utils.ts +105 -0
  267. package/aws/infra/api/integration.js +0 -52
  268. package/aws/infra/api/response.js +0 -61
  269. package/aws/infra/api/responses.js +0 -79
  270. package/aws/infra/api/static-integration.js +0 -54
  271. package/aws/infra/canaries/canary-alarm.js +0 -26
  272. package/aws/infra/canaries/canary-parameters.js +0 -3
  273. package/aws/infra/canaries/canary-role.js +0 -46
  274. package/aws/infra/canaries/canary.js +0 -32
  275. package/aws/infra/canaries/database-canary.js +0 -55
  276. package/aws/infra/canaries/database-checker.js +0 -109
  277. package/aws/infra/canaries/url-canary.js +0 -46
  278. package/aws/infra/canaries/url-checker.js +0 -238
  279. package/aws/infra/documentation.js +0 -95
  280. package/aws/infra/scheduler.js +0 -31
  281. package/aws/infra/security-rule.js +0 -39
  282. package/aws/infra/sqs-integration.js +0 -93
  283. package/aws/infra/sqs-queue.js +0 -130
  284. package/aws/infra/stack/lambda-configs.js +0 -93
  285. package/aws/infra/stack/monitoredfunction.js +0 -135
  286. package/aws/infra/stack/rest_apis.js +0 -185
  287. package/aws/infra/stack/stack-checking-aspect.js +0 -174
  288. package/aws/infra/stack/stack.js +0 -60
  289. package/aws/infra/stack/subscription.js +0 -41
  290. package/aws/infra/usage-plans.js +0 -42
  291. package/aws/runtime/apikey.js +0 -13
  292. package/aws/runtime/digitraffic-integration-response.js +0 -26
  293. package/aws/runtime/environment.js +0 -12
  294. package/aws/runtime/messaging.js +0 -31
  295. package/aws/runtime/s3.js +0 -30
  296. package/aws/runtime/secrets/dbsecret.js +0 -96
  297. package/aws/runtime/secrets/proxy-holder.js +0 -26
  298. package/aws/runtime/secrets/rds-holder.js +0 -26
  299. package/aws/runtime/secrets/secret-holder.js +0 -73
  300. package/aws/runtime/secrets/secret.js +0 -43
  301. package/aws/types/errors.js +0 -9
  302. package/aws/types/lambda-response.js +0 -28
  303. package/aws/types/mediatypes.js +0 -15
  304. package/aws/types/model-with-reference.js +0 -3
  305. package/aws/types/proxytypes.js +0 -3
  306. package/aws/types/tags.js +0 -7
  307. package/database/cached.js +0 -32
  308. package/database/database.js +0 -62
  309. package/database/last-updated.js +0 -54
  310. package/database/models.js +0 -3
  311. package/index.d.ts +0 -1
  312. package/index.js +0 -18
  313. package/marine/id_utils.js +0 -33
  314. package/marine/rtz.js +0 -3
  315. package/test/asserter.js +0 -45
  316. package/test/db-testutils.js +0 -31
  317. package/test/httpserver.js +0 -67
  318. package/test/secret.js +0 -25
  319. package/test/secrets-manager.js +0 -59
  320. package/test/testutils.js +0 -44
  321. package/types/input-error.js +0 -7
  322. package/types/language.js +0 -10
  323. package/types/traffictype.js +0 -13
  324. package/types/validator.js +0 -14
  325. package/utils/api-model.js +0 -129
  326. package/utils/base64.js +0 -21
  327. package/utils/date-utils.js +0 -34
  328. package/utils/geojson-types.js +0 -18
  329. package/utils/geometry.js +0 -140
  330. package/utils/retry.js +0 -50
  331. package/utils/slack.js +0 -25
  332. package/utils/utils.js +0 -64
@@ -0,0 +1,342 @@
1
+ import { Function, FunctionProps } from "aws-cdk-lib/aws-lambda";
2
+ import { Stack } from "aws-cdk-lib";
3
+ import { SnsAction } from "aws-cdk-lib/aws-cloudwatch-actions";
4
+ import { ComparisonOperator, Metric } from "aws-cdk-lib/aws-cloudwatch";
5
+ import { DigitrafficStack } from "../stack/stack";
6
+ import { ITopic } from "aws-cdk-lib/aws-sns";
7
+ import {
8
+ databaseFunctionProps,
9
+ LambdaEnvironment,
10
+ MonitoredFunctionParameters,
11
+ } from "../stack/lambda-configs";
12
+ import { pascalCase } from "change-case";
13
+ import { DigitrafficLogSubscriptions } from "../stack/subscription";
14
+ import { TrafficType } from "../../../types/traffictype";
15
+
16
+ /**
17
+ * Allows customization of CloudWatch Alarm properties
18
+ */
19
+ export type MonitoredFunctionAlarmProps = {
20
+ /**
21
+ * Setting this to false will not create a CloudWatch alarm
22
+ */
23
+ readonly create: boolean;
24
+
25
+ readonly threshold?: number;
26
+
27
+ readonly evaluationPeriods?: number;
28
+
29
+ readonly datapointsToAlarm?: number;
30
+
31
+ readonly comparisonOperator?: ComparisonOperator;
32
+ };
33
+
34
+ export type MonitoredFunctionProps = {
35
+ readonly durationAlarmProps?: MonitoredFunctionAlarmProps;
36
+
37
+ readonly durationWarningProps?: MonitoredFunctionAlarmProps;
38
+
39
+ readonly errorAlarmProps?: MonitoredFunctionAlarmProps;
40
+
41
+ readonly throttleAlarmProps?: MonitoredFunctionAlarmProps;
42
+ };
43
+
44
+ /**
45
+ * Creates a Lambda function that monitors default CloudWatch Lambda metrics with CloudWatch Alarms.
46
+ */
47
+ export class MonitoredFunction extends Function {
48
+ readonly givenName: string;
49
+
50
+ /** disable all alarms */
51
+ public static readonly DISABLE_ALARMS: MonitoredFunctionProps = {
52
+ durationAlarmProps: {
53
+ create: false,
54
+ },
55
+ durationWarningProps: {
56
+ create: false,
57
+ },
58
+ errorAlarmProps: {
59
+ create: false,
60
+ },
61
+ throttleAlarmProps: {
62
+ create: false,
63
+ },
64
+ };
65
+
66
+ /**
67
+ * Create new MonitoredFunction. Use topics from given DigitrafficStack.
68
+ *
69
+ * @param stack DigitrafficStack
70
+ * @param id Lambda construct Id
71
+ * @param functionProps Lambda function properties
72
+ * @param props Monitored function properties
73
+ */
74
+ static create(
75
+ stack: DigitrafficStack,
76
+ id: string,
77
+ functionProps: FunctionProps,
78
+ props?: MonitoredFunctionProps
79
+ ): MonitoredFunction {
80
+ if (
81
+ props === MonitoredFunction.DISABLE_ALARMS &&
82
+ stack.configuration.production
83
+ ) {
84
+ throw new Error(
85
+ `Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`
86
+ );
87
+ }
88
+
89
+ return new MonitoredFunction(
90
+ stack,
91
+ id,
92
+ functionProps,
93
+ stack.alarmTopic,
94
+ stack.warningTopic,
95
+ stack.configuration.production,
96
+ stack.configuration.trafficType,
97
+ props
98
+ );
99
+ }
100
+
101
+ /**
102
+ * Create new MonitoredFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
103
+ *
104
+ * For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
105
+ *
106
+ * @param stack DigitrafficStack
107
+ * @param name param-case name
108
+ * @param environment Lambda environment
109
+ * @param functionParameters Lambda function parameters
110
+ */
111
+ static createV2(
112
+ stack: DigitrafficStack,
113
+ name: string,
114
+ environment: LambdaEnvironment,
115
+ functionParameters?: MonitoredFunctionParameters
116
+ ): MonitoredFunction {
117
+ const functionName =
118
+ functionParameters?.functionName ||
119
+ `${stack.configuration.shortName}-${pascalCase(name)}`;
120
+ const functionProps = databaseFunctionProps(
121
+ stack,
122
+ environment,
123
+ functionName,
124
+ name,
125
+ functionParameters
126
+ );
127
+
128
+ return MonitoredFunction.create(
129
+ stack,
130
+ functionName,
131
+ functionProps,
132
+ functionParameters
133
+ );
134
+ }
135
+
136
+ /**
137
+ * @param scope Stack
138
+ * @param id Lambda construct Id
139
+ * @param functionProps Lambda function properties
140
+ * @param alarmSnsTopic SNS topic for alarms
141
+ * @param warningSnsTopic SNS topic for warnings
142
+ * @param production Is the stack a production stack, used for determining the alarm topic
143
+ * @param trafficType Traffic type, used for alarm names. Set to null if Lambda is not related to any traffic type.
144
+ * @param props Monitored function properties
145
+ */
146
+ constructor(
147
+ scope: Stack,
148
+ id: string,
149
+ functionProps: FunctionProps,
150
+ alarmSnsTopic: ITopic,
151
+ warningSnsTopic: ITopic,
152
+ production: boolean,
153
+ trafficType: TrafficType | null,
154
+ props?: MonitoredFunctionProps
155
+ ) {
156
+ super(scope, id, functionProps);
157
+
158
+ if (functionProps.functionName === undefined) {
159
+ throw new Error("Function name not provided");
160
+ }
161
+ this.givenName = functionProps.functionName;
162
+
163
+ const alarmSnsAction = new SnsAction(alarmSnsTopic);
164
+ const warningSnsAction = new SnsAction(warningSnsTopic);
165
+
166
+ if (props?.durationAlarmProps?.create !== false) {
167
+ if (!functionProps.timeout) {
168
+ throw new Error("Timeout needs to be explicitly set");
169
+ }
170
+
171
+ this.createAlarm(
172
+ scope,
173
+ this.metricDuration().with({ statistic: "max" }),
174
+ "Duration",
175
+ "Duration alarm",
176
+ `Duration has exceeded ${functionProps.timeout.toSeconds()} seconds`,
177
+ trafficType,
178
+ this.getAlarmActionForEnv(
179
+ alarmSnsAction,
180
+ warningSnsAction,
181
+ production
182
+ ),
183
+ functionProps.timeout.toMilliseconds(),
184
+ 1,
185
+ 1,
186
+ ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
187
+ props?.durationAlarmProps
188
+ );
189
+ }
190
+ if (props?.durationWarningProps?.create !== false) {
191
+ if (!functionProps.timeout) {
192
+ throw new Error("Timeout needs to be explicitly set");
193
+ }
194
+
195
+ this.createAlarm(
196
+ scope,
197
+ this.metricDuration().with({ statistic: "max" }),
198
+ "Duration-Warning",
199
+ "Duration warning",
200
+ `Duration is 85 % of max ${functionProps.timeout.toSeconds()} seconds`,
201
+ trafficType,
202
+ warningSnsAction,
203
+ functionProps.timeout.toMilliseconds() * 0.85,
204
+ 1,
205
+ 1,
206
+ ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
207
+ props?.durationWarningProps
208
+ );
209
+ }
210
+
211
+ if (props?.errorAlarmProps?.create !== false) {
212
+ this.createAlarm(
213
+ scope,
214
+ this.metricErrors(),
215
+ "Errors",
216
+ "Errors alarm",
217
+ "Invocations did not succeed",
218
+ trafficType,
219
+ this.getAlarmActionForEnv(
220
+ alarmSnsAction,
221
+ warningSnsAction,
222
+ production
223
+ ),
224
+ 1,
225
+ 1,
226
+ 1,
227
+ ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
228
+ props?.errorAlarmProps
229
+ );
230
+ }
231
+
232
+ if (props?.throttleAlarmProps?.create !== false) {
233
+ this.createAlarm(
234
+ scope,
235
+ this.metricThrottles(),
236
+ "Throttles",
237
+ "Throttles alarm",
238
+ "Has throttled",
239
+ trafficType,
240
+ this.getAlarmActionForEnv(
241
+ alarmSnsAction,
242
+ warningSnsAction,
243
+ production
244
+ ),
245
+ 0,
246
+ 1,
247
+ 1,
248
+ ComparisonOperator.GREATER_THAN_THRESHOLD,
249
+ props?.throttleAlarmProps
250
+ );
251
+ }
252
+ }
253
+
254
+ private createAlarm(
255
+ stack: Stack,
256
+ metric: Metric,
257
+ alarmId: string,
258
+ alarmName: string,
259
+ alarmDescription: string,
260
+ trafficType: TrafficType | null,
261
+ alarmSnsAction: SnsAction,
262
+ threshold: number,
263
+ evaluationPeriods: number,
264
+ datapointsToAlarm: number,
265
+ comparisonOperator: ComparisonOperator,
266
+ alarmProps?: MonitoredFunctionAlarmProps
267
+ ) {
268
+ metric
269
+ .createAlarm(stack, `${this.node.id}-${alarmId}`, {
270
+ alarmName: `${trafficType ?? ""} ${stack.stackName} ${
271
+ this.functionName
272
+ } ${alarmName}`.trim(),
273
+ alarmDescription,
274
+ threshold: alarmProps?.threshold ?? threshold,
275
+ evaluationPeriods:
276
+ alarmProps?.evaluationPeriods ?? evaluationPeriods,
277
+ datapointsToAlarm:
278
+ alarmProps?.datapointsToAlarm ?? datapointsToAlarm,
279
+ comparisonOperator:
280
+ alarmProps?.comparisonOperator ?? comparisonOperator,
281
+ })
282
+ .addAlarmAction(alarmSnsAction);
283
+ }
284
+
285
+ private getAlarmActionForEnv(
286
+ alarmAction: SnsAction,
287
+ warningAction: SnsAction,
288
+ production: boolean
289
+ ): SnsAction {
290
+ return production ? alarmAction : warningAction;
291
+ }
292
+ }
293
+
294
+ export class MonitoredDBFunction {
295
+ /**
296
+ * Create new MonitoredDBFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
297
+ * Grant secret and create log subscription.
298
+ *
299
+ * For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
300
+ *
301
+ * If you don't need to pass any extra arguments to lambda-environment, you can leave environment out and this function will create the
302
+ * default Lambda Environment with SECRET_ID and DB_APPLICATION.
303
+ *
304
+ * @param stack DigitrafficStack
305
+ * @param name param-case name
306
+ * @param environment Lambda environment
307
+ * @param functionParameters Lambda function parameters
308
+ */
309
+ static create(
310
+ stack: DigitrafficStack,
311
+ name: string,
312
+ environment?: LambdaEnvironment,
313
+ functionParameters?: MonitoredFunctionParameters
314
+ ): MonitoredFunction {
315
+ const functionName =
316
+ functionParameters?.functionName ||
317
+ `${stack.configuration.shortName}-${pascalCase(name)}`;
318
+ const env = environment ? environment : stack.createLambdaEnvironment();
319
+ const functionProps = databaseFunctionProps(
320
+ stack,
321
+ env,
322
+ functionName,
323
+ name,
324
+ functionParameters
325
+ );
326
+
327
+ const mf = MonitoredFunction.create(
328
+ stack,
329
+ functionName,
330
+ functionProps,
331
+ functionParameters
332
+ );
333
+
334
+ stack.grantSecret(mf);
335
+
336
+ if (stack.configuration.logsDestinationArn) {
337
+ new DigitrafficLogSubscriptions(stack, mf);
338
+ }
339
+
340
+ return mf;
341
+ }
342
+ }
@@ -0,0 +1,223 @@
1
+ import {
2
+ RestApi,
3
+ MethodLoggingLevel,
4
+ GatewayResponse,
5
+ ResponseType,
6
+ EndpointType,
7
+ RestApiProps, JsonSchema, Model, CfnDocumentationPart, Resource,
8
+ } from 'aws-cdk-lib/aws-apigateway';
9
+ import {PolicyDocument, PolicyStatement, Effect, AnyPrincipal} from 'aws-cdk-lib/aws-iam';
10
+ import {Construct} from "constructs";
11
+ import {DigitrafficStack} from "./stack";
12
+ import {createDefaultUsagePlan, createUsagePlan} from "../usage-plans";
13
+ import {ModelWithReference} from "../../types/model-with-reference";
14
+ import {getModelReference} from "../../../utils/api-model";
15
+ import {MediaType} from "../../types/mediatypes";
16
+ import {DocumentationPart, DocumentationProperties} from "../documentation";
17
+
18
+ import R = require('ramda');
19
+
20
+ export class DigitrafficRestApi extends RestApi {
21
+ readonly apiKeyIds: string[];
22
+ readonly enableDocumentation: boolean;
23
+
24
+ constructor(
25
+ stack: DigitrafficStack, apiId: string, apiName: string, allowFromIpAddresses?: string[] | undefined, config?: Partial<RestApiProps>,
26
+ ) {
27
+ const policyDocument = allowFromIpAddresses == null ? createDefaultPolicyDocument() : createIpRestrictionPolicyDocument(allowFromIpAddresses);
28
+
29
+ // override default config with given extra config
30
+ const apiConfig = {...{
31
+ deployOptions: {
32
+ loggingLevel: MethodLoggingLevel.ERROR,
33
+ },
34
+ restApiName: apiName,
35
+ endpointTypes: [EndpointType.REGIONAL],
36
+ policy: policyDocument,
37
+ }, ...config};
38
+
39
+ super(stack, apiId, apiConfig);
40
+
41
+ this.apiKeyIds = [];
42
+ this.enableDocumentation = stack.configuration.stackFeatures?.enableDocumentation ?? true;
43
+
44
+ add404Support(this, stack);
45
+ }
46
+
47
+ hostname(): string {
48
+ return `${this.restApiId}.execute-api.${(this.stack as DigitrafficStack).region}.amazonaws.com`;
49
+ }
50
+
51
+ createUsagePlan(apiKeyId: string, apiKeyName: string): string {
52
+ const newKeyId = createUsagePlan(this, apiKeyId, apiKeyName).keyId;
53
+
54
+ this.apiKeyIds.push(newKeyId);
55
+
56
+ return newKeyId;
57
+ }
58
+
59
+ createUsagePlanV2(apiName: string): string {
60
+ const newKeyId = createDefaultUsagePlan(this, apiName).keyId;
61
+
62
+ this.apiKeyIds.push(newKeyId);
63
+
64
+ return newKeyId;
65
+ }
66
+
67
+ addJsonModel(modelName: string, schema: JsonSchema) {
68
+ return this.getModelWithReference(this.addModel(modelName, {
69
+ contentType: MediaType.APPLICATION_JSON,
70
+ modelName,
71
+ schema,
72
+ }));
73
+ }
74
+
75
+ addCSVModel(modelName: string) {
76
+ return this.getModelWithReference(this.addModel(modelName, {
77
+ contentType: MediaType.TEXT_CSV,
78
+ modelName,
79
+ schema: {},
80
+ }));
81
+ }
82
+
83
+ private getModelWithReference(model: Model): ModelWithReference {
84
+ return R.assoc('modelReference', getModelReference(model.modelId, this.restApiId), model) as ModelWithReference;
85
+ }
86
+
87
+ private addDocumentationPart(
88
+ resource: Resource, parameterName: string, resourceName: string, type: string, properties: DocumentationProperties,
89
+ ) {
90
+ const location: CfnDocumentationPart.LocationProperty = {
91
+ type,
92
+ path: resource.path,
93
+ name: type !== 'METHOD' ? parameterName : undefined,
94
+ };
95
+
96
+ new CfnDocumentationPart(this.stack, resourceName, {
97
+ restApiId: resource.api.restApiId,
98
+ location,
99
+ properties: JSON.stringify(properties),
100
+ });
101
+ }
102
+
103
+ documentResource(resource: Resource, ...documentationPart: DocumentationPart[]) {
104
+ if(this.enableDocumentation) {
105
+ documentationPart.forEach(dp => this.addDocumentationPart(
106
+ resource, dp.parameterName, `${resource.path}.${dp.parameterName}.Documentation`, dp.type, dp.documentationProperties,
107
+ ));
108
+ } else {
109
+ console.info("Skipping documentation for %s", resource.path);
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Due to AWS API design API Gateway will always return 403 'Missing Authentication Token' for requests
116
+ * with a non-existent endpoint. This function translates this response to a 404.
117
+ * Requests with an invalid or missing API key are not affected (still return 403 'Forbidden').
118
+ * @param restApi RestApi
119
+ * @param stack Construct
120
+ */
121
+ export function add404Support(restApi: RestApi, stack: Construct) {
122
+ new GatewayResponse(stack, `MissingAuthenticationTokenResponse-${restApi.restApiName}`, {
123
+ restApi,
124
+ type: ResponseType.MISSING_AUTHENTICATION_TOKEN,
125
+ statusCode: '404',
126
+ templates: {
127
+ 'application/json': '{"message": "Not found"}',
128
+ },
129
+ });
130
+ }
131
+
132
+ export function add401Support(restApi: RestApi, stack: Construct) {
133
+ new GatewayResponse(stack, `AuthenticationFailedResponse-${restApi.restApiName}`, {
134
+ restApi,
135
+ type: ResponseType.UNAUTHORIZED,
136
+ statusCode: "401",
137
+ responseHeaders: {
138
+ 'WWW-Authenticate': "'Basic'",
139
+ },
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Due to AWS API design API Gateway will always return 403 'Missing Authentication Token' for requests
145
+ * with a non-existent endpoint. This function converts this response to a custom one.
146
+ * Requests with an invalid or missing API key are not affected (still return 403 'Forbidden').
147
+ * @param returnCode
148
+ * @param message
149
+ * @param restApi RestApi
150
+ * @param stack Construct
151
+ */
152
+ export function setReturnCodeForMissingAuthenticationToken(returnCode: number,
153
+ message: string,
154
+ restApi: RestApi,
155
+ stack: Construct) {
156
+
157
+ new GatewayResponse(stack, `MissingAuthenticationTokenResponse-${restApi.restApiName}`, {
158
+ restApi,
159
+ type: ResponseType.MISSING_AUTHENTICATION_TOKEN,
160
+ statusCode: `${returnCode}`,
161
+ templates: {
162
+ 'application/json': `{"message": ${message}}`,
163
+ },
164
+ });
165
+ }
166
+
167
+ export function createRestApi(stack: Construct, apiId: string, apiName: string, allowFromIpAddresses?: string[] | undefined): RestApi {
168
+ const policyDocument = allowFromIpAddresses == null ? createDefaultPolicyDocument() : createIpRestrictionPolicyDocument(allowFromIpAddresses);
169
+ const restApi = new RestApi(stack, apiId, {
170
+ deployOptions: {
171
+ loggingLevel: MethodLoggingLevel.ERROR,
172
+ },
173
+ restApiName: apiName,
174
+ endpointTypes: [EndpointType.REGIONAL],
175
+ policy: policyDocument,
176
+ });
177
+ add404Support(restApi, stack);
178
+ return restApi;
179
+ }
180
+
181
+ export function createDefaultPolicyDocument() {
182
+ return new PolicyDocument({
183
+ statements: [
184
+ new PolicyStatement({
185
+ effect: Effect.ALLOW,
186
+ actions: [
187
+ "execute-api:Invoke",
188
+ ],
189
+ resources: [
190
+ "*",
191
+ ],
192
+ principals: [
193
+ new AnyPrincipal(),
194
+ ],
195
+ }),
196
+ ],
197
+ });
198
+ }
199
+
200
+
201
+ export function createIpRestrictionPolicyDocument(allowFromIpAddresses: string[]): PolicyDocument {
202
+ return new PolicyDocument({
203
+ statements: [
204
+ new PolicyStatement({
205
+ effect: Effect.ALLOW,
206
+ conditions: {
207
+ "IpAddress": {
208
+ "aws:SourceIp": allowFromIpAddresses,
209
+ },
210
+ },
211
+ actions: [
212
+ "execute-api:Invoke",
213
+ ],
214
+ resources: [
215
+ "*",
216
+ ],
217
+ principals: [
218
+ new AnyPrincipal(),
219
+ ],
220
+ }),
221
+ ],
222
+ });
223
+ }