@fishawack/lab-env 5.7.0-beta.1 → 5.7.0-beta.2
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 +16 -0
- package/_Test/provision.js +3 -1
- package/commands/create/cmds/deprovision.js +7 -0
- package/commands/create/cmds/provision.js +182 -48
- package/commands/create/cmds/sync-secrets.js +2 -1
- package/commands/create/libs/utilities.js +2 -0
- package/commands/create/libs/vars.js +53 -53
- package/commands/create/services/aws/acm.js +59 -0
- package/commands/create/services/aws/ec2.js +576 -28
- package/commands/create/services/aws/elasticbeanstalk.js +16 -0
- package/commands/create/services/aws/iam.js +254 -0
- package/commands/create/services/aws/index.js +462 -67
- package/commands/create/services/aws/opensearch.js +147 -0
- package/commands/create/services/aws/rds.js +38 -0
- package/commands/create/services/aws/s3.js +41 -7
- package/commands/create/services/aws/secretsmanager.js +16 -0
- package/package.json +3 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const {
|
|
2
|
+
OpenSearchClient,
|
|
3
|
+
CreateDomainCommand,
|
|
4
|
+
DeleteDomainCommand,
|
|
5
|
+
DescribeDomainCommand,
|
|
6
|
+
} = require("@aws-sdk/client-opensearch");
|
|
7
|
+
const { Spinner, poll } = require("../../libs/utilities");
|
|
8
|
+
|
|
9
|
+
module.exports.createOpenSearchDomain = async (
|
|
10
|
+
name,
|
|
11
|
+
securityGroupId,
|
|
12
|
+
privateSubnetIds,
|
|
13
|
+
instanceProfileRole,
|
|
14
|
+
) => {
|
|
15
|
+
const client = new OpenSearchClient({});
|
|
16
|
+
|
|
17
|
+
const accountId = instanceProfileRole.split(":")[4] || "*";
|
|
18
|
+
const region = process.env.AWS_REGION;
|
|
19
|
+
|
|
20
|
+
const res = await Spinner.prototype.simple(
|
|
21
|
+
`Creating OpenSearch domain ${name}`,
|
|
22
|
+
() => {
|
|
23
|
+
return client.send(
|
|
24
|
+
new CreateDomainCommand({
|
|
25
|
+
DomainName: name,
|
|
26
|
+
EngineVersion: "OpenSearch_2.19",
|
|
27
|
+
ClusterConfig: {
|
|
28
|
+
InstanceType: "t3.small.search",
|
|
29
|
+
InstanceCount: 2,
|
|
30
|
+
ZoneAwarenessEnabled: true,
|
|
31
|
+
ZoneAwarenessConfig: {
|
|
32
|
+
AvailabilityZoneCount: 2,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
EBSOptions: {
|
|
36
|
+
EBSEnabled: true,
|
|
37
|
+
VolumeType: "gp3",
|
|
38
|
+
VolumeSize: 20,
|
|
39
|
+
},
|
|
40
|
+
VPCOptions: {
|
|
41
|
+
SubnetIds: privateSubnetIds,
|
|
42
|
+
SecurityGroupIds: [securityGroupId],
|
|
43
|
+
},
|
|
44
|
+
EncryptionAtRestOptions: {
|
|
45
|
+
Enabled: true,
|
|
46
|
+
},
|
|
47
|
+
NodeToNodeEncryptionOptions: {
|
|
48
|
+
Enabled: true,
|
|
49
|
+
},
|
|
50
|
+
DomainEndpointOptions: {
|
|
51
|
+
EnforceHTTPS: true,
|
|
52
|
+
TLSSecurityPolicy: "Policy-Min-TLS-1-2-2019-07",
|
|
53
|
+
},
|
|
54
|
+
AdvancedSecurityOptions: {
|
|
55
|
+
Enabled: false,
|
|
56
|
+
InternalUserDatabaseEnabled: false,
|
|
57
|
+
},
|
|
58
|
+
AccessPolicies: JSON.stringify({
|
|
59
|
+
Version: "2012-10-17",
|
|
60
|
+
Statement: [
|
|
61
|
+
{
|
|
62
|
+
Effect: "Allow",
|
|
63
|
+
Principal: {
|
|
64
|
+
AWS: instanceProfileRole,
|
|
65
|
+
},
|
|
66
|
+
Action: "es:ESHttp*",
|
|
67
|
+
Resource: `arn:aws:es:${region}:${accountId}:domain/${name}/*`,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
}),
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return res;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
module.exports.waitForOpenSearchDomain = async (name) => {
|
|
80
|
+
const client = new OpenSearchClient({});
|
|
81
|
+
|
|
82
|
+
const res = await Spinner.prototype.simple(
|
|
83
|
+
`Waiting for OpenSearch domain to become available (this may take 15-20 minutes)`,
|
|
84
|
+
() => {
|
|
85
|
+
return poll(
|
|
86
|
+
async () => {
|
|
87
|
+
const { DomainStatus } = await client.send(
|
|
88
|
+
new DescribeDomainCommand({ DomainName: name }),
|
|
89
|
+
);
|
|
90
|
+
return DomainStatus;
|
|
91
|
+
},
|
|
92
|
+
(status) =>
|
|
93
|
+
status.Processing ||
|
|
94
|
+
(!status.Endpoint && !status.Endpoints),
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return res;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
module.exports.describeOpenSearchDomain = async (name) => {
|
|
103
|
+
const client = new OpenSearchClient({});
|
|
104
|
+
|
|
105
|
+
const res = await Spinner.prototype.simple(
|
|
106
|
+
`Describing OpenSearch domain ${name}`,
|
|
107
|
+
() => {
|
|
108
|
+
return client.send(new DescribeDomainCommand({ DomainName: name }));
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
return res.DomainStatus;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
module.exports.deleteOpenSearchDomain = async (name) => {
|
|
116
|
+
const client = new OpenSearchClient({});
|
|
117
|
+
|
|
118
|
+
await Spinner.prototype.simple(`Deleting OpenSearch domain ${name}`, () => {
|
|
119
|
+
return client.send(new DeleteDomainCommand({ DomainName: name }));
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
module.exports.waitForOpenSearchDeletion = async (name) => {
|
|
124
|
+
const client = new OpenSearchClient({});
|
|
125
|
+
|
|
126
|
+
await Spinner.prototype.simple(
|
|
127
|
+
`Waiting for OpenSearch domain to be deleted`,
|
|
128
|
+
() => {
|
|
129
|
+
return poll(
|
|
130
|
+
async () => {
|
|
131
|
+
try {
|
|
132
|
+
const { DomainStatus } = await client.send(
|
|
133
|
+
new DescribeDomainCommand({ DomainName: name }),
|
|
134
|
+
);
|
|
135
|
+
return DomainStatus;
|
|
136
|
+
} catch (e) {
|
|
137
|
+
if (e.name === "ResourceNotFoundException") {
|
|
138
|
+
return { deleted: true };
|
|
139
|
+
}
|
|
140
|
+
throw e;
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
(status) => !status.deleted,
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const {
|
|
2
2
|
RDSClient,
|
|
3
3
|
CreateDBInstanceCommand,
|
|
4
|
+
CreateDBSubnetGroupCommand,
|
|
4
5
|
DeleteDBInstanceCommand,
|
|
5
6
|
DescribeDBInstancesCommand,
|
|
6
7
|
DescribeDBSnapshotsCommand,
|
|
8
|
+
DescribeDBSubnetGroupsCommand,
|
|
7
9
|
RestoreDBInstanceFromDBSnapshotCommand,
|
|
8
10
|
ModifyDBInstanceCommand,
|
|
9
11
|
DescribeDBParameterGroupsCommand,
|
|
@@ -12,11 +14,44 @@ const {
|
|
|
12
14
|
} = require("@aws-sdk/client-rds");
|
|
13
15
|
const { Spinner, poll } = require("../../libs/utilities");
|
|
14
16
|
|
|
17
|
+
module.exports.ensureDBSubnetGroup = async (privateSubnetIds) => {
|
|
18
|
+
const client = new RDSClient({});
|
|
19
|
+
const name = "fw-auto-private-db-subnet-group";
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await client.send(
|
|
23
|
+
new DescribeDBSubnetGroupsCommand({
|
|
24
|
+
DBSubnetGroupName: name,
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return name;
|
|
29
|
+
} catch (e) {
|
|
30
|
+
if (e.name !== "DBSubnetGroupNotFoundFault") {
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
await Spinner.prototype.simple(`Creating DB subnet group ${name}`, () => {
|
|
36
|
+
return client.send(
|
|
37
|
+
new CreateDBSubnetGroupCommand({
|
|
38
|
+
DBSubnetGroupName: name,
|
|
39
|
+
DBSubnetGroupDescription:
|
|
40
|
+
"Private subnets for lab-env RDS instances",
|
|
41
|
+
SubnetIds: privateSubnetIds,
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return name;
|
|
47
|
+
};
|
|
48
|
+
|
|
15
49
|
module.exports.createRDSInstance = async (
|
|
16
50
|
name,
|
|
17
51
|
tags = [],
|
|
18
52
|
password,
|
|
19
53
|
securityGroupId,
|
|
54
|
+
subnetGroupName,
|
|
20
55
|
) => {
|
|
21
56
|
const client = new RDSClient({});
|
|
22
57
|
|
|
@@ -37,6 +72,7 @@ module.exports.createRDSInstance = async (
|
|
|
37
72
|
BackupRetentionPeriod: 7,
|
|
38
73
|
DBName: "ebdb",
|
|
39
74
|
DBParameterGroupName: "lab-env-mysql80-ssl-required",
|
|
75
|
+
DBSubnetGroupName: subnetGroupName,
|
|
40
76
|
VpcSecurityGroupIds: [securityGroupId],
|
|
41
77
|
Tags: [
|
|
42
78
|
{ Key: "client", Value: process.env.AWS_PROFILE },
|
|
@@ -157,6 +193,7 @@ module.exports.restoreRDSInstanceFromSnapshot = async (
|
|
|
157
193
|
snapshotId,
|
|
158
194
|
securityGroupId,
|
|
159
195
|
tags = [],
|
|
196
|
+
subnetGroupName,
|
|
160
197
|
) => {
|
|
161
198
|
const client = new RDSClient({});
|
|
162
199
|
|
|
@@ -170,6 +207,7 @@ module.exports.restoreRDSInstanceFromSnapshot = async (
|
|
|
170
207
|
DBInstanceClass: "db.t3.small",
|
|
171
208
|
PubliclyAccessible: false,
|
|
172
209
|
DBParameterGroupName: "lab-env-mysql80-ssl-required",
|
|
210
|
+
DBSubnetGroupName: subnetGroupName,
|
|
173
211
|
VpcSecurityGroupIds: [securityGroupId],
|
|
174
212
|
Tags: [
|
|
175
213
|
{ Key: "client", Value: process.env.AWS_PROFILE },
|
|
@@ -30,18 +30,23 @@ module.exports.createS3Bucket = async (
|
|
|
30
30
|
},
|
|
31
31
|
);
|
|
32
32
|
|
|
33
|
+
const publicAccessConfig =
|
|
34
|
+
typeof blockAccess === "object"
|
|
35
|
+
? blockAccess
|
|
36
|
+
: {
|
|
37
|
+
BlockPublicAcls: blockAccess,
|
|
38
|
+
BlockPublicPolicy: blockAccess,
|
|
39
|
+
IgnorePublicAcls: blockAccess,
|
|
40
|
+
RestrictPublicBuckets: blockAccess,
|
|
41
|
+
};
|
|
42
|
+
|
|
33
43
|
await Spinner.prototype.simple(
|
|
34
|
-
|
|
44
|
+
`Configuring public access settings for s3 bucket`,
|
|
35
45
|
() => {
|
|
36
46
|
return client.send(
|
|
37
47
|
new PutPublicAccessBlockCommand({
|
|
38
48
|
Bucket: bucket,
|
|
39
|
-
PublicAccessBlockConfiguration:
|
|
40
|
-
BlockPublicAcls: blockAccess,
|
|
41
|
-
BlockPublicPolicy: blockAccess,
|
|
42
|
-
IgnorePublicAcls: blockAccess,
|
|
43
|
-
RestrictPublicBuckets: blockAccess,
|
|
44
|
-
},
|
|
49
|
+
PublicAccessBlockConfiguration: publicAccessConfig,
|
|
45
50
|
}),
|
|
46
51
|
);
|
|
47
52
|
},
|
|
@@ -116,6 +121,35 @@ module.exports.setS3BucketPolicy = async (bucket, OAI) => {
|
|
|
116
121
|
return res;
|
|
117
122
|
};
|
|
118
123
|
|
|
124
|
+
module.exports.setPublicReadPolicy = async (bucket, prefix) => {
|
|
125
|
+
const client = new S3Client({});
|
|
126
|
+
|
|
127
|
+
let res = await Spinner.prototype.simple(
|
|
128
|
+
`Setting public read policy for ${prefix}`,
|
|
129
|
+
() => {
|
|
130
|
+
return client.send(
|
|
131
|
+
new PutBucketPolicyCommand({
|
|
132
|
+
Bucket: bucket,
|
|
133
|
+
Policy: JSON.stringify({
|
|
134
|
+
Version: "2012-10-17",
|
|
135
|
+
Statement: [
|
|
136
|
+
{
|
|
137
|
+
Sid: "PublicReadPrefix",
|
|
138
|
+
Effect: "Allow",
|
|
139
|
+
Principal: "*",
|
|
140
|
+
Action: "s3:GetObject",
|
|
141
|
+
Resource: `arn:aws:s3:::${bucket}/${prefix}`,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
}),
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return res;
|
|
151
|
+
};
|
|
152
|
+
|
|
119
153
|
module.exports.addFileToS3Bucket = async (bucket, filepath, file) => {
|
|
120
154
|
const client = new S3Client({});
|
|
121
155
|
|
|
@@ -3,6 +3,7 @@ const {
|
|
|
3
3
|
CreateSecretCommand,
|
|
4
4
|
DescribeSecretCommand,
|
|
5
5
|
GetSecretValueCommand,
|
|
6
|
+
PutSecretValueCommand,
|
|
6
7
|
DeleteSecretCommand,
|
|
7
8
|
} = require("@aws-sdk/client-secrets-manager");
|
|
8
9
|
const { Spinner } = require("../../libs/utilities");
|
|
@@ -57,6 +58,21 @@ module.exports.getSecretValue = async (name) => {
|
|
|
57
58
|
return JSON.parse(res.SecretString);
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
module.exports.updateSecretValue = async (name, secretObject) => {
|
|
62
|
+
const client = new SecretsManagerClient({});
|
|
63
|
+
|
|
64
|
+
let res = await Spinner.prototype.simple(`Updating secret ${name}`, () => {
|
|
65
|
+
return client.send(
|
|
66
|
+
new PutSecretValueCommand({
|
|
67
|
+
SecretId: name,
|
|
68
|
+
SecretString: JSON.stringify(secretObject),
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return res;
|
|
74
|
+
};
|
|
75
|
+
|
|
60
76
|
module.exports.deleteSecret = async (name) => {
|
|
61
77
|
const client = new SecretsManagerClient({});
|
|
62
78
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fishawack/lab-env",
|
|
3
|
-
"version": "5.7.0-beta.
|
|
3
|
+
"version": "5.7.0-beta.2",
|
|
4
4
|
"description": "Docker manager for FW",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,10 +21,12 @@
|
|
|
21
21
|
"fw": "cli.js"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"@aws-sdk/client-acm": "^3.1067.0",
|
|
24
25
|
"@aws-sdk/client-cloudfront": "^3.141.0",
|
|
25
26
|
"@aws-sdk/client-ec2": "^3.399.0",
|
|
26
27
|
"@aws-sdk/client-elastic-beanstalk": "^3.395.0",
|
|
27
28
|
"@aws-sdk/client-iam": "^3.150.0",
|
|
29
|
+
"@aws-sdk/client-opensearch": "^3.1065.0",
|
|
28
30
|
"@aws-sdk/client-rds": "^3.395.0",
|
|
29
31
|
"@aws-sdk/client-s3": "^3.141.0",
|
|
30
32
|
"@aws-sdk/client-secrets-manager": "^3.395.0",
|