aws-security-mcp 0.7.1 → 0.7.3

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.
@@ -4,9 +4,7 @@ import { join, extname, relative } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  import {
6
6
  S3Client,
7
- PutObjectCommand,
8
- PutBucketWebsiteCommand,
9
- PutBucketPolicyCommand
7
+ PutObjectCommand
10
8
  } from "@aws-sdk/client-s3";
11
9
  var __filename = fileURLToPath(import.meta.url);
12
10
  var __dirname = join(__filename, "..");
@@ -56,38 +54,8 @@ Expected: ${dashboardDir}`
56
54
  );
57
55
  }
58
56
  const s3 = new S3Client({ region });
59
- console.log(`Configuring s3://${bucket} for static website hosting...`);
60
- await s3.send(
61
- new PutBucketWebsiteCommand({
62
- Bucket: bucket,
63
- WebsiteConfiguration: {
64
- IndexDocument: { Suffix: "index.html" },
65
- ErrorDocument: { Key: "index.html" }
66
- // SPA fallback
67
- }
68
- })
69
- );
70
- const partition = region.startsWith("cn-") ? "aws-cn" : "aws";
71
- console.log(`Setting public read bucket policy on s3://${bucket}...`);
72
- await s3.send(
73
- new PutBucketPolicyCommand({
74
- Bucket: bucket,
75
- Policy: JSON.stringify({
76
- Version: "2012-10-17",
77
- Statement: [
78
- {
79
- Sid: "PublicReadGetObject",
80
- Effect: "Allow",
81
- Principal: "*",
82
- Action: "s3:GetObject",
83
- Resource: `arn:${partition}:s3:::${bucket}/*`
84
- }
85
- ]
86
- })
87
- })
88
- );
89
57
  const files = collectFiles(dashboardDir);
90
- console.log(`Uploading ${files.length} files to s3://${bucket}...`);
58
+ console.log(`Uploading ${files.length} files to s3://${bucket}/ ...`);
91
59
  for (const filePath of files) {
92
60
  const key = relative(dashboardDir, filePath);
93
61
  const ext = extname(filePath);
@@ -103,14 +71,14 @@ Expected: ${dashboardDir}`
103
71
  );
104
72
  console.log(` ${key}`);
105
73
  }
106
- const domain = region.startsWith("cn-") ? "amazonaws.com.cn" : "amazonaws.com";
107
- const websiteUrl = `http://${bucket}.s3-website.${region}.${domain}`;
108
74
  console.log(`
109
- Dashboard deployed successfully!`);
110
- console.log(`Website URL: ${websiteUrl}`);
111
- console.log(
112
- "\nNote: Ensure S3 Block Public Access is disabled on this bucket for the website to be accessible.\n"
113
- );
75
+ \u2705 Dashboard uploaded to s3://${bucket}/`);
76
+ console.log(`
77
+ S3 bucket remains private (Block Public Access enabled).`);
78
+ console.log(`Access control is managed via IAM permissions.`);
79
+ console.log(`
80
+ To view the dashboard locally:`);
81
+ console.log(` aws-security-mcp dashboard --port 3000`);
114
82
  }
