@studion/infra-code-blocks 0.0.7 → 0.0.9
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
CHANGED
|
@@ -131,6 +131,7 @@ export type WebServerService = {
|
|
|
131
131
|
environment?:
|
|
132
132
|
| aws.ecs.KeyValuePair[]
|
|
133
133
|
| ((services: Services) => aws.ecs.KeyValuePair[]);
|
|
134
|
+
secrets?: aws.ecs.Secret[];
|
|
134
135
|
image: pulumi.Input<string>;
|
|
135
136
|
port: pulumi.Input<number>;
|
|
136
137
|
domain: pulumi.Input<string>;
|
|
@@ -181,6 +182,27 @@ const project = new studion.Project('demo-project', {
|
|
|
181
182
|
});
|
|
182
183
|
```
|
|
183
184
|
|
|
185
|
+
In order to pass sensitive information to the container use `secrets` instead of `environment`. AWS will fetch values from
|
|
186
|
+
Secret Manager based on arn that is provided for the `valueFrom` field.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const project = new studion.Project('demo-project', {
|
|
190
|
+
environment: 'DEVELOPMENT',
|
|
191
|
+
services: [
|
|
192
|
+
{
|
|
193
|
+
type: 'WEB_SERVER',
|
|
194
|
+
serviceName: 'api',
|
|
195
|
+
image: imageUri,
|
|
196
|
+
port: 3000,
|
|
197
|
+
domain: 'api.my-domain.com',
|
|
198
|
+
secrets: [
|
|
199
|
+
{ name: 'DB_PASSWORD', valueFrom: 'arn-of-the-secret-manager-secret' },
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
184
206
|
### Database
|
|
185
207
|
|
|
186
208
|
AWS RDS Postgres instance.
|
|
@@ -331,6 +353,7 @@ export type WebServerArgs = {
|
|
|
331
353
|
maxCount?: pulumi.Input<number>;
|
|
332
354
|
size?: pulumi.Input<Size>;
|
|
333
355
|
environment?: aws.ecs.KeyValuePair[];
|
|
356
|
+
secrets?: aws.ecs.Secret[];
|
|
334
357
|
healtCheckPath?: pulumi.Input<string>;
|
|
335
358
|
taskExecutionRoleInlinePolicies?: pulumi.Input<
|
|
336
359
|
pulumi.Input<RoleInlinePolicy>[]
|
|
@@ -376,11 +399,12 @@ The [Database](#database) component deploys a database instance inside a private
|
|
|
376
399
|
and it's not publicly accessible from outside of VPC.
|
|
377
400
|
<br>
|
|
378
401
|
In order to connect to the database we need to deploy the ec2 instance which will be used
|
|
379
|
-
to
|
|
402
|
+
to forward traffic to the database instance.
|
|
380
403
|
<br>
|
|
381
|
-
Because of security reasons, ec2 instance is also deployed inside private subnet
|
|
404
|
+
Because of security reasons, the ec2 instance is also deployed inside a private subnet
|
|
382
405
|
which means we can't directly connect to it. For that purpose, we use AWS System Manager
|
|
383
|
-
which enables us to connect to the ec2 instance even though it's inside private subnet.
|
|
406
|
+
which enables us to connect to the ec2 instance even though it's inside a private subnet.
|
|
407
|
+
The benefit of using AWS SSM is that we don't need a ssh key pair.
|
|
384
408
|
|
|
385
409
|

|
|
386
410
|
|
|
@@ -392,18 +416,6 @@ which enables us to connect to the ec2 instance even though it's inside private
|
|
|
392
416
|
$ brew install --cask session-manager-plugin
|
|
393
417
|
```
|
|
394
418
|
|
|
395
|
-
2. Generate a new ssh key pair or use the existing one.
|
|
396
|
-
|
|
397
|
-
```bash
|
|
398
|
-
$ ssh-keygen -f my_rsa
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
3. Set stack config property by running:
|
|
402
|
-
|
|
403
|
-
```bash
|
|
404
|
-
$ pulumi config set ssh:publicKey "ssh-rsa Z...9= mymac@Studions-MBP.localdomain"
|
|
405
|
-
```
|
|
406
|
-
|
|
407
419
|
SSM Connect can be enabled by setting `enableSSMConnect` property to `true`.
|
|
408
420
|
|
|
409
421
|
```ts
|
|
@@ -418,20 +430,13 @@ export const ec2InstanceId = project.ec2SSMConnect?.ec2.id;
|
|
|
418
430
|
Open up your terminal and run the following command:
|
|
419
431
|
|
|
420
432
|
```bash
|
|
421
|
-
$ aws ssm start-session --target EC2_INSTANCE_ID --document-name AWS-
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
Where `EC2_INSTANCE_ID` is an ID of the EC2 instance that is created for you. ID can be
|
|
425
|
-
obtained by exporting it from the stack.
|
|
426
|
-
|
|
427
|
-
Next, open another terminal window and run the following command:
|
|
428
|
-
|
|
429
|
-
```bash
|
|
430
|
-
$ ssh ec2-user@localhost -p 9999 -N -L 5555:DATABASE_ADDRESS:DATABASE_PORT -i SSH_PRIVATE_KEY
|
|
433
|
+
$ aws ssm start-session --target EC2_INSTANCE_ID --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host": ["DATABASE_ADDRESS"], "portNumber":["DATABASE_PORT"], "localPortNumber":["5555"]}'
|
|
431
434
|
```
|
|
432
435
|
|
|
433
|
-
Where `
|
|
434
|
-
|
|
436
|
+
Where `EC2_INSTANCE_ID` is an ID of the EC2 instance that is created for you
|
|
437
|
+
(ID can be obtained by exporting it from the stack), and
|
|
438
|
+
`DATABASE_ADDRESS` and `DATABASE_PORT` are the address and port of the
|
|
439
|
+
database instance.
|
|
435
440
|
|
|
436
441
|
And that is it! 🥳
|
|
437
442
|
Now you can use your favorite database client to connect to the database.
|
|
@@ -439,9 +444,9 @@ Now you can use your favorite database client to connect to the database.
|
|
|
439
444
|

|
|
440
445
|
|
|
441
446
|
It is important that for the host you set `localhost` and for the port you set `5555`
|
|
442
|
-
because we
|
|
443
|
-
DATABASE_ADDRESS:DATABASE_PORT.
|
|
444
|
-
which are set in the `Project`.
|
|
447
|
+
because we are port forwarding traffic from
|
|
448
|
+
localhost:5555 to DATABASE_ADDRESS:DATABASE_PORT.
|
|
449
|
+
For the user, password, and database field, set values which are set in the `Project`.
|
|
445
450
|
|
|
446
451
|
```ts
|
|
447
452
|
const project = new studion.Project('demo-project', {
|
|
@@ -462,3 +467,4 @@ const project = new studion.Project('demo-project', {
|
|
|
462
467
|
|
|
463
468
|
- [ ] Add worker service for executing tasks
|
|
464
469
|
- [ ] Add MongoDB service
|
|
470
|
+
- [ ] Make db username & password fields optional and autogenerate db username & password if they are not provided
|
|
@@ -3,7 +3,6 @@ import * as aws from '@pulumi/aws';
|
|
|
3
3
|
import * as awsx from '@pulumi/awsx';
|
|
4
4
|
export type Ec2SSMConnectArgs = {
|
|
5
5
|
vpc: awsx.ec2.Vpc;
|
|
6
|
-
sshPublicKey: pulumi.Input<string>;
|
|
7
6
|
tags?: pulumi.Input<{
|
|
8
7
|
[key: string]: pulumi.Input<string>;
|
|
9
8
|
}>;
|
|
@@ -14,6 +13,5 @@ export declare class Ec2SSMConnect extends pulumi.ComponentResource {
|
|
|
14
13
|
ec2MessagesVpcEndpoint: aws.ec2.VpcEndpoint;
|
|
15
14
|
ssmMessagesVpcEndpoint: aws.ec2.VpcEndpoint;
|
|
16
15
|
ec2: aws.ec2.Instance;
|
|
17
|
-
sshKeyPair: aws.ec2.KeyPair;
|
|
18
16
|
constructor(name: string, args: Ec2SSMConnectArgs, opts?: pulumi.ComponentResourceOptions);
|
|
19
17
|
}
|
|
@@ -56,14 +56,10 @@ class Ec2SSMConnect extends pulumi.ComponentResource {
|
|
|
56
56
|
const ssmProfile = new aws.iam.InstanceProfile(`${name}-ssm-profile`, {
|
|
57
57
|
role: role.name,
|
|
58
58
|
}, { parent: this, dependsOn: [ssmPolicyAttachment] });
|
|
59
|
-
this.sshKeyPair = new aws.ec2.KeyPair(`${name}-ec2-keypair`, {
|
|
60
|
-
publicKey: args.sshPublicKey,
|
|
61
|
-
}, { parent: this });
|
|
62
59
|
this.ec2 = new aws.ec2.Instance(`${name}-ec2`, {
|
|
63
60
|
ami: 'ami-067d1e60475437da2',
|
|
64
61
|
associatePublicIpAddress: false,
|
|
65
62
|
instanceType: 't2.micro',
|
|
66
|
-
keyName: this.sshKeyPair.keyName,
|
|
67
63
|
iamInstanceProfile: ssmProfile.name,
|
|
68
64
|
subnetId,
|
|
69
65
|
vpcSecurityGroupIds: [this.ec2SecurityGroup.id],
|
|
@@ -39,10 +39,8 @@ class Project extends pulumi.ComponentResource {
|
|
|
39
39
|
this.vpc = this.createVpc();
|
|
40
40
|
this.createServices(services);
|
|
41
41
|
if (args.enableSSMConnect) {
|
|
42
|
-
const sshConfig = new pulumi.Config('ssh');
|
|
43
42
|
this.ec2SSMConnect = new ec2_ssm_connect_1.Ec2SSMConnect(`${name}-ssm-connect`, {
|
|
44
43
|
vpc: this.vpc,
|
|
45
|
-
sshPublicKey: sshConfig.require('publicKey'),
|
|
46
44
|
});
|
|
47
45
|
}
|
|
48
46
|
this.registerOutputs();
|
|
@@ -61,9 +61,16 @@ export type WebServerArgs = {
|
|
|
61
61
|
*/
|
|
62
62
|
size?: pulumi.Input<Size>;
|
|
63
63
|
/**
|
|
64
|
-
* The environment variables to pass to a container.
|
|
64
|
+
* The environment variables to pass to a container. Don't use this field for
|
|
65
|
+
* sensitive information such as passwords, API keys, etc. For that purpose,
|
|
66
|
+
* please use the `secrets` property.
|
|
67
|
+
* Defaults to [].
|
|
65
68
|
*/
|
|
66
69
|
environment?: aws.ecs.KeyValuePair[];
|
|
70
|
+
/**
|
|
71
|
+
* The secrets to pass to the container. Defaults to [].
|
|
72
|
+
*/
|
|
73
|
+
secrets?: aws.ecs.Secret[];
|
|
67
74
|
/**
|
|
68
75
|
* Path for the health check request. Defaults to "/healtcheck".
|
|
69
76
|
*/
|
|
@@ -26,6 +26,7 @@ const defaults = {
|
|
|
26
26
|
maxCount: 10,
|
|
27
27
|
size: 'small',
|
|
28
28
|
environment: [],
|
|
29
|
+
secrets: [],
|
|
29
30
|
healtCheckPath: '/healtcheck',
|
|
30
31
|
taskExecutionRoleInlinePolicies: [],
|
|
31
32
|
taskRoleInlinePolicies: [],
|
|
@@ -128,6 +129,20 @@ class WebServer extends pulumi.ComponentResource {
|
|
|
128
129
|
},
|
|
129
130
|
],
|
|
130
131
|
}, { parent: this });
|
|
132
|
+
const secretManagerSecretsInlinePolicy = {
|
|
133
|
+
name: `${name}-secret-manager-access`,
|
|
134
|
+
policy: JSON.stringify({
|
|
135
|
+
Version: '2012-10-17',
|
|
136
|
+
Statement: [
|
|
137
|
+
{
|
|
138
|
+
Sid: 'AllowContainerToGetSecretManagerSecrets',
|
|
139
|
+
Effect: 'Allow',
|
|
140
|
+
Action: ['secretsmanager:GetSecretValue'],
|
|
141
|
+
Resource: '*',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
131
146
|
const taskExecutionRole = new aws.iam.Role(`${name}-ecs-task-exec-role`, {
|
|
132
147
|
name: `${name}-ecs-task-exec-role`,
|
|
133
148
|
assumeRolePolicy,
|
|
@@ -135,7 +150,10 @@ class WebServer extends pulumi.ComponentResource {
|
|
|
135
150
|
'arn:aws:iam::aws:policy/CloudWatchFullAccess',
|
|
136
151
|
'arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess',
|
|
137
152
|
],
|
|
138
|
-
inlinePolicies:
|
|
153
|
+
inlinePolicies: [
|
|
154
|
+
secretManagerSecretsInlinePolicy,
|
|
155
|
+
...argsWithDefaults.taskExecutionRoleInlinePolicies,
|
|
156
|
+
],
|
|
139
157
|
}, { parent: this });
|
|
140
158
|
const execCmdInlinePolicy = {
|
|
141
159
|
name: `${name}-ecs-exec`,
|
|
@@ -191,10 +209,11 @@ class WebServer extends pulumi.ComponentResource {
|
|
|
191
209
|
argsWithDefaults.image,
|
|
192
210
|
argsWithDefaults.port,
|
|
193
211
|
argsWithDefaults.environment,
|
|
212
|
+
argsWithDefaults.secrets,
|
|
194
213
|
this.logGroup.name,
|
|
195
214
|
awsRegion,
|
|
196
215
|
])
|
|
197
|
-
.apply(([containerName, image, port, environment, logGroup, region]) => {
|
|
216
|
+
.apply(([containerName, image, port, environment, secrets, logGroup, region,]) => {
|
|
198
217
|
return JSON.stringify([
|
|
199
218
|
{
|
|
200
219
|
readonlyRootFilesystem: false,
|
|
@@ -216,6 +235,7 @@ class WebServer extends pulumi.ComponentResource {
|
|
|
216
235
|
},
|
|
217
236
|
},
|
|
218
237
|
environment,
|
|
238
|
+
secrets,
|
|
219
239
|
},
|
|
220
240
|
]);
|
|
221
241
|
}),
|