Skip to content

Commit

Permalink
Merge pull request #654 from opendevstack/fix/tls-issues
Browse files Browse the repository at this point in the history
Fix private cert issues discovered in manual testing
  • Loading branch information
michaelsauter authored Feb 10, 2023
2 parents 6a79c04 + de8182f commit a6b6ccb
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ jobs:
go test -v ./cmd/... | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
go test -v ./internal/... | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
go test -v ./pkg/... | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
go test -timeout 30m -v ./test/tasks/... -always-keep-tmp-workspaces | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
go test -timeout 45m -v ./test/tasks/... -always-keep-tmp-workspaces | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
go test -timeout 10m -v ./test/e2e/... | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
-
name: Log into ghcr.io
Expand Down
29 changes: 2 additions & 27 deletions build/package/Dockerfile.start
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ ARG TARGETARCH
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
USER root

ENV TEKTON_VERSION=0.24.0 \
TEKTONCD_PATH=/opt/app-root/src/go/src/github.com/tektoncd \
BINARY=git-init.orig \
KO_APP=/ko-app \
GIT_LFS_VERSION=3.0.2
ENV GIT_LFS_VERSION=3.0.2

# Build Go binary.
RUN mkdir -p /etc/go
Expand All @@ -20,25 +16,14 @@ COPY internal /etc/go/internal
COPY pkg /etc/go/pkg
RUN cd /etc/go/cmd/start && CGO_ENABLED=0 go build -o /usr/local/bin/ods-start

RUN mkdir -p $TEKTONCD_PATH && \
cd /tmp && \
curl -LO https://github.com/tektoncd/pipeline/archive/refs/tags/v$TEKTON_VERSION.tar.gz && \
tar -C $TEKTONCD_PATH -xzf v$TEKTON_VERSION.tar.gz && \
ln -s $TEKTONCD_PATH/pipeline-$TEKTON_VERSION $TEKTONCD_PATH/pipeline && \
cd -

WORKDIR $TEKTONCD_PATH/pipeline

# Install Git LFS.
RUN cd /tmp \
&& mkdir -p /tmp/git-lfs \
&& curl -LO https://github.com/git-lfs/git-lfs/releases/download/v${GIT_LFS_VERSION}/git-lfs-linux-${TARGETARCH}-v${GIT_LFS_VERSION}.tar.gz \
&& tar -zxvf git-lfs-linux-${TARGETARCH}-v${GIT_LFS_VERSION}.tar.gz -C /tmp/git-lfs \
&& bash /tmp/git-lfs/install.sh \
&& git lfs version

RUN CGO_ENABLED=0 go build -o /tmp/openshift-pipelines-git-init ./cmd/git-init && \
mkdir ${KO_APP} && cp /tmp/openshift-pipelines-git-init ${KO_APP}/${BINARY}

# Final image
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4

Expand All @@ -53,14 +38,4 @@ COPY --from=builder /usr/local/bin/ods-start /usr/local/bin/ods-start
COPY --from=builder /usr/local/bin/git-lfs /usr/local/bin/git-lfs
RUN git lfs version

RUN mkdir /ko-app
COPY --from=builder /ko-app/git-init.orig /ko-app/git-init.orig
COPY build/package/scripts/uidwrapper /ko-app/git-init

USER root
RUN chgrp -R 0 /ko-app && \
chmod -R g=u /ko-app /etc/passwd

USER 1001

ENTRYPOINT ["/ko-app/git-init"]
20 changes: 11 additions & 9 deletions build/package/scripts/configure-gradle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
CONTENT=""

