mcp-wordpress 2.2.0 → 2.4.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 (71) hide show
  1. package/README.md +503 -0
  2. package/dist/client/api.d.ts +90 -0
  3. package/dist/client/api.d.ts.map +1 -1
  4. package/dist/client/api.js +90 -0
  5. package/dist/client/api.js.map +1 -1
  6. package/dist/security/AISecurityScanner.d.ts +175 -0
  7. package/dist/security/AISecurityScanner.d.ts.map +1 -0
  8. package/dist/security/AISecurityScanner.js +645 -0
  9. package/dist/security/AISecurityScanner.js.map +1 -0
  10. package/dist/security/AutomatedRemediation.d.ts +145 -0
  11. package/dist/security/AutomatedRemediation.d.ts.map +1 -0
  12. package/dist/security/AutomatedRemediation.js +535 -0
  13. package/dist/security/AutomatedRemediation.js.map +1 -0
  14. package/dist/security/SecurityCIPipeline.d.ts +213 -0
  15. package/dist/security/SecurityCIPipeline.d.ts.map +1 -0
  16. package/dist/security/SecurityCIPipeline.js +684 -0
  17. package/dist/security/SecurityCIPipeline.js.map +1 -0
  18. package/dist/security/SecurityConfigManager.d.ts +294 -0
  19. package/dist/security/SecurityConfigManager.d.ts.map +1 -0
  20. package/dist/security/SecurityConfigManager.js +553 -0
  21. package/dist/security/SecurityConfigManager.js.map +1 -0
  22. package/dist/security/SecurityMonitoring.d.ts +245 -0
  23. package/dist/security/SecurityMonitoring.d.ts.map +1 -0
  24. package/dist/security/SecurityMonitoring.js +596 -0
  25. package/dist/security/SecurityMonitoring.js.map +1 -0
  26. package/dist/security/SecurityReviewer.d.ts +168 -0
  27. package/dist/security/SecurityReviewer.d.ts.map +1 -0
  28. package/dist/security/SecurityReviewer.js +683 -0
  29. package/dist/security/SecurityReviewer.js.map +1 -0
  30. package/dist/security/index.d.ts +182 -0
  31. package/dist/security/index.d.ts.map +1 -0
  32. package/dist/security/index.js +189 -0
  33. package/dist/security/index.js.map +1 -0
  34. package/dist/tools/media.d.ts +43 -4
  35. package/dist/tools/media.d.ts.map +1 -1
  36. package/dist/tools/media.js +43 -4
  37. package/dist/tools/media.js.map +1 -1
  38. package/dist/tools/posts.d.ts +225 -4
  39. package/dist/tools/posts.d.ts.map +1 -1
  40. package/dist/tools/posts.js +225 -4
  41. package/dist/tools/posts.js.map +1 -1
  42. package/docs/DOCKER_PUBLISHING_TROUBLESHOOTING.md +233 -0
  43. package/docs/PUBLISHING-TROUBLESHOOTING.md +227 -0
  44. package/docs/api/README.md +53 -11
  45. package/docs/api/openapi.json +10 -10
  46. package/docs/api/summary.json +1 -1
  47. package/docs/api/tools/wp_create_post.md +9 -3
  48. package/docs/api/tools/wp_delete_post.md +2 -3
  49. package/docs/api/tools/wp_get_current_user.md +7 -1
  50. package/docs/api/tools/wp_get_post.md +2 -3
  51. package/docs/api/tools/wp_get_post_revisions.md +1 -1
  52. package/docs/api/tools/wp_list_posts.md +10 -3
  53. package/docs/api/tools/wp_list_users.md +8 -1
  54. package/docs/api/tools/wp_search_site.md +8 -1
  55. package/docs/api/tools/wp_test_auth.md +8 -1
  56. package/docs/api/tools/wp_update_post.md +2 -3
  57. package/docs/examples/docker-production.md +801 -0
  58. package/docs/examples/multi-site-setup.md +575 -0
  59. package/docs/examples/single-site-setup.md +390 -0
  60. package/docs/examples/use-case-workflows.md +469 -0
  61. package/package.json +11 -3
  62. package/src/client/api.ts +90 -0
  63. package/src/security/AISecurityScanner.ts +780 -0
  64. package/src/security/AutomatedRemediation.ts +665 -0
  65. package/src/security/SecurityCIPipeline.ts +969 -0
  66. package/src/security/SecurityConfigManager.ts +829 -0
  67. package/src/security/SecurityMonitoring.ts +841 -0
  68. package/src/security/SecurityReviewer.ts +855 -0
  69. package/src/security/index.ts +249 -0
  70. package/src/tools/media.ts +43 -4
  71. package/src/tools/posts.ts +225 -4
