@connorbritain/mssql-mcp-core 0.1.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/dist/audit/AuditLogger.d.ts +37 -0
- package/dist/audit/AuditLogger.d.ts.map +1 -0
- package/dist/audit/AuditLogger.js +145 -0
- package/dist/audit/AuditLogger.js.map +1 -0
- package/dist/config/EnvironmentManager.d.ts +75 -0
- package/dist/config/EnvironmentManager.d.ts.map +1 -0
- package/dist/config/EnvironmentManager.js +305 -0
- package/dist/config/EnvironmentManager.js.map +1 -0
- package/dist/config/ScriptManager.d.ts +69 -0
- package/dist/config/ScriptManager.d.ts.map +1 -0
- package/dist/config/ScriptManager.js +166 -0
- package/dist/config/ScriptManager.js.map +1 -0
- package/dist/config/SecretResolver.d.ts +66 -0
- package/dist/config/SecretResolver.d.ts.map +1 -0
- package/dist/config/SecretResolver.js +230 -0
- package/dist/config/SecretResolver.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/routing/IntentRouter.d.ts +17 -0
- package/dist/routing/IntentRouter.d.ts.map +1 -0
- package/dist/routing/IntentRouter.js +243 -0
- package/dist/routing/IntentRouter.js.map +1 -0
- package/dist/server/createMcpServer.d.ts +7 -0
- package/dist/server/createMcpServer.d.ts.map +1 -0
- package/dist/server/createMcpServer.js +100 -0
- package/dist/server/createMcpServer.js.map +1 -0
- package/dist/server/toolsets.d.ts +42 -0
- package/dist/server/toolsets.d.ts.map +1 -0
- package/dist/server/toolsets.js +303 -0
- package/dist/server/toolsets.js.map +1 -0
- package/dist/server/wrapToolRun.d.ts +13 -0
- package/dist/server/wrapToolRun.d.ts.map +1 -0
- package/dist/server/wrapToolRun.js +102 -0
- package/dist/server/wrapToolRun.js.map +1 -0
- package/dist/shims.d.ts +2 -0
- package/dist/shims.d.ts.map +1 -0
- package/dist/shims.js +15 -0
- package/dist/shims.js.map +1 -0
- package/dist/tools/CreateIndexTool.d.ts +24 -0
- package/dist/tools/CreateIndexTool.d.ts.map +1 -0
- package/dist/tools/CreateIndexTool.js +64 -0
- package/dist/tools/CreateIndexTool.js.map +1 -0
- package/dist/tools/CreateTableTool.d.ts +12 -0
- package/dist/tools/CreateTableTool.d.ts.map +1 -0
- package/dist/tools/CreateTableTool.js +49 -0
- package/dist/tools/CreateTableTool.js.map +1 -0
- package/dist/tools/DeleteDataTool.d.ts +56 -0
- package/dist/tools/DeleteDataTool.d.ts.map +1 -0
- package/dist/tools/DeleteDataTool.js +103 -0
- package/dist/tools/DeleteDataTool.js.map +1 -0
- package/dist/tools/DescribeTableTool.d.ts +32 -0
- package/dist/tools/DescribeTableTool.d.ts.map +1 -0
- package/dist/tools/DescribeTableTool.js +116 -0
- package/dist/tools/DescribeTableTool.js.map +1 -0
- package/dist/tools/DropTableTool.d.ts +12 -0
- package/dist/tools/DropTableTool.d.ts.map +1 -0
- package/dist/tools/DropTableTool.js +37 -0
- package/dist/tools/DropTableTool.js.map +1 -0
- package/dist/tools/ExplainQueryTool.d.ts +24 -0
- package/dist/tools/ExplainQueryTool.d.ts.map +1 -0
- package/dist/tools/ExplainQueryTool.js +98 -0
- package/dist/tools/ExplainQueryTool.js.map +1 -0
- package/dist/tools/InsertDataTool.d.ts +17 -0
- package/dist/tools/InsertDataTool.d.ts.map +1 -0
- package/dist/tools/InsertDataTool.js +102 -0
- package/dist/tools/InsertDataTool.js.map +1 -0
- package/dist/tools/InspectDependenciesTool.d.ts +46 -0
- package/dist/tools/InspectDependenciesTool.d.ts.map +1 -0
- package/dist/tools/InspectDependenciesTool.js +215 -0
- package/dist/tools/InspectDependenciesTool.js.map +1 -0
- package/dist/tools/ListDatabasesTool.d.ts +27 -0
- package/dist/tools/ListDatabasesTool.d.ts.map +1 -0
- package/dist/tools/ListDatabasesTool.js +107 -0
- package/dist/tools/ListDatabasesTool.js.map +1 -0
- package/dist/tools/ListEnvironmentsTool.d.ts +49 -0
- package/dist/tools/ListEnvironmentsTool.d.ts.map +1 -0
- package/dist/tools/ListEnvironmentsTool.js +73 -0
- package/dist/tools/ListEnvironmentsTool.js.map +1 -0
- package/dist/tools/ListScriptsTool.d.ts +41 -0
- package/dist/tools/ListScriptsTool.d.ts.map +1 -0
- package/dist/tools/ListScriptsTool.js +86 -0
- package/dist/tools/ListScriptsTool.js.map +1 -0
- package/dist/tools/ListTableTool.d.ts +24 -0
- package/dist/tools/ListTableTool.d.ts.map +1 -0
- package/dist/tools/ListTableTool.js +85 -0
- package/dist/tools/ListTableTool.js.map +1 -0
- package/dist/tools/ProfileTableTool.d.ts +78 -0
- package/dist/tools/ProfileTableTool.d.ts.map +1 -0
- package/dist/tools/ProfileTableTool.js +373 -0
- package/dist/tools/ProfileTableTool.js.map +1 -0
- package/dist/tools/ReadDataTool.d.ts +61 -0
- package/dist/tools/ReadDataTool.d.ts.map +1 -0
- package/dist/tools/ReadDataTool.js +299 -0
- package/dist/tools/ReadDataTool.js.map +1 -0
- package/dist/tools/RelationshipInspectorTool.d.ts +46 -0
- package/dist/tools/RelationshipInspectorTool.d.ts.map +1 -0
- package/dist/tools/RelationshipInspectorTool.js +156 -0
- package/dist/tools/RelationshipInspectorTool.js.map +1 -0
- package/dist/tools/RunScriptTool.d.ts +214 -0
- package/dist/tools/RunScriptTool.d.ts.map +1 -0
- package/dist/tools/RunScriptTool.js +186 -0
- package/dist/tools/RunScriptTool.js.map +1 -0
- package/dist/tools/SearchSchemaTool.d.ts +88 -0
- package/dist/tools/SearchSchemaTool.d.ts.map +1 -0
- package/dist/tools/SearchSchemaTool.js +237 -0
- package/dist/tools/SearchSchemaTool.js.map +1 -0
- package/dist/tools/TestConnectionTool.d.ts +38 -0
- package/dist/tools/TestConnectionTool.d.ts.map +1 -0
- package/dist/tools/TestConnectionTool.js +156 -0
- package/dist/tools/TestConnectionTool.js.map +1 -0
- package/dist/tools/UpdateDataTool.d.ts +61 -0
- package/dist/tools/UpdateDataTool.d.ts.map +1 -0
- package/dist/tools/UpdateDataTool.js +117 -0
- package/dist/tools/UpdateDataTool.js.map +1 -0
- package/dist/tools/ValidateEnvironmentConfigTool.d.ts +51 -0
- package/dist/tools/ValidateEnvironmentConfigTool.d.ts.map +1 -0
- package/dist/tools/ValidateEnvironmentConfigTool.js +320 -0
- package/dist/tools/ValidateEnvironmentConfigTool.js.map +1 -0
- package/dist/tools/index.d.ts +21 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +22 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type AuditLevel = "none" | "basic" | "verbose";
|
|
2
|
+
export interface AuditLogEntry {
|
|
3
|
+
timestamp: string;
|
|
4
|
+
toolName: string;
|
|
5
|
+
environment?: string;
|
|
6
|
+
arguments?: Record<string, any>;
|
|
7
|
+
result?: {
|
|
8
|
+
success: boolean;
|
|
9
|
+
recordCount?: number;
|
|
10
|
+
error?: string;
|
|
11
|
+
data?: any;
|
|
12
|
+
};
|
|
13
|
+
durationMs?: number;
|
|
14
|
+
sessionId?: string;
|
|
15
|
+
userId?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class AuditLogger {
|
|
18
|
+
private readonly logFilePath;
|
|
19
|
+
private readonly enabled;
|
|
20
|
+
private readonly redactSensitiveData;
|
|
21
|
+
constructor();
|
|
22
|
+
private ensureLogDirectory;
|
|
23
|
+
private redactArguments;
|
|
24
|
+
log(entry: AuditLogEntry): void;
|
|
25
|
+
logToolInvocation(toolName: string, args: any, result: any, durationMs: number, options?: {
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
userId?: string;
|
|
28
|
+
environment?: string;
|
|
29
|
+
auditLevel?: AuditLevel;
|
|
30
|
+
}): void;
|
|
31
|
+
/**
|
|
32
|
+
* Truncate result data for verbose logging to prevent huge log entries
|
|
33
|
+
*/
|
|
34
|
+
private truncateResultData;
|
|
35
|
+
}
|
|
36
|
+
export declare const auditLogger: AuditLogger;
|
|
37
|
+
//# sourceMappingURL=AuditLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditLogger.d.ts","sourceRoot":"","sources":["../../src/audit/AuditLogger.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,CAAC;KACZ,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;;IAoB9C,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,eAAe;IA6BvB,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAkB/B,iBAAiB,CACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,UAAU,CAAC;KACzB,GACA,IAAI;IA+CP;;OAEG;IACH,OAAO,CAAC,kBAAkB;CA2B3B;AAGD,eAAO,MAAM,WAAW,aAAoB,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
export class AuditLogger {
|
|
4
|
+
constructor() {
|
|
5
|
+
// Read config from env vars
|
|
6
|
+
const logPath = process.env.AUDIT_LOG_PATH;
|
|
7
|
+
this.enabled = process.env.AUDIT_LOGGING !== "false"; // Enabled by default
|
|
8
|
+
this.redactSensitiveData = process.env.AUDIT_REDACT_SENSITIVE !== "false"; // Redact by default
|
|
9
|
+
if (this.enabled && logPath) {
|
|
10
|
+
this.logFilePath = path.resolve(logPath);
|
|
11
|
+
this.ensureLogDirectory();
|
|
12
|
+
}
|
|
13
|
+
else if (this.enabled) {
|
|
14
|
+
// Default to logs/audit.jsonl in the project root
|
|
15
|
+
this.logFilePath = path.resolve(process.cwd(), "logs", "audit.jsonl");
|
|
16
|
+
this.ensureLogDirectory();
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.logFilePath = "";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
ensureLogDirectory() {
|
|
23
|
+
if (!this.logFilePath)
|
|
24
|
+
return;
|
|
25
|
+
const dir = path.dirname(this.logFilePath);
|
|
26
|
+
if (!fs.existsSync(dir)) {
|
|
27
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
redactArguments(args) {
|
|
31
|
+
if (!this.redactSensitiveData) {
|
|
32
|
+
return args;
|
|
33
|
+
}
|
|
34
|
+
const redacted = { ...args };
|
|
35
|
+
const sensitiveKeys = [
|
|
36
|
+
"password",
|
|
37
|
+
"secret",
|
|
38
|
+
"token",
|
|
39
|
+
"key",
|
|
40
|
+
"authorization",
|
|
41
|
+
"auth",
|
|
42
|
+
"credential",
|
|
43
|
+
];
|
|
44
|
+
for (const [key, value] of Object.entries(redacted)) {
|
|
45
|
+
const lowerKey = key.toLowerCase();
|
|
46
|
+
if (sensitiveKeys.some((sensitive) => lowerKey.includes(sensitive))) {
|
|
47
|
+
redacted[key] = "[REDACTED]";
|
|
48
|
+
}
|
|
49
|
+
else if (typeof value === "string" && value.length > 500) {
|
|
50
|
+
// Truncate very long strings (likely large query results)
|
|
51
|
+
redacted[key] = value.substring(0, 500) + "... [TRUNCATED]";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return redacted;
|
|
55
|
+
}
|
|
56
|
+
log(entry) {
|
|
57
|
+
if (!this.enabled || !this.logFilePath) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const logEntry = {
|
|
62
|
+
...entry,
|
|
63
|
+
arguments: entry.arguments ? this.redactArguments(entry.arguments) : undefined,
|
|
64
|
+
};
|
|
65
|
+
const logLine = JSON.stringify(logEntry) + "\n";
|
|
66
|
+
fs.appendFileSync(this.logFilePath, logLine, { encoding: "utf-8" });
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error("Failed to write audit log:", error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
logToolInvocation(toolName, args, result, durationMs, options) {
|
|
73
|
+
const auditLevel = options?.auditLevel ?? "basic";
|
|
74
|
+
// Skip logging entirely for 'none' level
|
|
75
|
+
if (auditLevel === "none") {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Basic level: minimal info (tool name, success, timing, environment)
|
|
79
|
+
if (auditLevel === "basic") {
|
|
80
|
+
const entry = {
|
|
81
|
+
timestamp: new Date().toISOString(),
|
|
82
|
+
toolName,
|
|
83
|
+
environment: options?.environment,
|
|
84
|
+
result: {
|
|
85
|
+
success: result?.success ?? false,
|
|
86
|
+
recordCount: result?.recordCount ?? result?.rowsAffected,
|
|
87
|
+
error: result?.error,
|
|
88
|
+
},
|
|
89
|
+
durationMs: Math.round(durationMs),
|
|
90
|
+
sessionId: options?.sessionId,
|
|
91
|
+
userId: options?.userId,
|
|
92
|
+
};
|
|
93
|
+
this.log(entry);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Verbose level: full arguments and result data
|
|
97
|
+
const entry = {
|
|
98
|
+
timestamp: new Date().toISOString(),
|
|
99
|
+
toolName,
|
|
100
|
+
environment: options?.environment,
|
|
101
|
+
arguments: args || {},
|
|
102
|
+
result: {
|
|
103
|
+
success: result?.success ?? false,
|
|
104
|
+
recordCount: result?.recordCount ?? result?.rowsAffected,
|
|
105
|
+
error: result?.error,
|
|
106
|
+
data: this.truncateResultData(result?.data),
|
|
107
|
+
},
|
|
108
|
+
durationMs: Math.round(durationMs),
|
|
109
|
+
sessionId: options?.sessionId,
|
|
110
|
+
userId: options?.userId,
|
|
111
|
+
};
|
|
112
|
+
this.log(entry);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Truncate result data for verbose logging to prevent huge log entries
|
|
116
|
+
*/
|
|
117
|
+
truncateResultData(data) {
|
|
118
|
+
if (!data)
|
|
119
|
+
return undefined;
|
|
120
|
+
// If it's an array, limit to first 10 items
|
|
121
|
+
if (Array.isArray(data)) {
|
|
122
|
+
if (data.length > 10) {
|
|
123
|
+
return {
|
|
124
|
+
_truncated: true,
|
|
125
|
+
_totalCount: data.length,
|
|
126
|
+
items: data.slice(0, 10),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return data;
|
|
130
|
+
}
|
|
131
|
+
// If it's a large object (stringified > 10KB), truncate
|
|
132
|
+
const stringified = JSON.stringify(data);
|
|
133
|
+
if (stringified.length > 10000) {
|
|
134
|
+
return {
|
|
135
|
+
_truncated: true,
|
|
136
|
+
_originalSize: stringified.length,
|
|
137
|
+
preview: stringified.substring(0, 1000) + "...",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return data;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Singleton instance
|
|
144
|
+
export const auditLogger = new AuditLogger();
|
|
145
|
+
//# sourceMappingURL=AuditLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditLogger.js","sourceRoot":"","sources":["../../src/audit/AuditLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import sql from "mssql";
|
|
2
|
+
import { SecretResolver, SecretsConfig } from "./SecretResolver.js";
|
|
3
|
+
export type AccessLevel = "server" | "database";
|
|
4
|
+
export type TierLevel = "reader" | "writer" | "admin";
|
|
5
|
+
export type AuditLevel = "none" | "basic" | "verbose";
|
|
6
|
+
export interface EnvironmentConfig {
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
server: string;
|
|
10
|
+
database: string;
|
|
11
|
+
port?: number;
|
|
12
|
+
authMode: "sql" | "windows" | "aad";
|
|
13
|
+
username?: string;
|
|
14
|
+
password?: string;
|
|
15
|
+
domain?: string;
|
|
16
|
+
trustServerCertificate?: boolean;
|
|
17
|
+
connectionTimeout?: number;
|
|
18
|
+
requestTimeout?: number;
|
|
19
|
+
readonly?: boolean;
|
|
20
|
+
allowedTools?: string[];
|
|
21
|
+
deniedTools?: string[];
|
|
22
|
+
maxRowsDefault?: number;
|
|
23
|
+
requireApproval?: boolean;
|
|
24
|
+
auditLevel?: AuditLevel;
|
|
25
|
+
accessLevel?: AccessLevel;
|
|
26
|
+
allowedDatabases?: string[] | "*";
|
|
27
|
+
deniedDatabases?: string[];
|
|
28
|
+
allowedSchemas?: string[];
|
|
29
|
+
deniedSchemas?: string[];
|
|
30
|
+
tier?: TierLevel;
|
|
31
|
+
}
|
|
32
|
+
export interface EnvironmentsConfig {
|
|
33
|
+
defaultEnvironment?: string;
|
|
34
|
+
environments: EnvironmentConfig[];
|
|
35
|
+
scriptsPath?: string;
|
|
36
|
+
secrets?: SecretsConfig;
|
|
37
|
+
}
|
|
38
|
+
export declare class EnvironmentManager {
|
|
39
|
+
private readonly environments;
|
|
40
|
+
private defaultEnvironment?;
|
|
41
|
+
private readonly connections;
|
|
42
|
+
private secretResolver;
|
|
43
|
+
constructor(configPath?: string);
|
|
44
|
+
getSecretResolver(): SecretResolver;
|
|
45
|
+
private loadFromFile;
|
|
46
|
+
private loadFromEnvVars;
|
|
47
|
+
getEnvironment(name?: string): EnvironmentConfig;
|
|
48
|
+
listEnvironments(): EnvironmentConfig[];
|
|
49
|
+
/**
|
|
50
|
+
* Check if the environment allows access to a specific database.
|
|
51
|
+
* For database-level access, only the configured database is allowed.
|
|
52
|
+
* For server-level access, checks allowedDatabases/deniedDatabases.
|
|
53
|
+
*/
|
|
54
|
+
isDatabaseAllowed(environmentName: string | undefined, databaseName: string): {
|
|
55
|
+
allowed: boolean;
|
|
56
|
+
reason?: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Check if a schema.table reference is allowed based on allowedSchemas/deniedSchemas.
|
|
60
|
+
* Pattern matching supports wildcards (e.g., "audit.*", "*.sensitive_*")
|
|
61
|
+
*/
|
|
62
|
+
isSchemaAllowed(environmentName: string | undefined, schemaName: string, tableName?: string): {
|
|
63
|
+
allowed: boolean;
|
|
64
|
+
reason?: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Simple wildcard pattern matching (supports * as wildcard)
|
|
68
|
+
*/
|
|
69
|
+
private matchesPattern;
|
|
70
|
+
getConnection(environmentName?: string): Promise<sql.ConnectionPool>;
|
|
71
|
+
private createSqlConfig;
|
|
72
|
+
closeAll(): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
export declare function getEnvironmentManager(): EnvironmentManager;
|
|
75
|
+
//# sourceMappingURL=EnvironmentManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvironmentManager.d.ts","sourceRoot":"","sources":["../../src/config/EnvironmentManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { InteractiveBrowserCredential } from "@azure/identity";
|
|
4
|
+
import sql from "mssql";
|
|
5
|
+
import { createSecretResolver } from "./SecretResolver.js";
|
|
6
|
+
export class EnvironmentManager {
|
|
7
|
+
constructor(configPath) {
|
|
8
|
+
this.environments = new Map();
|
|
9
|
+
this.connections = new Map();
|
|
10
|
+
this.secretResolver = createSecretResolver(); // default: env-only
|
|
11
|
+
// Try to load from config file first
|
|
12
|
+
if (configPath) {
|
|
13
|
+
this.loadFromFile(configPath);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
// Fall back to environment variables for single environment
|
|
17
|
+
this.loadFromEnvVars();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
getSecretResolver() {
|
|
21
|
+
return this.secretResolver;
|
|
22
|
+
}
|
|
23
|
+
loadFromFile(configPath) {
|
|
24
|
+
try {
|
|
25
|
+
const resolvedPath = path.resolve(configPath);
|
|
26
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
27
|
+
console.warn(`Environment config file not found at ${resolvedPath}, falling back to env vars`);
|
|
28
|
+
this.loadFromEnvVars();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const configContent = fs.readFileSync(resolvedPath, "utf-8");
|
|
32
|
+
const config = JSON.parse(configContent);
|
|
33
|
+
// Build the secret resolver from config or fallback to DOTENV_PATH
|
|
34
|
+
let secretsConfig = config.secrets;
|
|
35
|
+
if (!secretsConfig) {
|
|
36
|
+
const dotenvPath = process.env.DOTENV_PATH;
|
|
37
|
+
if (dotenvPath) {
|
|
38
|
+
secretsConfig = { providers: [{ type: "env" }, { type: "dotenv", path: dotenvPath }] };
|
|
39
|
+
console.log(`Using DOTENV_PATH fallback: ${dotenvPath}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this.secretResolver = createSecretResolver(secretsConfig);
|
|
43
|
+
this.defaultEnvironment = config.defaultEnvironment;
|
|
44
|
+
for (const env of config.environments) {
|
|
45
|
+
// Resolve any secret placeholders in the config
|
|
46
|
+
const resolvedEnv = this.secretResolver.resolveObject(env);
|
|
47
|
+
this.environments.set(resolvedEnv.name, resolvedEnv);
|
|
48
|
+
}
|
|
49
|
+
console.log(`Loaded ${this.environments.size} environment(s) from ${resolvedPath}`);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error(`Failed to load environment config: ${error}`);
|
|
53
|
+
this.loadFromEnvVars();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
loadFromEnvVars() {
|
|
57
|
+
const server = process.env.SERVER_NAME;
|
|
58
|
+
const database = process.env.DATABASE_NAME;
|
|
59
|
+
if (!server || !database) {
|
|
60
|
+
throw new Error("No environment config file provided and SERVER_NAME/DATABASE_NAME env vars not set");
|
|
61
|
+
}
|
|
62
|
+
const defaultEnv = {
|
|
63
|
+
name: "default",
|
|
64
|
+
server,
|
|
65
|
+
database,
|
|
66
|
+
port: process.env.SQL_PORT ? parseInt(process.env.SQL_PORT, 10) : undefined,
|
|
67
|
+
authMode: process.env.SQL_AUTH_MODE?.toLowerCase() ?? "aad",
|
|
68
|
+
username: process.env.SQL_USERNAME,
|
|
69
|
+
password: process.env.SQL_PASSWORD,
|
|
70
|
+
domain: process.env.SQL_DOMAIN,
|
|
71
|
+
trustServerCertificate: process.env.TRUST_SERVER_CERTIFICATE?.toLowerCase() === "true",
|
|
72
|
+
connectionTimeout: process.env.CONNECTION_TIMEOUT
|
|
73
|
+
? parseInt(process.env.CONNECTION_TIMEOUT, 10)
|
|
74
|
+
: 30,
|
|
75
|
+
readonly: process.env.READONLY === "true",
|
|
76
|
+
};
|
|
77
|
+
this.environments.set("default", defaultEnv);
|
|
78
|
+
this.defaultEnvironment = "default";
|
|
79
|
+
console.log("Loaded default environment from environment variables");
|
|
80
|
+
}
|
|
81
|
+
getEnvironment(name) {
|
|
82
|
+
const targetName = name || this.defaultEnvironment || "default";
|
|
83
|
+
const env = this.environments.get(targetName);
|
|
84
|
+
if (!env) {
|
|
85
|
+
throw new Error(`Environment '${targetName}' not found. Available: ${Array.from(this.environments.keys()).join(", ")}`);
|
|
86
|
+
}
|
|
87
|
+
return env;
|
|
88
|
+
}
|
|
89
|
+
listEnvironments() {
|
|
90
|
+
return Array.from(this.environments.values());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if the environment allows access to a specific database.
|
|
94
|
+
* For database-level access, only the configured database is allowed.
|
|
95
|
+
* For server-level access, checks allowedDatabases/deniedDatabases.
|
|
96
|
+
*/
|
|
97
|
+
isDatabaseAllowed(environmentName, databaseName) {
|
|
98
|
+
const env = this.getEnvironment(environmentName);
|
|
99
|
+
const accessLevel = env.accessLevel ?? "database";
|
|
100
|
+
// Database-level access: only the configured database is allowed
|
|
101
|
+
if (accessLevel === "database") {
|
|
102
|
+
if (databaseName.toLowerCase() !== env.database.toLowerCase()) {
|
|
103
|
+
return {
|
|
104
|
+
allowed: false,
|
|
105
|
+
reason: `Environment '${env.name}' has database-level access and is restricted to database '${env.database}'. Cannot access '${databaseName}'.`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return { allowed: true };
|
|
109
|
+
}
|
|
110
|
+
// Server-level access: check allow/deny lists
|
|
111
|
+
const deniedDatabases = env.deniedDatabases ?? [];
|
|
112
|
+
const allowedDatabases = env.allowedDatabases;
|
|
113
|
+
// Check denied list first (takes precedence)
|
|
114
|
+
if (deniedDatabases.some((db) => db.toLowerCase() === databaseName.toLowerCase())) {
|
|
115
|
+
return {
|
|
116
|
+
allowed: false,
|
|
117
|
+
reason: `Database '${databaseName}' is in the denied list for environment '${env.name}'.`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// Check allowed list
|
|
121
|
+
if (allowedDatabases === "*") {
|
|
122
|
+
return { allowed: true };
|
|
123
|
+
}
|
|
124
|
+
if (Array.isArray(allowedDatabases) && allowedDatabases.length > 0) {
|
|
125
|
+
if (!allowedDatabases.some((db) => db.toLowerCase() === databaseName.toLowerCase())) {
|
|
126
|
+
return {
|
|
127
|
+
allowed: false,
|
|
128
|
+
reason: `Database '${databaseName}' is not in the allowed list for environment '${env.name}'. Allowed: ${allowedDatabases.join(", ")}.`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { allowed: true };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if a schema.table reference is allowed based on allowedSchemas/deniedSchemas.
|
|
136
|
+
* Pattern matching supports wildcards (e.g., "audit.*", "*.sensitive_*")
|
|
137
|
+
*/
|
|
138
|
+
isSchemaAllowed(environmentName, schemaName, tableName) {
|
|
139
|
+
const env = this.getEnvironment(environmentName);
|
|
140
|
+
const fullRef = tableName ? `${schemaName}.${tableName}` : schemaName;
|
|
141
|
+
const deniedSchemas = env.deniedSchemas ?? [];
|
|
142
|
+
const allowedSchemas = env.allowedSchemas;
|
|
143
|
+
// Check denied patterns first
|
|
144
|
+
for (const pattern of deniedSchemas) {
|
|
145
|
+
if (this.matchesPattern(fullRef, pattern) || this.matchesPattern(schemaName, pattern)) {
|
|
146
|
+
return {
|
|
147
|
+
allowed: false,
|
|
148
|
+
reason: `Schema/table '${fullRef}' matches denied pattern '${pattern}' in environment '${env.name}'.`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// If allowedSchemas is specified, check against it
|
|
153
|
+
if (allowedSchemas && allowedSchemas.length > 0) {
|
|
154
|
+
const isAllowed = allowedSchemas.some((pattern) => this.matchesPattern(fullRef, pattern) || this.matchesPattern(schemaName, pattern));
|
|
155
|
+
if (!isAllowed) {
|
|
156
|
+
return {
|
|
157
|
+
allowed: false,
|
|
158
|
+
reason: `Schema/table '${fullRef}' does not match any allowed pattern in environment '${env.name}'. Allowed: ${allowedSchemas.join(", ")}.`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { allowed: true };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Simple wildcard pattern matching (supports * as wildcard)
|
|
166
|
+
*/
|
|
167
|
+
matchesPattern(value, pattern) {
|
|
168
|
+
const regexPattern = pattern
|
|
169
|
+
.replace(/[.+?^${}()|[\]\\]/g, "\\$&") // Escape special regex chars except *
|
|
170
|
+
.replace(/\*/g, ".*"); // Convert * to .*
|
|
171
|
+
const regex = new RegExp(`^${regexPattern}$`, "i");
|
|
172
|
+
return regex.test(value);
|
|
173
|
+
}
|
|
174
|
+
async getConnection(environmentName) {
|
|
175
|
+
const env = this.getEnvironment(environmentName);
|
|
176
|
+
const cached = this.connections.get(env.name);
|
|
177
|
+
// Check if we have a valid cached connection
|
|
178
|
+
if (cached &&
|
|
179
|
+
cached.pool.connected &&
|
|
180
|
+
(!cached.expiresOn || cached.expiresOn > new Date(Date.now() + 2 * 60 * 1000))) {
|
|
181
|
+
return cached.pool;
|
|
182
|
+
}
|
|
183
|
+
// Create new connection
|
|
184
|
+
const { config, expiresOn } = await this.createSqlConfig(env);
|
|
185
|
+
// Close old connection if exists
|
|
186
|
+
if (cached?.pool && cached.pool.connected) {
|
|
187
|
+
await cached.pool.close();
|
|
188
|
+
}
|
|
189
|
+
const pool = new sql.ConnectionPool(config);
|
|
190
|
+
pool.on("error", (err) => {
|
|
191
|
+
console.error(`[mssql] Pool error for '${env.name}':`, err.message);
|
|
192
|
+
});
|
|
193
|
+
await pool.connect();
|
|
194
|
+
this.connections.set(env.name, { pool, expiresOn });
|
|
195
|
+
return pool;
|
|
196
|
+
}
|
|
197
|
+
async createSqlConfig(env) {
|
|
198
|
+
const baseConfig = {
|
|
199
|
+
server: env.server,
|
|
200
|
+
database: env.database,
|
|
201
|
+
port: env.port,
|
|
202
|
+
connectionTimeout: (env.connectionTimeout || 30) * 1000,
|
|
203
|
+
requestTimeout: (env.requestTimeout || 120) * 1000,
|
|
204
|
+
pool: {
|
|
205
|
+
max: 10,
|
|
206
|
+
min: 0,
|
|
207
|
+
idleTimeoutMillis: 30000,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
if (env.authMode === "sql") {
|
|
211
|
+
if (!env.username || !env.password) {
|
|
212
|
+
throw new Error(`Environment '${env.name}' requires username and password for SQL auth`);
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
config: {
|
|
216
|
+
...baseConfig,
|
|
217
|
+
user: env.username,
|
|
218
|
+
password: env.password,
|
|
219
|
+
options: {
|
|
220
|
+
encrypt: false,
|
|
221
|
+
trustServerCertificate: env.trustServerCertificate ?? false,
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (env.authMode === "windows") {
|
|
227
|
+
if (!env.username || !env.password) {
|
|
228
|
+
throw new Error(`Environment '${env.name}' requires username and password for Windows auth`);
|
|
229
|
+
}
|
|
230
|
+
// Strip DOMAIN\ prefix from username if present — tedious NTLM expects
|
|
231
|
+
// the username and domain as separate fields
|
|
232
|
+
let ntlmUser = env.username;
|
|
233
|
+
let ntlmDomain = env.domain || "";
|
|
234
|
+
const backslashIndex = ntlmUser.indexOf("\\");
|
|
235
|
+
if (backslashIndex !== -1) {
|
|
236
|
+
if (!ntlmDomain) {
|
|
237
|
+
ntlmDomain = ntlmUser.substring(0, backslashIndex);
|
|
238
|
+
}
|
|
239
|
+
ntlmUser = ntlmUser.substring(backslashIndex + 1);
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
config: {
|
|
243
|
+
...baseConfig,
|
|
244
|
+
options: {
|
|
245
|
+
encrypt: false,
|
|
246
|
+
trustServerCertificate: env.trustServerCertificate ?? false,
|
|
247
|
+
},
|
|
248
|
+
authentication: {
|
|
249
|
+
type: "ntlm",
|
|
250
|
+
options: {
|
|
251
|
+
userName: ntlmUser,
|
|
252
|
+
password: env.password,
|
|
253
|
+
domain: ntlmDomain,
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
// Azure AD auth
|
|
260
|
+
const credential = new InteractiveBrowserCredential({
|
|
261
|
+
redirectUri: "http://localhost",
|
|
262
|
+
});
|
|
263
|
+
const accessToken = await credential.getToken("https://database.windows.net/.default");
|
|
264
|
+
if (!accessToken?.token) {
|
|
265
|
+
throw new Error(`Failed to acquire Azure AD token for environment '${env.name}'`);
|
|
266
|
+
}
|
|
267
|
+
return {
|
|
268
|
+
config: {
|
|
269
|
+
...baseConfig,
|
|
270
|
+
options: {
|
|
271
|
+
encrypt: true,
|
|
272
|
+
trustServerCertificate: env.trustServerCertificate ?? false,
|
|
273
|
+
},
|
|
274
|
+
authentication: {
|
|
275
|
+
type: "azure-active-directory-access-token",
|
|
276
|
+
options: {
|
|
277
|
+
token: accessToken.token,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
expiresOn: accessToken?.expiresOnTimestamp
|
|
282
|
+
? new Date(accessToken.expiresOnTimestamp)
|
|
283
|
+
: new Date(Date.now() + 30 * 60 * 1000),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
async closeAll() {
|
|
287
|
+
for (const [name, { pool }] of this.connections.entries()) {
|
|
288
|
+
if (pool.connected) {
|
|
289
|
+
await pool.close();
|
|
290
|
+
console.log(`Closed connection for environment '${name}'`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
this.connections.clear();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Singleton instance
|
|
297
|
+
let environmentManager;
|
|
298
|
+
export function getEnvironmentManager() {
|
|
299
|
+
if (!environmentManager) {
|
|
300
|
+
const configPath = process.env.ENVIRONMENTS_CONFIG_PATH;
|
|
301
|
+
environmentManager = new EnvironmentManager(configPath);
|
|
302
|
+
}
|
|
303
|
+
return environmentManager;
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=EnvironmentManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvironmentManager.js","sourceRoot":"","sources":["../../src/config/EnvironmentManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { TierLevel } from "./EnvironmentManager.js";
|
|
2
|
+
export interface ScriptParameter {
|
|
3
|
+
name: string;
|
|
4
|
+
type: "string" | "number" | "boolean";
|
|
5
|
+
required?: boolean;
|
|
6
|
+
default?: string | number | boolean;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ScriptDefinition {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
file: string;
|
|
13
|
+
parameters?: ScriptParameter[];
|
|
14
|
+
allowedEnvironments?: string[];
|
|
15
|
+
deniedEnvironments?: string[];
|
|
16
|
+
tier?: TierLevel;
|
|
17
|
+
requiresApproval?: boolean;
|
|
18
|
+
readonly?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface ScriptsManifest {
|
|
21
|
+
scripts: ScriptDefinition[];
|
|
22
|
+
}
|
|
23
|
+
export interface LoadedScript extends ScriptDefinition {
|
|
24
|
+
sql: string;
|
|
25
|
+
}
|
|
26
|
+
export declare class ScriptManager {
|
|
27
|
+
private readonly scriptsPath;
|
|
28
|
+
private readonly scripts;
|
|
29
|
+
private loaded;
|
|
30
|
+
constructor(scriptsPath?: string);
|
|
31
|
+
/**
|
|
32
|
+
* Load scripts from the configured path
|
|
33
|
+
*/
|
|
34
|
+
private loadScripts;
|
|
35
|
+
/**
|
|
36
|
+
* Get all available scripts
|
|
37
|
+
*/
|
|
38
|
+
listScripts(): LoadedScript[];
|
|
39
|
+
/**
|
|
40
|
+
* Get a specific script by name
|
|
41
|
+
*/
|
|
42
|
+
getScript(name: string): LoadedScript | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a script can run in a given environment
|
|
45
|
+
*/
|
|
46
|
+
canRunInEnvironment(scriptName: string, environmentName: string): {
|
|
47
|
+
allowed: boolean;
|
|
48
|
+
reason?: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Resolve script parameters into the SQL template
|
|
52
|
+
* Parameters in SQL use @paramName syntax
|
|
53
|
+
*/
|
|
54
|
+
resolveParameters(script: LoadedScript, providedParams: Record<string, any>): {
|
|
55
|
+
sql: string;
|
|
56
|
+
errors: string[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Get the scripts path (for display/debugging)
|
|
60
|
+
*/
|
|
61
|
+
getScriptsPath(): string | null;
|
|
62
|
+
/**
|
|
63
|
+
* Check if scripts are configured
|
|
64
|
+
*/
|
|
65
|
+
isConfigured(): boolean;
|
|
66
|
+
}
|
|
67
|
+
export declare function getScriptManager(scriptsPath?: string): ScriptManager;
|
|
68
|
+
export declare function initScriptManager(scriptsPath?: string): void;
|
|
69
|
+
//# sourceMappingURL=ScriptManager.d.ts.map
|