if [ -f /etc/ssl/certs/private-cert.pem ]; then
echo "Configuring Gradle to trust private cert ..."
configure-truststore --dest-store ".ods-cache/truststore/cacerts"
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
exit 1
fi
# Configure Gradle to use the modified trust store.
CONTENT+="systemProp.javax.net.ssl.trustStore=.ods-cache/keystore/cacerts\n"
CONTENT+="systemProp.javax.net.ssl.trustStorePassword=password\n"
truststore_location="$(pwd)/.ods-cache/truststore/cacerts"
truststore_pass="changeit"
echo "Configuring Gradle to trust private cert ..."
configure-truststore --dest-store="${truststore_location}" --dest-storepass="${truststore_pass}"
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
exit 1
fi
# Configure Gradle to use the modified trust store.
CONTENT+="systemProp.javax.net.ssl.trustStore=${truststore_location}\n"
CONTENT+="systemProp.javax.net.ssl.trustStorePassword=${truststore_pass}\n"
fi

if [ "${HTTP_PROXY}" != "" ]; then
Expand Down
11 changes: 9 additions & 2 deletions build/package/scripts/configure-truststore.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -u

md5_bin="${MD5_BIN:-"md5sum --tag"}"
md5_bin="${MD5_BIN:-"md5sum"}"
private_cert="/etc/ssl/certs/private-cert.pem"
src_truststore="${JAVA_HOME}/lib/security/cacerts"
src_pass="changeit"
Expand Down Expand Up @@ -30,16 +30,20 @@ esac; shift; done
dest_truststore_dir="${dest_truststore%/*}"
mkdir -p "${dest_truststore_dir}"
md5_private_cert_path="${dest_truststore_dir}/.md5-private-cert"
md5_private_cert=$(${md5_bin} "${private_cert}")
md5_private_cert=$(${md5_bin} < "${private_cert}" | cut -d- -f1)

if [ ! -f "${dest_truststore}" ] || [ "${md5_private_cert}" != "$(cat "${md5_private_cert_path}")" ]; then
echo "Creating truststore with private cert ..."
# Copy global keystone to location where we can write to (hide output containing warnings).
if [ -f "${dest_truststore}" ]; then
rm "${dest_truststore}"
fi
keytool -importkeystore \
-srckeystore "${src_truststore}" -destkeystore "${dest_truststore}" \
-deststorepass "${dest_pass}" -srcstorepass "${src_pass}" &> keytool-output.txt
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
echo "error importing keystore:"
cat keytool-output.txt; exit 1
fi
# Trust private cert (hide output containing warnings).
Expand All @@ -48,7 +52,10 @@ if [ ! -f "${dest_truststore}" ] || [ "${md5_private_cert}" != "$(cat "${md5_pri
-keystore "${dest_truststore}" -storepass "${dest_pass}" &> keytool-output.txt
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
echo "error importing cert:"
cat keytool-output.txt; exit 1
fi
echo "${md5_private_cert}" > "${md5_private_cert_path}"
else
echo "Trustore with private cert exists already and is up-to-date."
fi
7 changes: 4 additions & 3 deletions build/package/scripts/download-aqua-scanner.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -eu

md5_bin="${MD5_BIN:-"md5sum --tag"}"
md5_bin="${MD5_BIN:-"md5sum"}"
aqua_scanner_url=""
bin_dir=".ods-cache/bin"

Expand All @@ -21,15 +21,16 @@ esac; shift; done

aqua_scanner_path="${bin_dir}/aquasec"
md5_aqua_scanner_url_path="${bin_dir}/.md5-aquasec"
mkdir -p "${bin_dir}"

# Optionally install Aqua scanner.
# If the binary already exists and was downloaded from the
# URL given by aqua_scanner_url, skip download.
if [ -n "${aqua_scanner_url}" ] && [ "${aqua_scanner_url}" != "none" ]; then
md5_aqua_scanner_url=$(${md5_bin} -s "${aqua_scanner_url}")
md5_aqua_scanner_url=$(printf "%s" "${aqua_scanner_url}" | ${md5_bin} | cut -d- -f1)
if [ ! -f "${md5_aqua_scanner_url_path}" ] || [ "${md5_aqua_scanner_url}" != "$(cat "${md5_aqua_scanner_url_path}")" ]; then
echo 'Installing Aqua scanner...'
curl -v -sSf -L "${aqua_scanner_url}" -o aquasec
curl -sSf -L "${aqua_scanner_url}" -o aquasec
mv aquasec "${aqua_scanner_path}"
chmod +x "${aqua_scanner_path}"
echo "${md5_aqua_scanner_url}" > "${md5_aqua_scanner_url_path}"
Expand Down
82 changes: 54 additions & 28 deletions cmd/start/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"errors"
"flag"
"fmt"
Expand Down Expand Up @@ -365,7 +366,7 @@ func downloadArtifacts(
logger,
)
if err != nil {
return err
return fmt.Errorf("download group %s: %w", group, err)
}
return pipelinectxt.WriteJsonArtifact(am, artifactsDir, pipelinectxt.ArtifactsManifestFilename)

Expand All @@ -374,65 +375,81 @@ func downloadArtifacts(
func checkoutAndAssembleContext(
checkoutDir, url, gitFullRef, gitRefSpec, sslVerify, submodules, depth string,
baseCtxt *pipelinectxt.ODSContext,
logger logging.LeveledLoggerInterface) (*pipelinectxt.ODSContext, error) {
logger logging.LeveledLoggerInterface) (ctxt *pipelinectxt.ODSContext, err error) {
workingDir, err := os.Getwd()
if err != nil {
return
}
// Change back to working dir after checkout.
defer func(wd string) {
if err != nil { // if there are previous errors, give them predence.
return
}
err = os.Chdir(wd)
}(workingDir)

absCheckoutDir, err := filepath.Abs(checkoutDir)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("absolute path: %w", err)
}
logger.Infof("Checking out %s@%s into %s ...", url, gitFullRef, absCheckoutDir)
gitInitArgs := []string{
fmt.Sprintf("-url=%v", url),
fmt.Sprintf("-revision=%v", gitFullRef),
fmt.Sprintf("-refspec=%v", gitRefSpec),
fmt.Sprintf("-path=%v", absCheckoutDir),
fmt.Sprintf("-sslVerify=%v", sslVerify),
fmt.Sprintf("-submodules=%v", submodules),
fmt.Sprintf("-depth=%v", depth),
}
logger.Debugf("git-init %s", strings.Join(gitInitArgs, " "))
stdout, stderr, err := command.RunBuffered("/ko-app/git-init", gitInitArgs)
if err != nil {
logger.Errorf(string(stderr))
log.Fatal(err)
if err := os.Chdir(absCheckoutDir); err != nil {
return nil, fmt.Errorf("change dir: %w", err)
}
if err := runGit("init"); err != nil {
return nil, fmt.Errorf("run git cmd: %w", err)
}

if err := runGit("remote", "add", "origin", url); err != nil {
return nil, fmt.Errorf("run git cmd: %w", err)
}
if err := runGit("fetch",
"--recurse-submodules=yes", fmt.Sprintf("--depth=%s", depth),
"origin",
"--update-head-ok", "--force", gitFullRef,
); err != nil {
return nil, fmt.Errorf("run git cmd: %w", err)
}
if err := runGit("checkout", "-f", "FETCH_HEAD"); err != nil {
return nil, fmt.Errorf("run git cmd: %w", err)
}
logger.Infof(string(stdout))

odsPipelineIgnoreFile := filepath.Join(absCheckoutDir, ".git", "info", "exclude")
if err := pipelinectxt.WriteGitIgnore(odsPipelineIgnoreFile); err != nil {
log.Fatal(err)
return nil, fmt.Errorf("write git ignore: %w", err)
}
logger.Infof("Wrote gitignore exclude at %s", odsPipelineIgnoreFile)

// check git LFS state and maybe pull
lfs, err := gitLfsInUse(logger, absCheckoutDir)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("check if git LFS is in use: %w", err)
}
if lfs {
logger.Infof("Git LFS detected, enabling and pulling files...")
err := gitLfsEnableAndPullFiles(logger, absCheckoutDir)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("git LFS enable and pull: %w", err)
}
}

// write ODS cache
sha, err := getCommitSHA(absCheckoutDir)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("commit SHA: %w", err)
}
ctxt := baseCtxt.Copy()
ctxt = baseCtxt.Copy()
ctxt.GitFullRef = gitFullRef
ctxt.GitCommitSHA = sha
err = ctxt.Assemble(absCheckoutDir)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("assemble ODS context: %w", err)
}
err = ctxt.WriteCache(absCheckoutDir)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("write ODS context cache: %w", err)
}
return ctxt, nil
return
}

