From b1968f2606964bc1b7f86a89957c4b660c302622 Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Thu, 28 Nov 2024 15:09:42 +0100 Subject: [PATCH] feat: Initial commit Signed-off-by: Anatolii Bazko --- .github/workflows/pr-check.yml | 27 ++++++ .github/workflows/release.yaml | 41 +++++++++ Dockerfile | 20 ++++ README.md | 27 ++++++ entrypoint.sh | 164 +++++++++++++++++++++++++++++++++ 5 files changed, 279 insertions(+) create mode 100644 .github/workflows/pr-check.yml create mode 100644 .github/workflows/release.yaml create mode 100644 Dockerfile create mode 100644 README.md create mode 100755 entrypoint.sh diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..68959c6 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,27 @@ +# +# Copyright (c) 2020 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +name: PR check +on: pull_request +jobs: + multiplatform-image-build: + runs-on: ubuntu-22.04 + steps: + - name: Checkout source code + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build images + uses: docker/build-push-action@v3 + with: + file: Dockerfile + platforms: linux/amd64,linux/ppc64le,linux/arm64 + tags: quay.io/eclipse/che-tls-secret-creator:next diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..cb79f22 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,41 @@ +# +# Copyright (c) 2020 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +name: Build and push image + +on: + push: + branches: + - 'main' + workflow_dispatch: + inputs: + reason: + description: 'Reason to trigger' + required: false + +jobs: + multiplatform-image-build: + runs-on: ubuntu-22.04 + steps: + - name: Checkout source code + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build images + uses: docker/build-push-action@v3 + with: + file: Dockerfile + platforms: linux/amd64,linux/ppc64le,linux/arm64 + tags: quay.io/eclipse/che-tls-secret-creator:next + push: true + env: + DOCKER_USERNAME: ${{ secrets.QUAY_USERNAME }} + DOCKER_PASSWORD: ${{ secrets.QUAY_PASSWORD }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1981ee1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +FROM registry.access.redhat.com/ubi8-minimal:8.10-1130 + +ARG KUBERNETES_VERSION=v1.31.0 + +RUN export ARCH="$(uname -m)" && if [[ ${ARCH} == "x86_64" ]]; then export ARCH="amd64"; elif [[ ${ARCH} == "aarch64" ]]; then export ARCH="arm64"; fi && \ + microdnf install -y openssl && \ + cd /usr/local/bin && \ + curl -sLO https://storage.googleapis.com/kubernetes-release/release/${KUBERNETES_VERSION}/bin/linux/${ARCH}/kubectl && \ + chmod +x kubectl && \ + microdnf clean all + +COPY entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..65a0971 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Che TLS certificates and secrets creation image + +This images generates TLS certificates required for Eclipse Che deployment and creates corresponding secrets in Eclipse Che dedicated namespace. +It is used as Kubernetes job image and should be run before Eclipse Che deploying process is started. +The job is usually started from Che operator reconcile loop. + +All parameters to this image is passed as environment variables. + +Required parameters: + + - `DOMAIN` should be set with the list of cluster public domains with or without wildcard. + +Optional parameters: + + - `CHE_NAMESPACE` is the namespace name into which Eclipse Che should be deployed. + If now specified, default value `che` is used. + - `CHE_SERVER_TLS_SECRET_NAME` is the name of TLS secret into which generated TLS certificate should be saved. + The namespace is defined by `CHE_NAMESPACE` environment variable. + Default value is `che-tls`. + - `CHE_CA_CERTIFICATE_SECRET_NAME` is the name of the secret in which Che CA certificate should be saved. + This certificate should be shared with all users and each user should add it into OS or browser trust store. + The namespace is defined by `CHE_NAMESPACE` environment variable. + Default value is `self-signed-certificate`. + - `LABELS` is a space separated list of labels to add to the generated secret. + Could be empty. + +Image repository is `quay.io/eclipse/che-tls-secret-creator` and could be found [here](https://quay.io/repository/eclipse/che-tls-secret-creator). diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..d59bfb3 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,164 @@ +#!/bin/bash +# Copyright (c) 2020 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + + +######################################### +# Generate Che CA and server certificates +######################################### + +# Should be provided as environment variable. +# Examples: +# che.domain.net +# 192.168.99.100.nip.io +DOMAIN=${DOMAIN} +if [ -z "$DOMAIN" ]; then + echo 'Error: "DOMAIN" environment variable is not set' + exit 1 +fi +DNS_ENTRIES=DNS:$(echo ${DOMAIN} | sed 's|,|,DNS:|g') +CHE_CA_CN='Local Eclipse Che Signer' +CHE_CA_KEY_FILE='ca.key' +CHE_CA_CERT_FILE='ca.crt' + +ECLIPSE_CHE_SERVER='Eclipse Che Server' +CHE_SERVER_ORG='Local Eclipse Che' +CHE_SERVER_KEY_FILE='domain.key' +CHE_SERVER_CERT_REQUEST_FILE='domain.csr' +CHE_SERVER_CERT_FILE='domain.crt' + +# Figure out openssl configuration file location +OPENSSL_CNF='/etc/pki/tls/openssl.cnf' +if [ ! -f $OPENSSL_CNF ]; then + OPENSSL_CNF='/etc/ssl/openssl.cnf' +fi + +# Change directory to writable one +cd $HOME + +# Generate private key for Che root CA +# Options: +# -out : name of file to write generated key to +# 4096 : number of bits in the key +openssl genrsa -out $CHE_CA_KEY_FILE 4096 + +# Generate Che root CA certificate and sign it with previously generated key. +# Options: +# -batch : script (non-interactive) mode +# -new : creates new sertificate request +# -x509 : produces self signed sertificate instead of certificate request +# -nodes : no DES, do not encrypt private key +# -key : private key to use to sign this certificate +# -sha256 : hash to use +# -subj : subject name. Should contain at least distinguished (common) name (CN). Format: /type0=value0/type1=value1 +# -days : number of days this certificate will be valid for +# -reqexts : specifies extension to be included +# -extensions : adds extensions (with its configuration) +# -config : openssl config file to use +# -outform : format of the certificate container +# -out : name of file to write generated certificate to +openssl req -batch -new -x509 -nodes -key $CHE_CA_KEY_FILE -sha256 \ + -subj /CN="${CHE_CA_CN}" \ + -days 1024 \ + -reqexts SAN -extensions SAN \ + -config <(cat ${OPENSSL_CNF} <(printf '[SAN]\nbasicConstraints=critical, CA:TRUE\nkeyUsage=keyCertSign, cRLSign, digitalSignature')) \ + -outform PEM -out $CHE_CA_CERT_FILE + +# Generate Che server prvate key. +# Options: +# -out : name of file to write generated key to +# 2048 : number of bits in the key +openssl genrsa -out $CHE_SERVER_KEY_FILE 2048 + +# Create certificate request for the Che server domain. +# Options: +# -batch : script (non-interactive) mode +# -new : creates new sertificate request +# -sha256 : hash to use +# -key : private key to use to sign this certificate request +# -subj : subject name, defines some information about future certificate +# -reqexts : specifies extension to be included +# -config : openssl config file to use +# -outform : format of the certificate container +# -out : name of file to write generated certificate to +openssl req --batch -new -sha256 -key $CHE_SERVER_KEY_FILE \ + -subj "/O=${CHE_SERVER_ORG}/CN=${ECLIPSE_CHE_SERVER}" \ + -reqexts SAN \ + -config <(cat $OPENSSL_CNF <(printf "\n[SAN]\nsubjectAltName=${DNS_ENTRIES}\nbasicConstraints=critical, CA:FALSE\nkeyUsage=digitalSignature, keyEncipherment, keyAgreement, dataEncipherment\nextendedKeyUsage=serverAuth")) \ + -outform PEM -out $CHE_SERVER_CERT_REQUEST_FILE + +# Create certificate for the Che server domain based on given certificate request. +# Options: +# -req : process certificate request instead of certificate +# -in : specifies file with certificate request to process +# -CA : CA certificate which should be used for signing the certificate request +# -CAkey : specifies CA private key to sign the certificate request with +# -CAcreateserial : generate and include certificate serial number +# -sha256 : hash to use +# -days : number of days this certificate will be valid for +# -extfile : config file which contains certificate extensions which should be included in the resulting certificate +# -outform : format of the certificate container +# -out : name of file to write generated certificate to +openssl x509 -req -in $CHE_SERVER_CERT_REQUEST_FILE -CA $CHE_CA_CERT_FILE -CAkey $CHE_CA_KEY_FILE -CAcreateserial \ + -days 365 \ + -sha256 \ + -extfile <(printf "subjectAltName=${DNS_ENTRIES}\nbasicConstraints=critical, CA:FALSE\nkeyUsage=digitalSignature, keyEncipherment, keyAgreement, dataEncipherment\nextendedKeyUsage=serverAuth") \ + -outform PEM -out $CHE_SERVER_CERT_FILE + +# Check that required files have been created +if ! [[ -f $CHE_CA_CERT_FILE && -f $CHE_SERVER_KEY_FILE && -f $CHE_SERVER_CERT_FILE ]]; then + echo 'Error during certificates generation phase. Check logs above.' + exit 10 +fi + +#Log that all certificates are created +echo 'Che TLS certificates are created.' + + +############################################ +# Create secrets from generated certificates +############################################ + +# It is supposed that the Che namespace is already exists + +CHE_NAMESPACE="${CHE_NAMESPACE:-che}" +CHE_SERVER_TLS_SECRET_NAME="${CHE_SERVER_TLS_SECRET_NAME:-che-tls}" +CHE_CA_CERTIFICATE_SECRET_NAME="${CHE_CA_CERTIFICATE_SECRET_NAME:-self-signed-certificate}" + +# Create Che server TLS secret for trafic encryption. Private. +kubectl create secret tls $CHE_SERVER_TLS_SECRET_NAME --key=$CHE_SERVER_KEY_FILE --cert=$CHE_SERVER_CERT_FILE --namespace=$CHE_NAMESPACE +if [ $? -ne 0 ]; then + echo "Error while creating TLS secret \"${CHE_SERVER_TLS_SECRET_NAME}\"." + exit 20 +fi + +# Create Che certificate authority secret. Public. Should be shared with users and imported in browser. +kubectl create secret generic $CHE_CA_CERTIFICATE_SECRET_NAME --from-file=$CHE_CA_CERT_FILE --namespace=$CHE_NAMESPACE +if [ $? -ne 0 ]; then + echo "Error while creating secret \"${CHE_CA_CERTIFICATE_SECRET_NAME}\"." + exit 21 +fi + +# Label the resulting secrets. +# It is used to have the secret cached in the operator client. +if [ -n "$LABELS" ]; then + kubectl label secret "${CHE_SERVER_TLS_SECRET_NAME}" ${LABELS} --namespace=$CHE_NAMESPACE + if [ $? -ne 0 ]; then + echo "Error while labeling secret \"${CHE_SERVER_TLS_SECRET_NAME}\"." + exit 22 + fi + + kubectl label secret "${CHE_CA_CERTIFICATE_SECRET_NAME}" ${LABELS} --namespace=$CHE_NAMESPACE + if [ $? -ne 0 ]; then + echo "Error while labeling secret \"${CHE_CA_CERTIFICATE_SECRET_NAME}\"." + exit 23 + fi +fi + +# Log that everything is done +echo 'Che TLS secrets are created.'