timonel 2.8.0-beta.5 → 2.8.0

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 (128) hide show
  1. package/CHANGELOG.md +9 -25
  2. package/README.md +12 -55
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/{src/cli.js → cli.js} +4 -35
  5. package/dist/cli.js.map +1 -0
  6. package/dist/index.d.ts +14 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +13 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/{src/lib → lib}/helm.d.ts +234 -4
  11. package/dist/lib/helm.d.ts.map +1 -0
  12. package/dist/{src/lib → lib}/helm.js +309 -20
  13. package/dist/lib/helm.js.map +1 -0
  14. package/dist/lib/helmChartWriter.d.ts.map +1 -0
  15. package/dist/{src/lib → lib}/helmChartWriter.js +5 -19
  16. package/dist/lib/helmChartWriter.js.map +1 -0
  17. package/dist/{src/lib → lib}/resources/baseResourceProvider.d.ts +1 -1
  18. package/dist/lib/resources/baseResourceProvider.d.ts.map +1 -0
  19. package/dist/lib/resources/baseResourceProvider.js.map +1 -0
  20. package/dist/{src/lib → lib}/resources/cloud/aws/awsResources.d.ts +5 -14
  21. package/dist/lib/resources/cloud/aws/awsResources.d.ts.map +1 -0
  22. package/dist/{src/lib → lib}/resources/cloud/aws/awsResources.js +63 -78
  23. package/dist/lib/resources/cloud/aws/awsResources.js.map +1 -0
  24. package/dist/lib/resources/cloud/aws/karpenterResources.d.ts.map +1 -0
  25. package/dist/lib/resources/cloud/aws/karpenterResources.js.map +1 -0
  26. package/dist/lib/rutter.d.ts +445 -0
  27. package/dist/lib/rutter.d.ts.map +1 -0
  28. package/dist/lib/rutter.js +585 -0
  29. package/dist/lib/rutter.js.map +1 -0
  30. package/dist/{src/lib → lib}/security.d.ts +2 -72
  31. package/dist/lib/security.d.ts.map +1 -0
  32. package/dist/lib/security.js +390 -0
  33. package/dist/lib/security.js.map +1 -0
  34. package/dist/lib/umbrella.d.ts.map +1 -0
  35. package/dist/lib/umbrella.js.map +1 -0
  36. package/dist/{src/lib → lib}/umbrellaRutter.d.ts +1 -1
  37. package/dist/lib/umbrellaRutter.d.ts.map +1 -0
  38. package/dist/lib/umbrellaRutter.js.map +1 -0
  39. package/dist/{src/lib → lib}/utils/helmHelpers.d.ts +2 -12
  40. package/dist/lib/utils/helmHelpers.d.ts.map +1 -0
  41. package/dist/{src/lib → lib}/utils/helmHelpers.js +2 -46
  42. package/dist/lib/utils/helmHelpers.js.map +1 -0
  43. package/package.json +3 -4
  44. package/dist/src/cli.d.ts.map +0 -1
  45. package/dist/src/cli.js.map +0 -1
  46. package/dist/src/index.d.ts +0 -23
  47. package/dist/src/index.d.ts.map +0 -1
  48. package/dist/src/index.js +0 -15
  49. package/dist/src/index.js.map +0 -1
  50. package/dist/src/lib/constants.d.ts +0 -142
  51. package/dist/src/lib/constants.d.ts.map +0 -1
  52. package/dist/src/lib/constants.js +0 -167
  53. package/dist/src/lib/constants.js.map +0 -1
  54. package/dist/src/lib/helm.d.ts.map +0 -1
  55. package/dist/src/lib/helm.js.map +0 -1
  56. package/dist/src/lib/helmChartWriter.d.ts.map +0 -1
  57. package/dist/src/lib/helmChartWriter.js.map +0 -1
  58. package/dist/src/lib/resources/autoscaling/autoscalingResources.d.ts +0 -248
  59. package/dist/src/lib/resources/autoscaling/autoscalingResources.d.ts.map +0 -1
  60. package/dist/src/lib/resources/autoscaling/autoscalingResources.js +0 -81
  61. package/dist/src/lib/resources/autoscaling/autoscalingResources.js.map +0 -1
  62. package/dist/src/lib/resources/baseResourceProvider.d.ts.map +0 -1
  63. package/dist/src/lib/resources/baseResourceProvider.js.map +0 -1
  64. package/dist/src/lib/resources/cloud/aws/awsResources.d.ts.map +0 -1
  65. package/dist/src/lib/resources/cloud/aws/awsResources.js.map +0 -1
  66. package/dist/src/lib/resources/cloud/aws/karpenterResources.d.ts.map +0 -1
  67. package/dist/src/lib/resources/cloud/aws/karpenterResources.js.map +0 -1
  68. package/dist/src/lib/resources/cloud/azure/azureResources.d.ts +0 -169
  69. package/dist/src/lib/resources/cloud/azure/azureResources.d.ts.map +0 -1
  70. package/dist/src/lib/resources/cloud/azure/azureResources.js +0 -218
  71. package/dist/src/lib/resources/cloud/azure/azureResources.js.map +0 -1
  72. package/dist/src/lib/resources/cloud/gcp/gcpResources.d.ts +0 -164
  73. package/dist/src/lib/resources/cloud/gcp/gcpResources.d.ts.map +0 -1
  74. package/dist/src/lib/resources/cloud/gcp/gcpResources.js +0 -192
  75. package/dist/src/lib/resources/cloud/gcp/gcpResources.js.map +0 -1
  76. package/dist/src/lib/resources/core/coreResources.d.ts +0 -790
  77. package/dist/src/lib/resources/core/coreResources.d.ts.map +0 -1
  78. package/dist/src/lib/resources/core/coreResources.js +0 -1115
  79. package/dist/src/lib/resources/core/coreResources.js.map +0 -1
  80. package/dist/src/lib/resources/core/storageResources.d.ts +0 -133
  81. package/dist/src/lib/resources/core/storageResources.d.ts.map +0 -1
  82. package/dist/src/lib/resources/core/storageResources.js +0 -120
  83. package/dist/src/lib/resources/core/storageResources.js.map +0 -1
  84. package/dist/src/lib/resources/network/networkResources.d.ts +0 -515
  85. package/dist/src/lib/resources/network/networkResources.d.ts.map +0 -1
  86. package/dist/src/lib/resources/network/networkResources.js +0 -784
  87. package/dist/src/lib/resources/network/networkResources.js.map +0 -1
  88. package/dist/src/lib/resources/security/encryption.d.ts +0 -290
  89. package/dist/src/lib/resources/security/encryption.d.ts.map +0 -1
  90. package/dist/src/lib/resources/security/encryption.js +0 -295
  91. package/dist/src/lib/resources/security/encryption.js.map +0 -1
  92. package/dist/src/lib/resources/security/index.d.ts +0 -6
  93. package/dist/src/lib/resources/security/index.d.ts.map +0 -1
  94. package/dist/src/lib/resources/security/index.js +0 -6
  95. package/dist/src/lib/resources/security/index.js.map +0 -1
  96. package/dist/src/lib/resources/validation/validationResources.d.ts +0 -26
  97. package/dist/src/lib/resources/validation/validationResources.d.ts.map +0 -1
  98. package/dist/src/lib/resources/validation/validationResources.js +0 -33
  99. package/dist/src/lib/resources/validation/validationResources.js.map +0 -1
  100. package/dist/src/lib/rutter.d.ts +0 -1106
  101. package/dist/src/lib/rutter.d.ts.map +0 -1
  102. package/dist/src/lib/rutter.js +0 -1295
  103. package/dist/src/lib/rutter.js.map +0 -1
  104. package/dist/src/lib/security.d.ts.map +0 -1
  105. package/dist/src/lib/security.js +0 -569
  106. package/dist/src/lib/security.js.map +0 -1
  107. package/dist/src/lib/umbrella.d.ts.map +0 -1
  108. package/dist/src/lib/umbrella.js.map +0 -1
  109. package/dist/src/lib/umbrellaRutter.d.ts.map +0 -1
  110. package/dist/src/lib/umbrellaRutter.js.map +0 -1
  111. package/dist/src/lib/utils/helmHelpers.d.ts.map +0 -1
  112. package/dist/src/lib/utils/helmHelpers.js.map +0 -1
  113. package/dist/src/lib/utils/podTemplates.d.ts +0 -192
  114. package/dist/src/lib/utils/podTemplates.d.ts.map +0 -1
  115. package/dist/src/lib/utils/podTemplates.js +0 -331
  116. package/dist/src/lib/utils/podTemplates.js.map +0 -1
  117. package/dist/src/lib/utils/resourceNaming.d.ts +0 -57
  118. package/dist/src/lib/utils/resourceNaming.d.ts.map +0 -1
  119. package/dist/src/lib/utils/resourceNaming.js +0 -82
  120. package/dist/src/lib/utils/resourceNaming.js.map +0 -1
  121. /package/dist/{src/cli.d.ts → cli.d.ts} +0 -0
  122. /package/dist/{src/lib → lib}/helmChartWriter.d.ts +0 -0
  123. /package/dist/{src/lib → lib}/resources/baseResourceProvider.js +0 -0
  124. /package/dist/{src/lib → lib}/resources/cloud/aws/karpenterResources.d.ts +0 -0
  125. /package/dist/{src/lib → lib}/resources/cloud/aws/karpenterResources.js +0 -0
  126. /package/dist/{src/lib → lib}/umbrella.d.ts +0 -0
  127. /package/dist/{src/lib → lib}/umbrella.js +0 -0
  128. /package/dist/{src/lib → lib}/umbrellaRutter.js +0 -0
