@factiii/stack 0.1.34 → 0.1.35
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 +441 -441
- package/bin/stack +46 -0
- package/dist/cli/fix.js +10 -10
- package/dist/cli/fix.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +20 -7
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/scan.d.ts.map +1 -1
- package/dist/cli/scan.js +14 -22
- package/dist/cli/scan.js.map +1 -1
- package/dist/generators/generate-stack-yml.d.ts +1 -1
- package/dist/generators/generate-stack-yml.d.ts.map +1 -1
- package/dist/generators/generate-stack-yml.js +96 -69
- package/dist/generators/generate-stack-yml.js.map +1 -1
- package/dist/plugins/addons/openclaw/index.d.ts +45 -0
- package/dist/plugins/addons/openclaw/index.d.ts.map +1 -0
- package/dist/plugins/addons/openclaw/index.js +107 -0
- package/dist/plugins/addons/openclaw/index.js.map +1 -0
- package/dist/plugins/addons/openclaw/scanfix/setup.d.ts +19 -0
- package/dist/plugins/addons/openclaw/scanfix/setup.d.ts.map +1 -0
- package/dist/plugins/addons/openclaw/scanfix/setup.js +441 -0
- package/dist/plugins/addons/openclaw/scanfix/setup.js.map +1 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +8 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/pipelines/aws/index.js +15 -15
- package/dist/plugins/pipelines/aws/prod.js +7 -7
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.d.ts +3 -1
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.js +17 -7
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/credentials.d.ts +1 -1
- package/dist/plugins/pipelines/aws/scanfix/credentials.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/credentials.js +27 -73
- package/dist/plugins/pipelines/aws/scanfix/credentials.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/db-replication.d.ts +1 -4
- package/dist/plugins/pipelines/aws/scanfix/db-replication.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/db-replication.js +9 -39
- package/dist/plugins/pipelines/aws/scanfix/db-replication.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ec2.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/ec2.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ec2.js +61 -110
- package/dist/plugins/pipelines/aws/scanfix/ec2.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ecr.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/ecr.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ecr.js +25 -34
- package/dist/plugins/pipelines/aws/scanfix/ecr.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/iam.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/iam.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/iam.js +35 -44
- package/dist/plugins/pipelines/aws/scanfix/iam.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/rds.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/rds.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/rds.js +39 -104
- package/dist/plugins/pipelines/aws/scanfix/rds.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/s3.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/s3.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/s3.js +44 -53
- package/dist/plugins/pipelines/aws/scanfix/s3.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/security-groups.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/security-groups.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/security-groups.js +80 -79
- package/dist/plugins/pipelines/aws/scanfix/security-groups.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ses.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/ses.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ses.js +28 -50
- package/dist/plugins/pipelines/aws/scanfix/ses.js.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/ssh-bridge.d.ts +17 -0
- package/dist/plugins/pipelines/aws/scanfix/ssh-bridge.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/scanfix/ssh-bridge.js +180 -0
- package/dist/plugins/pipelines/aws/scanfix/ssh-bridge.js.map +1 -0
- package/dist/plugins/pipelines/aws/scanfix/vpc.d.ts +1 -0
- package/dist/plugins/pipelines/aws/scanfix/vpc.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/scanfix/vpc.js +93 -94
- package/dist/plugins/pipelines/aws/scanfix/vpc.js.map +1 -1
- package/dist/plugins/pipelines/aws/utils/aws-helpers.d.ts +101 -28
- package/dist/plugins/pipelines/aws/utils/aws-helpers.d.ts.map +1 -1
- package/dist/plugins/pipelines/aws/utils/aws-helpers.js +428 -76
- package/dist/plugins/pipelines/aws/utils/aws-helpers.js.map +1 -1
- package/dist/plugins/pipelines/factiii/index.d.ts +11 -1
- package/dist/plugins/pipelines/factiii/index.d.ts.map +1 -1
- package/dist/plugins/pipelines/factiii/index.js +183 -33
- package/dist/plugins/pipelines/factiii/index.js.map +1 -1
- package/dist/plugins/pipelines/factiii/scanfix/config.d.ts +1 -1
- package/dist/plugins/pipelines/factiii/scanfix/config.js +4 -4
- package/dist/plugins/pipelines/factiii/scanfix/secrets.d.ts.map +1 -1
- package/dist/plugins/pipelines/factiii/scanfix/secrets.js +68 -8
- package/dist/plugins/pipelines/factiii/scanfix/secrets.js.map +1 -1
- package/dist/plugins/servers/mac/index.js +13 -13
- package/dist/plugins/servers/mac/staging.js +4 -4
- package/dist/scanfix/fixes/certbot.js +1 -1
- package/dist/scripts/validate-example-values.d.ts +1 -1
- package/dist/scripts/validate-example-values.js +6 -6
- package/dist/utils/config-helpers.d.ts +3 -0
- package/dist/utils/config-helpers.d.ts.map +1 -1
- package/dist/utils/config-helpers.js.map +1 -1
- package/dist/utils/secret-prompts.d.ts +5 -2
- package/dist/utils/secret-prompts.d.ts.map +1 -1
- package/dist/utils/secret-prompts.js +55 -32
- package/dist/utils/secret-prompts.js.map +1 -1
- package/dist/utils/template-generator.js +71 -71
- package/package.json +8 -1
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Provisions EC2 key pair, instance, and Elastic IP.
|
|
6
6
|
* Uses Ubuntu 22.04 AMI, t3.micro (free tier), public subnet.
|
|
7
7
|
* Key pair private key is stored in Ansible Vault.
|
|
8
|
+
* Uses AWS SDK v3.
|
|
8
9
|
*/
|
|
9
10
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
11
|
if (k2 === undefined) k2 = k;
|
|
@@ -42,80 +43,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
42
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
44
|
exports.ec2Fixes = void 0;
|
|
44
45
|
const aws_helpers_js_1 = require("../utils/aws-helpers.js");
|
|
45
|
-
/**
|
|
46
|
-
* Find VPC by factiii:project tag
|
|
47
|
-
*/
|
|
48
|
-
function findVpc(projectName, region) {
|
|
49
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-vpcs --filters "Name=tag:factiii:project,Values=' + projectName + '" --query "Vpcs[0].VpcId" --output text', region);
|
|
50
|
-
if (!result || result === 'None' || result === 'null')
|
|
51
|
-
return null;
|
|
52
|
-
return result.replace(/"/g, '');
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Find subnet by tag and type
|
|
56
|
-
*/
|
|
57
|
-
function findSubnet(projectName, region, type) {
|
|
58
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-subnets --filters "Name=tag:factiii:project,Values=' + projectName + '" "Name=tag:factiii:subnet-type,Values=' + type + '" --query "Subnets[0].SubnetId" --output text', region);
|
|
59
|
-
if (!result || result === 'None' || result === 'null')
|
|
60
|
-
return null;
|
|
61
|
-
return result.replace(/"/g, '');
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Find security group by name and VPC
|
|
65
|
-
*/
|
|
66
|
-
function findSecurityGroup(groupName, vpcId, region) {
|
|
67
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-security-groups --filters "Name=group-name,Values=' + groupName + '" "Name=vpc-id,Values=' + vpcId + '" --query "SecurityGroups[0].GroupId" --output text', region);
|
|
68
|
-
if (!result || result === 'None' || result === 'null')
|
|
69
|
-
return null;
|
|
70
|
-
return result.replace(/"/g, '');
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Find EC2 key pair by name
|
|
74
|
-
*/
|
|
75
|
-
function findKeyPair(keyName, region) {
|
|
76
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-key-pairs --key-names ' + keyName + ' --query "KeyPairs[0].KeyPairId" --output text', region);
|
|
77
|
-
return !!result && result !== 'None' && result !== 'null';
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Find running EC2 instance by tag
|
|
81
|
-
*/
|
|
82
|
-
function findInstance(projectName, region) {
|
|
83
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-instances --filters "Name=tag:factiii:project,Values=' + projectName + '" "Name=instance-state-name,Values=running,stopped" --query "Reservations[0].Instances[0].InstanceId" --output text', region);
|
|
84
|
-
if (!result || result === 'None' || result === 'null')
|
|
85
|
-
return null;
|
|
86
|
-
return result.replace(/"/g, '');
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Find Elastic IP associated with an instance
|
|
90
|
-
*/
|
|
91
|
-
function findElasticIp(instanceId, region) {
|
|
92
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-addresses --filters "Name=instance-id,Values=' + instanceId + '" --query "Addresses[0].PublicIp" --output text', region);
|
|
93
|
-
if (!result || result === 'None' || result === 'null')
|
|
94
|
-
return null;
|
|
95
|
-
return result.replace(/"/g, '');
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Get latest Ubuntu 22.04 AMI for the region
|
|
99
|
-
*/
|
|
100
|
-
function getUbuntuAmi(region) {
|
|
101
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ec2 describe-images --owners 099720109477 --filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" "Name=state,Values=available" --query "sort_by(Images, &CreationDate)[-1].ImageId" --output text', region);
|
|
102
|
-
if (!result || result === 'None' || result === 'null')
|
|
103
|
-
return null;
|
|
104
|
-
return result.replace(/"/g, '');
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Check if AWS is configured for this project
|
|
108
|
-
*/
|
|
109
|
-
function isAwsConfigured(config) {
|
|
110
|
-
if ((0, aws_helpers_js_1.isOnServer)())
|
|
111
|
-
return false;
|
|
112
|
-
if (config.aws)
|
|
113
|
-
return true;
|
|
114
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
115
|
-
const { extractEnvironments } = require('../../../../utils/config-helpers.js');
|
|
116
|
-
const environments = extractEnvironments(config);
|
|
117
|
-
return Object.values(environments).some((e) => e.pipeline === 'aws');
|
|
118
|
-
}
|
|
119
46
|
exports.ec2Fixes = [
|
|
120
47
|
{
|
|
121
48
|
id: 'aws-keypair-missing',
|
|
@@ -123,19 +50,24 @@ exports.ec2Fixes = [
|
|
|
123
50
|
severity: 'critical',
|
|
124
51
|
description: '🖥️ EC2 key pair not created for SSH access',
|
|
125
52
|
scan: async (config) => {
|
|
126
|
-
if (!isAwsConfigured(config))
|
|
53
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
127
54
|
return false;
|
|
128
55
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
129
56
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
130
|
-
return !findKeyPair('factiii-' + projectName, region);
|
|
57
|
+
return !(await (0, aws_helpers_js_1.findKeyPair)('factiii-' + projectName, region));
|
|
131
58
|
},
|
|
132
59
|
fix: async (config) => {
|
|
133
60
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
134
61
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
135
62
|
const keyName = 'factiii-' + projectName;
|
|
136
63
|
try {
|
|
64
|
+
const ec2 = (0, aws_helpers_js_1.getEC2Client)(region);
|
|
137
65
|
// Create key pair — AWS returns the private key material
|
|
138
|
-
const result = (
|
|
66
|
+
const result = await ec2.send(new aws_helpers_js_1.CreateKeyPairCommand({
|
|
67
|
+
KeyName: keyName,
|
|
68
|
+
KeyType: 'ed25519',
|
|
69
|
+
}));
|
|
70
|
+
const privateKey = result.KeyMaterial;
|
|
139
71
|
// Save private key to ~/.ssh/prod_deploy_key
|
|
140
72
|
const os = await Promise.resolve().then(() => __importStar(require('os')));
|
|
141
73
|
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
@@ -145,10 +77,9 @@ exports.ec2Fixes = [
|
|
|
145
77
|
fs.mkdirSync(sshDir, { mode: 0o700 });
|
|
146
78
|
}
|
|
147
79
|
const keyPath = path.join(sshDir, 'prod_deploy_key');
|
|
148
|
-
fs.writeFileSync(keyPath,
|
|
80
|
+
fs.writeFileSync(keyPath, privateKey + '\n', { mode: 0o600 });
|
|
149
81
|
console.log(' Created key pair: ' + keyName);
|
|
150
82
|
console.log(' Private key saved to: ' + keyPath);
|
|
151
|
-
// Store in Ansible Vault if configured
|
|
152
83
|
if (config.ansible?.vault_path) {
|
|
153
84
|
console.log(' TIP: Add this key to Ansible Vault with: npx stack secrets edit');
|
|
154
85
|
}
|
|
@@ -167,62 +98,76 @@ exports.ec2Fixes = [
|
|
|
167
98
|
severity: 'critical',
|
|
168
99
|
description: '🖥️ EC2 instance not created (Ubuntu 22.04, t3.micro)',
|
|
169
100
|
scan: async (config) => {
|
|
170
|
-
if (!isAwsConfigured(config))
|
|
101
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
171
102
|
return false;
|
|
172
103
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
173
104
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
174
|
-
return !findInstance(projectName, region);
|
|
105
|
+
return !(await (0, aws_helpers_js_1.findInstance)(projectName, region));
|
|
175
106
|
},
|
|
176
107
|
fix: async (config) => {
|
|
177
108
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
178
109
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
179
|
-
const vpcId = findVpc(projectName, region);
|
|
110
|
+
const vpcId = await (0, aws_helpers_js_1.findVpc)(projectName, region);
|
|
180
111
|
if (!vpcId) {
|
|
181
112
|
console.log(' VPC must be created first');
|
|
182
113
|
return false;
|
|
183
114
|
}
|
|
184
|
-
const publicSubnet = findSubnet(projectName, region, 'public');
|
|
115
|
+
const publicSubnet = await (0, aws_helpers_js_1.findSubnet)(projectName, region, 'public');
|
|
185
116
|
if (!publicSubnet) {
|
|
186
117
|
console.log(' Public subnet must be created first');
|
|
187
118
|
return false;
|
|
188
119
|
}
|
|
189
|
-
const ec2SgId = findSecurityGroup('factiii-' + projectName + '-ec2', vpcId, region);
|
|
120
|
+
const ec2SgId = await (0, aws_helpers_js_1.findSecurityGroup)('factiii-' + projectName + '-ec2', vpcId, region);
|
|
190
121
|
if (!ec2SgId) {
|
|
191
122
|
console.log(' EC2 security group must be created first');
|
|
192
123
|
return false;
|
|
193
124
|
}
|
|
194
125
|
const keyName = 'factiii-' + projectName;
|
|
195
|
-
if (!findKeyPair(keyName, region)) {
|
|
126
|
+
if (!(await (0, aws_helpers_js_1.findKeyPair)(keyName, region))) {
|
|
196
127
|
console.log(' Key pair must be created first');
|
|
197
128
|
return false;
|
|
198
129
|
}
|
|
199
130
|
try {
|
|
131
|
+
const ec2 = (0, aws_helpers_js_1.getEC2Client)(region);
|
|
200
132
|
// Get latest Ubuntu 22.04 AMI
|
|
201
|
-
const
|
|
133
|
+
const amiResult = await ec2.send(new aws_helpers_js_1.DescribeImagesCommand({
|
|
134
|
+
Owners: ['099720109477'],
|
|
135
|
+
Filters: [
|
|
136
|
+
{ Name: 'name', Values: ['ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*'] },
|
|
137
|
+
{ Name: 'state', Values: ['available'] },
|
|
138
|
+
],
|
|
139
|
+
}));
|
|
140
|
+
const images = (amiResult.Images ?? []).sort((a, b) => (b.CreationDate ?? '').localeCompare(a.CreationDate ?? ''));
|
|
141
|
+
const amiId = images[0]?.ImageId;
|
|
202
142
|
if (!amiId) {
|
|
203
143
|
console.log(' Failed to find Ubuntu 22.04 AMI for region ' + region);
|
|
204
144
|
return false;
|
|
205
145
|
}
|
|
206
146
|
console.log(' Using AMI: ' + amiId);
|
|
207
147
|
// Launch instance
|
|
208
|
-
const instanceResult = (
|
|
209
|
-
|
|
210
|
-
'
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
148
|
+
const instanceResult = await ec2.send(new aws_helpers_js_1.RunInstancesCommand({
|
|
149
|
+
ImageId: amiId,
|
|
150
|
+
InstanceType: 't3.micro',
|
|
151
|
+
KeyName: keyName,
|
|
152
|
+
SecurityGroupIds: [ec2SgId],
|
|
153
|
+
SubnetId: publicSubnet,
|
|
154
|
+
MinCount: 1,
|
|
155
|
+
MaxCount: 1,
|
|
156
|
+
TagSpecifications: [(0, aws_helpers_js_1.tagSpec)('instance', projectName)],
|
|
157
|
+
}));
|
|
158
|
+
const instanceId = instanceResult.Instances?.[0]?.InstanceId;
|
|
217
159
|
console.log(' Launched EC2 instance: ' + instanceId);
|
|
218
160
|
console.log(' Instance type: t3.micro (free tier eligible)');
|
|
219
161
|
console.log(' Waiting for instance to be running...');
|
|
220
162
|
// Wait for instance to be running
|
|
221
|
-
(0, aws_helpers_js_1.
|
|
163
|
+
await (0, aws_helpers_js_1.waitUntilInstanceRunning)({ client: ec2, maxWaitTime: 300 }, { InstanceIds: [instanceId] });
|
|
222
164
|
// Get public IP
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
165
|
+
const descResult = await ec2.send(new aws_helpers_js_1.DescribeInstancesCommand({
|
|
166
|
+
InstanceIds: [instanceId],
|
|
167
|
+
}));
|
|
168
|
+
const publicIp = descResult.Reservations?.[0]?.Instances?.[0]?.PublicIpAddress;
|
|
169
|
+
if (publicIp) {
|
|
170
|
+
console.log(' Public IP: ' + publicIp);
|
|
226
171
|
console.log(' NOTE: This IP will change on restart. Run fix again for Elastic IP.');
|
|
227
172
|
}
|
|
228
173
|
return true;
|
|
@@ -240,34 +185,40 @@ exports.ec2Fixes = [
|
|
|
240
185
|
severity: 'warning',
|
|
241
186
|
description: '🖥️ Elastic IP not assigned to EC2 instance (IP changes on restart)',
|
|
242
187
|
scan: async (config) => {
|
|
243
|
-
if (!isAwsConfigured(config))
|
|
188
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
244
189
|
return false;
|
|
245
190
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
246
191
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
247
|
-
const instanceId = findInstance(projectName, region);
|
|
192
|
+
const instanceId = await (0, aws_helpers_js_1.findInstance)(projectName, region);
|
|
248
193
|
if (!instanceId)
|
|
249
|
-
return false;
|
|
250
|
-
return !findElasticIp(instanceId, region);
|
|
194
|
+
return false;
|
|
195
|
+
return !(await (0, aws_helpers_js_1.findElasticIp)(instanceId, region));
|
|
251
196
|
},
|
|
252
197
|
fix: async (config, rootDir) => {
|
|
253
198
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
254
199
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
255
|
-
const instanceId = findInstance(projectName, region);
|
|
200
|
+
const instanceId = await (0, aws_helpers_js_1.findInstance)(projectName, region);
|
|
256
201
|
if (!instanceId) {
|
|
257
202
|
console.log(' EC2 instance must be created first');
|
|
258
203
|
return false;
|
|
259
204
|
}
|
|
260
205
|
try {
|
|
206
|
+
const ec2 = (0, aws_helpers_js_1.getEC2Client)(region);
|
|
261
207
|
// Allocate Elastic IP
|
|
262
|
-
const eipResult =
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
208
|
+
const eipResult = await ec2.send(new aws_helpers_js_1.AllocateAddressCommand({
|
|
209
|
+
Domain: 'vpc',
|
|
210
|
+
TagSpecifications: [(0, aws_helpers_js_1.tagSpec)('elastic-ip', projectName)],
|
|
211
|
+
}));
|
|
212
|
+
const allocationId = eipResult.AllocationId;
|
|
213
|
+
const publicIp = eipResult.PublicIp;
|
|
266
214
|
console.log(' Allocated Elastic IP: ' + publicIp);
|
|
267
215
|
// Associate with instance
|
|
268
|
-
(
|
|
216
|
+
await ec2.send(new aws_helpers_js_1.AssociateAddressCommand({
|
|
217
|
+
AllocationId: allocationId,
|
|
218
|
+
InstanceId: instanceId,
|
|
219
|
+
}));
|
|
269
220
|
console.log(' Associated with instance: ' + instanceId);
|
|
270
|
-
// Auto-update stack.yml
|
|
221
|
+
// Auto-update stack.yml
|
|
271
222
|
const { updateConfigValue } = await Promise.resolve().then(() => __importStar(require('../../../../utils/config-writer.js')));
|
|
272
223
|
const dir = rootDir || process.cwd();
|
|
273
224
|
updateConfigValue(dir, 'prod.domain', publicIp);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ec2.js","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/ec2.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"ec2.js","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/ec2.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ecr.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/ecr.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ecr.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/ecr.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAiB,GAAG,EAAE,MAAM,4BAA4B,CAAC;AAYrE,eAAO,MAAM,QAAQ,EAAE,GAAG,EAiFzB,CAAC"}
|
|
@@ -4,30 +4,11 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Provisions ECR (Elastic Container Registry) repository
|
|
6
6
|
* with lifecycle policy to keep costs down.
|
|
7
|
+
* Uses AWS SDK v3.
|
|
7
8
|
*/
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.ecrFixes = void 0;
|
|
10
11
|
const aws_helpers_js_1 = require("../utils/aws-helpers.js");
|
|
11
|
-
/**
|
|
12
|
-
* Check if ECR repository exists
|
|
13
|
-
*/
|
|
14
|
-
function findEcrRepo(repoName, region) {
|
|
15
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws ecr describe-repositories --repository-names ' + repoName, region);
|
|
16
|
-
return !!result && !result.includes('RepositoryNotFoundException');
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Check if AWS is configured for this project
|
|
20
|
-
*/
|
|
21
|
-
function isAwsConfigured(config) {
|
|
22
|
-
if ((0, aws_helpers_js_1.isOnServer)())
|
|
23
|
-
return false;
|
|
24
|
-
if (config.aws)
|
|
25
|
-
return true;
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
|
-
const { extractEnvironments } = require('../../../../utils/config-helpers.js');
|
|
28
|
-
const environments = extractEnvironments(config);
|
|
29
|
-
return Object.values(environments).some((e) => e.pipeline === 'aws');
|
|
30
|
-
}
|
|
31
12
|
exports.ecrFixes = [
|
|
32
13
|
{
|
|
33
14
|
id: 'aws-ecr-repo-missing',
|
|
@@ -35,26 +16,28 @@ exports.ecrFixes = [
|
|
|
35
16
|
severity: 'warning',
|
|
36
17
|
description: '📦 ECR repository not created for container images',
|
|
37
18
|
scan: async (config) => {
|
|
38
|
-
if (!isAwsConfigured(config))
|
|
19
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
39
20
|
return false;
|
|
40
21
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
41
22
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
42
|
-
return !findEcrRepo(projectName, region);
|
|
23
|
+
return !(await (0, aws_helpers_js_1.findEcrRepo)(projectName, region));
|
|
43
24
|
},
|
|
44
25
|
fix: async (config) => {
|
|
45
26
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
46
27
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
47
28
|
try {
|
|
29
|
+
const ecr = (0, aws_helpers_js_1.getECRClient)(region);
|
|
48
30
|
// Create ECR repository
|
|
49
|
-
const result = (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
31
|
+
const result = await ecr.send(new aws_helpers_js_1.CreateRepositoryCommand({
|
|
32
|
+
repositoryName: projectName,
|
|
33
|
+
imageScanningConfiguration: { scanOnPush: true },
|
|
34
|
+
}));
|
|
35
|
+
const repoUri = result.repository?.repositoryUri;
|
|
53
36
|
console.log(' Created ECR repository: ' + projectName);
|
|
54
37
|
if (repoUri) {
|
|
55
38
|
console.log(' Repository URI: ' + repoUri);
|
|
56
39
|
}
|
|
57
|
-
// Set lifecycle policy to keep only 10 images
|
|
40
|
+
// Set lifecycle policy to keep only 10 images
|
|
58
41
|
const lifecyclePolicy = JSON.stringify({
|
|
59
42
|
rules: [{
|
|
60
43
|
rulePriority: 1,
|
|
@@ -67,8 +50,10 @@ exports.ecrFixes = [
|
|
|
67
50
|
action: { type: 'expire' },
|
|
68
51
|
}],
|
|
69
52
|
});
|
|
70
|
-
(
|
|
71
|
-
|
|
53
|
+
await ecr.send(new aws_helpers_js_1.PutLifecyclePolicyCommand({
|
|
54
|
+
repositoryName: projectName,
|
|
55
|
+
lifecyclePolicyText: lifecyclePolicy,
|
|
56
|
+
}));
|
|
72
57
|
console.log(' Set lifecycle policy: keep 10 most recent images');
|
|
73
58
|
return true;
|
|
74
59
|
}
|
|
@@ -85,15 +70,21 @@ exports.ecrFixes = [
|
|
|
85
70
|
severity: 'info',
|
|
86
71
|
description: '📦 ECR Docker login not working from dev machine',
|
|
87
72
|
scan: async (config) => {
|
|
88
|
-
if (!isAwsConfigured(config))
|
|
73
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
89
74
|
return false;
|
|
90
75
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
91
76
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
92
|
-
if (!findEcrRepo(projectName, region))
|
|
77
|
+
if (!(await (0, aws_helpers_js_1.findEcrRepo)(projectName, region)))
|
|
93
78
|
return false;
|
|
94
|
-
// Test ECR
|
|
95
|
-
|
|
96
|
-
|
|
79
|
+
// Test ECR authorization token
|
|
80
|
+
try {
|
|
81
|
+
const ecr = (0, aws_helpers_js_1.getECRClient)(region);
|
|
82
|
+
const result = await ecr.send(new aws_helpers_js_1.GetAuthorizationTokenCommand({}));
|
|
83
|
+
return !(result.authorizationData?.length);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
97
88
|
},
|
|
98
89
|
fix: null,
|
|
99
90
|
manualFix: 'Test ECR login: aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ecr.js","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/ecr.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"ecr.js","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/ecr.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iam.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/iam.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"iam.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/pipelines/aws/scanfix/iam.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAiB,GAAG,EAAE,MAAM,4BAA4B,CAAC;AA4IrE,eAAO,MAAM,QAAQ,EAAE,GAAG,EAuHzB,CAAC"}
|
|
@@ -5,30 +5,11 @@
|
|
|
5
5
|
* Creates IAM users with scoped policies:
|
|
6
6
|
* - Dev user: read-only access for development
|
|
7
7
|
* - Prod user: full access for deployment
|
|
8
|
+
* Uses AWS SDK v3.
|
|
8
9
|
*/
|
|
9
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
11
|
exports.iamFixes = void 0;
|
|
11
12
|
const aws_helpers_js_1 = require("../utils/aws-helpers.js");
|
|
12
|
-
/**
|
|
13
|
-
* Check if IAM user exists
|
|
14
|
-
*/
|
|
15
|
-
function findIamUser(userName, region) {
|
|
16
|
-
const result = (0, aws_helpers_js_1.awsExecSafe)('aws iam get-user --user-name ' + userName, region);
|
|
17
|
-
return !!result && !result.includes('NoSuchEntity');
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Check if AWS is configured for this project
|
|
21
|
-
*/
|
|
22
|
-
function isAwsConfigured(config) {
|
|
23
|
-
if ((0, aws_helpers_js_1.isOnServer)())
|
|
24
|
-
return false;
|
|
25
|
-
if (config.aws)
|
|
26
|
-
return true;
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
|
-
const { extractEnvironments } = require('../../../../utils/config-helpers.js');
|
|
29
|
-
const environments = extractEnvironments(config);
|
|
30
|
-
return Object.values(environments).some((e) => e.pipeline === 'aws');
|
|
31
|
-
}
|
|
32
13
|
/**
|
|
33
14
|
* Generate dev IAM policy (read-only)
|
|
34
15
|
*/
|
|
@@ -161,34 +142,39 @@ exports.iamFixes = [
|
|
|
161
142
|
severity: 'warning',
|
|
162
143
|
description: '👤 IAM dev user not created (read-only access)',
|
|
163
144
|
scan: async (config) => {
|
|
164
|
-
if (!isAwsConfigured(config))
|
|
145
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
165
146
|
return false;
|
|
166
147
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
167
148
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
168
|
-
return !findIamUser('factiii-' + projectName + '-dev', region);
|
|
149
|
+
return !(await (0, aws_helpers_js_1.findIamUser)('factiii-' + projectName + '-dev', region));
|
|
169
150
|
},
|
|
170
151
|
fix: async (config) => {
|
|
171
152
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
172
153
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
173
154
|
const userName = 'factiii-' + projectName + '-dev';
|
|
174
155
|
try {
|
|
156
|
+
const iam = (0, aws_helpers_js_1.getIAMClient)(region);
|
|
175
157
|
// Get account ID for ARNs
|
|
176
|
-
const
|
|
177
|
-
|
|
158
|
+
const accountId = await (0, aws_helpers_js_1.getAwsAccountId)(region);
|
|
159
|
+
if (!accountId) {
|
|
160
|
+
console.log(' Could not get AWS account ID');
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
178
163
|
// Create IAM user
|
|
179
|
-
(
|
|
164
|
+
await iam.send(new aws_helpers_js_1.CreateUserCommand({ UserName: userName }));
|
|
180
165
|
console.log(' Created IAM user: ' + userName);
|
|
181
166
|
// Create and attach inline policy
|
|
182
167
|
const policy = getDevPolicy(projectName, region, accountId);
|
|
183
|
-
(
|
|
184
|
-
|
|
185
|
-
|
|
168
|
+
await iam.send(new aws_helpers_js_1.PutUserPolicyCommand({
|
|
169
|
+
UserName: userName,
|
|
170
|
+
PolicyName: 'factiii-' + projectName + '-dev-policy',
|
|
171
|
+
PolicyDocument: policy,
|
|
172
|
+
}));
|
|
186
173
|
console.log(' Attached dev policy (read-only ECR, S3, EC2, RDS)');
|
|
187
174
|
// Create access key
|
|
188
|
-
const keyResult = (
|
|
189
|
-
const
|
|
190
|
-
const
|
|
191
|
-
const secretKey = parsed.AccessKey?.SecretAccessKey;
|
|
175
|
+
const keyResult = await iam.send(new aws_helpers_js_1.CreateAccessKeyCommand({ UserName: userName }));
|
|
176
|
+
const accessKeyId = keyResult.AccessKey?.AccessKeyId;
|
|
177
|
+
const secretKey = keyResult.AccessKey?.SecretAccessKey;
|
|
192
178
|
console.log('');
|
|
193
179
|
console.log(' Dev credentials (save these!):');
|
|
194
180
|
console.log(' Access Key ID: ' + accessKeyId);
|
|
@@ -210,34 +196,39 @@ exports.iamFixes = [
|
|
|
210
196
|
severity: 'warning',
|
|
211
197
|
description: '👤 IAM prod user not created (deployment access)',
|
|
212
198
|
scan: async (config) => {
|
|
213
|
-
if (!isAwsConfigured(config))
|
|
199
|
+
if (!(0, aws_helpers_js_1.isAwsConfigured)(config))
|
|
214
200
|
return false;
|
|
215
201
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
216
202
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
217
|
-
return !findIamUser('factiii-' + projectName + '-prod', region);
|
|
203
|
+
return !(await (0, aws_helpers_js_1.findIamUser)('factiii-' + projectName + '-prod', region));
|
|
218
204
|
},
|
|
219
205
|
fix: async (config) => {
|
|
220
206
|
const { region } = (0, aws_helpers_js_1.getAwsConfig)(config);
|
|
221
207
|
const projectName = (0, aws_helpers_js_1.getProjectName)(config);
|
|
222
208
|
const userName = 'factiii-' + projectName + '-prod';
|
|
223
209
|
try {
|
|
210
|
+
const iam = (0, aws_helpers_js_1.getIAMClient)(region);
|
|
224
211
|
// Get account ID for ARNs
|
|
225
|
-
const
|
|
226
|
-
|
|
212
|
+
const accountId = await (0, aws_helpers_js_1.getAwsAccountId)(region);
|
|
213
|
+
if (!accountId) {
|
|
214
|
+
console.log(' Could not get AWS account ID');
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
227
217
|
// Create IAM user
|
|
228
|
-
(
|
|
218
|
+
await iam.send(new aws_helpers_js_1.CreateUserCommand({ UserName: userName }));
|
|
229
219
|
console.log(' Created IAM user: ' + userName);
|
|
230
220
|
// Create and attach inline policy
|
|
231
221
|
const policy = getProdPolicy(projectName, region, accountId);
|
|
232
|
-
(
|
|
233
|
-
|
|
234
|
-
|
|
222
|
+
await iam.send(new aws_helpers_js_1.PutUserPolicyCommand({
|
|
223
|
+
UserName: userName,
|
|
224
|
+
PolicyName: 'factiii-' + projectName + '-prod-policy',
|
|
225
|
+
PolicyDocument: policy,
|
|
226
|
+
}));
|
|
235
227
|
console.log(' Attached prod policy (full ECR, S3, EC2, RDS, SES)');
|
|
236
228
|
// Create access key
|
|
237
|
-
const keyResult = (
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
const secretKey = parsed.AccessKey?.SecretAccessKey;
|
|
229
|
+
const keyResult = await iam.send(new aws_helpers_js_1.CreateAccessKeyCommand({ UserName: userName }));
|
|
230
|
+
const accessKeyId = keyResult.AccessKey?.AccessKeyId;
|
|
231
|
+
const secretKey = keyResult.AccessKey?.SecretAccessKey;
|
|
241
232
|
console.log('');
|
|
242
233
|
console.log(' Prod credentials (save these!):');
|
|
243
234
|
console.log(' Access Key ID: ' + accessKeyId);
|