diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 68a055a..20d8957 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -101,6 +101,14 @@ steps: - --set - django.image.tag=$COMMIT_SHA - --set + - secret_manager.file_name=${_SETTINGS_NAME} + - --set + - django.env.django_settings_module=${_K8TS_DJANGO_SETTINGS_MODULE} + - --set + - django.env.postgres_host=${_K8TS_PG_HOST} + - --set + - django.env.postgres_port=${_K8TS_PG_PORT} + - --set - ingress.networking.domain=${_DOMAIN_NAME} - --set - ingress.networking.issuer.name=${_LETSENCRYPT_SERVER_TYPE} @@ -116,6 +124,8 @@ steps: - cloud_sql.env.cloudsql_connection_instance=${_CLOUDSQL_INSTANCE_CONNECTION_NAME} - --set - django.configmap.config_name=${_CONFIGMAP_FILE} + - --set + - common.service_account_key=${_IAM_SERVICE_ACCOUNT_KEY} - . # Update essential Variables and Deploy to cluster @@ -128,6 +138,7 @@ steps: - upgrade - --install - ${_APP_NAME}-${_DEPLOYMENT_TYPE} + - --debug - --namespace=${_NAMESPACE} - --values - values.yaml @@ -138,6 +149,14 @@ steps: - --set - django.image.tag=$COMMIT_SHA - --set + - secret_manager.file_name=${_SETTINGS_NAME} + - --set + - django.env.django_settings_module=${_K8TS_DJANGO_SETTINGS_MODULE} + - --set + - django.env.postgres_host=${_K8TS_PG_HOST} + - --set + - django.env.postgres_port=${_K8TS_PG_PORT} + - --set - ingress.networking.domain=${_DOMAIN_NAME} - --set - ingress.networking.issuer.name=${_LETSENCRYPT_SERVER_TYPE} @@ -153,6 +172,8 @@ steps: - cloud_sql.env.cloudsql_connection_instance=${_CLOUDSQL_INSTANCE_CONNECTION_NAME} - --set - django.configmap.config_name=${_CONFIGMAP_FILE} + - --set + - common.service_account_key=${_IAM_SERVICE_ACCOUNT_KEY} - . images: diff --git a/deploy/ReadMe.md b/deploy/README.md similarity index 100% rename from deploy/ReadMe.md rename to deploy/README.md diff --git a/deploy/templates/django/deployment.yaml b/deploy/templates/django/deployment.yaml index a3102ec..16b7487 100644 --- a/deploy/templates/django/deployment.yaml +++ b/deploy/templates/django/deployment.yaml @@ -28,7 +28,7 @@ spec: name: {{ .Values.django.configmap.config_name }} volumeMounts: - name: env-var-vol - mountPath: /secrets/environment_variables + mountPath: /secrets readOnly: true volumes: diff --git a/deploy/templates/pg-bouncer/deployment.yaml b/deploy/templates/pg-bouncer/deployment.yaml index d5a3c0c..f038cd0 100644 --- a/deploy/templates/pg-bouncer/deployment.yaml +++ b/deploy/templates/pg-bouncer/deployment.yaml @@ -34,13 +34,13 @@ spec: - "--structured-logs" - "--port=5432" - "{{ .Values.cloud_sql.env.cloudsql_connection_instance }}" - - "--credentials-file=/secrets/service_account_secrets/service_account.json" + - "--credentials-file=/secrets/{{ .Values.common.service_account_name }}/service_account.json" securityContext: runAsNonRoot: true - volumeMounts: - - name: sa-secret-vol - mountPath: /secrets/service_account_secrets - readOnly: true +# volumeMounts: +# - name: sa-secret-vol +# mountPath: /secrets/iam-service-account-key +# readOnly: true volumes: - name: user-config configMap: @@ -50,6 +50,6 @@ spec: configMap: name: {{ .Values.pg_bouncer.app_name }}-pgb-config - - name: sa-secret-vol - secret: - secretName: {{ .Values.namespace }}-sa-secrets +# - name: sa-secret-vol +# secret: +# secretName: {{ .Values.namespace }}-sa-secrets diff --git a/deploy/templates/service_account/environment.yml b/deploy/templates/service_account/environment.yml new file mode 100644 index 0000000..bd91867 --- /dev/null +++ b/deploy/templates/service_account/environment.yml @@ -0,0 +1,102 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: configmap-creator + namespace: {{ .Values.namespace }} +spec: + template: + metadata: + name: configmap-creator + spec: + restartPolicy: OnFailure + containers: + - name: configmap-creator + image: gcr.io/google.com/cloudsdktool/cloud-sdk:459.0.0 + env: + - name: K8TS_DJANGO_SETTINGS_MODULE + value: {{ .Values.django.env.django_settings_module }} + - name: K8TS_POSTGRES_HOST + value: {{ .Values.django.env.postgres_host }} + - name: K8TS_POSTGRES_PORT + value: {{ .Values.django.env.postgres_port | quote }} + - name: SECRET_MANAGER_FILE_NAME + value: {{ .Values.secret_manager.file_name }} + - name: CONFIGMAP_NAME + value: {{ .Values.django.configmap.config_name }} + - name: GCP_COMPUTE_ZONE + value: europe-west1-b + - name: CLUSTER_NAME + value: fyj-apps + - name: SERVICE_ACCOUNT_NAME + value: {{ .Values.common.service_account_name }} + - name: KUBECONFIG + value: /workspace/.kube/config + command: ["/bin/sh", "-c"] + args: + - | + set -e + # Step 0: Authenticate with Google Cloud using the provided service account key + gcloud auth activate-service-account --key-file=/secrets/${SERVICE_ACCOUNT_NAME}/service_account.json + # Step 1: Get the credentials for the GKE cluster and set up kubectl configuration. + gcloud container clusters get-credentials ${CLUSTER_NAME} --zone=${GCP_COMPUTE_ZONE} --project=$PROJECT_ID + + # Step 2: Fetch the latest version of the specified secret from Secret Manager + gcloud secrets versions access latest --secret=${SECRET_MANAGER_FILE_NAME} > /secrets/test_settings.txt + ENV_VARS="/secrets/test_settings.txt" + . "$ENV_VARS" + echo "CONN_MAX_AGE: $CONN_MAX_AGE" + echo "COMPRESS_ENABLED: $COMPRESS_ENABLED" + echo "GOOGLE_APPLICATION_CREDENTIALS_KEY: $GOOGLE_APPLICATION_CREDENTIALS_KEY" + MY_CONTEXT=$(kubectl config get-contexts) + CONFIG_VIEW=$(kubectl config view) + echo "MY_CONTEXT: $MY_CONTEXT" + echo "CONFIG_VIEW: $CONFIG_VIEW" + echo "Override some variables that was used to create containers at cloudbuild" + kubectl create configmap $CONFIGMAP_NAME \ + --from-literal=PORT="$PORT" \ + --from-literal=CONN_MAX_AGE="$CONN_MAX_AGE" \ + --from-literal=COMPRESS_ENABLED="$COMPRESS_ENABLED" \ + --from-literal=DJANGO_ACCOUNT_ALLOW_REGISTRATION="$DJANGO_ACCOUNT_ALLOW_REGISTRATION" \ + --from-literal=DJANGO_ADMIN_URL="$DJANGO_ADMIN_URL" \ + --from-literal=DJANGO_ALLOWED_HOSTS="$DJANGO_ALLOWED_HOSTS" \ + --from-literal=DJANGO_DEBUG="$DJANGO_DEBUG" \ + --from-literal=DJANGO_DEFAULT_FROM_EMAIL="$DJANGO_DEFAULT_FROM_EMAIL" \ + --from-literal=DJANGO_EMAIL_SUBJECT_PREFIX="$DJANGO_EMAIL_SUBJECT_PREFIX" \ + --from-literal=DJANGO_GCP_STORAGE_BUCKET_NAME="$DJANGO_GCP_STORAGE_BUCKET_NAME" \ + --from-literal=DJANGO_READ_DOT_ENV_FILE="$DJANGO_READ_DOT_ENV_FILE" \ + --from-literal=DJANGO_SECRET_KEY="$DJANGO_SECRET_KEY" \ + --from-literal=DJANGO_SECURE_BROWSER_XSS_FILTER="$DJANGO_SECURE_BROWSER_XSS_FILTER" \ + --from-literal=DJANGO_SECURE_CONTENT_TYPE_NOSNIFF="$DJANGO_SECURE_CONTENT_TYPE_NOSNIFF" \ + --from-literal=DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS="$DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS" \ + --from-literal=DJANGO_SECURE_FRAME_DENY="$DJANGO_SECURE_FRAME_DENY" \ + --from-literal=DJANGO_SECURE_SSL_REDIRECT="$DJANGO_SECURE_SSL_REDIRECT" \ + --from-literal=DJANGO_SERVER_EMAIL="$DJANGO_SERVER_EMAIL" \ + --from-literal=DJANGO_SESSION_COOKIE_HTTPONLY="$DJANGO_SESSION_COOKIE_HTTPONLY" \ + --from-literal=DJANGO_SESSION_COOKIE_SECURE="$DJANGO_SESSION_COOKIE_SECURE" \ + --from-literal=DJANGO_SETTINGS_MODULE=${K8TS_DJANGO_SETTINGS_MODULE} \ + --from-literal=GOOGLE_ANALYTICS_ID="$GOOGLE_ANALYTICS_ID" \ + --from-literal=GOOGLE_APPLICATION_CREDENTIALS_KEY="$GOOGLE_APPLICATION_CREDENTIALS_KEY" \ + --from-literal=GOOGLE_CLOUD_PROJECT="$GOOGLE_CLOUD_PROJECT" \ + --from-literal=INSTANCE_CONNECTION_NAME="$INSTANCE_CONNECTION_NAME" \ + --from-literal=MAILGUN_DOMAIN="$MAILGUN_DOMAIN" \ + --from-literal=MAILGUN_API_URL="$MAILGUN_API_URL" \ + --from-literal=MAILGUN_API_KEY="$MAILGUN_API_KEY" \ + --from-literal=POSTGRES_DB="$POSTGRES_DB" \ + --from-literal=POSTGRES_HOST="${K8TS_POSTGRES_HOST}" \ + --from-literal=POSTGRES_PORT="${K8TS_POSTGRES_PORT}" \ + --from-literal=POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \ + --from-literal=POSTGRES_USER="$POSTGRES_USER" \ + --from-literal=PUB_SUB_TOPIC="$PUB_SUB_TOPIC" \ + --from-literal=SENTRY_DSN="$SENTRY_DSN" \ + --from-literal=SENTRY_ENVIRONMENT="$SENTRY_ENVIRONMENT" \ + --from-literal=USE_DOCKER="$USE_DOCKER" \ + --from-literal=WEB_CONCURRENCY="$WEB_CONCURRENCY" \ + --from-literal=WHITELISTED_DOMAINS="$WHITELISTED_DOMAINS" + volumeMounts: + - name: env-var-vol + mountPath: /secrets + readOnly: true + volumes: + - name: env-var-vol + configMap: + name: {{ .Values.django.configmap.config_name }} diff --git a/deploy/templates/service_account/secrets.yml b/deploy/templates/service_account/secrets.yml new file mode 100644 index 0000000..c6bf140 --- /dev/null +++ b/deploy/templates/service_account/secrets.yml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.common.service_account_name }} + namespace: {{ .Values.namespace }} +type: Opaque +data: + # base64 -w 0 /path/to/sa_key.json + service_account.json: {{ .Values.common.service_account_key }} + +--- + +apiVersion: v1 +kind: Pod +metadata: + name: mount-service-account + namespace: {{ .Values.namespace }} +spec: + containers: + - name: alpine-container + image: alpine:latest + command: ["sleep", "3600"] # Sleep to keep the pod running + volumeMounts: + - name: service-account-vol + mountPath: "/secrets/{{ .Values.common.service_account_name }}" + readOnly: true + volumes: + - name: service-account-vol + secret: + secretName: {{ .Values.common.service_account_name }} diff --git a/deploy/values.yaml b/deploy/values.yaml index 5e66c1f..5e6a010 100644 --- a/deploy/values.yaml +++ b/deploy/values.yaml @@ -1,5 +1,8 @@ namespace: cluster_namespace +common: + service_account_key: "base64_encoded_sa_key" + service_account_name: "iam-service-account-key" django: app_name: django replica_count: 2 @@ -15,6 +18,10 @@ django: config_name: "config_name" secrets: secrets_name: "secrets_name" + env: + django_settings_module: django_settings_module + postgres_host: postgres_host + postgres_port: postgres_port cloud_sql: app_name: cloudsql-proxy @@ -41,6 +48,9 @@ pg_bouncer: db_user: "database_user" db_password: "database_password" +secret_manager: + file_name: secret_manager_file_name + ingress: app_name: ingress networking: