From 9fe331c4a3ea39b64645018d67826c2382c35740 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Fri, 16 Feb 2024 05:43:12 +0700 Subject: [PATCH] update: set custom CA Certificate installation docs (#2136) --- .github/workflows/helm-chart-test.yml | 2 + Base/Dockerfile | 8 +++- Makefile | 3 ++ README.md | 56 ++++++++++----------------- tests/customCACert/Dockerfile | 21 ++++++++++ tests/customCACert/bootstrap.sh | 32 +++++++++++++++ tests/customCACert/cert-script.sh | 24 ++++++++++++ 7 files changed, 109 insertions(+), 37 deletions(-) create mode 100644 tests/customCACert/Dockerfile create mode 100755 tests/customCACert/bootstrap.sh create mode 100644 tests/customCACert/cert-script.sh diff --git a/.github/workflows/helm-chart-test.yml b/.github/workflows/helm-chart-test.yml index e1908bcd5..55886a7b3 100644 --- a/.github/workflows/helm-chart-test.yml +++ b/.github/workflows/helm-chart-test.yml @@ -79,6 +79,8 @@ jobs: command: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make chart_cluster_setup - name: Build Docker images run: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build + - name: Test set custom CA certificate + run: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make test_custom_ca_cert - name: Set test parameters if: (matrix.test-strategy == 'job' || matrix.test-strategy == 'deployment') && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') run: | diff --git a/Base/Dockerfile b/Base/Dockerfile index 387f8b0bf..27a9980a3 100644 --- a/Base/Dockerfile +++ b/Base/Dockerfile @@ -95,7 +95,8 @@ COPY supervisord.conf /etc #========== # Selenium & relaxing permissions for OpenShift and other non-sudo environments #========== -RUN mkdir -p /opt/selenium /opt/selenium/assets /var/run/supervisor /var/log/supervisor ${SEL_DOWNLOAD_DIR} ${HOME}/.mozilla ${HOME}/.vnc \ +RUN mkdir -p /opt/selenium /opt/selenium/assets /var/run/supervisor /var/log/supervisor ${SEL_DOWNLOAD_DIR} \ + ${HOME}/.mozilla ${HOME}/.vnc $HOME/.pki/nssdb \ && touch /opt/selenium/config.toml \ && chown -R ${SEL_USER}:${SEL_GROUP} /opt/selenium /var/run/supervisor /var/log/supervisor /etc/passwd ${HOME} \ && chmod -R 775 /opt/selenium /var/run/supervisor /var/log/supervisor /etc/passwd ${HOME} \ @@ -129,6 +130,11 @@ RUN rm -fr /root/.cache/* #=================================================== USER ${SEL_UID}:${SEL_GID} +#========== +# NSSDB initialization with an empty password +#========== +RUN certutil -d sql:$HOME/.pki/nssdb -N --empty-password + # Boolean value, maps "--bind-host" ENV SE_BIND_HOST false # Boolean value, maps "--reject-unsupported-caps" diff --git a/Makefile b/Makefile index ed26be294..e6fa5a22d 100644 --- a/Makefile +++ b/Makefile @@ -413,6 +413,9 @@ test_video: video hub chrome firefox edge docker run -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) -v error -i ./tests/videos/firefox_video.mp4 -f null - 2>error.log docker run -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) -v error -i ./tests/videos/edge_video.mp4 -f null - 2>error.log +test_custom_ca_cert: + VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/customCACert/bootstrap.sh + chart_setup_env: ./tests/charts/make/chart_setup_env.sh diff --git a/README.md b/README.md index 8d65f8bec..fdcdc0f08 100644 --- a/README.md +++ b/README.md @@ -1122,45 +1122,29 @@ ___ ## Install certificates for Chromium-based browsers -If you need to install custom certificates, CA, intermediate CA, or client certificates (for example enterprise internal CA) -you can use the different utils that come from libnss3-tools. -The chromium-based browser uses nssdb as a certificate store. -Create a new nssdb: -```bash -certutil -d sql:$HOME/.pki/nssdb -N -``` -For example, to trust a root CA certificate for issuing SSL server certificates, use -```bash -certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n -i -``` -To import an intermediate CA certificate, use -```bash -certutil -d sql:$HOME/.pki/nssdb -A -t ",," -n -i -``` -You can find more information [here](https://chromium.googlesource.com/chromium/src/+/master/docs/linux/cert_management.md) -Usage example: -If your company has an internal CA you can create your own dockerimage from selenium node image. +By default, the based image is installed `libnss3-tools` and initializes `/home/seluser/.pki/nssdb`, +so you are able to add your certs with rootless. +If you need to install custom certificates, CA, intermediate CA, +or client certificates (for example, enterprise internal CA) +you can create your own docker image from selenium node image. +The Chromium-based browser uses `nssdb` as a certificate store. You can then install all required internal certificates in your Dockerfile like this: + +- Create a script for installing the certificates. For example, [cert-script.sh](tests/customCACert/cert-script.sh) +- Create a Dockerfile that uses the selenium node image as a base and copies the script to the container, and executes it. +For example, [Dockerfile](tests/customCACert/Dockerfile) +- If you have to create a set of different certificates and node images. You can create a bootstrap script to do that in one-shot. +For example, [bootstrap.sh](tests/customCACert/bootstrap.sh) + +The above example can be tested with the following command: + ```bash -FROM selenium/node-edge:latest -USER root -COPY certs/ /etc/certs # copy over the certificate file - -#========= -# libnss3-tools -# Network Security Service tools -# Manage certificates in nssdb (certutil, pk12util, modutil, shlibsign, signtool, ssltap) -#========= -RUN apt-get update -qqy \ - && apt-get -qqy install \ - libnss3-tools \ - && rm -rf /var/lib/apt/lists/* /var/cache/apt/* - -RUN mkdir -p -m755 /home/seluser/.pki/nssdb \ #create nssdb folder - && certutil -d sql:/home/seluser/.pki/nssdb -N --empty-password \ # create new db without password - && certutil -d sql:/home/seluser/.pki/nssdb -A -t "C,," -n companyca -i /etc/certs/companeca.pem \ #trust company CA - && pk12util -d sql:/home/seluser/.pki/nssdb -i client_cert.p12 -W password_of_clent_cert # client certificate install +make test_custom_ca_cert +# ./tests/customCACert/bootstrap.sh ``` + +You can find more information [here](https://chromium.googlesource.com/chromium/src/+/master/docs/linux/cert_management.md) + This way the certificates will be installed and the node will start automatically as before. ___ diff --git a/tests/customCACert/Dockerfile b/tests/customCACert/Dockerfile new file mode 100644 index 000000000..38750c2af --- /dev/null +++ b/tests/customCACert/Dockerfile @@ -0,0 +1,21 @@ +ARG NAMESPACE=selenium +ARG BASE=node-chrome +ARG VERSION=latest +FROM ${NAMESPACE}/${BASE}:${VERSION} + +USER root + +ARG CERT_FILE +ARG PERM=577 +RUN mkdir -p /usr/share/ca-certificates/extra/ +COPY ${CERT_FILE} /usr/share/ca-certificates/extra/ +RUN chmod -R ${PERM} /usr/share/ca-certificates/extra/ +RUN update-ca-certificates + +ARG CERT_SCRIPT +COPY --chown="${SEL_UID}:${SEL_GID}" ${CERT_SCRIPT} /usr/share/ca-certificates/cert-script.sh +RUN chmod +x /usr/share/ca-certificates/cert-script.sh + +USER ${SEL_UID} +ARG TRUST_ATTR=TCu,Cu,Tu +RUN bash /usr/share/ca-certificates/cert-script.sh /usr/share/ca-certificates/extra/ ${TRUST_ATTR} diff --git a/tests/customCACert/bootstrap.sh b/tests/customCACert/bootstrap.sh new file mode 100755 index 000000000..cd83a37de --- /dev/null +++ b/tests/customCACert/bootstrap.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -x + +# Function to be executed on command failure +on_failure() { + local exit_status=$? + echo "There is step failed with exit status $exit_status" + exit $exit_status +} + +# Trap ERR signal and call on_failure function +trap 'on_failure' ERR + +NAMESPACE=${NAME:-"selenium"} +VERSION=${VERSION:-$TAG_VERSION} +CERT_FILE=${CERT_FILE:-"./charts/selenium-grid/certs/*.pem"} +CERT_SCRIPT=${CERT_SCRIPT:-"./tests/customCACert/cert-script.sh"} + +COMMON_BUILD_ARGS="--build-arg NAMESPACE=${NAMESPACE} --build-arg VERSION=${VERSION} --build-arg CERT_FILE=${CERT_FILE} --build-arg CERT_SCRIPT=${CERT_SCRIPT}" + +docker build ${COMMON_BUILD_ARGS} --build-arg BASE=node-chrome -t ${NAMESPACE}/node-chrome:${VERSION} -f ./tests/customCACert/Dockerfile . +docker build ${COMMON_BUILD_ARGS} --build-arg BASE=node-firefox -t ${NAMESPACE}/node-firefox:${VERSION} -f ./tests/customCACert/Dockerfile . +docker build ${COMMON_BUILD_ARGS} --build-arg BASE=node-edge -t ${NAMESPACE}/node-edge:${VERSION} -f ./tests/customCACert/Dockerfile . + +list_cert_files=($(find ./charts/selenium-grid/certs/ -name "*.pem")) +for cert_file_path in "${list_cert_files[@]}"; do + cert_file_name="$(basename ${cert_file_path})" + cert_name="${cert_file_name%.*}" + docker run --entrypoint="" --rm ${NAMESPACE}/node-chrome:${VERSION} bash -c "certutil -L -d sql:/home/seluser/.pki/nssdb -n ${cert_name}" | grep -q "SeleniumHQ" + docker run --entrypoint="" --rm ${NAMESPACE}/node-firefox:${VERSION} bash -c "certutil -L -d sql:/home/seluser/.pki/nssdb -n ${cert_name}" | grep -q "SeleniumHQ" + docker run --entrypoint="" --rm ${NAMESPACE}/node-edge:${VERSION} bash -c "certutil -L -d sql:/home/seluser/.pki/nssdb -n ${cert_name}" | grep -q "SeleniumHQ" +done diff --git a/tests/customCACert/cert-script.sh b/tests/customCACert/cert-script.sh new file mode 100644 index 000000000..24ab4389c --- /dev/null +++ b/tests/customCACert/cert-script.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -x + +echo "$(whoami) is running cert script!" + +CERT_DIR=${1:-"/usr/share/ca-certificates/extra/"} +TRUST_ATTR=${2:-"TCu,Cu,Tu"} + +# Get the list of certs copied +cert_files=($(ls $CERT_DIR)) + +# Find all "cert9.db" files +cert_db_files=($(find ${HOME}/ -name "cert9.db")) + +for cert_file in "${cert_files[@]}"; do + cert_file="${CERT_DIR}/${cert_file}" + file_name=$(basename $cert_file) + cert_name="${file_name%.*}" + for cert_db_file in "${cert_db_files[@]}"; do + cert_db_path=$(dirname $cert_db_file) + certutil -d "sql:${cert_db_path}" -A -t "${TRUST_ATTR}" -n "${cert_name}" -i "${cert_file}" + certutil -L -d "sql:${cert_db_path}" -n "${cert_name}" + done +done