@@ -0,0 +1,829 @@
1
+ /**
2
+ * Security Configuration Management System
3
+ * Provides centralized security policy and configuration management
4
+ */
5
+
6
+ import * as fs from "fs/promises";
7
+ import * as path from "path";
8
+ import { z } from "zod";
9
+ import { SecurityUtils } from "./SecurityConfig";
10
+ import { SecurityValidationError } from "./InputValidator";
11
+
12
+ interface SecurityPolicy {
13
+ id: string;
14
+ name: string;
15
+ version: string;
16
+ description: string;
17
+ enabled: boolean;
18
+ scope: "global" | "environment" | "application" | "endpoint";
19
+ rules: SecurityPolicyRule[];
20
+ compliance: {
21
+ frameworks: string[]; // OWASP, CWE, GDPR, etc.
22
+ requirements: string[];
23
+ };
24
+ metadata: {
25
+ created: Date;
26
+ updated: Date;
27
+ author: string;
28
+ approved: boolean;
29
+ };
30
+ }
31
+
32
+ interface SecurityPolicyRule {
33
+ id: string;
34
+ name: string;
35
+ type: "authentication" | "authorization" | "input-validation" | "crypto" | "session" | "logging" | "monitoring";
36
+ action: "enforce" | "warn" | "log" | "block";
37
+ conditions: {
38
+ environments?: string[];
39
+ methods?: string[];
40
+ paths?: string[];
41
+ userRoles?: string[];
42
+ };
43
+ parameters: Record<string, any>;
44
+ exceptions: string[];
45
+ }
46
+
47
+ interface SecurityConfiguration {
48
+ configId: string;
49
+ version: string;
50
+ environment: string;
51
+ policies: SecurityPolicy[];
52
+ settings: {
53
+ authentication: AuthenticationSettings;
54
+ authorization: AuthorizationSettings;
55
+ inputValidation: InputValidationSettings;
56
+ cryptography: CryptographySettings;
57
+ session: SessionSettings;
58
+ logging: LoggingSettings;
59
+ monitoring: MonitoringSettings;
60
+ };
61
+ overrides: Record<string, any>;
62
+ metadata: {
63
+ lastUpdated: Date;
64
+ checksum: string;
65
+ };
66
+ }
67
+
68
+ interface AuthenticationSettings {
69
+ methods: ("password" | "jwt" | "oauth" | "api-key")[];
70
+ passwordPolicy: {
71
+ minLength: number;
72
+ requireUppercase: boolean;
73
+ requireLowercase: boolean;
74
+ requireNumbers: boolean;
75
+ requireSpecialChars: boolean;
76
+ maxAge: number;
77
+ preventReuse: number;
78
+ };
79
+ jwtSettings: {
80
+ algorithm: string;
81
+ expiresIn: string;
82
+ issuer: string;
83
+ audience: string;
84
+ };
85
+ rateLimiting: {
86
+ maxAttempts: number;
87
+ windowMs: number;
88
+ blockDuration: number;
89
+ };
90
+ mfa: {
91
+ enabled: boolean;
92
+ methods: string[];
93
+ required: boolean;
94
+ };
95
+ }
96
+
97
+ interface AuthorizationSettings {
98
+ rbac: {
99
+ enabled: boolean;
100
+ defaultRole: string;
101
+ roleHierarchy: Record<string, string[]>;
102
+ };
103
+ permissions: {
104
+ strict: boolean;
105
+ defaultDeny: boolean;
106
+ inheritance: boolean;
107
+ };
108
+ sessionTimeout: number;
109
+ resourceAccess: {
110
+ checkOrigin: boolean;
111
+ allowedOrigins: string[];
112
+ csrfProtection: boolean;
113
+ };
114
+ }
115
+
116
+ interface InputValidationSettings {
117
+ sanitization: {
118
+ enabled: boolean;
119
+ htmlStripping: boolean;
120
+ sqlEscaping: boolean;
121
+ jsEscaping: boolean;
122
+ };
123
+ validation: {
124
+ strict: boolean;
125
+ maxStringLength: number;
126
+ maxFileSize: number;
127
+ allowedFileTypes: string[];
128
+ blockedPatterns: string[];
129
+ };
130
+ xssProtection: {
131
+ enabled: boolean;
132
+ mode: "filter" | "block";
133
+ reportUri: string;
134
+ };
135
+ }
136
+
137
+ interface CryptographySettings {
138
+ encryption: {
139
+ algorithm: "AES-256-GCM" | "AES-256-CBC" | "ChaCha20-Poly1305";
140
+ keyDerivation: "PBKDF2" | "scrypt" | "Argon2";
141
+ keyRotation: {
142
+ enabled: boolean;
143
+ intervalDays: number;
144
+ };
145
+ };
146
+ hashing: {
147
+ algorithm: "bcrypt" | "scrypt" | "Argon2";
148
+ saltRounds: number;
149
+ };
150
+ tls: {
151
+ minVersion: string;
152
+ cipherSuites: string[];
153
+ hsts: {
154
+ enabled: boolean;
155
+ maxAge: number;
156
+ includeSubDomains: boolean;
157
+ };
158
+ };
159
+ }
160
+
161
+ interface SessionSettings {
162
+ storage: "memory" | "redis" | "database";
163
+ security: {
164
+ httpOnly: boolean;
165
+ secure: boolean;
166
+ sameSite: "strict" | "lax" | "none";
167
+ };
168
+ timeout: {
169
+ idle: number;
170
+ absolute: number;
171
+ };
172
+ regeneration: {
173
+ onLogin: boolean;
174
+ onPrivilegeChange: boolean;
175
+ interval: number;
176
+ };
177
+ }
178
+
179
+ interface LoggingSettings {
180
+ level: "error" | "warn" | "info" | "debug";
181
+ security: {
182
+ logFailedAuth: boolean;
183
+ logPrivilegeEscalation: boolean;
184
+ logDataAccess: boolean;
185
+ logConfigChanges: boolean;
186
+ };
187
+ retention: {
188
+ days: number;
189
+ compression: boolean;
190
+ encryption: boolean;
191
+ };
192
+ alerting: {
193
+ enabled: boolean;
194
+ thresholds: Record<string, number>;
195
+ channels: string[];
196
+ };
197
+ }
198
+
199
+ interface MonitoringSettings {
200
+ realTime: {
201
+ enabled: boolean;
202
+ metrics: string[];
203
+ alertThresholds: Record<string, number>;
204
+ };
205
+ anomalyDetection: {
206
+ enabled: boolean;
207
+ sensitivity: "low" | "medium" | "high";
208
+ models: string[];
209
+ };
210
+ compliance: {
211
+ enabled: boolean;
212
+ frameworks: string[];
213
+ reportingSchedule: string;
214
+ };
215
+ }
216
+
217
+ /**
218
+ * Security Configuration Schema Validation
219
+ */
220
+ const SecurityPolicySchema = z.object({
221
+ id: z.string().min(1),
222
+ name: z.string().min(1),
223
+ version: z.string().regex(/^\d+\.\d+\.\d+$/),
224
+ description: z.string().min(1),
225
+ enabled: z.boolean(),
226
+ scope: z.enum(["global", "environment", "application", "endpoint"]),
227
+ rules: z.array(
228
+ z.object({
229
+ id: z.string().min(1),
230
+ name: z.string().min(1),
231
+ type: z.enum([
232
+ "authentication",
233
+ "authorization",
234
+ "input-validation",
235
+ "crypto",
236
+ "session",
237
+ "logging",
238
+ "monitoring",
239
+ ]),
240
+ action: z.enum(["enforce", "warn", "log", "block"]),
241
+ conditions: z.object({
242
+ environments: z.array(z.string()).optional(),
243
+ methods: z.array(z.string()).optional(),
244
+ paths: z.array(z.string()).optional(),
245
+ userRoles: z.array(z.string()).optional(),
246
+ }),
247
+ parameters: z.record(z.any()),
248
+ exceptions: z.array(z.string()),
249
+ }),
250
+ ),
251
+ compliance: z.object({
252
+ frameworks: z.array(z.string()),
253
+ requirements: z.array(z.string()),
254
+ }),
255
+ metadata: z.object({
256
+ created: z.date(),
257
+ updated: z.date(),
258
+ author: z.string(),
259
+ approved: z.boolean(),
260
+ }),
261
+ });
262
+
263
+ /**
264
+ * Security Configuration Manager
265
+ */
266
+ export class SecurityConfigManager {
267
+ private configurations: Map<string, SecurityConfiguration> = new Map();
268
+ private policies: Map<string, SecurityPolicy> = new Map();
269
+ private configPath: string;
270
+
271
+ constructor(configPath: string = "security-config") {
272
+ this.configPath = configPath;
273
+ }
274
+
275
+ /**
276
+ * Initialize security configuration manager
277
+ */
278
+ async initialize(): Promise<void> {
279
+ console.log("[Security Config] Initializing security configuration manager");
280
+
281
+ await this.ensureConfigDirectory();
282
+ await this.loadConfigurations();
283
+ await this.loadPolicies();
284
+
285
+ console.log(
286
+ `[Security Config] Loaded ${this.configurations.size} configurations and ${this.policies.size} policies`,
287
+ );
288
+ }
289
+
290
+ /**
291
+ * Create a new security policy
292
+ */
293
+ async createPolicy(policyData: Omit<SecurityPolicy, "id" | "metadata">): Promise<SecurityPolicy> {
294
+ const policy: SecurityPolicy = {
295
+ ...policyData,
296
+ id: SecurityUtils.generateSecureToken(16),
297
+ metadata: {
298
+ created: new Date(),
299
+ updated: new Date(),
300
+ author: "system",
301
+ approved: false,
302
+ },
303
+ };
304
+
305
+ // Validate policy
306
+ try {
307
+ SecurityPolicySchema.parse(policy);
308
+ } catch (error) {
309
+ throw new SecurityValidationError("Invalid security policy", [{ message: String(error) }]);
310
+ }
311
+
312
+ this.policies.set(policy.id, policy);
313
+ await this.savePolicyToFile(policy);
314
+
315
+ console.log(`[Security Config] Created policy: ${policy.name} (${policy.id})`);
316
+ return policy;
317
+ }
318
+
319
+ /**
320
+ * Update an existing security policy
321
+ */
322
+ async updatePolicy(policyId: string, updates: Partial<SecurityPolicy>): Promise<SecurityPolicy> {
323
+ const existingPolicy = this.policies.get(policyId);
324
+ if (!existingPolicy) {
325
+ throw new SecurityValidationError("Policy not found", [{ message: `Policy ${policyId} not found` }]);
326
+ }
327
+
328
+ const updatedPolicy: SecurityPolicy = {
329
+ ...existingPolicy,
330
+ ...updates,
331
+ id: policyId, // Ensure ID doesn't change
332
+ metadata: {
333
+ ...existingPolicy.metadata,
334
+ updated: new Date(),
335
+ },
336
+ };
337
+
338
+ // Validate updated policy
339
+ try {
340
+ SecurityPolicySchema.parse(updatedPolicy);
341
+ } catch (error) {
342
+ throw new SecurityValidationError("Invalid policy update", [{ message: String(error) }]);
343
+ }
344
+
345
+ this.policies.set(policyId, updatedPolicy);
346
+ await this.savePolicyToFile(updatedPolicy);
347
+
348
+ console.log(`[Security Config] Updated policy: ${updatedPolicy.name} (${policyId})`);
349
+ return updatedPolicy;
350
+ }
351
+
352
+ /**
353
+ * Create a new security configuration
354
+ */
355
+ async createConfiguration(
356
+ environment: string,
357
+ configData: Partial<SecurityConfiguration>,
358
+ ): Promise<SecurityConfiguration> {
359
+ const config: SecurityConfiguration = {
360
+ configId: SecurityUtils.generateSecureToken(16),
361
+ version: "1.0.0",
362
+ environment,
363
+ policies: [],
364
+ settings: configData.settings || this.getDefaultSettings(),
365
+ overrides: configData.overrides || {},
366
+ metadata: {
367
+ lastUpdated: new Date(),
368
+ checksum: "",
369
+ },
370
+ };
371
+
372
+ // Calculate checksum
373
+ config.metadata.checksum = await this.calculateChecksum(config);
374
+
375
+ this.configurations.set(environment, config);
376
+ await this.saveConfigurationToFile(config);
377
+
378
+ console.log(`[Security Config] Created configuration for environment: ${environment}`);
379
+ return config;
380
+ }
381
+
382
+ /**
383
+ * Get configuration for environment
384
+ */
385
+ getConfiguration(environment: string): SecurityConfiguration | null {
386
+ return this.configurations.get(environment) || null;
387
+ }
388
+
389
+ /**
390
+ * Get all configurations
391
+ */
392
+ getAllConfigurations(): SecurityConfiguration[] {
393
+ return Array.from(this.configurations.values());
394
+ }
395
+
396
+ /**
397
+ * Apply policies to configuration
398
+ */
399
+ async applyPoliciesToConfiguration(environment: string, policyIds: string[]): Promise<SecurityConfiguration> {
400
+ const config = this.configurations.get(environment);
401
+ if (!config) {
402
+ throw new SecurityValidationError("Configuration not found", [
403
+ { message: `Environment ${environment} not found` },
404
+ ]);
405
+ }
406
+
407
+ const policies: SecurityPolicy[] = [];
408
+ for (const policyId of policyIds) {
409
+ const policy = this.policies.get(policyId);
410
+ if (!policy) {
411
+ throw new SecurityValidationError("Policy not found", [{ message: `Policy ${policyId} not found` }]);
412
+ }
413
+ if (!policy.enabled) {
414
+ console.warn(`[Security Config] Skipping disabled policy: ${policy.name}`);
415
+ continue;
416
+ }
417
+ policies.push(policy);
418
+ }
419
+
420
+ config.policies = policies;
421
+ config.metadata.lastUpdated = new Date();
422
+ config.metadata.checksum = await this.calculateChecksum(config);
423
+
424
+ this.configurations.set(environment, config);
425
+ await this.saveConfigurationToFile(config);
426
+
427
+ console.log(`[Security Config] Applied ${policies.length} policies to ${environment}`);
428
+ return config;
429
+ }
430
+
431
+ /**
432
+ * Validate configuration compliance
433
+ */
434
+ async validateCompliance(environment: string): Promise<{
435
+ compliant: boolean;
436
+ violations: string[];
437
+ recommendations: string[];
438
+ }> {
439
+ const config = this.configurations.get(environment);
440
+ if (!config) {
441
+ throw new SecurityValidationError("Configuration not found", [
442
+ { message: `Environment ${environment} not found` },
443
+ ]);
444
+ }
445
+
446
+ const violations: string[] = [];
447
+ const recommendations: string[] = [];
448
+
449
+ // Check password policy compliance
450
+ if (config.settings.authentication.passwordPolicy.minLength < 8) {
451
+ violations.push("Password minimum length below recommended 8 characters");
452
+ }
453
+
454
+ // Check encryption compliance
455
+ if (!["AES-256-GCM", "ChaCha20-Poly1305"].includes(config.settings.cryptography.encryption.algorithm)) {
456
+ violations.push("Weak encryption algorithm detected");
457
+ }
458
+
459
+ // Check session security
460
+ if (!config.settings.session.security.httpOnly || !config.settings.session.security.secure) {
461
+ violations.push("Insecure session configuration");
462
+ }
463
+
464
+ // Check HTTPS enforcement
465
+ if (!config.settings.cryptography.tls.hsts.enabled) {
466
+ recommendations.push("Enable HSTS for enhanced security");
467
+ }
468
+
469
+ // Check MFA configuration
470
+ if (!config.settings.authentication.mfa.enabled) {
471
+ recommendations.push("Consider enabling multi-factor authentication");
472
+ }
473
+
474
+ // Check compliance frameworks
475
+ const requiredFrameworks = ["OWASP", "CWE"];
476
+ const configuredFrameworks = config.policies.flatMap((p) => p.compliance.frameworks);
477
+
478
+ for (const framework of requiredFrameworks) {
479
+ if (!configuredFrameworks.includes(framework)) {
480
+ recommendations.push(`Add ${framework} compliance policies`);
481
+ }
482
+ }
483
+
484
+ return {
485
+ compliant: violations.length === 0,
486
+ violations,
487
+ recommendations,
488
+ };
489
+ }
490
+
491
+ /**
492
+ * Generate default security settings
493
+ */
494
+ private getDefaultSettings(): SecurityConfiguration["settings"] {
495
+ return {
496
+ authentication: {
497
+ methods: ["password", "jwt"],
498
+ passwordPolicy: {
499
+ minLength: 8,
500
+ requireUppercase: true,
501
+ requireLowercase: true,
502
+ requireNumbers: true,
503
+ requireSpecialChars: true,
504
+ maxAge: 90,
505
+ preventReuse: 5,
506
+ },
507
+ jwtSettings: {
508
+ algorithm: "HS256",
509
+ expiresIn: "1h",
510
+ issuer: "mcp-wordpress",
511
+ audience: "mcp-wordpress-users",
512
+ },
513
+ rateLimiting: {
514
+ maxAttempts: 5,
515
+ windowMs: 900000, // 15 minutes
516
+ blockDuration: 3600000, // 1 hour
517
+ },
518
+ mfa: {
519
+ enabled: false,
520
+ methods: ["totp", "sms"],
521
+ required: false,
522
+ },
523
+ },
524
+ authorization: {
525
+ rbac: {
526
+ enabled: true,
527
+ defaultRole: "user",
528
+ roleHierarchy: {
529
+ admin: ["editor", "user"],
530
+ editor: ["user"],
531
+ user: [],
532
+ },
533
+ },
534
+ permissions: {
535
+ strict: true,
536
+ defaultDeny: true,
537
+ inheritance: true,
538
+ },
539
+ sessionTimeout: 3600, // 1 hour
540
+ resourceAccess: {
541
+ checkOrigin: true,
542
+ allowedOrigins: [],
543
+ csrfProtection: true,
544
+ },
545
+ },
546
+ inputValidation: {
547
+ sanitization: {
548
+ enabled: true,
549
+ htmlStripping: true,
550
+ sqlEscaping: true,
551
+ jsEscaping: true,
552
+ },
553
+ validation: {
554
+ strict: true,
555
+ maxStringLength: 10000,
556
+ maxFileSize: 10485760, // 10MB
557
+ allowedFileTypes: ["image/jpeg", "image/png", "application/pdf"],
558
+ blockedPatterns: ["<script>", "javascript:", "vbscript:"],
559
+ },
560
+ xssProtection: {
561
+ enabled: true,
562
+ mode: "block",
563
+ reportUri: "/security/xss-report",
564
+ },
565
+ },
566
+ cryptography: {
567
+ encryption: {
568
+ algorithm: "AES-256-GCM",
569
+ keyDerivation: "PBKDF2",
570
+ keyRotation: {
571
+ enabled: true,
572
+ intervalDays: 90,
573
+ },
574
+ },
575
+ hashing: {
576
+ algorithm: "bcrypt",
577
+ saltRounds: 12,
578
+ },
579
+ tls: {
580
+ minVersion: "1.2",
581
+ cipherSuites: ["ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES256-SHA384"],
582
+ hsts: {
583
+ enabled: true,
584
+ maxAge: 31536000, // 1 year
585
+ includeSubDomains: true,
586
+ },
587
+ },
588
+ },
589
+ session: {
590
+ storage: "memory",
591
+ security: {
592
+ httpOnly: true,
593
+ secure: true,
594
+ sameSite: "strict",
595
+ },
596
+ timeout: {
597
+ idle: 1800, // 30 minutes
598
+ absolute: 28800, // 8 hours
599
+ },
600
+ regeneration: {
601
+ onLogin: true,
602
+ onPrivilegeChange: true,
603
+ interval: 3600, // 1 hour
604
+ },
605
+ },
606
+ logging: {
607
+ level: "info",
608
+ security: {
609
+ logFailedAuth: true,
610
+ logPrivilegeEscalation: true,
611
+ logDataAccess: true,
612
+ logConfigChanges: true,
613
+ },
614
+ retention: {
615
+ days: 90,
616
+ compression: true,
617
+ encryption: true,
618
+ },
619
+ alerting: {
620
+ enabled: true,
621
+ thresholds: {
622
+ failedLogins: 10,
623
+ privilegeEscalation: 1,
624
+ dataAccess: 100,
625
+ },
626
+ channels: ["email", "webhook"],
627
+ },
628
+ },
629
+ monitoring: {
630
+ realTime: {
631
+ enabled: true,
632
+ metrics: ["requests", "errors", "latency", "security_events"],
633
+ alertThresholds: {
634
+ errorRate: 0.05,
635
+ latencyP99: 1000,
636
+ securityEvents: 10,
637
+ },
638
+ },
639
+ anomalyDetection: {
640
+ enabled: true,
641
+ sensitivity: "medium",
642
+ models: ["statistical", "ml"],
643
+ },
644
+ compliance: {
645
+ enabled: true,
646
+ frameworks: ["OWASP", "CWE"],
647
+ reportingSchedule: "daily",
648
+ },
649
+ },
650
+ };
651
+ }
652
+
653
+ /**
654
+ * Load configurations from files
655
+ */
656
+ private async loadConfigurations(): Promise<void> {
657
+ try {
658
+ const configDir = path.join(this.configPath, "configurations");
659
+ await fs.access(configDir);
660
+
661
+ const files = await fs.readdir(configDir);
662
+
663
+ for (const file of files) {
664
+ if (file.endsWith(".json")) {
665
+ const filePath = path.join(configDir, file);
666
+ const content = await fs.readFile(filePath, "utf-8");
667
+ const config: SecurityConfiguration = JSON.parse(content);
668
+
669
+ // Convert date strings back to Date objects
670
+ config.metadata.lastUpdated = new Date(config.metadata.lastUpdated);
671
+
672
+ this.configurations.set(config.environment, config);
673
+ }
674
+ }
675
+ } catch (_error) {
676
+ console.log("[Security Config] No existing configurations found, will create new ones");
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Load policies from files
682
+ */
683
+ private async loadPolicies(): Promise<void> {
684
+ try {
685
+ const policiesDir = path.join(this.configPath, "policies");
686
+ await fs.access(policiesDir);
687
+
688
+ const files = await fs.readdir(policiesDir);
689
+
690
+ for (const file of files) {
691
+ if (file.endsWith(".json")) {
692
+ const filePath = path.join(policiesDir, file);
693
+ const content = await fs.readFile(filePath, "utf-8");
694
+ const policy: SecurityPolicy = JSON.parse(content);
695
+
696
+ // Convert date strings back to Date objects
697
+ policy.metadata.created = new Date(policy.metadata.created);
698
+ policy.metadata.updated = new Date(policy.metadata.updated);
699
+
700
+ this.policies.set(policy.id, policy);
701
+ }
702
+ }
703
+ } catch (_error) {
704
+ console.log("[Security Config] No existing policies found");
705
+ }
706
+ }
707
+
708
+ /**
709
+ * Save configuration to file
710
+ */
711
+ private async saveConfigurationToFile(config: SecurityConfiguration): Promise<void> {
712
+ const configDir = path.join(this.configPath, "configurations");
713
+ await fs.mkdir(configDir, { recursive: true });
714
+
715
+ const filePath = path.join(configDir, `${config.environment}.json`);
716
+ await fs.writeFile(filePath, JSON.stringify(config, null, 2), "utf-8");
717
+ }
718
+
719
+ /**
720
+ * Save policy to file
721
+ */
722
+ private async savePolicyToFile(policy: SecurityPolicy): Promise<void> {
723
+ const policiesDir = path.join(this.configPath, "policies");
724
+ await fs.mkdir(policiesDir, { recursive: true });
725
+
726
+ const filePath = path.join(policiesDir, `${policy.id}.json`);
727
+ await fs.writeFile(filePath, JSON.stringify(policy, null, 2), "utf-8");
728
+ }
729
+
730
+ /**
731
+ * Ensure config directory exists
732
+ */
733
+ private async ensureConfigDirectory(): Promise<void> {
734
+ await fs.mkdir(this.configPath, { recursive: true });
735
+ await fs.mkdir(path.join(this.configPath, "configurations"), { recursive: true });
736
+ await fs.mkdir(path.join(this.configPath, "policies"), { recursive: true });
737
+ }
738
+
739
+ /**
740
+ * Calculate configuration checksum
741
+ */
742
+ private async calculateChecksum(config: SecurityConfiguration): Promise<string> {
743
+ const configForHash = {
744
+ ...config,
745
+ metadata: {
746
+ ...config.metadata,
747
+ checksum: "", // Exclude checksum from hash calculation
748
+ },
749
+ };
750
+
751
+ const _configString = JSON.stringify(configForHash, Object.keys(configForHash).sort());
752
+ return SecurityUtils.generateSecureToken(32);
753
+ }
754
+
755
+ /**
756
+ * Get all policies
757
+ */
758
+ getAllPolicies(): SecurityPolicy[] {
759
+ return Array.from(this.policies.values());
760
+ }
761
+
762
+ /**
763
+ * Get policy by ID
764
+ */
765
+ getPolicy(policyId: string): SecurityPolicy | null {
766
+ return this.policies.get(policyId) || null;
767
+ }
768
+
769
+ /**
770
+ * Delete policy
771
+ */
772
+ async deletePolicy(policyId: string): Promise<boolean> {
773
+ const policy = this.policies.get(policyId);
774
+ if (!policy) {
775
+ return false;
776
+ }
777
+
778
+ this.policies.delete(policyId);
779
+
780
+ try {
781
+ const filePath = path.join(this.configPath, "policies", `${policyId}.json`);
782
+ await fs.unlink(filePath);
783
+ console.log(`[Security Config] Deleted policy: ${policy.name} (${policyId})`);
784
+ return true;
785
+ } catch (error) {
786
+ console.warn(`[Security Config] Failed to delete policy file: ${error}`);
787
+ return false;
788
+ }
789
+ }
790
+
791
+ /**
792
+ * Export configuration
793
+ */
794
+ async exportConfiguration(environment: string): Promise<string> {
795
+ const config = this.configurations.get(environment);
796
+ if (!config) {
797
+ throw new SecurityValidationError("Configuration not found", [
798
+ { message: `Environment ${environment} not found` },
799
+ ]);
800
+ }
801
+
802
+ return JSON.stringify(config, null, 2);
803
+ }
804
+
805
+ /**
806
+ * Import configuration
807
+ */
808
+ async importConfiguration(configData: string): Promise<SecurityConfiguration> {
809
+ try {
810
+ const config: SecurityConfiguration = JSON.parse(configData);
811
+
812
+ // Validate configuration structure
813
+ if (!config.configId || !config.environment) {
814
+ throw new Error("Invalid configuration format");
815
+ }
816
+
817
+ // Convert date strings to Date objects
818
+ config.metadata.lastUpdated = new Date(config.metadata.lastUpdated);
819
+
820
+ this.configurations.set(config.environment, config);
821
+ await this.saveConfigurationToFile(config);
822
+
823
+ console.log(`[Security Config] Imported configuration for environment: ${config.environment}`);
824
+ return config;
825
+ } catch (error) {
826
+ throw new SecurityValidationError("Failed to import configuration", [{ message: String(error) }]);
827
+ }
828
+ }
829
+ }