@frontpoint/aws-infra-mcp 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/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/core/aws-analyzer.d.ts +73 -0
- package/dist/core/aws-analyzer.d.ts.map +1 -0
- package/dist/core/aws-analyzer.js +429 -0
- package/dist/core/aws-analyzer.js.map +1 -0
- package/dist/core/cdk-generator.d.ts +26 -0
- package/dist/core/cdk-generator.d.ts.map +1 -0
- package/dist/core/cdk-generator.js +790 -0
- package/dist/core/cdk-generator.js.map +1 -0
- package/dist/core/template-engine.d.ts +32 -0
- package/dist/core/template-engine.d.ts.map +1 -0
- package/dist/core/template-engine.js +131 -0
- package/dist/core/template-engine.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +158 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/aws-add-compute.d.ts +8 -0
- package/dist/tools/aws-add-compute.d.ts.map +1 -0
- package/dist/tools/aws-add-compute.js +269 -0
- package/dist/tools/aws-add-compute.js.map +1 -0
- package/dist/tools/aws-add-database.d.ts +8 -0
- package/dist/tools/aws-add-database.d.ts.map +1 -0
- package/dist/tools/aws-add-database.js +230 -0
- package/dist/tools/aws-add-database.js.map +1 -0
- package/dist/tools/aws-add-network.d.ts +8 -0
- package/dist/tools/aws-add-network.d.ts.map +1 -0
- package/dist/tools/aws-add-network.js +240 -0
- package/dist/tools/aws-add-network.js.map +1 -0
- package/dist/tools/aws-add-storage.d.ts +8 -0
- package/dist/tools/aws-add-storage.d.ts.map +1 -0
- package/dist/tools/aws-add-storage.js +207 -0
- package/dist/tools/aws-add-storage.js.map +1 -0
- package/dist/tools/aws-analyze.d.ts +8 -0
- package/dist/tools/aws-analyze.d.ts.map +1 -0
- package/dist/tools/aws-analyze.js +123 -0
- package/dist/tools/aws-analyze.js.map +1 -0
- package/dist/tools/aws-generate-all.d.ts +8 -0
- package/dist/tools/aws-generate-all.d.ts.map +1 -0
- package/dist/tools/aws-generate-all.js +197 -0
- package/dist/tools/aws-generate-all.js.map +1 -0
- package/dist/tools/aws-init.d.ts +8 -0
- package/dist/tools/aws-init.d.ts.map +1 -0
- package/dist/tools/aws-init.js +114 -0
- package/dist/tools/aws-init.js.map +1 -0
- package/dist/tools/aws-status.d.ts +8 -0
- package/dist/tools/aws-status.d.ts.map +1 -0
- package/dist/tools/aws-status.js +110 -0
- package/dist/tools/aws-status.js.map +1 -0
- package/dist/tools/index.d.ts +51 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +644 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 frontpoint
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# AWS Infra MCP
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for generating AWS CDK TypeScript infrastructure code with resource analysis.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **AWS Resource Analysis**: Scan existing AWS resources (EC2, RDS, Lambda, S3, DynamoDB, ECS, EKS, ECR, VPC, API Gateway)
|
|
8
|
+
- **CDK Code Generation**: Generate type-safe AWS CDK TypeScript projects
|
|
9
|
+
- **Full Service Coverage**: Support for compute, database, storage, and network resources
|
|
10
|
+
- **Interactive Configuration**: Add resources incrementally with MCP tools
|
|
11
|
+
- **Cost Estimation**: Preview estimated monthly costs (coming soon)
|
|
12
|
+
- **Security Validation**: IAM and security group validation (coming soon)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g @frontpoint/aws-infra-mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### As MCP Server
|
|
23
|
+
|
|
24
|
+
Add to your Claude Code MCP configuration:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"aws-infra": {
|
|
30
|
+
"command": "aws-infra-mcp",
|
|
31
|
+
"args": ["/path/to/your/project"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### CLI
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Start MCP server in current directory
|
|
41
|
+
aws-infra-mcp
|
|
42
|
+
|
|
43
|
+
# Start with specific project path
|
|
44
|
+
aws-infra-mcp /path/to/project
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Available Tools
|
|
48
|
+
|
|
49
|
+
| Tool | Description |
|
|
50
|
+
|------|-------------|
|
|
51
|
+
| `aws-init` | Initialize project with AWS credentials verification |
|
|
52
|
+
| `aws-analyze` | Scan existing AWS resources in your account |
|
|
53
|
+
| `aws-status` | Show current configuration status |
|
|
54
|
+
| `aws-add-compute` | Add EC2, Lambda, ECS, EKS resources |
|
|
55
|
+
| `aws-add-database` | Add RDS, Aurora, DynamoDB resources |
|
|
56
|
+
| `aws-add-storage` | Add S3, ECR resources |
|
|
57
|
+
| `aws-add-network` | Add VPC, API Gateway resources |
|
|
58
|
+
| `aws-generate-all` | Generate complete CDK project |
|
|
59
|
+
|
|
60
|
+
## Supported AWS Services
|
|
61
|
+
|
|
62
|
+
### Compute
|
|
63
|
+
- EC2 Instances & Auto Scaling Groups
|
|
64
|
+
- Lambda Functions with event sources
|
|
65
|
+
- ECS Clusters, Services, Task Definitions
|
|
66
|
+
- EKS Clusters with Node Groups
|
|
67
|
+
|
|
68
|
+
### Database
|
|
69
|
+
- RDS (MySQL, PostgreSQL, MariaDB)
|
|
70
|
+
- Aurora (MySQL, PostgreSQL, Serverless v2)
|
|
71
|
+
- DynamoDB Tables with GSI/LSI
|
|
72
|
+
|
|
73
|
+
### Storage
|
|
74
|
+
- S3 Buckets with lifecycle policies
|
|
75
|
+
- ECR Repositories
|
|
76
|
+
|
|
77
|
+
### Network
|
|
78
|
+
- VPC with public/private subnets
|
|
79
|
+
- NAT Gateways
|
|
80
|
+
- API Gateway (REST, HTTP, WebSocket)
|
|
81
|
+
|
|
82
|
+
## Example Workflow
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# 1. Initialize project
|
|
86
|
+
aws-init projectName: my-app region: ap-northeast-2
|
|
87
|
+
|
|
88
|
+
# 2. Analyze existing resources (optional)
|
|
89
|
+
aws-analyze
|
|
90
|
+
|
|
91
|
+
# 3. Add infrastructure resources
|
|
92
|
+
aws-add-network type: vpc name: main-vpc cidrBlock: 10.0.0.0/16
|
|
93
|
+
aws-add-database type: dynamodb name: users-table partitionKey: userId:S
|
|
94
|
+
aws-add-storage type: s3 name: my-app-assets versioning: true
|
|
95
|
+
aws-add-compute type: lambda name: api-handler runtime: nodejs20.x
|
|
96
|
+
|
|
97
|
+
# 4. Generate CDK project
|
|
98
|
+
aws-generate-all
|
|
99
|
+
|
|
100
|
+
# 5. Deploy
|
|
101
|
+
cd cdk-infra && npm install && npx cdk deploy --all
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Generated CDK Structure
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
cdk-infra/
|
|
108
|
+
├── bin/
|
|
109
|
+
│ └── app.ts # CDK app entry point
|
|
110
|
+
├── lib/
|
|
111
|
+
│ └── stacks/
|
|
112
|
+
│ ├── network-stack.ts
|
|
113
|
+
│ ├── compute-stack.ts
|
|
114
|
+
│ ├── database-stack.ts
|
|
115
|
+
│ └── storage-stack.ts
|
|
116
|
+
├── cdk.json
|
|
117
|
+
├── package.json
|
|
118
|
+
└── tsconfig.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Requirements
|
|
122
|
+
|
|
123
|
+
- Node.js >= 18.0.0
|
|
124
|
+
- AWS CLI configured with credentials
|
|
125
|
+
- AWS CDK CLI (`npm install -g aws-cdk`)
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
Configuration is stored in `.aws-infra-mcp/` directory:
|
|
130
|
+
|
|
131
|
+
- `config.json` - Infrastructure configuration
|
|
132
|
+
- `state.json` - Generation state and history
|
|
133
|
+
- `analysis-cache.json` - Cached AWS resource analysis
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT
|
|
138
|
+
|
|
139
|
+
## Author
|
|
140
|
+
|
|
141
|
+
frontpoint
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Resource Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Analyzes existing AWS resources using AWS SDK v3
|
|
5
|
+
*/
|
|
6
|
+
import type { AWSRegion, AWSResourceAnalysis, AnalyzedEC2Instance, AnalyzedRDSInstance, AnalyzedLambdaFunction, AnalyzedS3Bucket, AnalyzedDynamoDBTable, AnalyzedECSCluster, AnalyzedEKSCluster, AnalyzedECRRepository, AnalyzedVPC, AnalyzedAPIGateway } from '../types.js';
|
|
7
|
+
export interface AWSAnalyzerOptions {
|
|
8
|
+
region: AWSRegion;
|
|
9
|
+
profile?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AWSCredentialsInfo {
|
|
12
|
+
account: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
arn: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class AWSAnalyzer {
|
|
17
|
+
private region;
|
|
18
|
+
private clientConfig;
|
|
19
|
+
constructor(options: AWSAnalyzerOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Verify AWS credentials and get account info
|
|
22
|
+
*/
|
|
23
|
+
verifyCredentials(): Promise<AWSCredentialsInfo>;
|
|
24
|
+
/**
|
|
25
|
+
* Analyze all AWS resources
|
|
26
|
+
*/
|
|
27
|
+
analyzeAll(): Promise<AWSResourceAnalysis>;
|
|
28
|
+
/**
|
|
29
|
+
* Analyze EC2 instances
|
|
30
|
+
*/
|
|
31
|
+
analyzeEC2(): Promise<AnalyzedEC2Instance[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Analyze RDS instances
|
|
34
|
+
*/
|
|
35
|
+
analyzeRDS(): Promise<AnalyzedRDSInstance[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Analyze Lambda functions
|
|
38
|
+
*/
|
|
39
|
+
analyzeLambda(): Promise<AnalyzedLambdaFunction[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Analyze S3 buckets
|
|
42
|
+
*/
|
|
43
|
+
analyzeS3(): Promise<AnalyzedS3Bucket[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Analyze DynamoDB tables
|
|
46
|
+
*/
|
|
47
|
+
analyzeDynamoDB(): Promise<AnalyzedDynamoDBTable[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Analyze ECS clusters
|
|
50
|
+
*/
|
|
51
|
+
analyzeECS(): Promise<AnalyzedECSCluster[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Analyze EKS clusters
|
|
54
|
+
*/
|
|
55
|
+
analyzeEKS(): Promise<AnalyzedEKSCluster[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Analyze ECR repositories
|
|
58
|
+
*/
|
|
59
|
+
analyzeECR(): Promise<AnalyzedECRRepository[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Analyze VPCs
|
|
62
|
+
*/
|
|
63
|
+
analyzeVPC(): Promise<AnalyzedVPC[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Analyze API Gateways
|
|
66
|
+
*/
|
|
67
|
+
analyzeAPIGateway(): Promise<AnalyzedAPIGateway[]>;
|
|
68
|
+
/**
|
|
69
|
+
* Build importable resources list
|
|
70
|
+
*/
|
|
71
|
+
private buildImportableResources;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=aws-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-analyzer.d.ts","sourceRoot":"","sources":["../../src/core/aws-analyzer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAqB;gBAE7B,OAAO,EAAE,kBAAkB;IAWvC;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAWtD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwChD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IA8BlD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAoBlD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;IAmBxD;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAwC9C;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAgCzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IA0BjD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IA+BjD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAgBpD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAmB1C;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAgBxD;;OAEG;IACH,OAAO,CAAC,wBAAwB;CA2HjC"}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Resource Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Analyzes existing AWS resources using AWS SDK v3
|
|
5
|
+
*/
|
|
6
|
+
import { EC2Client, DescribeInstancesCommand, DescribeVpcsCommand } from '@aws-sdk/client-ec2';
|
|
7
|
+
import { RDSClient, DescribeDBInstancesCommand } from '@aws-sdk/client-rds';
|
|
8
|
+
import { S3Client, ListBucketsCommand, GetBucketVersioningCommand, GetBucketEncryptionCommand } from '@aws-sdk/client-s3';
|
|
9
|
+
import { LambdaClient, ListFunctionsCommand } from '@aws-sdk/client-lambda';
|
|
10
|
+
import { DynamoDBClient, ListTablesCommand, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
|
|
11
|
+
import { ECSClient, ListClustersCommand, DescribeClustersCommand } from '@aws-sdk/client-ecs';
|
|
12
|
+
import { EKSClient, ListClustersCommand as EKSListClustersCommand, DescribeClusterCommand } from '@aws-sdk/client-eks';
|
|
13
|
+
import { ECRClient, DescribeRepositoriesCommand } from '@aws-sdk/client-ecr';
|
|
14
|
+
import { ApiGatewayV2Client, GetApisCommand } from '@aws-sdk/client-apigatewayv2';
|
|
15
|
+
import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
|
|
16
|
+
export class AWSAnalyzer {
|
|
17
|
+
region;
|
|
18
|
+
clientConfig;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.region = options.region;
|
|
21
|
+
this.clientConfig = { region: options.region };
|
|
22
|
+
// If profile is specified, set environment variable
|
|
23
|
+
// AWS SDK v3 will automatically use AWS_PROFILE
|
|
24
|
+
if (options.profile) {
|
|
25
|
+
process.env.AWS_PROFILE = options.profile;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Verify AWS credentials and get account info
|
|
30
|
+
*/
|
|
31
|
+
async verifyCredentials() {
|
|
32
|
+
const client = new STSClient(this.clientConfig);
|
|
33
|
+
const response = await client.send(new GetCallerIdentityCommand({}));
|
|
34
|
+
return {
|
|
35
|
+
account: response.Account || '',
|
|
36
|
+
userId: response.UserId || '',
|
|
37
|
+
arn: response.Arn || '',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Analyze all AWS resources
|
|
42
|
+
*/
|
|
43
|
+
async analyzeAll() {
|
|
44
|
+
const credentials = await this.verifyCredentials();
|
|
45
|
+
const [ec2, rds, lambda, s3, dynamodb, ecs, eks, ecr, vpc, apiGateway,] = await Promise.all([
|
|
46
|
+
this.analyzeEC2(),
|
|
47
|
+
this.analyzeRDS(),
|
|
48
|
+
this.analyzeLambda(),
|
|
49
|
+
this.analyzeS3(),
|
|
50
|
+
this.analyzeDynamoDB(),
|
|
51
|
+
this.analyzeECS(),
|
|
52
|
+
this.analyzeEKS(),
|
|
53
|
+
this.analyzeECR(),
|
|
54
|
+
this.analyzeVPC(),
|
|
55
|
+
this.analyzeAPIGateway(),
|
|
56
|
+
]);
|
|
57
|
+
const importableResources = this.buildImportableResources({
|
|
58
|
+
ec2, rds, lambda, s3, dynamodb, ecs, eks, ecr, vpc, apiGateway,
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
region: this.region,
|
|
62
|
+
account: credentials.account,
|
|
63
|
+
analyzedAt: new Date().toISOString(),
|
|
64
|
+
resources: { ec2, rds, lambda, s3, dynamodb, ecs, eks, ecr, vpc, apiGateway },
|
|
65
|
+
importableResources,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Analyze EC2 instances
|
|
70
|
+
*/
|
|
71
|
+
async analyzeEC2() {
|
|
72
|
+
try {
|
|
73
|
+
const client = new EC2Client(this.clientConfig);
|
|
74
|
+
const response = await client.send(new DescribeInstancesCommand({}));
|
|
75
|
+
const instances = [];
|
|
76
|
+
for (const reservation of response.Reservations || []) {
|
|
77
|
+
for (const instance of reservation.Instances || []) {
|
|
78
|
+
const nameTag = instance.Tags?.find((t) => t.Key === 'Name');
|
|
79
|
+
instances.push({
|
|
80
|
+
instanceId: instance.InstanceId || '',
|
|
81
|
+
name: nameTag?.Value,
|
|
82
|
+
instanceType: instance.InstanceType || '',
|
|
83
|
+
state: instance.State?.Name || '',
|
|
84
|
+
vpcId: instance.VpcId,
|
|
85
|
+
subnetId: instance.SubnetId,
|
|
86
|
+
publicIpAddress: instance.PublicIpAddress,
|
|
87
|
+
privateIpAddress: instance.PrivateIpAddress,
|
|
88
|
+
tags: Object.fromEntries((instance.Tags || []).map((t) => [t.Key || '', t.Value || ''])),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return instances;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Analyze RDS instances
|
|
100
|
+
*/
|
|
101
|
+
async analyzeRDS() {
|
|
102
|
+
try {
|
|
103
|
+
const client = new RDSClient(this.clientConfig);
|
|
104
|
+
const response = await client.send(new DescribeDBInstancesCommand({}));
|
|
105
|
+
return (response.DBInstances || []).map((db) => ({
|
|
106
|
+
dbInstanceIdentifier: db.DBInstanceIdentifier || '',
|
|
107
|
+
engine: db.Engine || '',
|
|
108
|
+
engineVersion: db.EngineVersion || '',
|
|
109
|
+
dbInstanceClass: db.DBInstanceClass || '',
|
|
110
|
+
allocatedStorage: db.AllocatedStorage || 0,
|
|
111
|
+
status: db.DBInstanceStatus || '',
|
|
112
|
+
multiAZ: db.MultiAZ || false,
|
|
113
|
+
publiclyAccessible: db.PubliclyAccessible || false,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Analyze Lambda functions
|
|
122
|
+
*/
|
|
123
|
+
async analyzeLambda() {
|
|
124
|
+
try {
|
|
125
|
+
const client = new LambdaClient(this.clientConfig);
|
|
126
|
+
const response = await client.send(new ListFunctionsCommand({}));
|
|
127
|
+
return (response.Functions || []).map((fn) => ({
|
|
128
|
+
functionName: fn.FunctionName || '',
|
|
129
|
+
functionArn: fn.FunctionArn || '',
|
|
130
|
+
runtime: fn.Runtime || '',
|
|
131
|
+
handler: fn.Handler || '',
|
|
132
|
+
memorySize: fn.MemorySize || 0,
|
|
133
|
+
timeout: fn.Timeout || 0,
|
|
134
|
+
lastModified: fn.LastModified || '',
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Analyze S3 buckets
|
|
143
|
+
*/
|
|
144
|
+
async analyzeS3() {
|
|
145
|
+
try {
|
|
146
|
+
const client = new S3Client(this.clientConfig);
|
|
147
|
+
const response = await client.send(new ListBucketsCommand({}));
|
|
148
|
+
const buckets = [];
|
|
149
|
+
for (const bucket of response.Buckets || []) {
|
|
150
|
+
let versioning = false;
|
|
151
|
+
let encryption = false;
|
|
152
|
+
try {
|
|
153
|
+
const versioningResponse = await client.send(new GetBucketVersioningCommand({ Bucket: bucket.Name }));
|
|
154
|
+
versioning = versioningResponse.Status === 'Enabled';
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Bucket might be in different region
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
await client.send(new GetBucketEncryptionCommand({ Bucket: bucket.Name }));
|
|
161
|
+
encryption = true;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// No encryption or different region
|
|
165
|
+
}
|
|
166
|
+
buckets.push({
|
|
167
|
+
name: bucket.Name || '',
|
|
168
|
+
creationDate: bucket.CreationDate?.toISOString() || '',
|
|
169
|
+
region: this.region,
|
|
170
|
+
versioning,
|
|
171
|
+
encryption,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return buckets;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Analyze DynamoDB tables
|
|
182
|
+
*/
|
|
183
|
+
async analyzeDynamoDB() {
|
|
184
|
+
try {
|
|
185
|
+
const client = new DynamoDBClient(this.clientConfig);
|
|
186
|
+
const listResponse = await client.send(new ListTablesCommand({}));
|
|
187
|
+
const tables = [];
|
|
188
|
+
for (const tableName of listResponse.TableNames || []) {
|
|
189
|
+
try {
|
|
190
|
+
const describeResponse = await client.send(new DescribeTableCommand({ TableName: tableName }));
|
|
191
|
+
const table = describeResponse.Table;
|
|
192
|
+
if (table) {
|
|
193
|
+
tables.push({
|
|
194
|
+
tableName: table.TableName || '',
|
|
195
|
+
tableArn: table.TableArn || '',
|
|
196
|
+
status: table.TableStatus || '',
|
|
197
|
+
itemCount: Number(table.ItemCount) || 0,
|
|
198
|
+
tableSizeBytes: Number(table.TableSizeBytes) || 0,
|
|
199
|
+
billingMode: table.BillingModeSummary?.BillingMode || 'PROVISIONED',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Skip tables we can't describe
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return tables;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return [];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Analyze ECS clusters
|
|
215
|
+
*/
|
|
216
|
+
async analyzeECS() {
|
|
217
|
+
try {
|
|
218
|
+
const client = new ECSClient(this.clientConfig);
|
|
219
|
+
const listResponse = await client.send(new ListClustersCommand({}));
|
|
220
|
+
if (!listResponse.clusterArns?.length) {
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
const describeResponse = await client.send(new DescribeClustersCommand({ clusters: listResponse.clusterArns }));
|
|
224
|
+
return (describeResponse.clusters || []).map((cluster) => ({
|
|
225
|
+
clusterName: cluster.clusterName || '',
|
|
226
|
+
clusterArn: cluster.clusterArn || '',
|
|
227
|
+
status: cluster.status || '',
|
|
228
|
+
runningTasksCount: cluster.runningTasksCount || 0,
|
|
229
|
+
pendingTasksCount: cluster.pendingTasksCount || 0,
|
|
230
|
+
activeServicesCount: cluster.activeServicesCount || 0,
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Analyze EKS clusters
|
|
239
|
+
*/
|
|
240
|
+
async analyzeEKS() {
|
|
241
|
+
try {
|
|
242
|
+
const client = new EKSClient(this.clientConfig);
|
|
243
|
+
const listResponse = await client.send(new EKSListClustersCommand({}));
|
|
244
|
+
const clusters = [];
|
|
245
|
+
for (const clusterName of listResponse.clusters || []) {
|
|
246
|
+
try {
|
|
247
|
+
const describeResponse = await client.send(new DescribeClusterCommand({ name: clusterName }));
|
|
248
|
+
const cluster = describeResponse.cluster;
|
|
249
|
+
if (cluster) {
|
|
250
|
+
clusters.push({
|
|
251
|
+
name: cluster.name || '',
|
|
252
|
+
arn: cluster.arn || '',
|
|
253
|
+
version: cluster.version || '',
|
|
254
|
+
status: cluster.status || '',
|
|
255
|
+
endpoint: cluster.endpoint || '',
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// Skip clusters we can't describe
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return clusters;
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Analyze ECR repositories
|
|
271
|
+
*/
|
|
272
|
+
async analyzeECR() {
|
|
273
|
+
try {
|
|
274
|
+
const client = new ECRClient(this.clientConfig);
|
|
275
|
+
const response = await client.send(new DescribeRepositoriesCommand({}));
|
|
276
|
+
return (response.repositories || []).map((repo) => ({
|
|
277
|
+
repositoryName: repo.repositoryName || '',
|
|
278
|
+
repositoryArn: repo.repositoryArn || '',
|
|
279
|
+
repositoryUri: repo.repositoryUri || '',
|
|
280
|
+
imageCount: 0, // Would need additional API call
|
|
281
|
+
}));
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Analyze VPCs
|
|
289
|
+
*/
|
|
290
|
+
async analyzeVPC() {
|
|
291
|
+
try {
|
|
292
|
+
const client = new EC2Client(this.clientConfig);
|
|
293
|
+
const response = await client.send(new DescribeVpcsCommand({}));
|
|
294
|
+
return (response.Vpcs || []).map((vpc) => ({
|
|
295
|
+
vpcId: vpc.VpcId || '',
|
|
296
|
+
cidrBlock: vpc.CidrBlock || '',
|
|
297
|
+
state: vpc.State || '',
|
|
298
|
+
isDefault: vpc.IsDefault || false,
|
|
299
|
+
tags: Object.fromEntries((vpc.Tags || []).map((t) => [t.Key || '', t.Value || ''])),
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return [];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Analyze API Gateways
|
|
308
|
+
*/
|
|
309
|
+
async analyzeAPIGateway() {
|
|
310
|
+
try {
|
|
311
|
+
const client = new ApiGatewayV2Client(this.clientConfig);
|
|
312
|
+
const response = await client.send(new GetApisCommand({}));
|
|
313
|
+
return (response.Items || []).map((api) => ({
|
|
314
|
+
apiId: api.ApiId || '',
|
|
315
|
+
name: api.Name || '',
|
|
316
|
+
protocolType: api.ProtocolType || '',
|
|
317
|
+
apiEndpoint: api.ApiEndpoint || '',
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return [];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Build importable resources list
|
|
326
|
+
*/
|
|
327
|
+
buildImportableResources(resources) {
|
|
328
|
+
const importable = [];
|
|
329
|
+
// EC2 instances
|
|
330
|
+
for (const instance of resources.ec2) {
|
|
331
|
+
importable.push({
|
|
332
|
+
type: 'AWS::EC2::Instance',
|
|
333
|
+
id: instance.instanceId,
|
|
334
|
+
name: instance.name || instance.instanceId,
|
|
335
|
+
importCommand: `cdk import ${instance.instanceId}`,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
// RDS instances
|
|
339
|
+
for (const db of resources.rds) {
|
|
340
|
+
importable.push({
|
|
341
|
+
type: 'AWS::RDS::DBInstance',
|
|
342
|
+
id: db.dbInstanceIdentifier,
|
|
343
|
+
name: db.dbInstanceIdentifier,
|
|
344
|
+
importCommand: `cdk import ${db.dbInstanceIdentifier}`,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
// Lambda functions
|
|
348
|
+
for (const fn of resources.lambda) {
|
|
349
|
+
importable.push({
|
|
350
|
+
type: 'AWS::Lambda::Function',
|
|
351
|
+
id: fn.functionName,
|
|
352
|
+
name: fn.functionName,
|
|
353
|
+
arn: fn.functionArn,
|
|
354
|
+
importCommand: `cdk import ${fn.functionName}`,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
// S3 buckets
|
|
358
|
+
for (const bucket of resources.s3) {
|
|
359
|
+
importable.push({
|
|
360
|
+
type: 'AWS::S3::Bucket',
|
|
361
|
+
id: bucket.name,
|
|
362
|
+
name: bucket.name,
|
|
363
|
+
importCommand: `cdk import ${bucket.name}`,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
// DynamoDB tables
|
|
367
|
+
for (const table of resources.dynamodb) {
|
|
368
|
+
importable.push({
|
|
369
|
+
type: 'AWS::DynamoDB::Table',
|
|
370
|
+
id: table.tableName,
|
|
371
|
+
name: table.tableName,
|
|
372
|
+
arn: table.tableArn,
|
|
373
|
+
importCommand: `cdk import ${table.tableName}`,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
// ECS clusters
|
|
377
|
+
for (const cluster of resources.ecs) {
|
|
378
|
+
importable.push({
|
|
379
|
+
type: 'AWS::ECS::Cluster',
|
|
380
|
+
id: cluster.clusterName,
|
|
381
|
+
name: cluster.clusterName,
|
|
382
|
+
arn: cluster.clusterArn,
|
|
383
|
+
importCommand: `cdk import ${cluster.clusterName}`,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
// EKS clusters
|
|
387
|
+
for (const cluster of resources.eks) {
|
|
388
|
+
importable.push({
|
|
389
|
+
type: 'AWS::EKS::Cluster',
|
|
390
|
+
id: cluster.name,
|
|
391
|
+
name: cluster.name,
|
|
392
|
+
arn: cluster.arn,
|
|
393
|
+
importCommand: `cdk import ${cluster.name}`,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
// ECR repositories
|
|
397
|
+
for (const repo of resources.ecr) {
|
|
398
|
+
importable.push({
|
|
399
|
+
type: 'AWS::ECR::Repository',
|
|
400
|
+
id: repo.repositoryName,
|
|
401
|
+
name: repo.repositoryName,
|
|
402
|
+
arn: repo.repositoryArn,
|
|
403
|
+
importCommand: `cdk import ${repo.repositoryName}`,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
// VPCs
|
|
407
|
+
for (const vpc of resources.vpc) {
|
|
408
|
+
if (!vpc.isDefault) {
|
|
409
|
+
importable.push({
|
|
410
|
+
type: 'AWS::EC2::VPC',
|
|
411
|
+
id: vpc.vpcId,
|
|
412
|
+
name: vpc.tags['Name'] || vpc.vpcId,
|
|
413
|
+
importCommand: `cdk import ${vpc.vpcId}`,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// API Gateways
|
|
418
|
+
for (const api of resources.apiGateway) {
|
|
419
|
+
importable.push({
|
|
420
|
+
type: 'AWS::ApiGatewayV2::Api',
|
|
421
|
+
id: api.apiId,
|
|
422
|
+
name: api.name,
|
|
423
|
+
importCommand: `cdk import ${api.apiId}`,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
return importable;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
//# sourceMappingURL=aws-analyzer.js.map
|