From 4c23ce19c3c6fcf51ce6ab6f505314111ca8739c Mon Sep 17 00:00:00 2001 From: Adrien Date: Mon, 18 Sep 2023 22:31:19 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20First=20commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + carrramba-encore-rate-deployment.yaml | 240 +++++++++++++++++++ init.sh | 110 +++++++++ observability.yaml | 25 ++ postgres.yaml | 114 +++++++++ redis.yaml | 66 +++++ vault-carrramba-encore-rate-admin-policy.hcl | 7 + vault-carrramba-encore-rate-api-policy.hcl | 7 + vault-postgres-policy.hcl | 19 ++ 9 files changed, 592 insertions(+) create mode 100644 .gitignore create mode 100644 carrramba-encore-rate-deployment.yaml create mode 100755 init.sh create mode 100644 observability.yaml create mode 100644 postgres.yaml create mode 100644 redis.yaml create mode 100644 vault-carrramba-encore-rate-admin-policy.hcl create mode 100644 vault-carrramba-encore-rate-api-policy.hcl create mode 100644 vault-postgres-policy.hcl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d0f195 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +setup_env.sh +kubeconfig-k8s-projects.yaml +**/*.old +**/*.new diff --git a/carrramba-encore-rate-deployment.yaml b/carrramba-encore-rate-deployment.yaml new file mode 100644 index 0000000..8b76fe6 --- /dev/null +++ b/carrramba-encore-rate-deployment.yaml @@ -0,0 +1,240 @@ +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-carrramba + namespace: default +spec: + acme: + email: me@adrien.run + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-carrramba + solvers: + - http01: + ingress: + class: istio + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: carrramba-encore-rate-frontend + labels: + app: carrramba-encore-rate-frontend +spec: + replicas: 1 + selector: + matchLabels: + app: carrramba-encore-rate-frontend + template: + metadata: + labels: + app: carrramba-encore-rate-frontend + spec: + containers: + - name: carrramba-encore-rate-frontend + image: rg.fr-par.scw.cloud/asr-projects/carrramba-encore-rate-frontend:latest + ports: + - name: web + containerPort: 80 + imagePullSecrets: + - name: registry-secret + +--- +apiVersion: v1 +kind: Service +metadata: + name: carrramba-encore-rate-frontend + labels: + app: carrramba-encore-rate-frontend +spec: + ports: + - name: web + port: 80 + targetPort: web + selector: + app: carrramba-encore-rate-frontend + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: carrramba-encore-rate-frontend-ingress + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web +spec: + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: carrramba-encore-rate-frontend + port: + name: web + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: strip-api-prefix +spec: + stripPrefix: + prefixes: + - /api + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: carrramba-encore-rate-api-ingress + annotations: + cert-manager.io/cluster-issuer: letsencrypt-carrramba + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.middlewares: default-strip-api-prefix@kubernetescrd +spec: + tls: + - hosts: + - carrramba.adrien.run + secretName: tls-carrramba-encore-rate-ingress + rules: + - http: + paths: + - path: /api/ + pathType: Prefix + backend: + service: + name: carrramba-encore-rate-api + port: + name: web + +--- +# Service account to allow pod access to Vault via K8s auth +apiVersion: v1 +kind: ServiceAccount +metadata: + name: carrramba-encore-rate-api +automountServiceAccountToken: true + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: carrramba-encore-rate-api + labels: + app: carrramba-encore-rate-api +spec: + replicas: 1 + selector: + matchLabels: + app: carrramba-encore-rate-api + template: + metadata: + labels: + app: carrramba-encore-rate-api + annotations: + vault.hashicorp.com/agent-inject: "true" + vault.hashicorp.com/agent-inject-secret-carrramba-encore-rate-api: "database/creds/carrramba-encore-rate-api" + vault.hashicorp.com/agent-inject-template-carrramba-encore-rate-api: | + {{ with secret "database/creds/carrramba-encore-rate-api" -}} + export CER__DB__NAME=carrramba_encore_rate + export CER__DB__HOST=postgres + export CER__DB__PORT=5432 + export CER__DB__USER={{ .Data.username }} + export CER__DB__PASSWORD={{ .Data.password }} + {{- end }} + {{ with secret "carrramba-encore-rate-api/idfm-api-key" -}} + export CER__IDFM_API_KEY={{ .Data.key }} + {{- end}} + vault.hashicorp.com/role: "carrramba-encore-rate-api" + spec: + containers: + - name: carrramba-encore-rate-api + image: rg.fr-par.scw.cloud/asr-projects/carrramba-encore-rate-api:latest + command: ["/bin/bash"] + args: ["-c", "source ${BASH_ENV} ; python ./main.py "] + # args: ["-c", "while true; do echo hello; sleep 10;done"] + ports: + - name: web + containerPort: 8080 + env: + - name: BASH_ENV + value: /vault/secrets/carrramba-encore-rate-api + - name: CONFIG_PATH + value: ./config.sample.yaml + - name: CER__TRACING__ENABLE + value: "true" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://jaeger-all-in-one-collector.observability.svc.cluster.local:$(JAEGER_ALL_IN_ONE_COLLECTOR_SERVICE_PORT_HTTP_OTLP)" + imagePullPolicy: Always + imagePullSecrets: + - name: registry-secret + serviceAccountName: carrramba-encore-rate-api + +--- +apiVersion: v1 +kind: Service +metadata: + name: carrramba-encore-rate-api + labels: + app: carrramba-encore-rate-api +spec: + ports: + - name: web + port: 8080 + targetPort: web + selector: + app: carrramba-encore-rate-api + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: db-update +spec: + schedule: "0 1 * * 5" # At 01:00 on Friday + jobTemplate: + spec: + template: + metadata: + annotations: + vault.hashicorp.com/agent-inject: "true" + vault.hashicorp.com/agent-inject-secret-carrramba-encore-rate-admin: "database/creds/carrramba-encore-rate-admin" + vault.hashicorp.com/agent-inject-template-carrramba-encore-rate-admin: | + {{ with secret "database/creds/carrramba-encore-rate-admin" -}} + export CER__DB__NAME=carrramba_encore_rate + export CER__DB__HOST=postgres + export CER__DB__PORT=5432 + export CER__DB__USER={{ .Data.username }} + export CER__DB__PASSWORD={{ .Data.password }} + {{- end }} + {{ with secret "carrramba-encore-rate-api/idfm-api-key" -}} + export CER__IDFM_API_KEY={{ .Data.key }} + {{- end}} + vault.hashicorp.com/role: "carrramba-encore-rate-admin" + spec: + containers: + - name: db-update + image: rg.fr-par.scw.cloud/asr-projects/carrramba-encore-rate-db-updater:latest + command: ["/bin/bash"] + args: ["-c", "source ${BASH_ENV} ; python -m db_updater.fill_db"] + imagePullPolicy: IfNotPresent + env: + - name: BASH_ENV + value: /vault/secrets/carrramba-encore-rate-admin + - name: CONFIG_PATH + value: ./config.sample.yaml + restartPolicy: Never + imagePullSecrets: + - name: registry-secret + serviceAccountName: carrramba-encore-rate-admin + +--- +# Service account to allow pod access to Vault via K8s auth +apiVersion: v1 +kind: ServiceAccount +metadata: + name: carrramba-encore-rate-admin +automountServiceAccountToken: true diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..07cdaa3 --- /dev/null +++ b/init.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +source ./setup_env.sh + +snap install kubectl --classic +snap install vault --classic + +kubectl create secret docker-registry registry-secret \ + --docker-server=rg.fr-par.scw.cloud \ + --docker-username=asr-projects \ + --docker-password=$SCW_SECRET_KEY + +kubectl get secret registry-secret --output=yaml + +# Install traefik +helm repo add traefik https://traefik.github.io/charts +helm repo update +kubectl create ns traefik +helm --kubeconfig ./kubeconfig-k8s-projects.yaml install -n traefik traefik traefik/traefik + +# Install cert-manager +helm repo add jetstack https://charts.jetstack.io +helm repo update +helm --kubeconfig ./kubeconfig-k8s-projects.yaml install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --version v1.12\ + --set installCRDs=true + +# Install vault +helm repo add hashicorp https://helm.releases.hashicorp.com +helm repo update +helm install vault hashicorp/vault +vault secrets enable database + +# Install traefik +helm repo add traefik https://traefik.github.io/charts +helm repo update +helm install traefik traefik/traefik + +# Install prometheus +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm repo update +kubectl create ns monitoring +helm --kubeconfig ./kubeconfig-k8s-projects.yaml \ + -n monitoring install kube-prometheus-stack prometheus-community/kube-prometheus-stack + +kubectl port-forward vault-0 8200:8200 & +export VAULT_ADDR='http://127.0.0.1:8200' + +# Enable db passwords management by Vault +# Cf. https://www.hashicorp.com/blog/dynamic-database-credentials-with-vault-and-kubernetes +vault auth enable kubernetes +vault write auth/kubernetes/config \ + kubernetes_host=https://5c3a37c1-03b3-4a9d-b36f-45566ece9847.api.k8s.fr-par.scw.cloud:6443 \ + disable_local_ca_jwt=true + +vault secrets enable database +vault write database/config/carrramba_encore_rate \ + plugin_name=postgresql-database-plugin \ + verify_connection=false \ + allowed_roles="*" \ + connection_url="postgresql://{{username}}:{{password}}@postgres:5432/carrramba_encore_rate?sslmode=disable" \ + username="postgres" \ + password="password" + +vault policy write carrramba-encore-rate-api vault-carrramba-encore-rate-api-policy.hcl + +vault write --force /database/rotate-root/carrramba_encore_rate + +# TODO: Restore default_ttl and max_ttl once the api able to reload env variable on change. +vault write database/roles/carrramba-encore-rate-api \ + db_name=carrramba_encore_rate \ + creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \ + GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \ + revocation_statements="ALTER ROLE \"{{name}}\" NOLOGIN;"\ + default_ttl="768h" \ + max_ttl="768h" + # default_ttl="1h" \ + # max_ttl="24h" +vault write auth/kubernetes/role/carrramba_encore_rate_api \ + bound_service_account_names=carrramba-encore-rate-api \ + bound_service_account_namespaces=default \ + policies=carrramba-encore-rate-api \ + ttl=1h + +vault policy write carrramba-encore-rate-admin vault-carrramba-encore-rate-admin-policy.hcl +vault write database/roles/carrramba-encore-rate-admin \ + db_name=carrramba_encore_rate \ + creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \ + ALTER ROLE \"{{name}}\" SUPERUSER;" \ + revocation_statements="ALTER ROLE \"{{name}}\" NOLOGIN;"\ + default_ttl="1h" \ + max_ttl="24h" +vault write auth/kubernetes/role/carrramba-encore-rate-admin \ + bound_service_account_names=carrramba-encore-rate-admin \ + bound_service_account_namespaces=default \ + policies=carrramba-encore-rate-admin \ + ttl=1h + +vault secrets enable -path="carrramba-encore-rate-api" -description="carrramba-encore-rate secrets" kv +vault kv put carrramba-encore-rate-api/idfm-api-key key=$(pass dev/idfm_prim_api_token) + +# Install tracing (cf. https://www.jaegertracing.io/docs/1.49/operator/) +kubectl create namespace observability +kubectl create -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.49.0/jaeger-operator.yaml -n observability +kubectl apply -f observability.yaml -n observability + +kubectl apply -f carrramba-cert.yaml +kubectl apply -f carrramba-encore-rate-deployment.yaml diff --git a/observability.yaml b/observability.yaml new file mode 100644 index 0000000..0d511bb --- /dev/null +++ b/observability.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: jaegertracing.io/v1 +kind: Jaeger +metadata: + name: jaeger-all-in-one +spec: + strategy: allInOne + storage: + type: memory + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jaeger-all-in-one +spec: + template: + spec: + containers: + - name: jaeger-all-in-one + image: jaegertracing/jaeger-operator:master + args: ["start"] + env: + - name: COLLECTOR_OTLP_ENABLED + value: "true" diff --git a/postgres.yaml b/postgres.yaml new file mode 100644 index 0000000..7d6f235 --- /dev/null +++ b/postgres.yaml @@ -0,0 +1,114 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: postgres-pv-volume + labels: + type: local + app: postgres +spec: + storageClassName: manual + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + hostPath: + path: "/mnt/data" + +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: postgres-pv-claim + labels: + app: postgres +spec: + storageClassName: manual + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: postgres-config +# labels: +# app: postgres +# data: +# POSTGRES_DB: carrramba_encore_rate +# POSTGRES_USER: postgres +# POSTGRES_PASSWORD: password +# --- + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + service: postgres + spec: + containers: + - name: postgres + image: postgres:15.3 + # command: [ "sh", "-c"] + # args: ["while true; do echo 'yo' && sleep 5; done;"] + # imagePullPolicy: "IfNotPresent" + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: carrramba_encore_rate + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + value: password + # envFrom: + # - configMapRef: + # name: postgres-config + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgredb + - mountPath: /docker-entrypoint-initdb.d + name: initdb + volumes: + - name: postgredb + persistentVolumeClaim: + claimName: postgres-pv-claim + - name: initdb + configMap: + name: postgres-initdb-config + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-initdb-config +data: + initdb.sql: | + CREATE DATABASE carrramba_encore_rate; + CREATE EXTENSION IF NOT EXISTS pg_trgm; +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + labels: + app: postgres +spec: + type: ClusterIP + ports: + - port: 5432 + targetPort: 5432 + selector: + app: postgres + diff --git a/redis.yaml b/redis.yaml new file mode 100644 index 0000000..211262f --- /dev/null +++ b/redis.yaml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: redis-config +data: + redis-config: | + maxmemory 1gb + maxmemory-policy allkeys-lru + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:latest + command: + - redis-server + - "/redis-master/redis.conf" + env: + - name: MASTER + value: "true" + ports: + - containerPort: 6379 + # resources: + # limits: + # cpu: "0.1" + volumeMounts: + - mountPath: /redis-master-data + name: data + - mountPath: /redis-master + name: config + volumes: + - name: data + emptyDir: {} + - name: config + configMap: + name: redis-config + items: + - key: redis-config + path: redis.conf + +--- +apiVersion: v1 +kind: Service +metadata: + name: redis + labels: + app: redis +spec: + type: NodePort + ports: + - port: 6379 + selector: + app: redis diff --git a/vault-carrramba-encore-rate-admin-policy.hcl b/vault-carrramba-encore-rate-admin-policy.hcl new file mode 100644 index 0000000..d7a8eef --- /dev/null +++ b/vault-carrramba-encore-rate-admin-policy.hcl @@ -0,0 +1,7 @@ +path "database/creds/carrramba-encore-rate-admin" { + capabilities = ["read"] +} + +path "carrramba-encore-rate-api/idfm-api-key" { + capabilities = [ "read" ] +} diff --git a/vault-carrramba-encore-rate-api-policy.hcl b/vault-carrramba-encore-rate-api-policy.hcl new file mode 100644 index 0000000..cc074e1 --- /dev/null +++ b/vault-carrramba-encore-rate-api-policy.hcl @@ -0,0 +1,7 @@ +path "database/creds/carrramba-encore-rate-api" { + capabilities = ["read"] +} + +path "carrramba-encore-rate-api/idfm-api-key" { + capabilities = [ "read" ] +} diff --git a/vault-postgres-policy.hcl b/vault-postgres-policy.hcl new file mode 100644 index 0000000..f21bd04 --- /dev/null +++ b/vault-postgres-policy.hcl @@ -0,0 +1,19 @@ +# Mount secrets engines +path "sys/mounts/*" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} + +# Configure the database secrets engine and create roles +path "database/*" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} + +# Write ACL policies +path "sys/policies/acl/*" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} + +# Manage tokens for verification +path "auth/token/create" { + capabilities = [ "create", "read", "update", "delete", "list", "sudo" ] +}