@fishawack/lab-env 5.7.0-beta.2 → 5.7.0-beta.4

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/_Test/provision.js +1 -8
  3. package/_Test/prune.js +8 -5
  4. package/bitbucket-pipelines.yml +2 -2
  5. package/cli.js +1 -0
  6. package/commands/create/cmds/dekey.js +13 -9
  7. package/commands/create/cmds/deprovision.js +29 -0
  8. package/commands/create/cmds/key.js +60 -41
  9. package/commands/create/cmds/provision.js +425 -55
  10. package/commands/create/cmds/rekey.js +218 -0
  11. package/commands/create/libs/output-credentials.js +59 -0
  12. package/commands/create/libs/parallel-runner.js +204 -0
  13. package/commands/create/libs/resolve-operator.js +59 -0
  14. package/commands/create/libs/utilities.js +71 -8
  15. package/commands/create/libs/vars.js +70 -86
  16. package/commands/create/services/aws/acm.js +4 -2
  17. package/commands/create/services/aws/cloudfront.js +51 -45
  18. package/commands/create/services/aws/ec2.js +132 -53
  19. package/commands/create/services/aws/elasticache.js +159 -0
  20. package/commands/create/services/aws/elasticbeanstalk.js +141 -60
  21. package/commands/create/services/aws/iam.js +178 -98
  22. package/commands/create/services/aws/index.js +1202 -466
  23. package/commands/create/services/aws/opensearch.js +25 -17
  24. package/commands/create/services/aws/rds.js +22 -34
  25. package/commands/create/services/aws/s3.js +14 -27
  26. package/commands/create/services/aws/secretsmanager.js +8 -15
  27. package/commands/create/services/aws/ses.js +195 -0
  28. package/commands/create/templates/elasticbeanstalk/.ebextensions/laravel/cron.config +45 -0
  29. package/commands/create/templates/elasticbeanstalk/.ebextensions/laravel/queue-worker.config +29 -0
  30. package/commands/create/templates/elasticbeanstalk/.ebextensions/laravel/software.config +12 -0
  31. package/commands/create/templates/elasticbeanstalk/.ebextensions/misc/setvars.config +2 -16
  32. package/commands/create/templates/elasticbeanstalk/.platform/confighooks/postdeploy/rewrite-flush.sh +1 -1
  33. package/commands/create/templates/elasticbeanstalk/.platform/confighooks/postdeploy/setvars.sh +19 -0
  34. package/commands/create/templates/elasticbeanstalk/.platform/hooks/postdeploy/restart_queue.sh +4 -0
  35. package/commands/create/templates/elasticbeanstalk/.platform/hooks/prebuild/setvars.sh +19 -0
  36. package/commands/scan.js +1 -1
  37. package/package.json +5 -2
@@ -5,22 +5,24 @@ const {
5
5
  DescribeDomainCommand,
6
6
  } = require("@aws-sdk/client-opensearch");
7
7
  const { Spinner, poll } = require("../../libs/utilities");
8
+ const { awsClientConfig } = require("../../libs/vars");
9
+
10
+ const getClient = () => new OpenSearchClient(awsClientConfig);
8
11
 
9
12
  module.exports.createOpenSearchDomain = async (
10
13
  name,
11
14
  securityGroupId,
12
15
  privateSubnetIds,
13
16
  instanceProfileRole,
17
+ tags = [],
14
18
  ) => {
15
- const client = new OpenSearchClient({});
16
-
17
19
  const accountId = instanceProfileRole.split(":")[4] || "*";
18
20
  const region = process.env.AWS_REGION;
19
21
 
20
22
  const res = await Spinner.prototype.simple(
21
23
  `Creating OpenSearch domain ${name}`,
22
24
  () => {
23
- return client.send(
25
+ return getClient().send(
24
26
  new CreateDomainCommand({
25
27
  DomainName: name,
26
28
  EngineVersion: "OpenSearch_2.19",
@@ -68,6 +70,14 @@ module.exports.createOpenSearchDomain = async (
68
70
  },
69
71
  ],
70
72
  }),
73
+ TagList: [
74
+ { Key: "client", Value: process.env.AWS_PROFILE },
75
+ ].concat(
76
+ tags.map((t) => ({
77
+ Key: t.Key,
78
+ Value: String(t.Value),
79
+ })),
80
+ ),
71
81
  }),
72
82
  );
73
83
  },
