Skip to content

Commit 9b055a7

Browse files
authored
port from zero-deployable-backend-sevice and make enhancement (#153)
* port from zero-deployable-backend-sevice and make enhancement * fixed the run order * fixed interpolation-only expressions
1 parent 0ddb1e7 commit 9b055a7

8 files changed

Lines changed: 290 additions & 5 deletions

File tree

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ SHELL := /bin/bash
22

33
run:
44
cd $(PROJECT_DIR) && AUTO_APPROVE="-auto-approve" make
5+
kubectl -n ${PROJECT_NAME} get secrets ${PROJECT_NAME} > /dev/null 2>&1 || ( \
6+
export REGION=${region}; \
7+
export SEED=${randomSeed}; \
8+
export PROJECT_NAME=${PROJECT_NAME}; \
9+
export ENVIRONMENT=${ENVIRONMENT}; \
10+
export DATABASE=${database}; \
11+
sh ./db-ops/create-db-user.sh )
512

613
summary:
714
@echo "zero-aws-eks-stack:"

db-ops/create-db-user.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/sh
2+
3+
usage () {
4+
echo "Usage:"
5+
echo "$0"
6+
exit 1
7+
}
8+
9+
# check parameters
10+
([[ -z "${REGION}" ]] || \
11+
[[ -z "${SEED}" ]] || \
12+
[[ -z "${PROJECT_NAME}" ]] || \
13+
[[ -z "${ENVIRONMENT}" ]] || \
14+
[[ -z "${DATABASE}" ]] ) && \
15+
echo "Environment variables (REGION/REGION/PROJECT_NAME/ENVIRONMENT/DATABASE) are not set properly. Please have a check." && usage
16+
17+
# docker image with postgres.mysql client
18+
DOCKER_IMAGE_TAG=commitdev/zero-k8s-utilities:0.0.3
19+
20+
# database info preparation
21+
DB_ENDPOINT=database.$PROJECT_NAME
22+
DB_NAME=$(aws rds describe-db-instances --region=$REGION --query "DBInstances[?DBInstanceIdentifier=='$PROJECT_NAME-$ENVIRONMENT'].DBName" | jq -r '.[0]')
23+
## get rds master
24+
SECRET_ID=$(aws secretsmanager list-secrets --region $REGION --query "SecretList[?Name=='$PROJECT_NAME-$ENVIRONMENT-rds-$SEED'].Name" | jq -r ".[0]")
25+
MASTER_RDS_USERNAME=master_user
26+
MASTER_RDS_PASSWORD=$(aws secretsmanager get-secret-value --region=$REGION --secret-id=$SECRET_ID | jq -r ".SecretString")
27+
## get application user/pass
28+
DB_APP_USERNAME=$PROJECT_NAME
29+
DB_APP_PASSWORD=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | base64 | head -c 16)
30+
31+
# fill in env-vars to db user creation manifest
32+
JOB_ID=$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 8)
33+
eval "echo \"$(cat ./db-ops/job-create-db-$DATABASE.yml.tpl)\"" > ./k8s-job-create-db.yml
34+
# the manifest creates 4 things
35+
# 1. Namespace: db-ops
36+
# 2. Secret in db-ops: db-create-users (with master password, and a .sql file
37+
# 3. Job in db-ops: db-create-users (runs the .sql file against the RDS given master_password from env)
38+
# 4. Secret in Application namespace with DB_USERNAME / DB_PASSWORD
39+
40+
# execution
41+
kubectl apply -f ./k8s-job-create-db.yml
42+
rm -f ./k8s-job-create-db.yml
43+
44+
# clean up
45+
## Deleting the entire db-ops namespace, leaving ONLY application-namespace's secret behind
46+
kubectl -n db-ops wait --for=condition=complete --timeout=10s job db-create-users-${JOB_ID}
47+
if [ $? -eq 0 ]
48+
then
49+
kubectl delete namespace db-ops
50+
else
51+
echo "Failed to create application database user, please see 'kubectl logs -n db-ops -l job-name=db-create-users-${JOB_ID}'"
52+
fi