func getCommitSHA(dir string) (string, error) {
Expand All @@ -454,13 +471,22 @@ func gitLfsInUse(logger logging.LeveledLoggerInterface, dir string) (lfs bool, e
func gitLfsEnableAndPullFiles(logger logging.LeveledLoggerInterface, dir string) (err error) {
stdout, stderr, err := command.RunBufferedInDir("git", []string{"lfs", "install"}, dir)
if err != nil {
return fmt.Errorf("cannot enable git lfs: %s (%w)", stderr, err)
return fmt.Errorf("lfs install: %s (%w)", stderr, err)
}
logger.Infof(string(stdout))
stdout, stderr, err = command.RunBufferedInDir("git", []string{"lfs", "pull"}, dir)
if err != nil {
return fmt.Errorf("cannot git pull lfs files: %s (%w)", stderr, err)
return fmt.Errorf("lfs pull: %s (%w)", stderr, err)
}
logger.Infof(string(stdout))
return err
}

func runGit(args ...string) error {
var output bytes.Buffer
err := command.Run("git", args, []string{}, &output, &output)
if err != nil {
return fmt.Errorf("git %v: %w\n%s", args, err, output.String())
}
return nil
}
4 changes: 2 additions & 2 deletions deploy/ods-pipeline/charts/tasks/templates/_sonar-step.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@

truststore="${JAVA_HOME}/lib/security/cacerts"
if [ -f /etc/ssl/certs/private-cert.pem ]; then
truststore=".ods-cache/truststore/cacerts"
truststore="$(pwd)/.ods-cache/truststore/cacerts"
configure-truststore --dest-store "${truststore}"
fi
configure-truststore --dest-store "${truststore}"
# sonar is built from cmd/sonar/main.go.
sonar \
-working-dir=$(params.working-dir) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ spec:
name: ods-pipeline
resources: {}
script: |
if [ -f /etc/ssl/certs/private-cert.pem ]; then
git config --global http.sslCAInfo /etc/ssl/certs/private-cert.pem
cat /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/certs/private-cert.pem > /tekton/home/git-cert.pem
git config --global http.sslCAInfo /tekton/home/git-cert.pem
fi
# ods-start is built from cmd/start/main.go.
Expand Down
8 changes: 1 addition & 7 deletions docs/design/software-design-specification.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Input parameters: TODO

| SDS-TASK-8
| `ods-start` container image
| Container image to start a pipeline. Based on `ubi8/ubi-minimal` (SDS-EXT-2), includes SDS-EXT-9, SDS-EXT-13, SDS-EXT-22, SDS-EXT-27, SDS-EXT-30 and SDS-TASK-9.
| Container image to start a pipeline. Based on `ubi8/ubi-minimal` (SDS-EXT-2), includes SDS-EXT-9, SDS-EXT-13, SDS-EXT-27, SDS-EXT-30 and SDS-TASK-9.

| SDS-TASK-9
| `start` binary
Expand Down Expand Up @@ -616,12 +616,6 @@ a| The script installs the Helm chart located in `deploy/ods-pipeline`. Further,
| Manages secrets with Git workflow.
| https://github.com/jkroepke/helm-secrets

| SDS-EXT-22
| Tekton
| 0.24
| Cloud-native Pipeline resource.
| https://github.com/tektoncd/pipeline

| SDS-EXT-23
| Sops
| 3.7
Expand Down

0 comments on commit a6b6ccb

Please sign in to comment.