@digitraffic/common 2026.3.17-1 → 2026.3.26-1-beta

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 (238) hide show
  1. package/README.md +18 -1
  2. package/dist/__test__/asserter.d.ts +13 -0
  3. package/dist/__test__/asserter.js +39 -0
  4. package/dist/__test__/db-testutils.d.ts +3 -0
  5. package/dist/__test__/db-testutils.js +38 -0
  6. package/dist/__test__/dependencies.test.d.ts +1 -0
  7. package/dist/__test__/dependencies.test.js +21 -0
  8. package/dist/__test__/imports.test.d.ts +1 -0
  9. package/dist/__test__/imports.test.js +318 -0
  10. package/dist/__test__/infra/acl-builder.test.d.ts +1 -0
  11. package/dist/__test__/infra/acl-builder.test.js +72 -0
  12. package/dist/__test__/infra/api/handler-factory.test.d.ts +1 -0
  13. package/dist/__test__/infra/api/handler-factory.test.js +42 -0
  14. package/dist/__test__/infra/api/integration.test.d.ts +1 -0
  15. package/dist/__test__/infra/api/integration.test.js +162 -0
  16. package/dist/__test__/infra/api/response.test.d.ts +1 -0
  17. package/dist/__test__/infra/api/response.test.js +77 -0
  18. package/dist/__test__/infra/api/static-integration.test.d.ts +1 -0
  19. package/dist/__test__/infra/api/static-integration.test.js +35 -0
  20. package/dist/__test__/infra/documentation.test.d.ts +1 -0
  21. package/dist/__test__/infra/documentation.test.js +38 -0
  22. package/dist/__test__/infra/scheduler.test.d.ts +1 -0
  23. package/dist/__test__/infra/scheduler.test.js +23 -0
  24. package/dist/__test__/infra/security-rule.test.d.ts +1 -0
  25. package/dist/__test__/infra/security-rule.test.js +21 -0
  26. package/dist/__test__/infra/stack/rest-apis.test.d.ts +1 -0
  27. package/dist/__test__/infra/stack/rest-apis.test.js +47 -0
  28. package/dist/__test__/marine/id_utils.test.d.ts +1 -0
  29. package/dist/__test__/marine/id_utils.test.js +45 -0
  30. package/dist/__test__/mock-ky.d.ts +2 -0
  31. package/dist/__test__/mock-ky.js +15 -0
  32. package/dist/__test__/promise/promise.test.d.ts +1 -0
  33. package/dist/__test__/promise/promise.test.js +126 -0
  34. package/dist/__test__/runtime/dt-logger.test.d.ts +1 -0
  35. package/dist/__test__/runtime/dt-logger.test.js +193 -0
  36. package/dist/__test__/secrets/secret-holder.test.d.ts +1 -0
  37. package/dist/__test__/secrets/secret-holder.test.js +96 -0
  38. package/dist/__test__/secrets/secret.test.d.ts +1 -0
  39. package/dist/__test__/secrets/secret.test.js +57 -0
  40. package/dist/__test__/stack/dt-function.test.d.ts +1 -0
  41. package/dist/__test__/stack/dt-function.test.js +340 -0
  42. package/dist/__test__/stack/rest-apis.test.d.ts +1 -0
  43. package/dist/__test__/stack/rest-apis.test.js +45 -0
  44. package/dist/__test__/test/mock-ky.test.d.ts +1 -0
  45. package/dist/__test__/test/mock-ky.test.js +46 -0
  46. package/dist/__test__/testutils.d.ts +12 -0
  47. package/dist/__test__/testutils.js +32 -0
  48. package/dist/__test__/types/lambda-proxy-types.test.d.ts +8 -0
  49. package/dist/__test__/types/lambda-proxy-types.test.js +155 -0
  50. package/dist/__test__/types/lambda-response-builder.test.d.ts +1 -0
  51. package/dist/__test__/types/lambda-response-builder.test.js +81 -0
  52. package/dist/__test__/types/lambda-response.test.d.ts +9 -0
  53. package/dist/__test__/types/lambda-response.test.js +73 -0
  54. package/dist/__test__/utils/base64.test.d.ts +1 -0
  55. package/dist/__test__/utils/base64.test.js +38 -0
  56. package/dist/__test__/utils/date-utils.test.d.ts +1 -0
  57. package/dist/__test__/utils/date-utils.test.js +32 -0
  58. package/dist/__test__/utils/geometry.test.d.ts +1 -0
  59. package/dist/__test__/utils/geometry.test.js +25 -0
  60. package/dist/__test__/utils/lambda-proxy-event.test.d.ts +1 -0
  61. package/dist/__test__/utils/lambda-proxy-event.test.js +45 -0
  62. package/dist/__test__/utils/logging.test.d.ts +1 -0
  63. package/dist/__test__/utils/logging.test.js +75 -0
  64. package/dist/__test__/utils/stop-watch.test.d.ts +1 -0
  65. package/dist/__test__/utils/stop-watch.test.js +118 -0
  66. package/dist/__test__/utils/utils.test.d.ts +1 -0
  67. package/dist/__test__/utils/utils.test.js +48 -0
  68. package/dist/aws/infra/acl-builder.d.ts +53 -0
  69. package/dist/aws/infra/acl-builder.js +407 -0
  70. package/dist/aws/infra/api/handler-factory.d.ts +22 -0
  71. package/dist/aws/infra/api/handler-factory.js +68 -0
  72. package/dist/aws/infra/api/integration.d.ts +49 -0
  73. package/dist/aws/infra/api/integration.js +162 -0
  74. package/dist/aws/infra/api/response.d.ts +62 -0
  75. package/dist/aws/infra/api/response.js +132 -0
  76. package/dist/aws/infra/api/responses.d.ts +60 -0
  77. package/dist/aws/infra/api/responses.js +90 -0
  78. package/dist/aws/infra/api/static-integration.d.ts +16 -0
  79. package/dist/aws/infra/api/static-integration.js +76 -0
  80. package/dist/aws/infra/bucket-policy.d.ts +38 -0
  81. package/dist/aws/infra/bucket-policy.js +30 -0
  82. package/dist/aws/infra/canaries/canary-alarm.d.ts +6 -0
  83. package/dist/aws/infra/canaries/canary-alarm.js +20 -0
  84. package/dist/aws/infra/canaries/canary-keys.d.ts +3 -0
  85. package/dist/aws/infra/canaries/canary-keys.js +4 -0
  86. package/dist/aws/infra/canaries/canary-parameters.d.ts +19 -0
  87. package/dist/aws/infra/canaries/canary-parameters.js +2 -0
  88. package/dist/aws/infra/canaries/canary-role.d.ts +14 -0
  89. package/dist/aws/infra/canaries/canary-role.js +51 -0
  90. package/dist/aws/infra/canaries/canary.d.ts +8 -0
  91. package/dist/aws/infra/canaries/canary.js +26 -0
  92. package/dist/aws/infra/canaries/database-canary.d.ts +17 -0
  93. package/dist/aws/infra/canaries/database-canary.js +65 -0
  94. package/dist/aws/infra/canaries/database-checker.d.ts +33 -0
  95. package/dist/aws/infra/canaries/database-checker.js +119 -0
  96. package/dist/aws/infra/canaries/url-canary.d.ts +16 -0
  97. package/dist/aws/infra/canaries/url-canary.js +55 -0
  98. package/dist/aws/infra/canaries/url-checker.d.ts +45 -0
  99. package/dist/aws/infra/canaries/url-checker.js +256 -0
  100. package/dist/aws/infra/documentation.d.ts +56 -0
  101. package/dist/aws/infra/documentation.js +90 -0
  102. package/dist/aws/infra/import-util.d.ts +17 -0
  103. package/dist/aws/infra/import-util.js +41 -0
  104. package/dist/aws/infra/scheduler.d.ts +12 -0
  105. package/dist/aws/infra/scheduler.js +27 -0
  106. package/dist/aws/infra/security-rule.d.ts +12 -0
  107. package/dist/aws/infra/security-rule.js +35 -0
  108. package/dist/aws/infra/sqs-integration.d.ts +4 -0
  109. package/dist/aws/infra/sqs-integration.js +85 -0
  110. package/dist/aws/infra/sqs-queue.d.ts +19 -0
  111. package/dist/aws/infra/sqs-queue.js +145 -0
  112. package/dist/aws/infra/stack/dt-function-alarms.d.ts +29 -0
  113. package/dist/aws/infra/stack/dt-function-alarms.js +54 -0
  114. package/dist/aws/infra/stack/dt-function.d.ts +124 -0
  115. package/dist/aws/infra/stack/dt-function.js +315 -0
  116. package/dist/aws/infra/stack/lambda-configs.d.ts +44 -0
  117. package/dist/aws/infra/stack/lambda-configs.js +71 -0
  118. package/dist/aws/infra/stack/lambda-log-group.d.ts +15 -0
  119. package/dist/aws/infra/stack/lambda-log-group.js +24 -0
  120. package/dist/aws/infra/stack/monitoredfunction.d.ts +85 -0
  121. package/dist/aws/infra/stack/monitoredfunction.js +147 -0
  122. package/dist/aws/infra/stack/parameters.d.ts +40 -0
  123. package/dist/aws/infra/stack/parameters.js +50 -0
  124. package/dist/aws/infra/stack/rest-api.d.ts +74 -0
  125. package/dist/aws/infra/stack/rest-api.js +235 -0
  126. package/dist/aws/infra/stack/stack-checking-aspect.d.ts +20 -0
  127. package/dist/aws/infra/stack/stack-checking-aspect.js +183 -0
  128. package/dist/aws/infra/stack/stack.d.ts +56 -0
  129. package/dist/aws/infra/stack/stack.js +71 -0
  130. package/dist/aws/infra/stack/subscription.d.ts +17 -0
  131. package/dist/aws/infra/stack/subscription.js +37 -0
  132. package/dist/aws/infra/stacks/db-dns-stack.d.ts +13 -0
  133. package/dist/aws/infra/stacks/db-dns-stack.js +60 -0
  134. package/dist/aws/infra/stacks/db-proxy-stack.d.ts +24 -0
  135. package/dist/aws/infra/stacks/db-proxy-stack.js +74 -0
  136. package/dist/aws/infra/stacks/db-stack.d.ts +65 -0
  137. package/dist/aws/infra/stacks/db-stack.js +189 -0
  138. package/dist/aws/infra/stacks/intra-stack-configuration.d.ts +5 -0
  139. package/dist/aws/infra/stacks/intra-stack-configuration.js +2 -0
  140. package/dist/aws/infra/stacks/network-stack.d.ts +14 -0
  141. package/dist/aws/infra/stacks/network-stack.js +45 -0
  142. package/dist/aws/infra/usage-plans.d.ts +16 -0
  143. package/dist/aws/infra/usage-plans.js +38 -0
  144. package/dist/aws/runtime/apikey.d.ts +2 -0
  145. package/dist/aws/runtime/apikey.js +13 -0
  146. package/dist/aws/runtime/digitraffic-integration-response.d.ts +8 -0
  147. package/dist/aws/runtime/digitraffic-integration-response.js +25 -0
  148. package/dist/aws/runtime/dt-logger-default.d.ts +9 -0
  149. package/dist/aws/runtime/dt-logger-default.js +6 -0
  150. package/dist/aws/runtime/dt-logger.d.ts +117 -0
  151. package/dist/aws/runtime/dt-logger.js +159 -0
  152. package/dist/aws/runtime/environment.d.ts +5 -0
  153. package/dist/aws/runtime/environment.js +7 -0
  154. package/dist/aws/runtime/s3.d.ts +3 -0
  155. package/dist/aws/runtime/s3.js +21 -0
  156. package/dist/aws/runtime/secrets/dbsecret.d.ts +16 -0
  157. package/dist/aws/runtime/secrets/dbsecret.js +26 -0
  158. package/dist/aws/runtime/secrets/proxy-holder.d.ts +9 -0
  159. package/dist/aws/runtime/secrets/proxy-holder.js +25 -0
  160. package/dist/aws/runtime/secrets/rds-holder.d.ts +9 -0
  161. package/dist/aws/runtime/secrets/rds-holder.js +25 -0
  162. package/dist/aws/runtime/secrets/secret-holder.d.ts +30 -0
  163. package/dist/aws/runtime/secrets/secret-holder.js +81 -0
  164. package/dist/aws/runtime/secrets/secret.d.ts +8 -0
  165. package/dist/aws/runtime/secrets/secret.js +61 -0
  166. package/dist/aws/types/errors.d.ts +8 -0
  167. package/dist/aws/types/errors.js +13 -0
  168. package/dist/aws/types/lambda-proxy-types.d.ts +59 -0
  169. package/dist/aws/types/lambda-proxy-types.js +210 -0
  170. package/dist/aws/types/lambda-response.d.ts +89 -0
  171. package/dist/aws/types/lambda-response.js +204 -0
  172. package/dist/aws/types/mediatypes.d.ts +11 -0
  173. package/dist/aws/types/mediatypes.js +14 -0
  174. package/dist/aws/types/model-with-reference.d.ts +7 -0
  175. package/dist/aws/types/model-with-reference.js +2 -0
  176. package/dist/aws/types/tags.d.ts +2 -0
  177. package/dist/aws/types/tags.js +4 -0
  178. package/dist/database/database.d.ts +27 -0
  179. package/dist/database/database.js +95 -0
  180. package/dist/database/last-updated.d.ts +15 -0
  181. package/dist/database/last-updated.js +46 -0
  182. package/dist/database/models.d.ts +6 -0
  183. package/dist/database/models.js +2 -0
  184. package/dist/index.d.ts +2 -0
  185. package/dist/index.js +2 -0
  186. package/dist/marine/id_utils.d.ts +3 -0
  187. package/dist/marine/id_utils.js +36 -0
  188. package/dist/marine/rtz.d.ts +48 -0
  189. package/dist/marine/rtz.js +2 -0
  190. package/dist/types/async-timeout-error.d.ts +3 -0
  191. package/dist/types/async-timeout-error.js +6 -0
  192. package/dist/types/either.d.ts +9 -0
  193. package/dist/types/either.js +2 -0
  194. package/dist/types/geojson.d.ts +47 -0
  195. package/dist/types/geojson.js +51 -0
  196. package/dist/types/http-error.d.ts +4 -0
  197. package/dist/types/http-error.js +8 -0
  198. package/dist/types/input-error.d.ts +2 -0
  199. package/dist/types/input-error.js +3 -0
  200. package/dist/types/language.d.ts +5 -0
  201. package/dist/types/language.js +7 -0
  202. package/dist/types/nullable.d.ts +24 -0
  203. package/dist/types/nullable.js +2 -0
  204. package/dist/types/openapi-schema.d.ts +932 -0
  205. package/dist/types/openapi-schema.js +151 -0
  206. package/dist/types/traffictype.d.ts +11 -0
  207. package/dist/types/traffictype.js +13 -0
  208. package/dist/types/urn.d.ts +1 -0
  209. package/dist/types/urn.js +2 -0
  210. package/dist/types/util-types.d.ts +11 -0
  211. package/dist/types/util-types.js +2 -0
  212. package/dist/types/validator.d.ts +4 -0
  213. package/dist/types/validator.js +9 -0
  214. package/dist/utils/api-model.d.ts +51 -0
  215. package/dist/utils/api-model.js +118 -0
  216. package/dist/utils/base64.d.ts +34 -0
  217. package/dist/utils/base64.js +53 -0
  218. package/dist/utils/date-utils.d.ts +27 -0
  219. package/dist/utils/date-utils.js +45 -0
  220. package/dist/utils/geojson-types.d.ts +14 -0
  221. package/dist/utils/geojson-types.js +15 -0
  222. package/dist/utils/geometry.d.ts +44 -0
  223. package/dist/utils/geometry.js +154 -0
  224. package/dist/utils/lambda-proxy-event.d.ts +9 -0
  225. package/dist/utils/lambda-proxy-event.js +31 -0
  226. package/dist/utils/logging.d.ts +40 -0
  227. package/dist/utils/logging.js +88 -0
  228. package/dist/utils/retry.d.ts +33 -0
  229. package/dist/utils/retry.js +135 -0
  230. package/dist/utils/slack.d.ts +5 -0
  231. package/dist/utils/slack.js +24 -0
  232. package/dist/utils/stop-watch.d.ts +46 -0
  233. package/dist/utils/stop-watch.js +114 -0
  234. package/dist/utils/utils.d.ts +95 -0
  235. package/dist/utils/utils.js +178 -0
  236. package/dist/utils/zod-utils.d.ts +27 -0
  237. package/dist/utils/zod-utils.js +57 -0
  238. package/package.json +30 -28
