Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[certificates]: validate that certs are valid for a Gitpod install #13471

Merged
merged 1 commit into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions components/BUILD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions components/kots-config-check/certificate/BUILD.yaml
Original file line number Diff line number Diff line change
@@ -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}
105 changes: 105 additions & 0 deletions components/kots-config-check/certificate/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/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"}"
TLS_KEY_KEY="${5:-"tls.key"}"

cert_exists="false"
domain="false"
in_date="false"

CRT_FILE="/tmp/tls.crt"
CRT_CONTENTS_FILE="/tmp/tls.crt.txt"
KEY_FILE="/tmp/tls.key"

function get_cert() {
# Get certificate from secret
kubectl get secret \
-n "${NAMESPACE}" \
"${SECRET_NAME}" \
-o jsonpath="{.data.${TLS_CRT_KEY//./\\.}}" \
| base64 -d \
> "${CRT_FILE}" || return 1

kubectl get secret \
-n "${NAMESPACE}" \
"${SECRET_NAME}" \
-o jsonpath="{.data.${TLS_KEY_KEY//./\\.}}" \
| base64 -d \
> "${KEY_FILE}" || return 1

# Decode it as an x509 certificate
openssl x509 -in "${CRT_FILE}" -text -noout > "${CRT_CONTENTS_FILE}"

CRT_SIG="$(openssl x509 -noout -modulus -in "${CRT_FILE}" | openssl md5)"
KEY_SIG="$(openssl rsa -noout -modulus -in "${KEY_FILE}" | openssl md5)"

if [ "${CRT_SIG}" != "${KEY_SIG}" ]; then
echo "Certificate (${TLS_CRT_KEY}) does not match key (${TLS_KEY_KEY})"
return 1
fi
}

function cert_matches_domain_name() {
grep "${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1
grep "\*.${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1
grep "\*.ws.${DOMAIN}" "${CRT_CONTENTS_FILE}" || return 1
}

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 -u "+%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
mrsimonemms marked this conversation as resolved.
Show resolved Hide resolved
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
9 changes: 9 additions & 0 deletions components/kots-config-check/certificate/leeway.Dockerfile
Original file line number Diff line number Diff line change
@@ -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" ]
45 changes: 45 additions & 0 deletions install/kots/manifests/kots-support-bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ metadata:
name: gitpod
spec:
collectors:
- runPod:
name: certificate
namespace: '{{repl Namespace }}'
podSpec:
serviceAccountName: kotsadm
containers:
- name: certificate
image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/certificate:mrsimonemms-add-kots-support-bundle-11865.7
args:
- '{{repl ConfigOption "domain" }}' # DOMAIN
- '{{repl Namespace }}' # NAMESPACE
- https-certificates # SECRET_NAME
- tls.crt # TLS_CRT_KEY
- tls.key # TLS_KEY_KEY
- run:
collectorName: database
image: eu.gcr.io/gitpod-core-dev/build/kots-config-check/database:sje-kots-config-check.9
Expand Down Expand Up @@ -125,3 +139,34 @@ spec:
- '{{repl LicenseFieldValue "appSlug" }}'
- --namespace
- '{{repl Namespace }}'
analyzers:
- textAnalyze:
checkName: TLS certificate exists
fileName: certificate/certificate.log
regexGroups: 'cert_exists: (?P<Valid>\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<Valid>\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<Valid>\w+)'
outcomes:
- pass:
when: "Valid == 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.