From b5d0e49300d297034b25fd1c98c4ce038433b8ed Mon Sep 17 00:00:00 2001 From: Simon Emms Date: Thu, 29 Sep 2022 20:02:09 +0000 Subject: [PATCH] [certificates]: validate that certs are valid for a Gitpod install --- .github/CODEOWNERS | 1 + components/BUILD.yaml | 1 + .../kots-config-check/certificate/BUILD.yaml | 14 +++ .../certificate/entrypoint.sh | 88 +++++++++++++++++++ .../certificate/leeway.Dockerfile | 9 ++ .../kots/manifests/kots-support-bundle.yaml | 40 +++++++++ 6 files changed, 153 insertions(+) create mode 100644 components/kots-config-check/certificate/BUILD.yaml create mode 100755 components/kots-config-check/certificate/entrypoint.sh create mode 100644 components/kots-config-check/certificate/leeway.Dockerfile diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cc28b9e7eba20a..e5ef1eb70a7e7d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -28,6 +28,7 @@ /components/image-builder-bob @gitpod-io/engineering-workspace /components/image-builder-mk3 @gitpod-io/engineering-workspace /components/installation-telemetry @gitpod-io/engineering-self-hosted +/components/kots-config-check @gitpod-io/engineering-self-hosted /install @gitpod-io/engineering-self-hosted /install/installer @gitpod-io/engineering-self-hosted # For testdata a single review from anyone who is allowed to review PRs is sufficent. diff --git a/components/BUILD.yaml b/components/BUILD.yaml index 66e53c5014ce82..331c5ce715c2c1 100644 --- a/components/BUILD.yaml +++ b/components/BUILD.yaml @@ -73,6 +73,7 @@ packages: - components/ide-proxy:docker - components/ide-metrics:docker - components/ide-service:docker + - components/kots-config-check/certificate:docker - components/kots-config-check/database:docker - components/kots-config-check/registry:docker - components/kots-config-check/storage:docker diff --git a/components/kots-config-check/certificate/BUILD.yaml b/components/kots-config-check/certificate/BUILD.yaml new file mode 100644 index 00000000000000..ee96c494ef4078 --- /dev/null +++ b/components/kots-config-check/certificate/BUILD.yaml @@ -0,0 +1,14 @@ +packages: + - name: docker + type: docker + argdeps: + - imageRepoBase + srcs: + - entrypoint.sh + config: + dockerfile: leeway.Dockerfile + metadata: + helm-component: kots-config-check.certificate + image: + - ${imageRepoBase}/kots-config-check/certificate:${version} + - ${imageRepoBase}/kots-config-check/certificate:commit-${__git_commit} diff --git a/components/kots-config-check/certificate/entrypoint.sh b/components/kots-config-check/certificate/entrypoint.sh new file mode 100755 index 00000000000000..fd7b33ab7795db --- /dev/null +++ b/components/kots-config-check/certificate/entrypoint.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# Copyright (c) 2022 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +set -euo pipefail + +DOMAIN="${1:-""}" +NAMESPACE="${2:-""}" +SECRET_NAME="${3:-""}" +TLS_CRT_KEY="${4:-"tls.crt"}" + +cert_exists="false" +domain="false" +in_date="false" + +CRT_FILE="/tmp/tls.crt" +CRT_CONTENTS_FILE="/tmp/tls.txt" + +function get_cert() { + # Get certificate from secret + kubectl get secret \ + -n "${NAMESPACE}" \ + "${SECRET_NAME}" \ + -o jsonpath="{.data.${TLS_CRT_KEY//./\\.}}" \ + | base64 -d \ + > "${CRT_FILE}" + + # Decode it as an x509 certificate + openssl x509 -in "${CRT_FILE}" -text -noout > "${CRT_CONTENTS_FILE}" +} + +function cert_matches_domain_name() { + grep "${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1 + grep "\*.${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 2 + grep "\*.ws.${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 3 +} + +function cert_in_date() { + DATES="$(openssl x509 -in "${CRT_FILE}" -noout -dates)" + + START_DATE="$(echo "${DATES}" | awk -F= '{a[$1]=$2} END {print(a["notBefore"])}')" + END_DATE="$(echo "${DATES}" | awk -F= '{a[$1]=$2} END {print(a["notAfter"])}')" + + echo "Certificate start date: ${START_DATE}" + echo "Certificate end date: ${END_DATE}" + + START_EPOCH="$(date -u -D "%b %e %H:%M:%S %Y" -d "${START_DATE}" "+%s")" + END_EPOCH="$(date -u -D "%b %e %H:%M:%S %Y" -d "${END_DATE}" "+%s")" + NOW_EPOCH="$(date "+%s")" + + if [ "${NOW_EPOCH}" -gt "${START_EPOCH}" ] && [ "${NOW_EPOCH}" -lt "${END_EPOCH}" ]; then + echo "Certificate is in date" + return 0 + fi + + return 1 +} + +if get_cert; then + cert_exists="true" + + if cert_matches_domain_name; then + domain="true" + fi + + if cert_in_date; then + in_date="true" + fi +fi + +if [ "${cert_exists}" = "true" ]; then + echo "cert_exists: ok" +else + echo "cert_exists: error" +fi + +if [ "${domain}" = "true" ]; then + echo "domain_name: ok" +else + echo "domain_name: error" +fi + +if [ "${in_date}" = "true" ]; then + echo "in_date: ok" +else + echo "in_date: error" +fi diff --git a/components/kots-config-check/certificate/leeway.Dockerfile b/components/kots-config-check/certificate/leeway.Dockerfile new file mode 100644 index 00000000000000..b40652d700e96c --- /dev/null +++ b/components/kots-config-check/certificate/leeway.Dockerfile @@ -0,0 +1,9 @@ +# Copyright (c) 2022 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License-AGPL.txt in the project root for license information. + +FROM alpine/openssl +COPY --from=bitnami/kubectl /opt/bitnami/kubectl/bin/kubectl /usr/local/bin/kubectl +COPY entrypoint.sh /entrypoint.sh +RUN apk add --no-cache bash +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/install/kots/manifests/kots-support-bundle.yaml b/install/kots/manifests/kots-support-bundle.yaml index 9b16b8c7c4ff53..ebc92682438e0d 100644 --- a/install/kots/manifests/kots-support-bundle.yaml +++ b/install/kots/manifests/kots-support-bundle.yaml @@ -7,6 +7,16 @@ metadata: name: gitpod spec: collectors: + - run: + collectorName: certificate + image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/certificate:mrsimonemms-add-kots-support-bundle-11865.1 + name: certificate + namespace: '{{repl Namespace }}' + args: + - '{{repl ConfigOption "domain" }}' # DOMAIN + - '{{repl Namespace }}' # NAMESPACE + - https-certificates # SECRET_NAME + - tls.crt #TLS_CRT_KEY - run: collectorName: database image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/database:sje-kots-config-check.9 @@ -125,3 +135,33 @@ spec: - '{{repl LicenseFieldValue "appSlug" }}' - --namespace - '{{repl Namespace }}' + - textAnalyze: + checkName: TLS certificate exists + fileName: certificate/certificate.log + regexGroups: 'cert_exists: (?P\w+)' + outcomes: + - pass: + when: "Valid == ok" + message: TLS certificate exists + - fail: + message: TLS certificate does not exist. If using cert-manager, please check your settings and that your domain name is pointing to the correct name server. If you are supplying your own certificate, this will need to be re-uploaded. + - textAnalyze: + checkName: TLS certificate domain name + fileName: certificate/certificate.log + regexGroups: 'domain_name: (?P\w+)' + outcomes: + - pass: + when: "Valid == ok" + message: TLS certificate has the correct domain names + - fail: + message: TLS certificate does not have the correct domain names. It requires the DNS names `{{repl ConfigOption "domain" }}`, `*.{{repl ConfigOption "domain" }}` and `*.ws.{{repl ConfigOption "domain" }}` on the certificate. + - textAnalyze: + checkName: TLS certificate in date + fileName: certificate/certificate.log + regexGroups: 'in_date: (?P\w+)' + outcomes: + - pass: + when: "Exists == ok" + message: TLS certificate is in date + - fail: + message: TLS certificate is not date and will need to be reissued. If using cert-manager, please check your settings and that your domain name is pointing to the correct name server. If you are supplying your own certificate, this will need to be re-uploaded.