@@ -0,0 +1,407 @@
1
+ import { CfnIPSet, CfnWebACL } from "aws-cdk-lib/aws-wafv2";
2
+ import { range, zipWith } from "es-toolkit";
3
+ import { logger } from "../runtime/dt-logger-default.js";
4
+ /**
5
+ * Builder class for building CfnWebACL.
6
+ *
7
+ * Currently supports:
8
+ * * Some AWS managed WAF rules
9
+ * * IP blacklisting/whitelisting
10
+ */
11
+ export class AclBuilder {
12
+ _construct;
13
+ _countRules = [];
14
+ _blockRules = [];
15
+ _name = "WebACL";
16
+ _scope = "CLOUDFRONT";
17
+ _customResponseBodies = {};
18
+ constructor(construct, name = "WebACL") {
19
+ this._construct = construct;
20
+ this._name = name;
21
+ }
22
+ isRuleDefined(rules, rule) {
23
+ return rules === "all" || rules.includes(rule);
24
+ }
25
+ withAWSManagedRules(rules = "all", excludedRules = {}) {
26
+ if (this.isRuleDefined(rules, "CommonRuleSet")) {
27
+ this._blockRules.push(createAWSCommonRuleSet(excludedRules?.CommonRuleSet));
28
+ }
29
+ if (this.isRuleDefined(rules, "AmazonIpReputationList")) {
30
+ this._blockRules.push(createAWSReputationList(excludedRules?.AmazonIpReputationList));
31
+ }
32
+ if (this.isRuleDefined(rules, "KnownBadInputsRuleSet")) {
33
+ this._blockRules.push(createAWSKnownBadInput(excludedRules?.KnownBadInputsRuleSet));
34
+ }
35
+ if (this.isRuleDefined(rules, "SQLiRuleSet")) {
36
+ this._blockRules.push(createAWSAntiSQLInjection(excludedRules?.SQLiRuleSet));
37
+ }
38
+ return this;
39
+ }
40
+ /**
41
+ * Block access from given addresses
42
+ */
43
+ withIpBlacklistRule(addresses) {
44
+ const blocklistIpSet = new CfnIPSet(this._construct, "BlocklistIpSet", {
45
+ ipAddressVersion: "IPV4",
46
+ scope: this._scope,
47
+ addresses,
48
+ });
49
+ this._blockRules.push({
50
+ name: "IpBlocklist",
51
+ action: { block: {} },
52
+ statement: {
53
+ ipSetReferenceStatement: {
54
+ arn: blocklistIpSet.attrArn,
55
+ },
56
+ },
57
+ visibilityConfig: {
58
+ sampledRequestsEnabled: false,
59
+ cloudWatchMetricsEnabled: true,
60
+ metricName: "IpBlocklist",
61
+ },
62
+ });
63
+ return this;
64
+ }
65
+ /**
66
+ * Allow access only from the given addresses
67
+ */
68
+ withIpWhitelistRule(addresses) {
69
+ const blocklistIpSet = new CfnIPSet(this._construct, "AllowlistIpSet", {
70
+ ipAddressVersion: "IPV4",
71
+ scope: this._scope,
72
+ addresses,
73
+ });
74
+ this._blockRules.push({
75
+ name: "IpAllowlist",
76
+ action: { block: {} },
77
+ statement: {
78
+ notStatement: {
79
+ statement: {
80
+ ipSetReferenceStatement: {
81
+ arn: blocklistIpSet.attrArn,
82
+ },
83
+ },
84
+ },
85
+ },
86
+ visibilityConfig: {
87
+ sampledRequestsEnabled: false,
88
+ cloudWatchMetricsEnabled: true,
89
+ metricName: "IpAllowlist",
90
+ },
91
+ });
92
+ return this;
93
+ }
94
+ withThrottleRule(name, limit, isHeaderRequired, isBasedOnIpAndUriPath, customResponseBodyKey, path) {
95
+ const isBlockRule = !!customResponseBodyKey;
96
+ const rules = isBlockRule ? this._blockRules : this._countRules;
97
+ const action = isBlockRule
98
+ ? {
99
+ block: {
100
+ customResponse: {
101
+ responseCode: 429,
102
+ customResponseBodyKey,
103
+ },
104
+ },
105
+ }
106
+ : {
107
+ count: {},
108
+ };
109
+ rules.push({
110
+ name,
111
+ visibilityConfig: {
112
+ sampledRequestsEnabled: true,
113
+ cloudWatchMetricsEnabled: true,
114
+ metricName: name,
115
+ },
116
+ action,
117
+ statement: createThrottleStatement(limit, isHeaderRequired, isBasedOnIpAndUriPath, path),
118
+ });
119
+ return this;
120
+ }
121
+ withCustomResponseBody(key, customResponseBody) {
122
+ if (key in this._customResponseBodies) {
123
+ logger.warn({
124
+ method: "acl-builder.withCustomResponseBody",
125
+ message: `Overriding custom response body with key ${key} for distribution ${this._name}`,
126
+ });
127
+ }
128
+ this._customResponseBodies[key] = customResponseBody;
129
+ return this;
130
+ }
131
+ withThrottleDigitrafficUserIp(limit) {
132
+ if (limit === undefined) {
133
+ return this;
134
+ }
135
+ const customResponseBodyKey = `IP_THROTTLE_DIGITRAFFIC_USER_${limit}`;
136
+ this._addThrottleResponseBody(customResponseBodyKey, limit);
137
+ return this.withThrottleRule("ThrottleRuleWithDigitrafficUser", limit, true, false, customResponseBodyKey);
138
+ }
139
+ withThrottleDigitrafficUserIpAndUriPath(limit) {
140
+ if (limit === undefined) {
141
+ return this;
142
+ }
143
+ const customResponseBodyKey = `IP_PATH_THROTTLE_DIGITRAFFIC_USER_${limit}`;
144
+ this._addThrottleResponseBody(customResponseBodyKey, limit);
145
+ return this.withThrottleRule("ThrottleRuleIPQueryWithDigitrafficUser", limit, true, true, customResponseBodyKey);
146
+ }
147
+ withThrottleAnonymousUserIp(limit) {
148
+ if (limit === undefined) {
149
+ return this;
150
+ }
151
+ const customResponseBodyKey = `IP_THROTTLE_ANONYMOUS_USER_${limit}`;
152
+ this._addThrottleResponseBody(customResponseBodyKey, limit);
153
+ return this.withThrottleRule("ThrottleRuleWithAnonymousUser", limit, false, false, customResponseBodyKey);
154
+ }
155
+ withThrottleAnonymousUserIpByUriPath(limit, path) {
156
+ if (limit === undefined || path === undefined) {
157
+ return this;
158
+ }
159
+ const customResponseBodyKey = `IP_THROTTLE_ANONYMOUS_USER_BY_PATH_${limit}`;
160
+ this._addThrottleResponseBody(customResponseBodyKey, limit);
161
+ return this.withThrottleRule("ThrottleRuleWithAnonymousUserByPath", limit, false, false, customResponseBodyKey, path);
162
+ }
163
+ withThrottleAnonymousUserIpAndUriPath(limit) {
164
+ if (limit === undefined) {
165
+ return this;
166
+ }
167
+ const customResponseBodyKey = `IP_PATH_THROTTLE_ANONYMOUS_USER_${limit}`;
168
+ this._addThrottleResponseBody(customResponseBodyKey, limit);
169
+ return this.withThrottleRule("ThrottleRuleIPQueryWithAnonymousUser", limit, false, true, customResponseBodyKey);
170
+ }
171
+ withCountDigitrafficUserIp(limit) {
172
+ if (limit === undefined) {
173
+ return this;
174
+ }
175
+ return this.withThrottleRule(`CountRuleWithDigitrafficUser${limit}`, limit, true, false);
176
+ }
177
+ withCountDigitrafficUserIpAndUriPath(limit) {
178
+ if (limit === undefined) {
179
+ return this;
180
+ }
181
+ return this.withThrottleRule(`CountRuleIPQueryWithDigitrafficUser${limit}`, limit, true, true);
182
+ }
183
+ withCountAnonymousUserIp(limit) {
184
+ if (limit === undefined) {
185
+ return this;
186
+ }
187
+ return this.withThrottleRule(`CountRuleWithAnonymousUser${limit}`, limit, false, false);
188
+ }
189
+ withCountAnonymousUserIpAndUriPath(limit) {
190
+ if (limit === undefined) {
191
+ return this;
192
+ }
193
+ return this.withThrottleRule(`CountRuleIPQueryWithAnonymousUser${limit}`, limit, false, true);
194
+ }
195
+ /**
196
+ * Block requests with a query string larger than the specified size.
197
+ */
198
+ withQueryStringSizeRestriction(limit) {
199
+ this._blockRules.push({
200
+ name: "QueryStringSizeRestriction",
201
+ action: { block: {} },
202
+ statement: {
203
+ sizeConstraintStatement: {
204
+ fieldToMatch: {
205
+ queryString: {},
206
+ },
207
+ comparisonOperator: "GT",
208
+ size: limit,
209
+ textTransformations: [{ priority: 0, type: "NONE" }],
210
+ },
211
+ },
212
+ visibilityConfig: {
213
+ sampledRequestsEnabled: true,
214
+ cloudWatchMetricsEnabled: true,
215
+ metricName: "QueryStringSizeRestriction",
216
+ },
217
+ });
218
+ return this;
219
+ }
220
+ _isCustomResponseBodyKeySet(key) {
221
+ return key in this._customResponseBodies;
222
+ }
223
+ _addThrottleResponseBody(customResponseBodyKey, limit) {
224
+ if (!this._isCustomResponseBodyKeySet(customResponseBodyKey)) {
225
+ this.withCustomResponseBody(customResponseBodyKey, {
226
+ content: `Request rate is limited to ${limit} requests in a 5 minute window.`,
227
+ contentType: "TEXT_PLAIN",
228
+ });
229
+ }
230
+ }
231
+ build() {
232
+ const addPriority = (rule, priority) => ({
233
+ ...rule,
234
+ priority,
235
+ });
236
+ const rules = [
237
+ ...zipWith(this._countRules, range(this._countRules.length), addPriority),
238
+ ...zipWith(this._blockRules, range(this._blockRules.length).map((n) => n + this._countRules.length), addPriority),
239
+ ];
240
+ if (rules.length === 0) {
241
+ throw new Error("No rules defined for WebACL");
242
+ }
243
+ const uniqueRuleNames = new Set(rules.map((rule) => rule.name));
244
+ if (uniqueRuleNames.size !== rules.length) {
245
+ throw new Error("Tried to create an Access Control List with multiple rules having the same name");
246
+ }
247
+ return new CfnWebACL(this._construct, this._name, {
248
+ defaultAction: { allow: {} },
249
+ scope: this._scope,
250
+ visibilityConfig: {
251
+ cloudWatchMetricsEnabled: true,
252
+ metricName: "WAF-Blocked",
253
+ sampledRequestsEnabled: false,
254
+ },
255
+ rules,
256
+ ...(this._customResponseBodies && {
257
+ customResponseBodies: this._customResponseBodies,
258
+ }),
259
+ });
260
+ }
261
+ }
262
+ const CUSTOM_KEYS_IP_AND_URI_PATH = [
263
+ {
264
+ uriPath: {
265
+ textTransformations: [
266
+ {
267
+ priority: 1,
268
+ type: "LOWERCASE",
269
+ },
270
+ {
271
+ priority: 2,
272
+ type: "NORMALIZE_PATH",
273
+ },
274
+ {
275
+ priority: 3,
276
+ type: "MD5",
277
+ },
278
+ ],
279
+ },
280
+ },
281
+ {
282
+ ip: {},
283
+ },
284
+ ];
285
+ function notStatement(statement) {
286
+ return {
287
+ notStatement: {
288
+ statement,
289
+ },
290
+ };
291
+ }
292
+ function createThrottleStatement(limit, isHeaderRequired, isBasedOnIpAndUriPath, path) {
293
+ // this statement matches empty digitraffic-user -header
294
+ const matchStatement = {
295
+ sizeConstraintStatement: {
296
+ comparisonOperator: isHeaderRequired ? "GT" : "GE",
297
+ fieldToMatch: {
298
+ singleHeader: {
299
+ Name: "digitraffic-user",
300
+ },
301
+ },
302
+ textTransformations: [{ priority: 0, type: "NONE" }],
303
+ size: 0,
304
+ },
305
+ };
306
+ // header present -> size > 0
307
+ // header not present -> NOT(size >= 0)
308
+ let scopeDownStatement = isHeaderRequired
309
+ ? matchStatement
310
+ : notStatement(matchStatement);
311
+ if (path) {
312
+ const pathMatchStatement = {
313
+ regexMatchStatement: {
314
+ fieldToMatch: {
315
+ uriPath: {},
316
+ },
317
+ regexString: path.source,
318
+ textTransformations: [{ priority: 0, type: "NONE" }],
319
+ },
320
+ };
321
+ scopeDownStatement = {
322
+ andStatement: {
323
+ statements: [scopeDownStatement, pathMatchStatement],
324
+ },
325
+ };
326
+ }
327
+ if (isBasedOnIpAndUriPath) {
328
+ return {
329
+ rateBasedStatement: {
330
+ aggregateKeyType: "CUSTOM_KEYS",
331
+ customKeys: CUSTOM_KEYS_IP_AND_URI_PATH,
332
+ limit: limit,
333
+ scopeDownStatement,
334
+ },
335
+ };
336
+ }
337
+ return {
338
+ rateBasedStatement: {
339
+ aggregateKeyType: "IP",
340
+ limit: limit,
341
+ scopeDownStatement,
342
+ },
343
+ };
344
+ }
345
+ function createAWSCommonRuleSet(excludedRules = []) {
346
+ return createRuleProperty("AWS-AWSManagedRulesCommonRuleSet", {
347
+ statement: {
348
+ managedRuleGroupStatement: {
349
+ vendorName: "AWS",
350
+ name: "AWSManagedRulesCommonRuleSet",
351
+ excludedRules: [
352
+ { name: "NoUserAgent_HEADER" },
353
+ { name: "SizeRestrictions_BODY" },
354
+ { name: "GenericRFI_BODY" },
355
+ ].concat((excludedRules ?? []).map((rule) => ({ name: rule }))),
356
+ },
357
+ },
358
+ });
359
+ }
360
+ function createAWSReputationList(excludedRules = []) {
361
+ return createRuleProperty("AWS-AWSManagedRulesAmazonIpReputationList", {
362
+ statement: {
363
+ managedRuleGroupStatement: {
364
+ vendorName: "AWS",
365
+ name: "AWSManagedRulesAmazonIpReputationList",
366
+ excludedRules: (excludedRules ?? []).map((rule) => ({ name: rule })),
367
+ },
368
+ },
369
+ });
370
+ }
371
+ function createAWSKnownBadInput(excludedRules = []) {
372
+ return createRuleProperty("AWS-AWSManagedRulesKnownBadInputsRuleSet", {
373
+ statement: {
374
+ managedRuleGroupStatement: {
375
+ vendorName: "AWS",
376
+ name: "AWSManagedRulesKnownBadInputsRuleSet",
377
+ excludedRules: (excludedRules ?? []).map((rule) => ({ name: rule })),
378
+ },
379
+ },
380
+ });
381
+ }
382
+ function createAWSAntiSQLInjection(excludedRules = []) {
383
+ return createRuleProperty("AWS-AWSManagedRulesSQLiRuleSet", {
384
+ statement: {
385
+ managedRuleGroupStatement: {
386
+ vendorName: "AWS",
387
+ name: "AWSManagedRulesSQLiRuleSet",
388
+ excludedRules: (excludedRules ?? []).map((rule) => ({ name: rule })),
389
+ },
390
+ },
391
+ });
392
+ }
393
+ function createRuleProperty(name, rule, overrideAction = true) {
394
+ return {
395
+ ...{
396
+ name,
397
+ visibilityConfig: {
398
+ sampledRequestsEnabled: true,
399
+ cloudWatchMetricsEnabled: true,
400
+ metricName: name,
401
+ },
402
+ },
403
+ ...rule,
404
+ ...(overrideAction ? { overrideAction: { none: {} } } : {}),
405
+ };
406
+ }
407
+ //# sourceMappingURL=acl-builder.js.map
@@ -0,0 +1,22 @@
1
+ import type { DtLogger } from "../../runtime/dt-logger.js";
2
+ import type { LambdaResponse } from "../../types/lambda-response.js";
3
+ export type LoggingHandler = (method: () => Promise<LambdaResponse>, logger: DtLogger) => Promise<LambdaResponse>;
4
+ export type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
5
+ /**
6
+ * Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
7
+ * with the defaults:
8
+ * * No error handling
9
+ * * Execution time logging
10
+ *
11
+ * You should instantiate HandlerFactory in your project with desired error handling and use the factory instance for
12
+ * creating handler-functions for your lambdas.
13
+ */
14
+ export declare class HandlerFactory {
15
+ private loggingHandler;
16
+ private errorHandler;
17
+ constructor();
18
+ withLoggingHandler(loggingHandler: LoggingHandler): HandlerFactory;
19
+ withErrorHandler(errorHandler: ErrorHandler): HandlerFactory;
20
+ createEventHandler(handler: (event: unknown) => Promise<LambdaResponse>, logger: DtLogger): (event: unknown) => Promise<LambdaResponse>;
21
+ }
22
+ export declare function createJsonLoggingHandler(): LoggingHandler;
@@ -0,0 +1,68 @@
1
+ import { getEnvVariableOrElse } from "../../../utils/utils.js";
2
+ import { logger } from "../../runtime/dt-logger-default.js";
3
+ const functionName = getEnvVariableOrElse("AWS_LAMBDA_FUNCTION_NAME", "test");
4
+ /**
5
+ * Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
6
+ * with the defaults:
7
+ * * No error handling
8
+ * * Execution time logging
9
+ *
10
+ * You should instantiate HandlerFactory in your project with desired error handling and use the factory instance for
11
+ * creating handler-functions for your lambdas.
12
+ */
13
+ export class HandlerFactory {
14
+ loggingHandler;
15
+ errorHandler;
16
+ constructor() {
17
+ this.loggingHandler = async (method) => {
18
+ const start = Date.now();
19
+ try {
20
+ return await method();
21
+ }
22
+ finally {
23
+ logger.info({
24
+ method: `${functionName}.handler`,
25
+ tookMs: Date.now() - start,
26
+ });
27
+ }
28
+ };
29
+ this.errorHandler = (error) => {
30
+ throw error;
31
+ };
32
+ }
33
+ withLoggingHandler(loggingHandler) {
34
+ this.loggingHandler = loggingHandler;
35
+ return this;
36
+ }
37
+ withErrorHandler(errorHandler) {
38
+ this.errorHandler = errorHandler;
39
+ return this;
40
+ }
41
+ createEventHandler(handler, logger) {
42
+ return async (event) => {
43
+ return await this.loggingHandler(async () => {
44
+ try {
45
+ return await handler(event);
46
+ }
47
+ catch (error) {
48
+ return this.errorHandler(error, logger);
49
+ }
50
+ }, logger);
51
+ };
52
+ }
53
+ }
54
+ export function createJsonLoggingHandler() {
55
+ return async (method, logger) => {
56
+ const start = Date.now();
57
+ try {
58
+ return await method();
59
+ }
60
+ finally {
61
+ logger.info({
62
+ method: `${functionName}.handler`,
63
+ tookMs: Date.now() - start,
64
+ });
65
+ }
66
+ };
67
+ }
68
+ //# sourceMappingURL=handler-factory.js.map
@@ -0,0 +1,49 @@
1
+ import type { IntegrationResponse } from "aws-cdk-lib/aws-apigateway";
2
+ import { LambdaIntegration } from "aws-cdk-lib/aws-apigateway";
3
+ import type { IFunction } from "aws-cdk-lib/aws-lambda";
4
+ import { MediaType } from "../../types/mediatypes.js";
5
+ type ParameterType = "path" | "querystring" | "multivaluequerystring" | "context" | "header";
6
+ interface ApiParameter {
7
+ type: ParameterType;
8
+ name: string;
9
+ }
10
+ export declare class DigitrafficIntegration<T extends string> {
11
+ readonly lambda: IFunction;
12
+ readonly mediaType: MediaType;
13
+ readonly parameters: ApiParameter[];
14
+ readonly deprecation: boolean;
15
+ readonly sunset?: string;
16
+ _passAllQueryParameters: boolean;
17
+ _passBody: boolean;
18
+ constructor(lambda: IFunction, mediaType?: MediaType, deprecation?: boolean, sunset?: string);
19
+ passAllQueryParameters(): this;
20
+ /**
21
+ * Body is passed as an base64-encoded string, so broken input should't break anything. You should
22
+ * decode, parse and validate the input in the lambda.
23
+ *
24
+ * The encoded body will be passed to handler with name payload!!
25
+ */
26
+ passBody(): this;
27
+ addParameter(type: ParameterType, name: string): this;
28
+ addPathParameter(...names: T[]): this;
29
+ addQueryParameter(...names: T[]): this;
30
+ addMultiValueQueryParameter(...names: T[]): this;
31
+ /**
32
+ * Note that context parameter values needs to be in json format as they will be parsed in template as json.
33
+ * See createRequestTemplates below.
34
+ * @param names for the parameters
35
+ * @returns
36
+ */
37
+ addContextParameter(...names: T[]): this;
38
+ /**
39
+ * Do not use Authorization header as that will be consumed by ApiGW.
40
+ * If Authorization header is needed, use lambda authorizers.
41
+ * @param names for the headers
42
+ */
43
+ addHeaderParameter(...names: T[]): this;
44
+ build(): LambdaIntegration;
45
+ createRequestParameters(): Record<string, string>;
46
+ createRequestTemplates(): Record<string, string>;
47
+ createResponses(): IntegrationResponse[];
48
+ }
49
+ export {};