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.
- package/README.md +503 -0
- package/dist/client/api.d.ts +90 -0
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +90 -0
- package/dist/client/api.js.map +1 -1
- package/dist/security/AISecurityScanner.d.ts +175 -0
- package/dist/security/AISecurityScanner.d.ts.map +1 -0
- package/dist/security/AISecurityScanner.js +645 -0
- package/dist/security/AISecurityScanner.js.map +1 -0
- package/dist/security/AutomatedRemediation.d.ts +145 -0
- package/dist/security/AutomatedRemediation.d.ts.map +1 -0
- package/dist/security/AutomatedRemediation.js +535 -0
- package/dist/security/AutomatedRemediation.js.map +1 -0
- package/dist/security/SecurityCIPipeline.d.ts +213 -0
- package/dist/security/SecurityCIPipeline.d.ts.map +1 -0
- package/dist/security/SecurityCIPipeline.js +684 -0
- package/dist/security/SecurityCIPipeline.js.map +1 -0
- package/dist/security/SecurityConfigManager.d.ts +294 -0
- package/dist/security/SecurityConfigManager.d.ts.map +1 -0
- package/dist/security/SecurityConfigManager.js +553 -0
- package/dist/security/SecurityConfigManager.js.map +1 -0
- package/dist/security/SecurityMonitoring.d.ts +245 -0
- package/dist/security/SecurityMonitoring.d.ts.map +1 -0
- package/dist/security/SecurityMonitoring.js +596 -0
- package/dist/security/SecurityMonitoring.js.map +1 -0
- package/dist/security/SecurityReviewer.d.ts +168 -0
- package/dist/security/SecurityReviewer.d.ts.map +1 -0
- package/dist/security/SecurityReviewer.js +683 -0
- package/dist/security/SecurityReviewer.js.map +1 -0
- package/dist/security/index.d.ts +182 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +189 -0
- package/dist/security/index.js.map +1 -0
- package/dist/tools/media.d.ts +43 -4
- package/dist/tools/media.d.ts.map +1 -1
- package/dist/tools/media.js +43 -4
- package/dist/tools/media.js.map +1 -1
- package/dist/tools/posts.d.ts +225 -4
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +225 -4
- package/dist/tools/posts.js.map +1 -1
- package/docs/DOCKER_PUBLISHING_TROUBLESHOOTING.md +233 -0
- package/docs/PUBLISHING-TROUBLESHOOTING.md +227 -0
- package/docs/api/README.md +53 -11
- package/docs/api/openapi.json +10 -10
- package/docs/api/summary.json +1 -1
- package/docs/api/tools/wp_create_post.md +9 -3
- package/docs/api/tools/wp_delete_post.md +2 -3
- package/docs/api/tools/wp_get_current_user.md +7 -1
- package/docs/api/tools/wp_get_post.md +2 -3
- package/docs/api/tools/wp_get_post_revisions.md +1 -1
- package/docs/api/tools/wp_list_posts.md +10 -3
- package/docs/api/tools/wp_list_users.md +8 -1
- package/docs/api/tools/wp_search_site.md +8 -1
- package/docs/api/tools/wp_test_auth.md +8 -1
- package/docs/api/tools/wp_update_post.md +2 -3
- package/docs/examples/docker-production.md +801 -0
- package/docs/examples/multi-site-setup.md +575 -0
- package/docs/examples/single-site-setup.md +390 -0
- package/docs/examples/use-case-workflows.md +469 -0
- package/package.json +11 -3
- package/src/client/api.ts +90 -0
- package/src/security/AISecurityScanner.ts +780 -0
- package/src/security/AutomatedRemediation.ts +665 -0
- package/src/security/SecurityCIPipeline.ts +969 -0
- package/src/security/SecurityConfigManager.ts +829 -0
- package/src/security/SecurityMonitoring.ts +841 -0
- package/src/security/SecurityReviewer.ts +855 -0
- package/src/security/index.ts +249 -0
- package/src/tools/media.ts +43 -4
- 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
|
+
}
|