#!/usr/bin/env bash # fix_gitlab_tls.sh — one-shot TLS repair for git.knoe.dev. # # Installs the Google-managed certificate + FrontendConfig and patches the # existing GitLab Ingress to use them. Safe to re-run. # # Runs on the APP cluster (knoe-dev-0). Requires DNS for git.knoe.dev to # already point at the GCLB external IP (otherwise cert provisioning stalls # in FailedNotVisible). # # Usage: # ./scripts/fix_gitlab_tls.sh # GITLAB_NAMESPACE=gitlab GITLAB_HOST=git.knoe.dev ./scripts/fix_gitlab_tls.sh set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" CTX="${APP_CLUSTER_KUBECONTEXT:-gke_plenary-truck-485623-p7_us-west3_knoe-dev-0}" NS="${GITLAB_NAMESPACE:-gitlab}" HOST="${GITLAB_HOST:-git.knoe.dev}" INGRESS="${GITLAB_INGRESS_NAME:-gitlab-kong-ingress}" CERT="${GITLAB_MANAGED_CERT_NAME:-gitlab-managed-cert}" FC="${GITLAB_FRONTEND_CONFIG_NAME:-gitlab-frontend-config}" log() { printf '[fix-tls] %s\n' "$*"; } die() { printf '[fix-tls] ERROR: %s\n' "$*" >&2; exit 1; } command -v kubectl >/dev/null || die "kubectl not on PATH" log "Context: ${CTX} Namespace: ${NS} Host: ${HOST}" kubectl --context="${CTX}" get ns "${NS}" >/dev/null \ || die "namespace '${NS}' not found on ${CTX}" # --------------------------------------------------------------------------- # 1. Apply ManagedCertificate + FrontendConfig # --------------------------------------------------------------------------- log "Applying ManagedCertificate + FrontendConfig from k8s/knoe/gitlab-managed-cert.yaml ..." kubectl --context="${CTX}" apply -f "${REPO_ROOT}/k8s/knoe/gitlab-managed-cert.yaml" # --------------------------------------------------------------------------- # 2. Patch the existing Ingress with the required annotations # --------------------------------------------------------------------------- if ! kubectl --context="${CTX}" -n "${NS}" get ingress "${INGRESS}" >/dev/null 2>&1; then die "Ingress ${NS}/${INGRESS} not found — run etc/init_gitlab.sh first" fi log "Annotating Ingress ${NS}/${INGRESS} ..." kubectl --context="${CTX}" -n "${NS}" annotate ingress "${INGRESS}" \ "networking.gke.io/managed-certificates=${CERT}" \ "networking.gke.io/v1beta1.FrontendConfig=${FC}" \ --overwrite # --------------------------------------------------------------------------- # 2b. Reconcile ingress rules to exactly the configured host list. # # An earlier install with conf/k3d.cfg (or a manual edit) may have left stale # hosts like git.knoe.org on the ingress. We replace spec.rules outright so # only the ManagedCertificate-covered host(s) remain served. # # Multi-host setups: set GITLAB_HOST to a comma-separated list; we build one # rule per host, all pointing at the same webservice backend. # --------------------------------------------------------------------------- WEBSERVICE_SVC="${WEBSERVICE_SVC:-gitlab-webservice-default}" WEBSERVICE_PORT="${WEBSERVICE_PORT:-8181}" IFS=',' read -r -a _hosts <<< "${HOST}" _rules_json="[" _first=1 for _h in "${_hosts[@]}"; do _h="${_h// /}"; [ -z "$_h" ] && continue [ "$_first" = 1 ] || _rules_json+="," _first=0 _rules_json+='{"host":"'"${_h}"'","http":{"paths":[{"path":"/","pathType":"Prefix","backend":{"service":{"name":"'"${WEBSERVICE_SVC}"'","port":{"number":'"${WEBSERVICE_PORT}"'}}}}]}}' done _rules_json+="]" _current_hosts=$(kubectl --context="${CTX}" -n "${NS}" get ingress "${INGRESS}" \ -o jsonpath='{.spec.rules[*].host}') log "Current ingress hosts: ${_current_hosts}" log "Reconciling to: ${HOST}" kubectl --context="${CTX}" -n "${NS}" patch ingress "${INGRESS}" --type=json \ -p='[{"op":"replace","path":"/spec/rules","value":'"${_rules_json}"'}]' # --------------------------------------------------------------------------- # 3. Report status (cert provisioning is async: ~10–60 min) # --------------------------------------------------------------------------- echo log "Current state:" kubectl --context="${CTX}" -n "${NS}" get ingress "${INGRESS}" \ -o custom-columns=NAME:.metadata.name,CLASS:.spec.ingressClassName,HOSTS:.spec.rules[*].host,ADDRESS:.status.loadBalancer.ingress[*].ip echo kubectl --context="${CTX}" -n "${NS}" get managedcertificate "${CERT}" \ -o custom-columns=NAME:.metadata.name,STATUS:.status.certificateStatus,DOMAINS:.spec.domains || true echo log "Done. Cert provisioning is async; it may take 10–60 minutes." log "Watch:" log " kubectl --context=${CTX} -n ${NS} get managedcertificate ${CERT} -w" log "Detailed status:" log " kubectl --context=${CTX} -n ${NS} describe managedcertificate ${CERT}" log "" log "Troubleshooting:" log " FailedNotVisible → DNS for ${HOST} not yet resolving to the GCLB IP." log " Verify: dig +short ${HOST} vs ingress ADDRESS above." log " Provisioning → normal; wait." log " Active → cert is live; https://${HOST}/ should now work."