db-ops/job-create-db-mysql.yml.tpl

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: db-ops
5+
---
6+
apiVersion: v1
7+
kind: Secret
8+
metadata:
9+
name: db-create-users
10+
namespace: db-ops
11+
type: Opaque
12+
stringData:
13+
create-user.sql: |
14+
DROP USER '$DB_APP_USERNAME';
15+
CREATE USER '$DB_APP_USERNAME' IDENTIFIED BY '$DB_APP_PASSWORD';
16+
GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_APP_USERNAME';
17+
RDS_MASTER_PASSWORD: $MASTER_RDS_PASSWORD
18+
---
19+
apiVersion: v1
20+
kind: Namespace
21+
metadata:
22+
name: $PROJECT_NAME
23+
---
24+
apiVersion: v1
25+
kind: Secret
26+
metadata:
27+
name: $PROJECT_NAME
28+
namespace: $PROJECT_NAME
29+
type: Opaque
30+
stringData:
31+
DATABASE_USERNAME: $DB_APP_USERNAME
32+
DATABASE_PASSWORD: $DB_APP_PASSWORD
33+
---
34+
apiVersion: batch/v1
35+
kind: Job
36+
metadata:
37+
name: db-create-users-$JOB_ID
38+
namespace: db-ops
39+
spec:
40+
template:
41+
spec:
42+
containers:
43+
- name: create-rds-user
44+
image: $DOCKER_IMAGE_TAG
45+
command:
46+
- sh
47+
args:
48+
- '-c'
49+
- mysql -u$MASTER_RDS_USERNAME -h $DB_ENDPOINT $DB_NAME < /db-ops/create-user.sql
50+
env:
51+
- name: DB_ENDPOINT
52+
value: $DB_ENDPOINT
53+
- name: DB_NAME
54+
value: $DB_NAME
55+
- name: MYSQL_PWD
56+
valueFrom:
57+
secretKeyRef:
58+
name: db-create-users
59+
key: RDS_MASTER_PASSWORD
60+
volumeMounts:
61+
- mountPath: /db-ops/create-user.sql
62+
name: db-create-users
63+
subPath: create-user.sql
64+
volumes:
65+
- name: db-create-users
66+
secret:
67+
secretName: db-create-users
68+
restartPolicy: Never
69+
backoffLimit: 1
70+
---
71+
apiVersion: apps/v1
72+
kind: Deployment
73+
metadata:
74+
name: db-pod
75+
namespace: $PROJECT_NAME
76+
spec:
77+
# this is purposely left at 0 so it can be enabled for troubleshooting purposes
78+
replicas: 0
79+
selector:
80+
matchLabels:
81+
app: db-pod
82+
template:
83+
metadata:
84+
labels:
85+
app: db-pod
86+
spec:
87+
automountServiceAccountToken: false
88+
containers:
89+
- command:
90+
- sh
91+
args:
92+
- "-c"
93+
# long running task so the pod doesn't exit with 0
94+
- tail -f /dev/null
95+
image: $DOCKER_IMAGE_TAG
96+
imagePullPolicy: Always
97+
name: db-pod
98+
env:
99+
- name: DB_ENDPOINT
100+
value: $DB_ENDPOINT
101+
- name: DB_NAME
102+
value: $DB_NAME
103+
- name: DB_USERNAME
104+
valueFrom:
105+
secretKeyRef:
106+
name: $PROJECT_NAME
107+
key: DATABASE_USERNAME
108+
- name: DB_PASSWORD
109+
valueFrom:
110+
secretKeyRef:
111+
name: $PROJECT_NAME
112+
key: DATABASE_PASSWORD
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: db-ops
5+
---
6+
apiVersion: v1
7+
kind: Secret
8+
metadata:
9+
name: db-create-users
10+
namespace: db-ops
11+
type: Opaque
12+
stringData:
13+
create-user.sql: |
14+
DROP USER $DB_APP_USERNAME
15+
CREATE USER $DB_APP_USERNAME WITH ENCRYPTED PASSWORD '$DB_APP_PASSWORD';
16+
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_APP_USERNAME;
17+
RDS_MASTER_PASSWORD: $MASTER_RDS_PASSWORD
18+
---
19+
apiVersion: v1
20+
kind: Namespace
21+
metadata:
22+
name: $PROJECT_NAME
23+
---
24+
apiVersion: v1
25+
kind: Secret
26+
metadata:
27+
name: $PROJECT_NAME
28+
namespace: $PROJECT_NAME
29+
type: Opaque
30+
stringData:
31+
DATABASE_USERNAME: $DB_APP_USERNAME
32+
DATABASE_PASSWORD: $DB_APP_PASSWORD
33+
---
34+
apiVersion: batch/v1
35+
kind: Job
36+
metadata:
37+
name: db-create-users-$JOB_ID
38+
namespace: db-ops
39+
spec:
40+
template:
41+
spec:
42+
containers:
43+
- name: create-rds-user
44+
image: $DOCKER_IMAGE_TAG
45+
command:
46+
- sh
47+
args:
48+
- '-c'
49+
- psql -U$MASTER_RDS_USERNAME -h $DB_ENDPOINT $DB_NAME -a -f/db-ops/create-user.sql > /dev/null
50+
env:
51+
- name: PGPASSWORD
52+
valueFrom:
53+
secretKeyRef:
54+
name: db-create-users
55+
key: RDS_MASTER_PASSWORD
56+
volumeMounts:
57+
- mountPath: /db-ops/create-user.sql
58+
name: db-create-users
59+
subPath: create-user.sql
60+
volumes:
61+
- name: db-create-users
62+
secret:
63+
secretName: db-create-users
64+
restartPolicy: Never
65+
backoffLimit: 1
66+
---
67+
apiVersion: apps/v1
68+
kind: Deployment
69+
metadata:
70+
name: db-pod
71+
namespace: $PROJECT_NAME
72+
spec:
73+
# this is purposely left at 0 so it can be enabled for troubleshooting purposes
74+
replicas: 0
75+
selector:
76+
matchLabels:
77+
app: db-pod
78+
template:
79+
metadata:
80+
labels:
81+
app: db-pod
82+
spec:
83+
automountServiceAccountToken: false
84+
containers:
85+
- command:
86+
- sh
87+
args:
88+
- "-c"
89+
# long running task so the pod doesn't exit with 0
90+
- tail -f /dev/null
91+
image: $DOCKER_IMAGE_TAG
92+
imagePullPolicy: Always
93+
name: db-pod
94+
env:
95+
- name: DB_ENDPOINT
96+
value: $DB_ENDPOINT
97+
- name: DB_NAME
98+
value: $DB_NAME
99+
- name: DB_USERNAME
100+
valueFrom:
101+
secretKeyRef:
102+
name: $PROJECT_NAME
103+
key: DATABASE_USERNAME
104+
- name: DB_PASSWORD
105+
valueFrom:
106+
secretKeyRef:
107+
name: $PROJECT_NAME
108+
key: DATABASE_PASSWORD

templates/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ apply-shared-remote-state:
2323
rm ./terraform.tfstate )
2424

2525
apply-secrets:
26-
aws secretsmanager list-secrets --filters "Key=name,Values=$(PROJECT)-$(ENVIRONMENT)-rds-<% index .Params `randomSeed` %>" > /dev/null 2>&1 || ( \
26+
aws secretsmanager describe-secret --secret-id "$(PROJECT)-$(ENVIRONMENT)-rds-<% index .Params `randomSeed` %>" > /dev/null 2>&1 || ( \
2727
cd terraform/bootstrap/secrets && \
2828
terraform init && \
2929
terraform apply $(AUTO_APPROVE) && \

templates/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ $ curl --request POST \
9090
```
9191
For Application use, see [Sendgrid resources][sendgrid-send-mail] on how to setup templates to send dynamic transactional emails. To setup emailing from your application deployment, you should create a kubernetes secret with your Sendgrid API Key(already stored in [AWS secret-manager](./terraform/bootstrap/secrets/main.tf)) in your application's namespace. Then mount the secret as an environment variable in your deployment.
9292

93+
#### Application database user creation
94+
A database user will automatically be created for a backend application with a random password, and the credentials will be stored in a kubernetes secret so they are available to the application.
95+
96+
_Note: the user creation only happens once during `zero apply`. If you want to run this process again to create a new password, you can run the script `sh dp-ops/create-db-user.sh` manually, though be aware that this will cause the user and its privileges to be removed and recreated, and may disrupt your application until it is restarted.
97+
98+
9399
# Resources
94100
### Infrastructure
95101
This [architecture-diagram][architecture-diagram] displays the original setup you get from the terraform templates

templates/kubernetes/terraform/modules/kubernetes/cert_manager.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ data "local_file" "cert_manager" {
2525
# Install the cert manager Custom Resource Definitions (this can't be done via helm/terraform)
2626
resource "null_resource" "cert_manager" {
2727
triggers = {
28-
manifest_sha1 = "${sha1("${data.local_file.cert_manager.content}")}"
28+
manifest_sha1 = sha1(data.local_file.cert_manager.content)
2929
}
3030
# local exec call requires kubeconfig to be updated
3131
provisioner "local-exec" {
@@ -37,7 +37,7 @@ resource "null_resource" "cert_manager" {
3737

3838
# Cert-manager issuer manifest
3939
data "template_file" "cert_manager_issuer" {
40-
template = "${file("${path.module}/files/cert_manager_issuer.yaml.tpl")}"
40+
template = file("${path.module}/files/cert_manager_issuer.yaml.tpl")
4141
vars = {
4242
name = local.cluster_issuer_name
4343
environment = var.environment
@@ -52,7 +52,7 @@ data "template_file" "cert_manager_issuer" {
5252
# does not have support for custom resources.
5353
resource "null_resource" "cert_manager_issuer" {
5454
triggers = {
55-
manifest_sha1 = "${sha1("${data.template_file.cert_manager_issuer.rendered}")}"
55+
manifest_sha1 = sha1(data.template_file.cert_manager_issuer.rendered)
5656
}
5757
# local exec call requires kubeconfig to be updated
5858
provisioner "local-exec" {

templates/kubernetes/terraform/modules/kubernetes/vpn.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ resource "kubernetes_config_map" "vpn_configmap" {
8282
}
8383

8484
data = {
85-
"wg0.conf" = "${data.template_file.vpn_server_conf.rendered}"
85+
"wg0.conf" = data.template_file.vpn_server_conf.rendered
8686
}
8787
}
8888

0 commit comments

Comments
 (0)