@fishawack/lab-env 2.0.2 → 3.0.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/CHANGELOG.md +19 -0
- package/_Test/_fixtures/.gitkeep +0 -0
- package/_Test/_helpers/globals.js +10 -0
- package/_Test/key.js +33 -0
- package/_Test/provision.js +33 -0
- package/cli.js +6 -6
- package/commands/create/cmds/dekey.js +75 -0
- package/commands/create/cmds/deprovision.js +54 -0
- package/commands/create/cmds/diagnose.js +5 -3
- package/commands/create/cmds/key.js +99 -0
- package/commands/create/cmds/provision.js +120 -0
- package/commands/create/libs/aws-cloudfront-auth.js +77 -0
- package/commands/create/libs/aws-cloudfront-simple.js +51 -0
- package/commands/create/libs/utilities.js +49 -2
- package/commands/create/services/aws/cloudfront.js +295 -0
- package/commands/create/services/aws/iam.js +170 -0
- package/commands/create/services/aws/index.js +25 -0
- package/commands/create/services/aws/misc.js +9 -0
- package/commands/create/services/aws/s3.js +109 -0
- package/commands/create/services/guide.js +13 -0
- package/core/{0.0.21 → 0.1.0}/Dockerfile +6 -0
- package/core/{0.0.21 → 0.1.0}/entrypoint.sh +0 -0
- package/core/CHANGELOG.md +4 -0
- package/core/package.json +1 -1
- package/drupal/9/apache/apache.conf +1 -0
- package/drupal/9/docker-compose.yml +1 -1
- package/drupal/9/php/Dockerfile +1 -1
- package/globals.js +8 -0
- package/package.json +16 -5
|
@@ -23,9 +23,12 @@ const colorize = module.exports.colorize = (str, type) => {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
let latestSpinner = null;
|
|
27
|
+
|
|
26
28
|
module.exports.Spinner = class Spinner {
|
|
27
|
-
constructor(startMessage) {
|
|
28
|
-
this.ora = ora(colorize(startMessage, 'info')).start();
|
|
29
|
+
constructor(startMessage, simple = false) {
|
|
30
|
+
this.ora = ora(simple ? startMessage : colorize(startMessage, 'info')).start();
|
|
31
|
+
latestSpinner = this;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
update(message, status) {
|
|
@@ -37,6 +40,50 @@ module.exports.Spinner = class Spinner {
|
|
|
37
40
|
this.ora.succeed(colorize(message, status || 'success'));
|
|
38
41
|
}
|
|
39
42
|
}
|
|
43
|
+
|
|
44
|
+
action(message, action, success, failure) {
|
|
45
|
+
return new Promise(async (resolve, reject) => {
|
|
46
|
+
let instance = new this.constructor(message);
|
|
47
|
+
let res;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
res = await action();
|
|
51
|
+
|
|
52
|
+
instance.update(success);
|
|
53
|
+
} catch (e){
|
|
54
|
+
instance.update(failure, 'fail');
|
|
55
|
+
reject(e);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
resolve(res);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
simple(message, action) {
|
|
63
|
+
return new Promise(async (resolve, reject) => {
|
|
64
|
+
let instance = new this.constructor(message, true);
|
|
65
|
+
let res;
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
res = await action();
|
|
69
|
+
|
|
70
|
+
instance.ora.succeed();
|
|
71
|
+
} catch (e){
|
|
72
|
+
instance.ora.fail();
|
|
73
|
+
reject(e);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
resolve(res);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ping(){
|
|
81
|
+
latestSpinner.ora.color = latestSpinner.ora.color === 'cyan' ? 'magenta' : 'cyan';
|
|
82
|
+
let message = ' - check: ';
|
|
83
|
+
let split = latestSpinner.ora.text.split(message);
|
|
84
|
+
let iteration = split[1] && +split[1].split(':')[0] || 0;
|
|
85
|
+
latestSpinner.ora.text = `${split[0]}${message}${iteration+1}`;
|
|
86
|
+
}
|
|
40
87
|
};
|
|
41
88
|
|
|
42
89
|
module.exports.encode = (username, password) => {
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
const { CloudFrontClient, CreateDistributionWithTagsCommand, CreateCloudFrontOriginAccessIdentityCommand, DeleteDistributionCommand , DeleteCloudFrontOriginAccessIdentityCommand, GetDistributionCommand, UpdateDistributionCommand, GetCloudFrontOriginAccessIdentityCommand, CreateFunctionCommand, GetFunctionCommand, UpdateFunctionCommand, PublishFunctionCommand, DeleteFunctionCommand, DescribeFunctionCommand } = require("@aws-sdk/client-cloudfront");
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { Spinner } = require('../../libs/utilities');
|
|
4
|
+
const { createClient } = require('./misc.js');
|
|
5
|
+
|
|
6
|
+
module.exports.createCloudFrontDistribution = async (name, account, tags = [], FunctionARN = null, region = 'us-east-1') => {
|
|
7
|
+
const client = createClient(CloudFrontClient, account, region);
|
|
8
|
+
|
|
9
|
+
let OAI = await Spinner.prototype.simple(`Creating CloudFront OAI`, () => {
|
|
10
|
+
return client.send(
|
|
11
|
+
new CreateCloudFrontOriginAccessIdentityCommand({
|
|
12
|
+
CloudFrontOriginAccessIdentityConfig: {
|
|
13
|
+
CallerReference: name,
|
|
14
|
+
Comment: `lab-env provisioned CloudFront OAI for s3 bucket ${name}`,
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
)
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
let res;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
res = await Spinner.prototype.simple(`Creating CloudFront distribution with CloudFront OAI and tags`, () => {
|
|
24
|
+
return client.send(
|
|
25
|
+
new CreateDistributionWithTagsCommand({
|
|
26
|
+
DistributionConfigWithTags: {
|
|
27
|
+
DistributionConfig: {
|
|
28
|
+
Enabled: true,
|
|
29
|
+
CallerReference: name,
|
|
30
|
+
Comment: `lab-env provisioned CloudFront distribution for project ${name}`,
|
|
31
|
+
CustomErrorResponses: {
|
|
32
|
+
Items: [
|
|
33
|
+
{
|
|
34
|
+
ErrorCachingMinTTL: 0,
|
|
35
|
+
ErrorCode: 403,
|
|
36
|
+
ResponseCode: 200,
|
|
37
|
+
ResponsePagePath: '/index.html'
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
Quantity: 1
|
|
41
|
+
},
|
|
42
|
+
DefaultCacheBehavior: {
|
|
43
|
+
Compress: true,
|
|
44
|
+
TargetOriginId: `${name}.s3.${region}.amazonaws.com`,
|
|
45
|
+
ViewerProtocolPolicy: 'redirect-to-https',
|
|
46
|
+
CachePolicyId: '658327ea-f89d-4fab-a63d-7e88639e58f6', // Built in, Managed AWS Policy - Cache Optimized
|
|
47
|
+
FunctionAssociations: FunctionARN && {
|
|
48
|
+
Items: [
|
|
49
|
+
{
|
|
50
|
+
EventType: 'viewer-request',
|
|
51
|
+
FunctionARN
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
Quantity: 1
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
Origins: {
|
|
58
|
+
Items: [
|
|
59
|
+
{
|
|
60
|
+
DomainName: `${name}.s3.${region}.amazonaws.com`,
|
|
61
|
+
Id: `${name}.s3.${region}.amazonaws.com`,
|
|
62
|
+
S3OriginConfig: {
|
|
63
|
+
OriginAccessIdentity: `origin-access-identity/cloudfront/${OAI.CloudFrontOriginAccessIdentity.Id}`
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
Quantity: 1
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
Tags: {
|
|
71
|
+
Items: [{Key: 'client', Value: account}].concat(tags)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
)
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await Spinner.prototype.simple(`Waiting for CloudFront distribution to deploy`, () => {
|
|
79
|
+
return module.exports.waitForCloudFrontDistribution(res.Distribution.Id, account);
|
|
80
|
+
});
|
|
81
|
+
} catch(e){
|
|
82
|
+
let Id = e.message.split(' ')[e.message.split(' ').length - 1];
|
|
83
|
+
|
|
84
|
+
res = await Spinner.prototype.simple(`Retrieving the already existing CloudFront distribution`, () => {
|
|
85
|
+
return client.send(
|
|
86
|
+
new GetDistributionCommand({ Id })
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return res;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports.removeCloudFrontDistribution = async (Id, account) => {
|
|
95
|
+
const client = createClient(CloudFrontClient, account);
|
|
96
|
+
|
|
97
|
+
let res = await Spinner.prototype.simple(`Retrieving the CloudFront distribution ${Id}`, () => {
|
|
98
|
+
return client.send(
|
|
99
|
+
new GetDistributionCommand({ Id })
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
let OAI = res.Distribution.DistributionConfig.Origins.Items[0].S3OriginConfig.OriginAccessIdentity.split('origin-access-identity/cloudfront/')[1];
|
|
104
|
+
|
|
105
|
+
res.Distribution.DistributionConfig.Enabled = false;
|
|
106
|
+
|
|
107
|
+
res = await Spinner.prototype.simple(`Disabling the CloudFront distribution`, () => {
|
|
108
|
+
return client.send(
|
|
109
|
+
new UpdateDistributionCommand({ DistributionConfig: res.Distribution.DistributionConfig, Id, IfMatch: res.ETag })
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await Spinner.prototype.simple(`Waiting for CloudFront distribution to deploy`, () => {
|
|
114
|
+
return module.exports.waitForCloudFrontDistribution(res.Distribution.Id, account);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
res = await Spinner.prototype.simple(`Deleting the CloudFront distribution`, () => {
|
|
118
|
+
return client.send(
|
|
119
|
+
new DeleteDistributionCommand({ Id, IfMatch: res.ETag })
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
res = await Spinner.prototype.simple(`Retrieving the CloudFront OAI`, () => {
|
|
124
|
+
return client.send(
|
|
125
|
+
new GetCloudFrontOriginAccessIdentityCommand({ Id: OAI })
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
res = await Spinner.prototype.simple(`Deleting the CloudFront OAI`, () => {
|
|
130
|
+
return client.send(
|
|
131
|
+
new DeleteCloudFrontOriginAccessIdentityCommand({ Id: OAI, IfMatch: res.ETag })
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports.waitForCloudFrontDistribution = async (Id, account) => {
|
|
137
|
+
const client = createClient(CloudFrontClient, account);
|
|
138
|
+
|
|
139
|
+
let status;
|
|
140
|
+
|
|
141
|
+
do{
|
|
142
|
+
await new Promise((resolve) => setTimeout(() => resolve(), 5000));
|
|
143
|
+
|
|
144
|
+
await Spinner.prototype.ping();
|
|
145
|
+
|
|
146
|
+
let check = await client.send(
|
|
147
|
+
new GetDistributionCommand({ Id })
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
status = check.Distribution.Status;
|
|
151
|
+
} while(status !== 'Deployed')
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports.createCloudFrontFunction = async (name, account, fn, config) => {
|
|
155
|
+
const client = createClient(CloudFrontClient, account);
|
|
156
|
+
|
|
157
|
+
let FunctionConfig = {
|
|
158
|
+
Comment: `lab-env provisioned cloudfront function for project ${name} using code snippet ${fn}.js`,
|
|
159
|
+
Runtime: `cloudfront-js-1.0`
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
let res;
|
|
163
|
+
|
|
164
|
+
try{
|
|
165
|
+
res = await Spinner.prototype.simple(`Creating CloudFront function`, () => {
|
|
166
|
+
return client.send(
|
|
167
|
+
new CreateFunctionCommand({
|
|
168
|
+
Name: name,
|
|
169
|
+
FunctionCode: new TextEncoder().encode(" "),
|
|
170
|
+
FunctionConfig
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
} catch (e){
|
|
175
|
+
res = await Spinner.prototype.simple(`Retrieving the already existing CloudFront function`, () => {
|
|
176
|
+
return client.send(
|
|
177
|
+
new GetFunctionCommand({
|
|
178
|
+
Name: name
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let processedFn = fs.readFileSync(`${__dirname}/../../libs/${fn}.js`).toString();
|
|
185
|
+
processedFn = processedFn.replace(/<%=.*%>/g, (el) => JSON.stringify(config[el.slice(3, el.length - 2).trim()], null, 4));
|
|
186
|
+
|
|
187
|
+
res = await Spinner.prototype.simple(`Updating CloudFront function with ${fn}.js code`, () => {
|
|
188
|
+
return client.send(
|
|
189
|
+
new UpdateFunctionCommand({
|
|
190
|
+
Name: name,
|
|
191
|
+
FunctionCode: new TextEncoder().encode(processedFn),
|
|
192
|
+
FunctionConfig,
|
|
193
|
+
IfMatch: res.ETag
|
|
194
|
+
})
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
res = await Spinner.prototype.simple(`Publishing CloudFront function`, () => {
|
|
199
|
+
return client.send(
|
|
200
|
+
new PublishFunctionCommand({
|
|
201
|
+
Name: name,
|
|
202
|
+
IfMatch: res.ETag
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
return res;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports.removeCloudFrontFunction = async (name, account) => {
|
|
211
|
+
const client = createClient(CloudFrontClient, account);
|
|
212
|
+
|
|
213
|
+
let res = await Spinner.prototype.simple(`Retrieving CloudFront function`, () => {
|
|
214
|
+
return client.send(
|
|
215
|
+
new GetFunctionCommand({
|
|
216
|
+
Name: name
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
res = await Spinner.prototype.simple(`Deleting CloudFront function`, () => {
|
|
222
|
+
return client.send(
|
|
223
|
+
new DeleteFunctionCommand({
|
|
224
|
+
Name: name,
|
|
225
|
+
IfMatch: res.ETag
|
|
226
|
+
})
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return res;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
module.exports.setCloudFrontFunctionAssociation = async (Id, account) => {
|
|
234
|
+
const client = createClient(CloudFrontClient, account);
|
|
235
|
+
|
|
236
|
+
let res = await Spinner.prototype.simple(`Retrieving CloudFront distribution`, () => {
|
|
237
|
+
return client.send(
|
|
238
|
+
new GetDistributionCommand({ Id })
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
let { FunctionSummary: { FunctionMetadata: { FunctionARN } } } = await Spinner.prototype.simple(`Retrieving CloudFront function`, () => {
|
|
243
|
+
return client.send(
|
|
244
|
+
new DescribeFunctionCommand({
|
|
245
|
+
Name: res.Distribution.DistributionConfig.CallerReference,
|
|
246
|
+
Stage: 'LIVE'
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
res.Distribution.DistributionConfig.DefaultCacheBehavior.FunctionAssociations = {
|
|
252
|
+
Items: [
|
|
253
|
+
{
|
|
254
|
+
EventType: 'viewer-request',
|
|
255
|
+
FunctionARN: FunctionARN
|
|
256
|
+
}
|
|
257
|
+
],
|
|
258
|
+
Quantity: 1
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
res = await Spinner.prototype.simple(`Adding CloudFront function to CloudFront distribution`, () => {
|
|
262
|
+
return client.send(
|
|
263
|
+
new UpdateDistributionCommand({ DistributionConfig: res.Distribution.DistributionConfig, Id, IfMatch: res.ETag })
|
|
264
|
+
);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
await Spinner.prototype.simple(`Waiting for CloudFront distribution to deploy`, () => {
|
|
268
|
+
return module.exports.waitForCloudFrontDistribution(res.Distribution.Id, account);
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
module.exports.removeCloudFrontFunctionAssociation = async (Id, account) => {
|
|
273
|
+
const client = createClient(CloudFrontClient, account);
|
|
274
|
+
|
|
275
|
+
let res = await Spinner.prototype.simple(`Retrieving CloudFront distribution`, () => {
|
|
276
|
+
return client.send(
|
|
277
|
+
new GetDistributionCommand({ Id })
|
|
278
|
+
);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
res.Distribution.DistributionConfig.DefaultCacheBehavior.FunctionAssociations = {
|
|
282
|
+
Items: [],
|
|
283
|
+
Quantity: 0
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
res = await Spinner.prototype.simple(`Removing CloudFront function from CloudFront distribution`, () => {
|
|
287
|
+
return client.send(
|
|
288
|
+
new UpdateDistributionCommand({ DistributionConfig: res.Distribution.DistributionConfig, Id, IfMatch: res.ETag })
|
|
289
|
+
);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
await Spinner.prototype.simple(`Waiting for CloudFront distribution to deploy`, () => {
|
|
293
|
+
return module.exports.waitForCloudFrontDistribution(res.Distribution.Id, account);
|
|
294
|
+
});
|
|
295
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
const { IAMClient, CreateUserCommand, GetUserCommand, DeleteUserCommand, AttachUserPolicyCommand, ListAttachedUserPoliciesCommand, DetachUserPolicyCommand, CreateAccessKeyCommand, DeleteAccessKeyCommand, ListAccessKeysCommand } = require("@aws-sdk/client-iam");
|
|
2
|
+
const { Spinner } = require('../../libs/utilities');
|
|
3
|
+
const { createClient } = require('./misc.js');
|
|
4
|
+
|
|
5
|
+
module.exports.createIAMUser = async (UserName, account) => {
|
|
6
|
+
const client = createClient(IAMClient, account);
|
|
7
|
+
|
|
8
|
+
let res;
|
|
9
|
+
|
|
10
|
+
try{
|
|
11
|
+
res = await Spinner.prototype.simple(`Creating IAM user ${UserName}`, () => {
|
|
12
|
+
return client.send(
|
|
13
|
+
new CreateUserCommand({ UserName })
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
} catch(e){
|
|
17
|
+
res = await Spinner.prototype.simple(`Retrieving the already existing IAM user ${UserName}`, () => {
|
|
18
|
+
return client.send(
|
|
19
|
+
new GetUserCommand({ UserName })
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return res;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
module.exports.createFWIAMUser = async (UserName, account) => {
|
|
28
|
+
await module.exports.createIAMUser(UserName, account);
|
|
29
|
+
|
|
30
|
+
await module.exports.syncFWIAMPolicies(UserName, account);
|
|
31
|
+
|
|
32
|
+
let res = await module.exports.createAccessKeySafe(UserName, account);
|
|
33
|
+
|
|
34
|
+
return res;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports.removeIAMUser = async (UserName, account) => {
|
|
38
|
+
const client = createClient(IAMClient, account);
|
|
39
|
+
|
|
40
|
+
let res;
|
|
41
|
+
|
|
42
|
+
try{
|
|
43
|
+
await Spinner.prototype.simple(`Checking if IAM user ${UserName} exists`, () => {
|
|
44
|
+
return client.send(
|
|
45
|
+
new GetUserCommand({ UserName })
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await module.exports.removeAllIAMPolicies(UserName, account);
|
|
50
|
+
|
|
51
|
+
await module.exports.removeAllAccessKeys(UserName, account);
|
|
52
|
+
|
|
53
|
+
res = await Spinner.prototype.simple(`Removing IAM user ${UserName}`, () => {
|
|
54
|
+
return client.send(
|
|
55
|
+
new DeleteUserCommand({ UserName })
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
} catch(e){
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return res;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
module.exports.attachIAMPolicy = async (UserName, account, policy) => {
|
|
65
|
+
const client = createClient(IAMClient, account);
|
|
66
|
+
|
|
67
|
+
let res = await Spinner.prototype.simple(`Attaching IAM policy ${policy}`, () => {
|
|
68
|
+
return client.send(
|
|
69
|
+
new AttachUserPolicyCommand({ UserName, PolicyArn: policy })
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return res;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
module.exports.syncFWIAMPolicies = async (UserName, account) => {
|
|
77
|
+
await module.exports.removeAllIAMPolicies(UserName, account);
|
|
78
|
+
await module.exports.attachIAMPolicy(UserName, account, 'arn:aws:iam::aws:policy/AmazonS3FullAccess');
|
|
79
|
+
await module.exports.attachIAMPolicy(UserName, account, 'arn:aws:iam::aws:policy/CloudFrontFullAccess');
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
module.exports.removeIAMPolicy = async (UserName, account, policy) => {
|
|
83
|
+
const client = createClient(IAMClient, account);
|
|
84
|
+
|
|
85
|
+
let res = await Spinner.prototype.simple(`Detaching IAM policy ${policy}`, () => {
|
|
86
|
+
return client.send(
|
|
87
|
+
new DetachUserPolicyCommand({ UserName, PolicyArn: policy })
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return res;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
module.exports.listIAMPolicies = async (UserName, account) => {
|
|
95
|
+
const client = createClient(IAMClient, account);
|
|
96
|
+
|
|
97
|
+
let res = await Spinner.prototype.simple(`Listing IAM policies`, () => {
|
|
98
|
+
return client.send(
|
|
99
|
+
new ListAttachedUserPoliciesCommand({ UserName })
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return res;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
module.exports.removeAllIAMPolicies = async (UserName, account) => {
|
|
107
|
+
let res = await module.exports.listIAMPolicies(UserName, account);
|
|
108
|
+
|
|
109
|
+
for(let i = 0; i < res.AttachedPolicies.length; i++){
|
|
110
|
+
await module.exports.removeIAMPolicy(UserName, account, res.AttachedPolicies[i].PolicyArn);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return res;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
module.exports.createAccessKey = async (UserName, account) => {
|
|
117
|
+
const client = createClient(IAMClient, account);
|
|
118
|
+
|
|
119
|
+
let res = await Spinner.prototype.simple(`Creating access key`, () => {
|
|
120
|
+
return client.send(
|
|
121
|
+
new CreateAccessKeyCommand({ UserName })
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return res;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
module.exports.removeAccessKey = async (UserName, account, AccessKeyId) => {
|
|
129
|
+
const client = createClient(IAMClient, account);
|
|
130
|
+
|
|
131
|
+
let res = await Spinner.prototype.simple(`Removing access key ${AccessKeyId}`, () => {
|
|
132
|
+
return client.send(
|
|
133
|
+
new DeleteAccessKeyCommand({ AccessKeyId, UserName })
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return res;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
module.exports.listAccessKeys = async (UserName, account) => {
|
|
141
|
+
const client = createClient(IAMClient, account);
|
|
142
|
+
|
|
143
|
+
let res = await Spinner.prototype.simple(`Listing access keys`, () => {
|
|
144
|
+
return client.send(
|
|
145
|
+
new ListAccessKeysCommand({ UserName })
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return res;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
module.exports.removeAllAccessKeys = async (UserName, account) => {
|
|
153
|
+
let res = await module.exports.listAccessKeys(UserName, account);
|
|
154
|
+
|
|
155
|
+
for(let i = 0; i < res.AccessKeyMetadata.length; i++){
|
|
156
|
+
await module.exports.removeAccessKey(UserName, account, res.AccessKeyMetadata[i].AccessKeyId);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return res;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
module.exports.createAccessKeySafe = async (UserName, account) => {
|
|
163
|
+
let res = await module.exports.listAccessKeys(UserName, account);
|
|
164
|
+
|
|
165
|
+
if(!res.AccessKeyMetadata.length){
|
|
166
|
+
res = await module.exports.createAccessKey(UserName, account);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return res;
|
|
170
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module.exports.s3 = require("./s3.js");
|
|
2
|
+
module.exports.cloudfront = require("./cloudfront.js");
|
|
3
|
+
module.exports.iam = require("./iam.js");
|
|
4
|
+
|
|
5
|
+
module.exports.slug = (repo, client, branch) => `fw-auto-${client}-${repo}-${branch}`;
|
|
6
|
+
|
|
7
|
+
module.exports.clients = ['fishawack', 'abbvie', 'sanofigenzyme', 'gsk', 'janssen', 'astrazeneca', 'ptc', 'jazz', 'pfizer', 'heron', 'novartis', 'training'];
|
|
8
|
+
|
|
9
|
+
module.exports.static = async (name, account, tags = [], credentials = []) => {
|
|
10
|
+
let s3 = await module.exports.s3.createS3Bucket(name, account, tags);
|
|
11
|
+
|
|
12
|
+
let cloudfrontFunction = await module.exports.cloudfront.createCloudFrontFunction(name, account, credentials.length ? 'aws-cloudfront-auth' : 'aws-cloudfront-simple', {credentials: credentials.map(d => `Basic ${Buffer.from(`${d.username}:${d.password}`).toString('base64')}`)});
|
|
13
|
+
|
|
14
|
+
let cloudfront = await module.exports.cloudfront.createCloudFrontDistribution(name, account, tags, cloudfrontFunction.FunctionSummary.FunctionMetadata.FunctionARN);
|
|
15
|
+
|
|
16
|
+
await module.exports.s3.setS3BucketPolicy(name, account, cloudfront.Distribution.DistributionConfig.Origins.Items[0].S3OriginConfig.OriginAccessIdentity.split('origin-access-identity/cloudfront/')[1]);
|
|
17
|
+
|
|
18
|
+
let config = {
|
|
19
|
+
"bucket": s3.Location,
|
|
20
|
+
"url": `https://${cloudfront.Distribution.DomainName}`,
|
|
21
|
+
"cloudfront": cloudfront.Distribution.Id,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return config;
|
|
25
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const { S3Client, CreateBucketCommand, DeleteBucketCommand, ListBucketsCommand, PutPublicAccessBlockCommand, PutBucketTaggingCommand, PutBucketPolicyCommand, PutObjectCommand, DeleteObjectCommand } = require("@aws-sdk/client-s3");
|
|
2
|
+
const { Spinner } = require('../../libs/utilities');
|
|
3
|
+
const { createClient } = require('./misc.js');
|
|
4
|
+
|
|
5
|
+
module.exports.createS3Bucket = async (bucket, account, tags = []) => {
|
|
6
|
+
const client = createClient(S3Client, account);
|
|
7
|
+
|
|
8
|
+
let res = await Spinner.prototype.simple(`Creating s3 bucket ${bucket}`, () => {
|
|
9
|
+
return client.send(
|
|
10
|
+
new CreateBucketCommand({ Bucket: bucket })
|
|
11
|
+
);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
await Spinner.prototype.simple(`Blocking all public access to s3 bucket`, () => {
|
|
15
|
+
return client.send(
|
|
16
|
+
new PutPublicAccessBlockCommand({ Bucket: bucket, PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, IgnorePublicAcls: true, RestrictPublicBuckets: true } })
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await Spinner.prototype.simple(`Adding tags to s3 bucket`, () => {
|
|
21
|
+
return client.send(
|
|
22
|
+
new PutBucketTaggingCommand({ Bucket: bucket, Tagging: {TagSet: [{Key: 'client', Value: account}].concat(tags)} })
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return res;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports.listS3Buckets = async (account) => {
|
|
30
|
+
const client = createClient(S3Client, account);
|
|
31
|
+
|
|
32
|
+
let res = await Spinner.prototype.simple(`Listing s3 buckets`, () => {
|
|
33
|
+
return client.send(
|
|
34
|
+
new ListBucketsCommand({})
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return res;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports.removeS3Bucket = async (bucket, account) => {
|
|
42
|
+
const client = createClient(S3Client, account);
|
|
43
|
+
|
|
44
|
+
await Spinner.prototype.simple(`Removing s3 bucket ${bucket}`, () => {
|
|
45
|
+
return client.send(
|
|
46
|
+
new DeleteBucketCommand({ Bucket: bucket })
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports.setS3BucketPolicy = async (bucket, account, OAI) => {
|
|
52
|
+
const client = createClient(S3Client, account);
|
|
53
|
+
|
|
54
|
+
let res = await Spinner.prototype.simple(`Updating s3 bucket policy`, () => {
|
|
55
|
+
return client.send(
|
|
56
|
+
new PutBucketPolicyCommand({
|
|
57
|
+
Bucket: bucket,
|
|
58
|
+
Policy: JSON.stringify({
|
|
59
|
+
"Version": "2008-10-17",
|
|
60
|
+
"Id": "PolicyForCloudFrontPrivateContent",
|
|
61
|
+
"Statement": [
|
|
62
|
+
{
|
|
63
|
+
"Sid": "1",
|
|
64
|
+
"Effect": "Allow",
|
|
65
|
+
"Principal": {
|
|
66
|
+
"AWS": `arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${OAI}`
|
|
67
|
+
},
|
|
68
|
+
"Action": "s3:GetObject",
|
|
69
|
+
"Resource": `arn:aws:s3:::${bucket}/*`
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return res;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports.addFileToS3Bucket = async (bucket, account, filepath, file) => {
|
|
81
|
+
const client = createClient(S3Client, account);
|
|
82
|
+
|
|
83
|
+
let res = await Spinner.prototype.simple(`Adding file to s3 bucket`, () => {
|
|
84
|
+
return client.send(
|
|
85
|
+
new PutObjectCommand({
|
|
86
|
+
Bucket: bucket,
|
|
87
|
+
Body: file,
|
|
88
|
+
Key: filepath
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return res;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
module.exports.removeFileToS3Bucket = async (bucket, account, filepath) => {
|
|
97
|
+
const client = createClient(S3Client, account);
|
|
98
|
+
|
|
99
|
+
let res = await Spinner.prototype.simple(`Removing file from s3 bucket`, () => {
|
|
100
|
+
return client.send(
|
|
101
|
+
new DeleteObjectCommand({
|
|
102
|
+
Bucket: bucket,
|
|
103
|
+
Key: filepath
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return res;
|
|
109
|
+
}
|
|
@@ -194,6 +194,19 @@ module.exports.preset = async () => {
|
|
|
194
194
|
return inputs.preset;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
module.exports.gitlabSkip = async () => {
|
|
198
|
+
let inputs = await inquirer.prompt([
|
|
199
|
+
{
|
|
200
|
+
type: 'confirm',
|
|
201
|
+
name: 'confirm',
|
|
202
|
+
message: 'Do you want to test gitlab setup? (VPN required)',
|
|
203
|
+
default: true
|
|
204
|
+
}
|
|
205
|
+
]);
|
|
206
|
+
|
|
207
|
+
return !inputs.confirm;
|
|
208
|
+
}
|
|
209
|
+
|
|
197
210
|
module.exports.config = async () => {
|
|
198
211
|
let inputs = await inquirer.prompt([
|
|
199
212
|
{
|