@@ -77,14 +87,12 @@ module.exports.createOpenSearchDomain = async (
77
87
  };
78
88
 
79
89
  module.exports.waitForOpenSearchDomain = async (name) => {
80
- const client = new OpenSearchClient({});
81
-
82
90
  const res = await Spinner.prototype.simple(
83
91
  `Waiting for OpenSearch domain to become available (this may take 15-20 minutes)`,
84
- () => {
92
+ (spinner) => {
85
93
  return poll(
86
94
  async () => {
87
- const { DomainStatus } = await client.send(
95
+ const { DomainStatus } = await getClient().send(
88
96
  new DescribeDomainCommand({ DomainName: name }),
89
97
  );
90
98
  return DomainStatus;
@@ -92,6 +100,8 @@ module.exports.waitForOpenSearchDomain = async (name) => {
92
100
  (status) =>
93
101
  status.Processing ||
94
102
  (!status.Endpoint && !status.Endpoints),
103
+ undefined,
104
+ spinner,
95
105
  );
96
106
  },
97
107
  );
@@ -100,12 +110,12 @@ module.exports.waitForOpenSearchDomain = async (name) => {
100
110
  };
101
111
 
102
112
  module.exports.describeOpenSearchDomain = async (name) => {
103
- const client = new OpenSearchClient({});
104
-
105
113
  const res = await Spinner.prototype.simple(
106
114
  `Describing OpenSearch domain ${name}`,
107
115
  () => {
108
- return client.send(new DescribeDomainCommand({ DomainName: name }));
116
+ return getClient().send(
117
+ new DescribeDomainCommand({ DomainName: name }),
118
+ );
109
119
  },
110
120
  );
111
121
 
@@ -113,23 +123,19 @@ module.exports.describeOpenSearchDomain = async (name) => {
113
123
  };
114
124
 
115
125
  module.exports.deleteOpenSearchDomain = async (name) => {
116
- const client = new OpenSearchClient({});
117
-
118
126
  await Spinner.prototype.simple(`Deleting OpenSearch domain ${name}`, () => {
119
- return client.send(new DeleteDomainCommand({ DomainName: name }));
127
+ return getClient().send(new DeleteDomainCommand({ DomainName: name }));
120
128
  });
121
129
  };
122
130
 
123
131
  module.exports.waitForOpenSearchDeletion = async (name) => {
124
- const client = new OpenSearchClient({});
125
-
126
132
  await Spinner.prototype.simple(
127
133
  `Waiting for OpenSearch domain to be deleted`,
128
- () => {
134
+ (spinner) => {
129
135
  return poll(
130
136
  async () => {
131
137
  try {
132
- const { DomainStatus } = await client.send(
138
+ const { DomainStatus } = await getClient().send(
133
139
  new DescribeDomainCommand({ DomainName: name }),
134
140
  );
135
141
  return DomainStatus;
@@ -141,6 +147,8 @@ module.exports.waitForOpenSearchDeletion = async (name) => {
141
147
  }
142
148
  },
143
149
  (status) => !status.deleted,
150
+ undefined,
151
+ spinner,
144
152
  );
145
153
  },
146
154
  );
@@ -13,13 +13,15 @@ const {
13
13
  ModifyDBParameterGroupCommand,
14
14
  } = require("@aws-sdk/client-rds");
15
15
  const { Spinner, poll } = require("../../libs/utilities");
16
+ const { awsClientConfig } = require("../../libs/vars");
17
+
18
+ const getClient = () => new RDSClient(awsClientConfig);
16
19
 
17
20
  module.exports.ensureDBSubnetGroup = async (privateSubnetIds) => {
18
- const client = new RDSClient({});
19
21
  const name = "fw-auto-private-db-subnet-group";
20
22
 
21
23
  try {
22
- await client.send(
24
+ await getClient().send(
23
25
  new DescribeDBSubnetGroupsCommand({
24
26
  DBSubnetGroupName: name,
25
27
  }),
@@ -33,7 +35,7 @@ module.exports.ensureDBSubnetGroup = async (privateSubnetIds) => {
33
35
  }
34
36
 
35
37
  await Spinner.prototype.simple(`Creating DB subnet group ${name}`, () => {
36
- return client.send(
38
+ return getClient().send(
37
39
  new CreateDBSubnetGroupCommand({
38
40
  DBSubnetGroupName: name,
39
41
  DBSubnetGroupDescription:
@@ -53,12 +55,10 @@ module.exports.createRDSInstance = async (
53
55
  securityGroupId,
54
56
  subnetGroupName,
55
57
  ) => {
56
- const client = new RDSClient({});
57
-
58
58
  let res = await Spinner.prototype.simple(
59
59
  `Creating RDS instance ${name}`,
60
60
  () => {
61
- return client.send(
61
+ return getClient().send(
62
62
  new CreateDBInstanceCommand({
63
63
  DBInstanceIdentifier: name,
64
64
  DBInstanceClass: "db.t3.small",
@@ -86,21 +86,21 @@ module.exports.createRDSInstance = async (
86
86
  };
87
87
 
88
88
  module.exports.waitForRDSInstance = async (name) => {
89
- const client = new RDSClient({});
90
-
91
89
  const res = await Spinner.prototype.simple(
92
90
  `Waiting for RDS instance to become available`,
93
- () => {
91
+ (spinner) => {
94
92
  return poll(
95
93
  async () =>
96
94
  (
97
- await client.send(
95
+ await getClient().send(
98
96
  new DescribeDBInstancesCommand({
99
97
  DBInstanceIdentifier: name,
100
98
  }),
101
99
  )
102
100
  ).DBInstances[0],
103
101
  ({ DBInstanceStatus }) => DBInstanceStatus !== "available",
102
+ undefined,
103
+ spinner,
104
104
  );
105
105
  },
106
106
  );
@@ -109,12 +109,10 @@ module.exports.waitForRDSInstance = async (name) => {
109
109
  };
110
110
 
111
111
  module.exports.describeRDSInstance = async (name) => {
112
- const client = new RDSClient({});
113
-
114
112
  let res = await Spinner.prototype.simple(
115
113
  `Describing RDS instance ${name}`,
116
114
  () => {
117
- return client.send(
115
+ return getClient().send(
118
116
  new DescribeDBInstancesCommand({
119
117
  DBInstanceIdentifier: name,
120
118
  }),
@@ -126,10 +124,8 @@ module.exports.describeRDSInstance = async (name) => {
126
124
  };
127
125
 
128
126
  module.exports.deleteRDSInstance = async (name) => {
129
- const client = new RDSClient({});
130
-
131
127
  await Spinner.prototype.simple(`Deleting RDS instance ${name}`, () => {
132
- return client.send(
128
+ return getClient().send(
133
129
  new DeleteDBInstanceCommand({
134
130
  DBInstanceIdentifier: name,
135
131
  SkipFinalSnapshot: true,
@@ -139,15 +135,13 @@ module.exports.deleteRDSInstance = async (name) => {
139
135
  };
140
136
 
141
137
  module.exports.waitForRDSDeletion = async (name) => {
142
- const client = new RDSClient({});
143
-
144
138
  await Spinner.prototype.simple(
145
139
  `Waiting for RDS instance to be deleted`,
146
- () => {
140
+ (spinner) => {
147
141
  return poll(
148
142
  async () => {
149
143
  try {
150
- const res = await client.send(
144
+ const res = await getClient().send(
151
145
  new DescribeDBInstancesCommand({
152
146
  DBInstanceIdentifier: name,
153
147
  }),
@@ -161,18 +155,18 @@ module.exports.waitForRDSDeletion = async (name) => {
161
155
  }
162
156
  },
163
157
  ({ DBInstanceStatus }) => DBInstanceStatus !== "deleted",
158
+ undefined,
159
+ spinner,
164
160
  );
165
161
  },
166
162
  );
167
163
  };
168
164
 
169
165
  module.exports.listManualSnapshots = async () => {
170
- const client = new RDSClient({});
171
-
172
166
  const res = await Spinner.prototype.simple(
173
167
  `Fetching manual RDS snapshots`,
174
168
  () => {
175
- return client.send(
169
+ return getClient().send(
176
170
  new DescribeDBSnapshotsCommand({
177
171
  SnapshotType: "manual",
178
172
  }),
@@ -195,12 +189,10 @@ module.exports.restoreRDSInstanceFromSnapshot = async (
195
189
  tags = [],
196
190
  subnetGroupName,
197
191
  ) => {
198
- const client = new RDSClient({});
199
-
200
192
  let res = await Spinner.prototype.simple(
201
193
  `Restoring RDS instance ${name} from snapshot ${snapshotId}`,
202
194
  () => {
203
- return client.send(
195
+ return getClient().send(
204
196
  new RestoreDBInstanceFromDBSnapshotCommand({
205
197
  DBInstanceIdentifier: name,
206
198
  DBSnapshotIdentifier: snapshotId,
@@ -221,12 +213,10 @@ module.exports.restoreRDSInstanceFromSnapshot = async (
221
213
  };
222
214
 
223
215
  module.exports.modifyRDSPassword = async (name, password) => {
224
- const client = new RDSClient({});
225
-
226
216
  await Spinner.prototype.simple(
227
217
  `Updating master password for RDS instance ${name}`,
228
218
  () => {
229
- return client.send(
219
+ return getClient().send(
230
220
  new ModifyDBInstanceCommand({
231
221
  DBInstanceIdentifier: name,
232
222
  MasterUserPassword: password,
@@ -240,10 +230,8 @@ module.exports.modifyRDSPassword = async (name, password) => {
240
230
  const SSL_PARAMETER_GROUP = "lab-env-mysql80-ssl-required";
241
231
 
242
232
  module.exports.ensureSSLParameterGroup = async () => {
243
- const client = new RDSClient({});
244
-
245
233
  try {
246
- await client.send(
234
+ await getClient().send(
247
235
  new DescribeDBParameterGroupsCommand({
248
236
  DBParameterGroupName: SSL_PARAMETER_GROUP,
249
237
  }),
@@ -252,7 +240,7 @@ module.exports.ensureSSLParameterGroup = async () => {
252
240
  await Spinner.prototype.simple(
253
241
  `Creating parameter group ${SSL_PARAMETER_GROUP}`,
254
242
  () => {
255
- return client.send(
243
+ return getClient().send(
256
244
  new CreateDBParameterGroupCommand({
257
245
  DBParameterGroupName: SSL_PARAMETER_GROUP,
258
246
  DBParameterGroupFamily: "mysql8.0",
@@ -266,7 +254,7 @@ module.exports.ensureSSLParameterGroup = async () => {
266
254
  await Spinner.prototype.simple(
267
255
  `Enabling require_secure_transport on ${SSL_PARAMETER_GROUP}`,
268
256
  () => {
269
- return client.send(
257
+ return getClient().send(
270
258
  new ModifyDBParameterGroupCommand({
271
259
  DBParameterGroupName: SSL_PARAMETER_GROUP,
272
260
  Parameters: [
@@ -12,6 +12,9 @@ const {
12
12
  DeleteObjectsCommand,
13
13
  } = require("@aws-sdk/client-s3");
14
14
  const { Spinner } = require("../../libs/utilities");
15
+ const { awsClientConfig } = require("../../libs/vars");
16
+
17
+ const getClient = () => new S3Client(awsClientConfig);
15
18
 
16
19
  module.exports.createS3Bucket = async (
17
20
  bucket,
@@ -19,12 +22,10 @@ module.exports.createS3Bucket = async (
19
22
  blockAccess = true,
20
23
  ObjectOwnership = "BucketOwnerEnforced",
21
24
  ) => {
22
- const client = new S3Client({});
23
-
24
25
  let res = await Spinner.prototype.simple(
25
26
  `Creating s3 bucket ${bucket}`,
26
27
  () => {
27
- return client.send(
28
+ return getClient().send(
28
29
  new CreateBucketCommand({ Bucket: bucket, ObjectOwnership }),
29
30
  );
30
31
  },
@@ -43,7 +44,7 @@ module.exports.createS3Bucket = async (
43
44
  await Spinner.prototype.simple(
44
45
  `Configuring public access settings for s3 bucket`,
45
46
  () => {
46
- return client.send(
47
+ return getClient().send(
47
48
  new PutPublicAccessBlockCommand({
48
49
  Bucket: bucket,
49
50
  PublicAccessBlockConfiguration: publicAccessConfig,
@@ -53,7 +54,7 @@ module.exports.createS3Bucket = async (
53
54
  );
54
55
 
55
56
  await Spinner.prototype.simple(`Adding tags to s3 bucket`, () => {
56
- return client.send(
57
+ return getClient().send(
57
58
  new PutBucketTaggingCommand({
58
59
  Bucket: bucket,
59
60
  Tagging: {
@@ -69,30 +70,24 @@ module.exports.createS3Bucket = async (
69
70
  };
70
71
 
71
72
  module.exports.listS3Buckets = async () => {
72
- const client = new S3Client({});
73
-
74
73
  let res = await Spinner.prototype.simple(`Listing s3 buckets`, () => {
75
- return client.send(new ListBucketsCommand({}));
74
+ return getClient().send(new ListBucketsCommand({}));
76
75
  });
77
76
 
78
77
  return res;
79
78
  };
80
79
 
81
80
  module.exports.removeS3Bucket = async (bucket) => {
82
- const client = new S3Client({});
83
-
84
81
  await Spinner.prototype.simple(`Removing s3 bucket ${bucket}`, () => {
85
- return client.send(new DeleteBucketCommand({ Bucket: bucket }));
82
+ return getClient().send(new DeleteBucketCommand({ Bucket: bucket }));
86
83
  });
87
84
  };
88
85
 
89
86
  module.exports.setS3BucketPolicy = async (bucket, OAI) => {
90
- const client = new S3Client({});
91
-
92
87
  let res = await Spinner.prototype.simple(
93
88
  `Updating s3 bucket policy`,
94
89
  () => {
95
- return client.send(
90
+ return getClient().send(
96
91
  new PutBucketPolicyCommand({
97
92
  Bucket: bucket,
98
93
  Policy: JSON.stringify({
@@ -122,12 +117,10 @@ module.exports.setS3BucketPolicy = async (bucket, OAI) => {
122
117
  };
123
118
 
124
119
  module.exports.setPublicReadPolicy = async (bucket, prefix) => {
125
- const client = new S3Client({});
126
-
127
120
  let res = await Spinner.prototype.simple(
128
121
  `Setting public read policy for ${prefix}`,
129
122
  () => {
130
- return client.send(
123
+ return getClient().send(
131
124
  new PutBucketPolicyCommand({
132
125
  Bucket: bucket,
133
126
  Policy: JSON.stringify({
@@ -151,10 +144,8 @@ module.exports.setPublicReadPolicy = async (bucket, prefix) => {
151
144
  };
152
145
 
153
146
  module.exports.addFileToS3Bucket = async (bucket, filepath, file) => {
154
- const client = new S3Client({});
155
-
156
147
  let res = await Spinner.prototype.simple(`Adding file to s3 bucket`, () => {
157
- return client.send(
148
+ return getClient().send(
158
149
  new PutObjectCommand({
159
150
  Bucket: bucket,
160
151
  Body: file,
@@ -167,12 +158,10 @@ module.exports.addFileToS3Bucket = async (bucket, filepath, file) => {
167
158
  };
168
159
 
169
160
  module.exports.removeFileToS3Bucket = async (bucket, filepath) => {
170
- const client = new S3Client({});
171
-
172
161
  let res = await Spinner.prototype.simple(
173
162
  `Removing file from s3 bucket`,
174
163
  () => {
175
- return client.send(
164
+ return getClient().send(
176
165
  new DeleteObjectCommand({
177
166
  Bucket: bucket,
178
167
  Key: filepath,
@@ -185,8 +174,6 @@ module.exports.removeFileToS3Bucket = async (bucket, filepath) => {
185
174
  };
186
175
 
187
176
  module.exports.emptyS3Bucket = async (bucket) => {
188
- const client = new S3Client({});
189
-
190
177
  await Spinner.prototype.simple(`Emptying s3 bucket`, () => {
191
178
  // eslint-disable-next-line no-async-promise-executor
192
179
  return new Promise(async (resolve, reject) => {
@@ -194,7 +181,7 @@ module.exports.emptyS3Bucket = async (bucket) => {
194
181
  let ContinuationToken = null;
195
182
 
196
183
  do {
197
- let list = await client.send(
184
+ let list = await getClient().send(
198
185
  new ListObjectsV2Command({
199
186
  Bucket: bucket,
200
187
  ContinuationToken,
@@ -202,7 +189,7 @@ module.exports.emptyS3Bucket = async (bucket) => {
202
189
  );
203
190
 
204
191
  if (list.KeyCount) {
205
- let deleted = await client.send(
192
+ let deleted = await getClient().send(
206
193
  new DeleteObjectsCommand({
207
194
  Bucket: bucket,
208
195
  Delete: {
@@ -7,12 +7,13 @@ const {
7
7
  DeleteSecretCommand,
8
8
  } = require("@aws-sdk/client-secrets-manager");
9
9
  const { Spinner } = require("../../libs/utilities");
10
+ const { awsClientConfig } = require("../../libs/vars");
10
11
 
11
- module.exports.createSecret = async (name, secretObject, tags = []) => {
12
- const client = new SecretsManagerClient({});
12
+ const getClient = () => new SecretsManagerClient(awsClientConfig);
13
13
 
14
+ module.exports.createSecret = async (name, secretObject, tags = []) => {
14
15
  let res = await Spinner.prototype.simple(`Creating secret ${name}`, () => {
15
- return client.send(
16
+ return getClient().send(
16
17
  new CreateSecretCommand({
17
18
  Name: name,
18
19
  SecretString: JSON.stringify(secretObject),
@@ -25,12 +26,10 @@ module.exports.createSecret = async (name, secretObject, tags = []) => {
25
26
  };
26
27
 
27
28
  module.exports.describeSecret = async (name) => {
28
- const client = new SecretsManagerClient({});
29
-
30
29
  let res = await Spinner.prototype.simple(
31
30
  `Checking for existing secret ${name}`,
32
31
  () => {
33
- return client.send(
32
+ return getClient().send(
34
33
  new DescribeSecretCommand({
35
34
  SecretId: name,
36
35
  }),
@@ -42,12 +41,10 @@ module.exports.describeSecret = async (name) => {
42
41
  };
43
42
 
44
43
  module.exports.getSecretValue = async (name) => {
45
- const client = new SecretsManagerClient({});
46
-
47
44
  let res = await Spinner.prototype.simple(
48
45
  `Retrieving secret ${name}`,
49
46
  () => {
50
- return client.send(
47
+ return getClient().send(
51
48
  new GetSecretValueCommand({
52
49
  SecretId: name,
53
50
  }),
@@ -59,10 +56,8 @@ module.exports.getSecretValue = async (name) => {
59
56
  };
60
57
 
61
58
  module.exports.updateSecretValue = async (name, secretObject) => {
62
- const client = new SecretsManagerClient({});
63
-
64
59
  let res = await Spinner.prototype.simple(`Updating secret ${name}`, () => {
65
- return client.send(
60
+ return getClient().send(
66
61
  new PutSecretValueCommand({
67
62
  SecretId: name,
68
63
  SecretString: JSON.stringify(secretObject),
@@ -74,10 +69,8 @@ module.exports.updateSecretValue = async (name, secretObject) => {
74
69
  };
75
70
 
76
71
  module.exports.deleteSecret = async (name) => {
77
- const client = new SecretsManagerClient({});
78
-
79
72
  let res = await Spinner.prototype.simple(`Deleting secret ${name}`, () => {
80
- return client.send(
73
+ return getClient().send(
81
74
  new DeleteSecretCommand({
82
75
  SecretId: name,
83
76
  ForceDeleteWithoutRecovery: true,