115
83
  export {
116
84
  deployDashboard
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/deploy-dashboard.ts"],"sourcesContent":["import { readdirSync, readFileSync, existsSync, copyFileSync } from \"node:fs\";\nimport { join, extname, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n S3Client,\n PutObjectCommand,\n PutBucketWebsiteCommand,\n PutBucketPolicyCommand,\n} from \"@aws-sdk/client-s3\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = join(__filename, \"..\");\n\nconst CONTENT_TYPES: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"text/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nfunction collectFiles(dir: string): string[] {\n const files: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...collectFiles(full));\n } else {\n files.push(full);\n }\n }\n return files;\n}\n\nexport async function deployDashboard(\n bucket: string,\n region: string,\n): Promise<void> {\n const dashboardDir = join(__dirname, \"../../dashboard/dist\");\n\n if (!existsSync(dashboardDir)) {\n console.error(\n `Dashboard not built. Run \"npm run build:dashboard\" first.\\n` +\n `Expected: ${dashboardDir}`,\n );\n process.exit(1);\n }\n\n // Copy real data.json if available\n const dataSource = join(\n process.env.HOME || process.env.USERPROFILE || \"~\",\n \".aws-security/dashboard/data.json\",\n );\n const dataDest = join(dashboardDir, \"data.json\");\n if (existsSync(dataSource)) {\n copyFileSync(dataSource, dataDest);\n console.log(`Loaded scan data from ${dataSource}`);\n } else {\n console.log(\n \"No scan data at ~/.aws-security/dashboard/data.json — deploying with bundled sample data\",\n );\n }\n\n const s3 = new S3Client({ region });\n\n // Configure static website hosting\n console.log(`Configuring s3://${bucket} for static website hosting...`);\n await s3.send(\n new PutBucketWebsiteCommand({\n Bucket: bucket,\n WebsiteConfiguration: {\n IndexDocument: { Suffix: \"index.html\" },\n ErrorDocument: { Key: \"index.html\" }, // SPA fallback\n },\n }),\n );\n\n // Set bucket policy for public read access\n const partition = region.startsWith(\"cn-\") ? \"aws-cn\" : \"aws\";\n console.log(`Setting public read bucket policy on s3://${bucket}...`);\n await s3.send(\n new PutBucketPolicyCommand({\n Bucket: bucket,\n Policy: JSON.stringify({\n Version: \"2012-10-17\",\n Statement: [\n {\n Sid: \"PublicReadGetObject\",\n Effect: \"Allow\",\n Principal: \"*\",\n Action: \"s3:GetObject\",\n Resource: `arn:${partition}:s3:::${bucket}/*`,\n },\n ],\n }),\n }),\n );\n\n // Upload all files\n const files = collectFiles(dashboardDir);\n console.log(`Uploading ${files.length} files to s3://${bucket}...`);\n\n for (const filePath of files) {\n const key = relative(dashboardDir, filePath);\n const ext = extname(filePath);\n const contentType = CONTENT_TYPES[ext] || \"application/octet-stream\";\n const body = readFileSync(filePath);\n\n await s3.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentType: contentType,\n }),\n );\n console.log(` ${key}`);\n }\n\n const domain = region.startsWith(\"cn-\") ? \"amazonaws.com.cn\" : \"amazonaws.com\";\n const websiteUrl = `http://${bucket}.s3-website.${region}.${domain}`;\n console.log(`\\nDashboard deployed successfully!`);\n console.log(`Website URL: ${websiteUrl}`);\n console.log(\n \"\\nNote: Ensure S3 Block Public Access is disabled on this bucket for the website to be accessible.\\n\",\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/commands/deploy-dashboard.ts"],"sourcesContent":["import { readdirSync, readFileSync, existsSync, copyFileSync } from \"node:fs\";\nimport { join, extname, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n S3Client,\n PutObjectCommand,\n} from \"@aws-sdk/client-s3\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = join(__filename, \"..\");\n\nconst CONTENT_TYPES: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"text/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nfunction collectFiles(dir: string): string[] {\n const files: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...collectFiles(full));\n } else {\n files.push(full);\n }\n }\n return files;\n}\n\nexport async function deployDashboard(\n bucket: string,\n region: string,\n): Promise<void> {\n const dashboardDir = join(__dirname, \"../../dashboard/dist\");\n\n if (!existsSync(dashboardDir)) {\n console.error(\n `Dashboard not built. Run \"npm run build:dashboard\" first.\\n` +\n `Expected: ${dashboardDir}`,\n );\n process.exit(1);\n }\n\n // Copy real data.json if available\n const dataSource = join(\n process.env.HOME || process.env.USERPROFILE || \"~\",\n \".aws-security/dashboard/data.json\",\n );\n const dataDest = join(dashboardDir, \"data.json\");\n if (existsSync(dataSource)) {\n copyFileSync(dataSource, dataDest);\n console.log(`Loaded scan data from ${dataSource}`);\n } else {\n console.log(\n \"No scan data at ~/.aws-security/dashboard/data.json — deploying with bundled sample data\",\n );\n }\n\n const s3 = new S3Client({ region });\n\n // Upload all files (private no public policy, no website hosting)\n const files = collectFiles(dashboardDir);\n console.log(`Uploading ${files.length} files to s3://${bucket}/ ...`);\n\n for (const filePath of files) {\n const key = relative(dashboardDir, filePath);\n const ext = extname(filePath);\n const contentType = CONTENT_TYPES[ext] || \"application/octet-stream\";\n const body = readFileSync(filePath);\n\n await s3.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentType: contentType,\n }),\n );\n console.log(` ${key}`);\n }\n\n console.log(`\\n✅ Dashboard uploaded to s3://${bucket}/`);\n console.log(`\\nS3 bucket remains private (Block Public Access enabled).`);\n console.log(`Access control is managed via IAM permissions.`);\n console.log(`\\nTo view the dashboard locally:`);\n console.log(` aws-security-mcp dashboard --port 3000`);\n}\n"],"mappings":";AAAA,SAAS,aAAa,cAAc,YAAY,oBAAoB;AACpE,SAAS,MAAM,SAAS,gBAAgB;AACxC,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,KAAK,YAAY,IAAI;AAEvC,IAAM,gBAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AACZ;AAEA,SAAS,aAAa,KAAuB;AAC3C,QAAM,QAAkB,CAAC;AACzB,aAAW,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,UAAM,OAAO,KAAK,KAAK,MAAM,IAAI;AACjC,QAAI,MAAM,YAAY,GAAG;AACvB,YAAM,KAAK,GAAG,aAAa,IAAI,CAAC;AAAA,IAClC,OAAO;AACL,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,gBACpB,QACA,QACe;AACf,QAAM,eAAe,KAAK,WAAW,sBAAsB;AAE3D,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,YAAQ;AAAA,MACN;AAAA,YACe,YAAY;AAAA,IAC7B;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,aAAa;AAAA,IACjB,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe;AAAA,IAC/C;AAAA,EACF;AACA,QAAM,WAAW,KAAK,cAAc,WAAW;AAC/C,MAAI,WAAW,UAAU,GAAG;AAC1B,iBAAa,YAAY,QAAQ;AACjC,YAAQ,IAAI,yBAAyB,UAAU,EAAE;AAAA,EACnD,OAAO;AACL,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,KAAK,IAAI,SAAS,EAAE,OAAO,CAAC;AAGlC,QAAM,QAAQ,aAAa,YAAY;AACvC,UAAQ,IAAI,aAAa,MAAM,MAAM,kBAAkB,MAAM,OAAO;AAEpE,aAAW,YAAY,OAAO;AAC5B,UAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,UAAM,MAAM,QAAQ,QAAQ;AAC5B,UAAM,cAAc,cAAc,GAAG,KAAK;AAC1C,UAAM,OAAO,aAAa,QAAQ;AAElC,UAAM,GAAG;AAAA,MACP,IAAI,iBAAiB;AAAA,QACnB,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AACA,YAAQ,IAAI,KAAK,GAAG,EAAE;AAAA,EACxB;AAEA,UAAQ,IAAI;AAAA,oCAAkC,MAAM,GAAG;AACvD,UAAQ,IAAI;AAAA,yDAA4D;AACxE,UAAQ,IAAI,gDAAgD;AAC5D,UAAQ,IAAI;AAAA,+BAAkC;AAC9C,UAAQ,IAAI,0CAA0C;AACxD;","names":[]}
@@ -127,10 +127,12 @@ declare function generateMarkdownReport(scanResults: FullScanResult, lang?: Lang
127
127
  declare function generateHtmlReport(scanResults: FullScanResult, history?: DashboardHistoryEntry[], lang?: Lang): string;
128
128
  declare function generateMlps3HtmlReport(scanResults: FullScanResult, history?: DashboardHistoryEntry[], lang?: Lang): string;
129
129
 
130
+ declare function generateHwDefenseHtmlReport(scanResults: FullScanResult, lang?: Lang): string;
131
+
130
132
  declare function calculateScore(summary: FullScanResult["summary"]): number;
131
133
  declare function saveResults(scanResults: FullScanResult, outputDir?: string): string;
132
134
 
133
135
  declare function createServer(defaultRegion: string): McpServer;
134
136
  declare function startServer(defaultRegion: string): Promise<void>;
135
137
 
136
- export { type DashboardData, type DashboardHistoryEntry, type Finding, type FullScanResult, type Lang, type OrgAccount, type Priority, type ScanContext, type ScanResult, type Scanner, type Severity, assumeRole, buildRoleArn, calculateScore, createServer, generateHtmlReport, generateMarkdownReport, generateMlps3HtmlReport, getCurrentAccountId, listOrgAccounts, runAllScanners, runMultiAccountScanners, saveResults, startServer };
138
+ export { type DashboardData, type DashboardHistoryEntry, type Finding, type FullScanResult, type Lang, type OrgAccount, type Priority, type ScanContext, type ScanResult, type Scanner, type Severity, assumeRole, buildRoleArn, calculateScore, createServer, generateHtmlReport, generateHwDefenseHtmlReport, generateMarkdownReport, generateMlps3HtmlReport, getCurrentAccountId, listOrgAccounts, runAllScanners, runMultiAccountScanners, saveResults, startServer };