@@ -1,784 +0,0 @@
1
- /**
2
- * @fileoverview Network resources for Kubernetes networking
3
- * @since 2.7.0
4
- */
5
- import { BaseResourceProvider } from '../baseResourceProvider.js';
6
- /**
7
- * Network resources provider for NetworkPolicy and Ingress
8
- * @extends BaseResourceProvider
9
- * @since 2.7.0
10
- */
11
- export class NetworkResources extends BaseResourceProvider {
12
- /**
13
- * Creates a NetworkPolicy resource with enhanced defaults
14
- * @param spec - NetworkPolicy specification
15
- * @returns Created NetworkPolicy ApiObject
16
- * @since 2.7.0
17
- */
18
- addNetworkPolicy(spec) {
19
- const policySpec = {
20
- podSelector: spec.podSelector,
21
- };
22
- // Provide default policy types if not specified
23
- let policyTypes = spec.policyTypes;
24
- if (!policyTypes) {
25
- // Determine policy types based on rules provided
26
- const hasIngress = spec.ingress && spec.ingress.length > 0;
27
- const hasEgress = spec.egress && spec.egress.length > 0;
28
- if (hasIngress && hasEgress) {
29
- policyTypes = ['Ingress', 'Egress'];
30
- }
31
- else if (hasIngress) {
32
- policyTypes = ['Ingress'];
33
- }
34
- else if (hasEgress) {
35
- policyTypes = ['Egress'];
36
- }
37
- else {
38
- // Default to both for explicit security posture
39
- policyTypes = ['Ingress', 'Egress'];
40
- console.warn(NetworkResources.NETWORK_POLICY_DEFAULT_WARNING.replace('{name}', spec.name));
41
- }
42
- }
43
- policySpec['policyTypes'] = policyTypes;
44
- if (spec.ingress) {
45
- policySpec['ingress'] = spec.ingress;
46
- }
47
- if (spec.egress) {
48
- policySpec['egress'] = spec.egress;
49
- }
50
- return this.createApiObject(spec.name, NetworkResources.NETWORKING_API_VERSION, 'NetworkPolicy', policySpec, spec.labels, spec.annotations);
51
- }
52
- /**
53
- * Creates a deny-all NetworkPolicy that blocks all ingress and egress traffic
54
- * @param name - Policy name
55
- * @param podSelector - Pod selector to apply policy to
56
- * @param labels - Optional labels
57
- * @param annotations - Optional annotations
58
- * @returns Created NetworkPolicy ApiObject
59
- * @since 2.7.0
60
- */
61
- addDenyAllNetworkPolicy(name, podSelector = {}, labels, annotations) {
62
- return this.addNetworkPolicy({
63
- name,
64
- podSelector,
65
- policyTypes: ['Ingress', 'Egress'],
66
- ingress: [],
67
- egress: [],
68
- ...(labels && { labels }),
69
- ...(annotations && { annotations }),
70
- });
71
- }
72
- /**
73
- * Creates a NetworkPolicy that allows traffic from specific pods
74
- * @param name - Policy name
75
- * @param podSelector - Pod selector to apply policy to
76
- * @param fromPodSelector - Pod selector for allowed source pods
77
- * @param ports - Optional ports to allow
78
- * @param labels - Optional labels
79
- * @param annotations - Optional annotations
80
- * @returns Created NetworkPolicy ApiObject
81
- * @since 2.7.0
82
- */
83
- addAllowFromPodsNetworkPolicy(name, podSelector, fromPodSelector, ports, labels, annotations) {
84
- const ingressRule = {};
85
- if (fromPodSelector) {
86
- ingressRule.podSelector = fromPodSelector;
87
- }
88
- if (ports) {
89
- ingressRule.ports = ports;
90
- }
91
- return this.addNetworkPolicy({
92
- name,
93
- podSelector,
94
- policyTypes: ['Ingress'],
95
- ingress: [ingressRule],
96
- ...(labels && { labels }),
97
- ...(annotations && { annotations }),
98
- });
99
- }
100
- /**
101
- * Creates a NetworkPolicy that allows traffic from specific namespaces
102
- * @param name - Policy name
103
- * @param podSelector - Pod selector to apply policy to
104
- * @param fromNamespaceSelector - Namespace selector for allowed source namespaces
105
- * @param ports - Optional ports to allow
106
- * @param labels - Optional labels
107
- * @param annotations - Optional annotations
108
- * @returns Created NetworkPolicy ApiObject
109
- * @since 2.7.0
110
- */
111
- addAllowFromNamespaceNetworkPolicy(name, podSelector, fromNamespaceSelector, ports, labels, annotations) {
112
- const ingressRule = {};
113
- if (fromNamespaceSelector) {
114
- ingressRule.namespaceSelector = fromNamespaceSelector;
115
- }
116
- if (ports) {
117
- ingressRule.ports = ports;
118
- }
119
- return this.addNetworkPolicy({
120
- name,
121
- podSelector,
122
- policyTypes: ['Ingress'],
123
- ingress: [ingressRule],
124
- ...(labels && { labels }),
125
- ...(annotations && { annotations }),
126
- });
127
- }
128
- /**
129
- * Validates TLS configuration for security compliance
130
- * @param spec - Ingress specification to validate
131
- * @throws Error if TLS validation fails
132
- * @since 2.8.0
133
- */
134
- validateIngressSecurity(spec) {
135
- const isProductionEnvironment = spec.environment === 'production';
136
- const tlsRequired = spec.requireTLS || isProductionEnvironment;
137
- // Check if TLS is required but not configured
138
- if (tlsRequired && (!spec.tls || spec.tls.length === 0)) {
139
- throw new Error(NetworkResources.TLS_REQUIRED_ERROR_MESSAGE);
140
- }
141
- // Validate TLS configuration if present
142
- if (spec.tls && spec.tls.length > 0) {
143
- spec.tls.forEach((tlsConfig, index) => {
144
- if (!tlsConfig.secretName) {
145
- throw new Error(`TLS configuration at index ${index} must specify a secretName. ` +
146
- 'The secret should contain "tls.crt" and "tls.key" data.');
147
- }
148
- // Validate secret name format (RFC 1123 DNS subdomain)
149
- // This regex is safe as it only matches alphanumeric characters and hyphens
150
- // eslint-disable-next-line security/detect-unsafe-regex
151
- const secretNameRegex = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
152
- if (!secretNameRegex.test(tlsConfig.secretName)) {
153
- throw new Error(`Invalid TLS secret name "${tlsConfig.secretName}" at index ${index}. ` +
154
- 'Secret names must be valid RFC 1123 DNS subdomains (lowercase alphanumeric and hyphens).');
155
- }
156
- // Validate hosts if specified
157
- if (tlsConfig.hosts && tlsConfig.hosts.length > 0) {
158
- tlsConfig.hosts.forEach((host, hostIndex) => {
159
- if (!this.isValidHostname(host)) {
160
- throw new Error(`Invalid hostname "${host}" in TLS configuration at index ${index}, host ${hostIndex}. ` +
161
- 'Hostnames must be valid DNS names or wildcard patterns.');
162
- }
163
- });
164
- }
165
- });
166
- }
167
- // Validate that TLS hosts match Ingress rule hosts
168
- if (spec.tls && spec.rules) {
169
- const tlsHosts = new Set(spec.tls.flatMap((tls) => tls.hosts || []));
170
- const ruleHosts = spec.rules
171
- .map((rule) => rule.host)
172
- .filter((host) => Boolean(host));
173
- for (const ruleHost of ruleHosts) {
174
- if (!tlsHosts.has(ruleHost)) {
175
- console.warn(`Warning: Host "${ruleHost}" in Ingress rules is not covered by TLS configuration. ` +
176
- 'Consider adding it to the TLS hosts for secure communication.');
177
- }
178
- }
179
- }
180
- }
181
- /**
182
- * Validates hostname format (supports wildcards) with ReDoS protection
183
- * @param hostname - Hostname to validate
184
- * @returns True if hostname is valid
185
- * @since 2.8.0
186
- */
187
- isValidHostname(hostname) {
188
- if (!hostname || hostname.length === 0 || hostname.length > 253) {
189
- return false;
190
- }
191
- // Split hostname into parts and validate each part
192
- const parts = hostname.split('.');
193
- if (parts.length < 2)
194
- return false;
195
- // Handle wildcard
196
- if (hostname.startsWith('*.')) {
197
- parts.shift(); // Remove wildcard part
198
- if (parts.length < 2)
199
- return false; // Must have at least two parts after wildcard
200
- }
201
- // Validate each part
202
- return parts.every((part) => {
203
- if (part.length === 0 || part.length > 63)
204
- return false;
205
- if (part.startsWith('-') || part.endsWith('-'))
206
- return false;
207
- return /^[a-z0-9-]+$/i.test(part);
208
- });
209
- }
210
- /**
211
- * Applies NGINX Ingress specific annotations
212
- * @param spec - Ingress specification
213
- * @param annotations - Base annotations to enhance
214
- * @returns Enhanced annotations with NGINX specific settings
215
- * @since 2.9.0
216
- */
217
- applyNginxAnnotations(spec, annotations) {
218
- if (!spec.nginx)
219
- return annotations;
220
- const nginxAnnotations = { ...annotations };
221
- this.applySSLAnnotations(spec.nginx, nginxAnnotations);
222
- this.applyHSTSAnnotations(spec.nginx, nginxAnnotations);
223
- this.applyProxyAnnotations(spec.nginx, nginxAnnotations);
224
- this.applyCORSAnnotations(spec.nginx, nginxAnnotations);
225
- this.applyRateLimitingAnnotations(spec.nginx, nginxAnnotations);
226
- this.applyRewriteAnnotations(spec.nginx, nginxAnnotations);
227
- this.applyBackendAnnotations(spec.nginx, nginxAnnotations);
228
- this.applySessionAffinityAnnotations(spec.nginx, nginxAnnotations);
229
- this.applySecurityAnnotations(spec.nginx, nginxAnnotations);
230
- this.applyCustomAnnotations(spec.nginx, nginxAnnotations);
231
- return nginxAnnotations;
232
- }
233
- /**
234
- * Apply SSL/TLS annotations
235
- * @private
236
- */
237
- applySSLAnnotations(nginx, annotations) {
238
- if (nginx.sslRedirect !== undefined) {
239
- annotations['nginx.ingress.kubernetes.io/ssl-redirect'] = nginx.sslRedirect.toString();
240
- }
241
- if (nginx.forceSSLRedirect !== undefined) {
242
- annotations['nginx.ingress.kubernetes.io/force-ssl-redirect'] =
243
- nginx.forceSSLRedirect.toString();
244
- }
245
- if (nginx.sslProtocols) {
246
- annotations['nginx.ingress.kubernetes.io/ssl-protocols'] = nginx.sslProtocols;
247
- }
248
- if (nginx.sslCiphers) {
249
- annotations['nginx.ingress.kubernetes.io/ssl-ciphers'] = nginx.sslCiphers;
250
- }
251
- }
252
- /**
253
- * Apply HSTS annotations
254
- * @private
255
- */
256
- applyHSTSAnnotations(nginx, annotations) {
257
- if (nginx.enableHSTS !== undefined) {
258
- annotations['nginx.ingress.kubernetes.io/hsts'] = nginx.enableHSTS.toString();
259
- }
260
- if (nginx.hstsMaxAge !== undefined) {
261
- annotations['nginx.ingress.kubernetes.io/hsts-max-age'] = nginx.hstsMaxAge.toString();
262
- }
263
- if (nginx.hstsIncludeSubdomains !== undefined) {
264
- annotations['nginx.ingress.kubernetes.io/hsts-include-subdomains'] =
265
- nginx.hstsIncludeSubdomains.toString();
266
- }
267
- if (nginx.hstsPreload !== undefined) {
268
- annotations['nginx.ingress.kubernetes.io/hsts-preload'] = nginx.hstsPreload.toString();
269
- }
270
- }
271
- /**
272
- * Apply proxy annotations
273
- * @private
274
- */
275
- applyProxyAnnotations(nginx, annotations) {
276
- if (nginx.proxyBodySize) {
277
- annotations['nginx.ingress.kubernetes.io/proxy-body-size'] = nginx.proxyBodySize;
278
- }
279
- if (nginx.proxyConnectTimeout !== undefined) {
280
- annotations['nginx.ingress.kubernetes.io/proxy-connect-timeout'] =
281
- nginx.proxyConnectTimeout.toString();
282
- }
283
- if (nginx.proxySendTimeout !== undefined) {
284
- annotations['nginx.ingress.kubernetes.io/proxy-send-timeout'] =
285
- nginx.proxySendTimeout.toString();
286
- }
287
- if (nginx.proxyReadTimeout !== undefined) {
288
- annotations['nginx.ingress.kubernetes.io/proxy-read-timeout'] =
289
- nginx.proxyReadTimeout.toString();
290
- }
291
- }
292
- /**
293
- * Apply CORS annotations
294
- * @private
295
- */
296
- applyCORSAnnotations(nginx, annotations) {
297
- if (nginx.enableCORS !== undefined) {
298
- annotations['nginx.ingress.kubernetes.io/enable-cors'] = nginx.enableCORS.toString();
299
- }
300
- if (nginx.corsAllowOrigin) {
301
- annotations['nginx.ingress.kubernetes.io/cors-allow-origin'] = nginx.corsAllowOrigin;
302
- }
303
- if (nginx.corsAllowMethods) {
304
- annotations['nginx.ingress.kubernetes.io/cors-allow-methods'] = nginx.corsAllowMethods;
305
- }
306
- if (nginx.corsAllowHeaders) {
307
- annotations['nginx.ingress.kubernetes.io/cors-allow-headers'] = nginx.corsAllowHeaders;
308
- }
309
- }
310
- /**
311
- * Apply rate limiting annotations
312
- * @private
313
- */
314
- applyRateLimitingAnnotations(nginx, annotations) {
315
- if (nginx.rateLimiting) {
316
- if (nginx.rateLimiting.rps !== undefined) {
317
- annotations['nginx.ingress.kubernetes.io/rate-limit-rps'] =
318
- nginx.rateLimiting.rps.toString();
319
- }
320
- if (nginx.rateLimiting.rpm !== undefined) {
321
- annotations['nginx.ingress.kubernetes.io/rate-limit-rpm'] =
322
- nginx.rateLimiting.rpm.toString();
323
- }
324
- if (nginx.rateLimiting.connections !== undefined) {
325
- annotations['nginx.ingress.kubernetes.io/rate-limit-connections'] =
326
- nginx.rateLimiting.connections.toString();
327
- }
328
- }
329
- }
330
- /**
331
- * Apply rewrite annotations
332
- * @private
333
- */
334
- applyRewriteAnnotations(nginx, annotations) {
335
- if (nginx.rewriteTarget) {
336
- annotations['nginx.ingress.kubernetes.io/rewrite-target'] = nginx.rewriteTarget;
337
- }
338
- if (nginx.useRegex !== undefined) {
339
- annotations['nginx.ingress.kubernetes.io/use-regex'] = nginx.useRegex.toString();
340
- }
341
- }
342
- /**
343
- * Apply backend annotations
344
- * @private
345
- */
346
- applyBackendAnnotations(nginx, annotations) {
347
- if (nginx.backendProtocol) {
348
- annotations['nginx.ingress.kubernetes.io/backend-protocol'] = nginx.backendProtocol;
349
- }
350
- if (nginx.upstreamHashBy) {
351
- annotations['nginx.ingress.kubernetes.io/upstream-hash-by'] = nginx.upstreamHashBy;
352
- }
353
- }
354
- /**
355
- * Apply session affinity annotations
356
- * @private
357
- */
358
- applySessionAffinityAnnotations(nginx, annotations) {
359
- if (nginx.sessionAffinity) {
360
- annotations['nginx.ingress.kubernetes.io/affinity'] = nginx.sessionAffinity;
361
- }
362
- if (nginx.sessionCookieName) {
363
- annotations['nginx.ingress.kubernetes.io/affinity-cookie-name'] = nginx.sessionCookieName;
364
- }
365
- if (nginx.sessionCookieExpires !== undefined) {
366
- annotations['nginx.ingress.kubernetes.io/affinity-cookie-expires'] =
367
- nginx.sessionCookieExpires.toString();
368
- }
369
- if (nginx.sessionCookieMaxAge !== undefined) {
370
- annotations['nginx.ingress.kubernetes.io/affinity-cookie-max-age'] =
371
- nginx.sessionCookieMaxAge.toString();
372
- }
373
- if (nginx.sessionCookiePath) {
374
- annotations['nginx.ingress.kubernetes.io/affinity-cookie-path'] = nginx.sessionCookiePath;
375
- }
376
- }
377
- /**
378
- * Apply security annotations
379
- * @private
380
- */
381
- applySecurityAnnotations(nginx, annotations) {
382
- if (nginx.whitelistSourceRange && nginx.whitelistSourceRange.length > 0) {
383
- annotations['nginx.ingress.kubernetes.io/whitelist-source-range'] =
384
- nginx.whitelistSourceRange.join(',');
385
- }
386
- }
387
- /**
388
- * Apply custom annotations
389
- * @private
390
- */
391
- applyCustomAnnotations(nginx, annotations) {
392
- if (nginx.configurationSnippet) {
393
- annotations['nginx.ingress.kubernetes.io/configuration-snippet'] = nginx.configurationSnippet;
394
- }
395
- if (nginx.serverSnippet) {
396
- annotations['nginx.ingress.kubernetes.io/server-snippet'] = nginx.serverSnippet;
397
- }
398
- }
399
- /**
400
- * Applies cert-manager annotations for automatic certificate management
401
- * @param spec - Ingress specification
402
- * @param annotations - Base annotations to enhance
403
- * @returns Enhanced annotations with cert-manager settings
404
- * @since 2.9.0
405
- */
406
- applyCertManagerAnnotations(spec, annotations) {
407
- if (!spec.certManager)
408
- return annotations;
409
- const certManager = spec.certManager;
410
- const certAnnotations = { ...annotations };
411
- // ClusterIssuer or Issuer
412
- if (certManager.clusterIssuer) {
413
- certAnnotations['cert-manager.io/cluster-issuer'] = certManager.clusterIssuer;
414
- }
415
- else if (certManager.issuer) {
416
- certAnnotations['cert-manager.io/issuer'] = certManager.issuer;
417
- }
418
- // ACME challenge type
419
- if (certManager.acmeChallenge) {
420
- certAnnotations['cert-manager.io/acme-challenge-type'] = certManager.acmeChallenge;
421
- }
422
- // Certificate class
423
- if (certManager.certificateClass) {
424
- certAnnotations['cert-manager.io/certificate-class'] = certManager.certificateClass;
425
- }
426
- return certAnnotations;
427
- }
428
- /**
429
- * Applies security defaults to Ingress annotations
430
- * @param spec - Ingress specification
431
- * @returns Enhanced annotations with security defaults
432
- * @since 2.8.0
433
- */
434
- applySecurityDefaults(spec) {
435
- let annotations = { ...spec.annotations };
436
- // Apply SSL redirect if TLS is configured or force SSL redirect is enabled
437
- if ((spec.tls && spec.tls.length > 0) || spec.forceSSLRedirect) {
438
- // NGINX Ingress Controller annotations
439
- annotations['nginx.ingress.kubernetes.io/ssl-redirect'] = 'true';
440
- annotations['nginx.ingress.kubernetes.io/force-ssl-redirect'] = 'true';
441
- // Traefik annotations
442
- annotations['traefik.ingress.kubernetes.io/redirect-entry-point'] = 'https';
443
- // HAProxy annotations
444
- annotations['haproxy.org/ssl-redirect'] = 'true';
445
- }
446
- // Add security headers for production environments
447
- if (spec.environment === 'production' || spec.requireTLS) {
448
- // NGINX security headers with CSP
449
- annotations['nginx.ingress.kubernetes.io/configuration-snippet'] = `
450
- more_set_headers "X-Frame-Options: DENY";
451
- more_set_headers "X-Content-Type-Options: nosniff";
452
- more_set_headers "X-XSS-Protection: 1; mode=block";
453
- more_set_headers "Referrer-Policy: strict-origin-when-cross-origin";
454
- more_set_headers "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';";
455
- `.trim();
456
- }
457
- // Apply NGINX specific annotations
458
- annotations = this.applyNginxAnnotations(spec, annotations);
459
- // Apply cert-manager annotations
460
- annotations = this.applyCertManagerAnnotations(spec, annotations);
461
- return annotations;
462
- }
463
- /**
464
- * Creates a secure Ingress with TLS validation and environment-aware defaults
465
- * @param spec - Enhanced Ingress specification
466
- * @returns Created Ingress ApiObject
467
- * @example
468
- * ```typescript
469
- * // Production Ingress with mandatory TLS
470
- * networkResources.addSecureIngress({
471
- * name: 'web-ingress',
472
- * environment: 'production',
473
- * tls: [{
474
- * hosts: ['example.com'],
475
- * secretName: 'example-tls'
476
- * }],
477
- * rules: [{
478
- * host: 'example.com',
479
- * http: {
480
- * paths: [{
481
- * path: '/',
482
- * pathType: 'Prefix',
483
- * backend: {
484
- * service: { name: 'web-service', port: { number: 80 } }
485
- * }
486
- * }]
487
- * }
488
- * }]
489
- * });
490
- * ```
491
- * @since 2.8.0
492
- */
493
- addSecureIngress(spec) {
494
- // Validate TLS configuration and security requirements
495
- this.validateIngressSecurity(spec);
496
- // Apply security defaults to annotations
497
- const enhancedAnnotations = this.applySecurityDefaults(spec);
498
- // Create the Ingress with enhanced security
499
- const ingressSpec = {};
500
- if (spec.ingressClassName) {
501
- ingressSpec['ingressClassName'] = spec.ingressClassName;
502
- }
503
- if (spec.tls) {
504
- ingressSpec['tls'] = spec.tls;
505
- }
506
- if (spec.rules) {
507
- ingressSpec['rules'] = spec.rules;
508
- }
509
- return this.createApiObject(spec.name, NetworkResources.NETWORKING_API_VERSION, 'Ingress', ingressSpec, spec.labels, enhancedAnnotations);
510
- }
511
- /**
512
- * Creates an Ingress resource with optional TLS validation
513
- * @param spec - Ingress specification
514
- * @returns Created Ingress ApiObject
515
- * @deprecated Use addSecureIngress for enhanced security validation
516
- * @since 2.7.0
517
- */
518
- addIngress(spec) {
519
- // Apply basic validation if environment is specified
520
- if (spec.environment || spec.requireTLS) {
521
- this.validateIngressSecurity(spec);
522
- const enhancedAnnotations = this.applySecurityDefaults(spec);
523
- const ingressSpec = {};
524
- if (spec.ingressClassName) {
525
- ingressSpec['ingressClassName'] = spec.ingressClassName;
526
- }
527
- if (spec.tls) {
528
- ingressSpec['tls'] = spec.tls;
529
- }
530
- if (spec.rules) {
531
- ingressSpec['rules'] = spec.rules;
532
- }
533
- return this.createApiObject(spec.name, NetworkResources.NETWORKING_API_VERSION, 'Ingress', ingressSpec, spec.labels, enhancedAnnotations);
534
- }
535
- // Legacy behavior for backward compatibility
536
- const ingressSpec = {};
537
- if (spec.ingressClassName) {
538
- ingressSpec['ingressClassName'] = spec.ingressClassName;
539
- }
540
- if (spec.tls) {
541
- ingressSpec['tls'] = spec.tls;
542
- }
543
- if (spec.rules) {
544
- ingressSpec['rules'] = spec.rules;
545
- }
546
- return this.createApiObject(spec.name, NetworkResources.NETWORKING_API_VERSION, 'Ingress', ingressSpec, spec.labels, spec.annotations);
547
- }
548
- /**
549
- * Creates an NGINX Ingress with enhanced configuration and cert-manager integration
550
- * @param spec - Enhanced Ingress specification with NGINX and cert-manager support
551
- * @returns Created Ingress ApiObject
552
- * @example
553
- * ```typescript
554
- * // NGINX Ingress with Let's Encrypt and advanced features
555
- * networkResources.addNginxIngress({
556
- * name: 'web-ingress',
557
- * ingressClassName: 'nginx',
558
- * environment: 'production',
559
- * rules: [{
560
- * host: 'example.com',
561
- * http: {
562
- * paths: [{
563
- * path: '/',
564
- * pathType: 'Prefix',
565
- * backend: {
566
- * service: { name: 'web-service', port: { number: 80 } }
567
- * }
568
- * }]
569
- * }
570
- * }],
571
- * tls: [{
572
- * hosts: ['example.com'],
573
- * secretName: 'example-tls'
574
- * }],
575
- * nginx: {
576
- * sslRedirect: true,
577
- * enableHSTS: true,
578
- * hstsMaxAge: 31536000,
579
- * proxyBodySize: '10m',
580
- * rateLimiting: { rps: 100 }
581
- * },
582
- * certManager: {
583
- * clusterIssuer: 'letsencrypt-prod'
584
- * }
585
- * });
586
- * ```
587
- * @since 2.9.0
588
- */
589
- addNginxIngress(spec) {
590
- // Set default ingress class for NGINX
591
- const nginxSpec = {
592
- ...spec,
593
- ingressClassName: spec.ingressClassName || 'nginx',
594
- };
595
- // Use the enhanced secure ingress method
596
- return this.addSecureIngress(nginxSpec);
597
- }
598
- /**
599
- * Creates an NGINX Ingress with Let's Encrypt certificate automation
600
- * @param name - Ingress name
601
- * @param host - Primary hostname
602
- * @param serviceName - Backend service name
603
- * @param servicePort - Backend service port
604
- * @param clusterIssuer - Let's Encrypt ClusterIssuer name
605
- * @param additionalHosts - Additional hostnames
606
- * @param path - URL path (default: '/')
607
- * @param pathType - Path type (default: 'Prefix')
608
- * @param nginxConfig - Optional NGINX configuration
609
- * @param labels - Optional labels
610
- * @param annotations - Optional additional annotations
611
- * @returns Created Ingress ApiObject
612
- * @example
613
- * ```typescript
614
- * // Simple NGINX Ingress with Let's Encrypt
615
- * networkResources.addNginxIngressWithLetsEncrypt(
616
- * 'web-ingress',
617
- * 'example.com',
618
- * 'web-service',
619
- * 80,
620
- * 'letsencrypt-prod',
621
- * ['www.example.com'],
622
- * '/',
623
- * 'Prefix',
624
- * { enableHSTS: true, rateLimiting: { rps: 50 } }
625
- * );
626
- * ```
627
- * @since 2.9.0
628
- */
629
- addNginxIngressWithLetsEncrypt(name, host, serviceName, servicePort, clusterIssuer, additionalHosts = [], path = '/', pathType = 'Prefix', nginxConfig, labels, annotations) {
630
- const allHosts = [host, ...additionalHosts];
631
- const secretName = `${name}-tls`;
632
- return this.addNginxIngress({
633
- name,
634
- ingressClassName: 'nginx',
635
- environment: 'production',
636
- tls: [
637
- {
638
- hosts: allHosts,
639
- secretName,
640
- },
641
- ],
642
- rules: [
643
- {
644
- host,
645
- http: {
646
- paths: [
647
- {
648
- path,
649
- pathType,
650
- backend: {
651
- service: {
652
- name: serviceName,
653
- port: { number: servicePort },
654
- },
655
- },
656
- },
657
- ],
658
- },
659
- },
660
- ],
661
- nginx: {
662
- sslRedirect: true,
663
- enableHSTS: true,
664
- hstsMaxAge: 31536000,
665
- hstsIncludeSubdomains: true,
666
- ...nginxConfig,
667
- },
668
- certManager: {
669
- clusterIssuer,
670
- },
671
- ...(labels && { labels }),
672
- ...(annotations && { annotations }),
673
- });
674
- }
675
- /**
676
- * Gets predefined NetworkPolicy templates for common security patterns
677
- * @returns Array of predefined NetworkPolicy templates
678
- * @since 2.9.0
679
- */
680
- static getNetworkPolicyTemplates() {
681
- return [
682
- {
683
- name: 'deny-all',
684
- description: 'Deny all ingress and egress traffic (Zero Trust baseline)',
685
- policyTypes: ['Ingress', 'Egress'],
686
- ingress: [],
687
- egress: [],
688
- },
689
- {
690
- name: 'allow-dns-only',
691
- description: 'Allow only DNS queries (port 53) for egress',
692
- policyTypes: ['Ingress', 'Egress'],
693
- ingress: [],
694
- egress: [
695
- {
696
- ports: [
697
- { protocol: 'UDP', port: 53 },
698
- { protocol: 'TCP', port: 53 },
699
- ],
700
- },
701
- ],
702
- },
703
- {
704
- name: 'web-frontend',
705
- description: 'Allow ingress on port 80/443, egress to backend services',
706
- policyTypes: ['Ingress', 'Egress'],
707
- ingress: [
708
- {
709
- ports: [
710
- { protocol: 'TCP', port: 80 },
711
- { protocol: 'TCP', port: 443 },
712
- ],
713
- },
714
- ],
715
- egress: [
716
- {
717
- ports: [
718
- { protocol: 'UDP', port: 53 },
719
- { protocol: 'TCP', port: 53 },
720
- ],
721
- },
722
- ],
723
- },
724
- ];
725
- }
726
- /**
727
- * Creates a NetworkPolicy from a predefined template
728
- * @param templateName - Name of the predefined template
729
- * @param name - Policy name
730
- * @param podSelector - Pod selector to apply policy to
731
- * @param labels - Optional labels
732
- * @param annotations - Optional annotations
733
- * @returns Created NetworkPolicy ApiObject
734
- * @example
735
- * ```typescript
736
- * // Create a deny-all policy
737
- * networkResources.addNetworkPolicyFromTemplate(
738
- * 'deny-all',
739
- * 'default-deny',
740
- * { matchLabels: { app: 'web' } }
741
- * );
742
- * ```
743
- * @since 2.9.0
744
- */
745
- addNetworkPolicyFromTemplate(templateName, name, podSelector, labels, annotations) {
746
- const templates = NetworkResources.getNetworkPolicyTemplates();
747
- const template = templates.find((t) => t.name === templateName);
748
- if (!template) {
749
- const availableTemplates = templates.map((t) => t.name).join(', ');
750
- throw new Error(`NetworkPolicy template '${templateName}' not found. Available templates: ${availableTemplates}`);
751
- }
752
- console.warn(NetworkResources.NETWORK_POLICY_TEMPLATE_INFO.replace('{templateName}', templateName).replace('{description}', template.description));
753
- return this.addNetworkPolicy({
754
- name,
755
- podSelector,
756
- policyTypes: template.policyTypes,
757
- ...(template.ingress && { ingress: template.ingress }),
758
- ...(template.egress && { egress: template.egress }),
759
- ...(labels && { labels }),
760
- ...(annotations && { annotations }),
761
- });
762
- }
763
- }
764
- /**
765
- * Error message for missing TLS configuration in production environments
766
- * @since 2.9.0
767
- */
768
- NetworkResources.TLS_REQUIRED_ERROR_MESSAGE = 'TLS configuration is required for production Ingress resources. Please configure the "tls" field with valid certificate references.';
769
- /**
770
- * Warning message for NetworkPolicy with default policy types
771
- * @since 2.9.0
772
- */
773
- NetworkResources.NETWORK_POLICY_DEFAULT_WARNING = "⚠️ WARNING: NetworkPolicy '{name}' has no explicit policyTypes or rules. Defaulting to ['Ingress', 'Egress'] for security. Consider specifying explicit rules.";
774
- /**
775
- * Info message for NetworkPolicy template usage
776
- * @since 2.9.0
777
- */
778
- NetworkResources.NETWORK_POLICY_TEMPLATE_INFO = "⚠️ INFO: Using NetworkPolicy template '{templateName}': {description}";
779
- /**
780
- * Kubernetes networking API version
781
- * @since 2.9.0
782
- */
783
- NetworkResources.NETWORKING_API_VERSION = 'networking.k8s.io/v1';
784
- //# sourceMappingURL=networkResources.js.map