feat: add iron bank Dockerfile & manifest (#5934)

* feat: add iron bank Dockerfile & manifest

Co-authored-by: Dean Sheather <dean@deansheather.com>

* add: tfrc file

* mv: ironbank/ /scripts

* fixup! Merge branch 'main' into iron-bank

* feat: add ironbank trivy scanning

* fixup! feat: add ironbank trivy scanning

* fixup! feat: add ironbank trivy scanning

* fixup! feat: add ironbank trivy scanning

* fixup! feat: add ironbank trivy scanning

---------

Co-authored-by: Dean Sheather <dean@deansheather.com>
This commit is contained in:
Eric Paulsen 2023-02-07 18:09:33 -05:00 committed by GitHub
parent 691495d761
commit f24547ecb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 319 additions and 2 deletions

View File

@ -92,6 +92,9 @@ jobs:
restore-keys: |
js-${{ runner.os }}-
- name: Install yq
run: go run github.com/mikefarah/yq/v4@v4.30.6
- name: Build Coder linux amd64 Docker image
id: build
run: |
@ -112,6 +115,17 @@ jobs:
make -j "$image_job"
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
- name: Build Coder linux amd64 Docker image (ironbank)
id: build-ironbank
run: |
set -euo pipefail
# NOTE: This is not a real image tag we publish.
image_tag="${{ steps.build.outputs.image }}-ironbank"
./scripts/ironbank/build_ironbank.sh \
--target "$image_tag" \
"build/coder_$(./scripts/version.sh)_linux_amd64"
echo "image=$image_tag" >> $GITHUB_OUTPUT
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5
with:
@ -124,10 +138,36 @@ jobs:
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: trivy-results.sarif
category: "Trivy"
- name: Run Trivy vulnerability scanner (ironbank)
uses: aquasecurity/trivy-action@7b7aa264d83dc58691451798b4d117d53d21edfe
with:
image-ref: ${{ steps.build-ironbank.outputs.image }}
format: sarif
output: trivy-results-ironbank.sarif
severity: "CRITICAL,HIGH"
# Update the tool name field in the ironbank SARIF file so it's not
# indistinguishable from findings in the non-ironbank SARIF file in the
# GitHub UI. Without this, findings from both scans would show up as
# "Trivy".
- name: Update tool name in SARIF file (ironbank)
run: |
set -euo pipefail
yq eval -i '.runs[0].tool.driver.name = "Trivy Ironbank"' trivy-results-ironbank.sarif
- name: Upload Trivy scan results to GitHub Security tab (ironbank)
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: trivy-results-ironbank.sarif
category: "Trivy Ironbank"
- name: Upload Trivy scan results as an artifact
uses: actions/upload-artifact@v2
with:
name: trivy
path: trivy-results.sarif
path: |
trivy-results.sarif
trivy-results-ironbank.sarif
retention-days: 7

6
scripts/ironbank/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
coder.tar.gz
terraform.zip
terraform-provider-coder.zip
.terraform.zip.*
.terraform-provider-coder.zip.*

View File

@ -0,0 +1,95 @@
ARG BASE_REGISTRY=registry1.dso.mil
ARG BASE_IMAGE=ironbank/redhat/ubi/ubi8-minimal
ARG BASE_TAG=8.7
FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG}
SHELL ["/bin/bash", "-c"]
ENV LANG=en_US.UTF-8
RUN microdnf update --assumeyes && \
microdnf install --assumeyes \
ca-certificates \
git \
gzip \
shadow-utils \
tar \
unzip && \
microdnf clean all
# Configure the cryptography policy manually. These policies likely
# have no impact, since Go doesn't link against these libraries.
#
# Normally, one uses the update-crypto-policies script to create these
# links, which is included in the crypto-policies-scripts package, but
# that pulls in Python, so we create the links manually here. This
# list of links comes from running strace on the update-crypto-policies
# script (strace update-crypto-policies --set FIPS) in Fedora, since
# RHEL and UBI do not provide an strace package by default.
RUN echo "FIPS" >/etc/crypto-policies/config && \
cp --force /usr/share/crypto-policies/policies/FIPS.pol /etc/crypto-policies/state/CURRENT.pol && \
echo "FIPS" >/etc/crypto-policies/state/current && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/bind.txt /etc/crypto-policies/back-ends/bind.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/gnutls.txt /etc/crypto-policies/back-ends/gnutls.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/java.txt /etc/crypto-policies/back-ends/java.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/krb5.txt /etc/crypto-policies/back-ends/krb5.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/libreswan.txt /etc/crypto-policies/back-ends/libreswan.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/libssh.txt /etc/crypto-policies/back-ends/libssh.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/nss.txt /etc/crypto-policies/back-ends/nss.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/openssh.txt /etc/crypto-policies/back-ends/openssh.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/opensshserver.txt /etc/crypto-policies/back-ends/opensshserver.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/openssl.txt /etc/crypto-policies/back-ends/openssl.config && \
ln --symbolic --force /usr/share/crypto-policies/FIPS/opensslcnf.txt /etc/crypto-policies/back-ends/opensslcnf.config
# Copy and extract Coder binary from tar file. We have to put this in /opt to
# match the Dockerfile.
ARG CODER_BIN=/opt/coder
ARG CODER_BIN_TAR_GZ=coder.tar.gz
COPY "$CODER_BIN_TAR_GZ" /tmp/coder.tar.gz
RUN mkdir -p /opt && \
tar -xzvf /tmp/coder.tar.gz --directory /opt --strip-components=1 ./coder && \
rm /tmp/coder.tar.gz
ENV PATH="/opt:${PATH}"
# Copy and extract Terraform binary from zip file.
ARG TERRAFORM_BIN_DIR=/opt/terraform
ARG TERRAFORM_BIN_ZIP=terraform.zip
COPY "$TERRAFORM_BIN_ZIP" /tmp/terraform.zip
RUN mkdir -p "$TERRAFORM_BIN_DIR" && \
unzip /tmp/terraform.zip -d "$TERRAFORM_BIN_DIR" && \
rm /tmp/terraform.zip
ENV PATH="${TERRAFORM_BIN_DIR}:${PATH}"
# Install the Coder Terraform provider to a well-known location.
ARG TERRAFORM_PLUGINS_DIR=/opt/terraform/plugins
ARG TERRAFORM_CODER_PROVIDER_VERSION
ARG TERRAFORM_CODER_PROVIDER_ZIP=terraform-provider-coder.zip
COPY "$TERRAFORM_CODER_PROVIDER_ZIP" "${TERRAFORM_PLUGINS_DIR}/registry.terraform.io/coder/coder/terraform-provider-coder_${TERRAFORM_CODER_PROVIDER_VERSION}_linux_amd64.zip"
# Configure Terraform to use plugins from this dir.
COPY terraform-filesystem-mirror.tfrc /opt/terraform/config.tfrc
ENV TF_CLI_CONFIG_FILE=/opt/terraform/config.tfrc
# Uninstall the build dependencies.
RUN microdnf remove --assumeyes \
tar \
unzip && \
microdnf clean all
# Transfer ownership of the binaries to the 'coder' user.
RUN useradd coder \
--create-home \
--shell=/bin/bash \
--uid=1000 \
--user-group && \
chown --recursive --quiet coder:coder "$CODER_BIN" && \
chown --recursive --quiet coder:coder "$TERRAFORM_BIN_DIR" && \
chown --recursive --quiet coder:coder "$TERRAFORM_PLUGINS_DIR" && \
chmod 0755 /home/coder
USER 1000
ENV HOME /home/coder
ENV USER=coder
ENTRYPOINT [ "/opt/coder", "server" ]

View File

@ -0,0 +1,106 @@
#!/usr/bin/env bash
# This script builds the ironbank Docker image of Coder containing the given
# binary. Other dependencies will be automatically downloaded and cached.
#
# Usage: ./build_ironbank.sh --target image_tag path/to/coder
set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/../lib.sh"
image_tag=""
args="$(getopt -o "" -l target: -- "$@")"
eval set -- "$args"
while true; do
case "$1" in
--target)
image_tag="$2"
shift 2
;;
--)
shift
break
;;
*)
error "Unrecognized option: $1"
;;
esac
done
if [[ "$image_tag" == "" ]]; then
error "The --image-tag parameter is required"
fi
# Check dependencies
dependencies docker sha256sum yq
if [[ $(yq --version) != *" v4."* ]]; then
error "yq version 4 is required"
fi
if [[ "$#" != 1 ]]; then
error "Exactly one argument must be provided to this script, $# were supplied"
fi
if [[ ! -f "$1" ]]; then
error "File '$1' does not exist or is not a regular file"
fi
input_file="$(realpath "$1")"
# Make temporary dir for Docker build context.
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
pushd "$(dirname "${BASH_SOURCE[0]}")"
cp Dockerfile "$tmpdir/"
cp terraform-filesystem-mirror.tfrc "$tmpdir/"
popd
# Create a coder.tar.gz file.
execrelative ../archive.sh \
--format tar.gz \
--os linux \
--output "$tmpdir/coder.tar.gz" \
"$input_file"
# Download all resources in the hardening_manifest.yaml file except for
# coder.tar.gz (which we will make ourselves).
manifest_path="$(dirname "${BASH_SOURCE[0]}")/hardening_manifest.yaml"
resources="$(yq e '.resources[] | select(.filename != "coder.tar.gz") | [.filename, .url, .validation.value] | @tsv' "$manifest_path")"
while read -r line; do
filename="$(echo "$line" | cut -f1)"
url="$(echo "$line" | cut -f2)"
sha256_hash="$(echo "$line" | cut -f3)"
pushd "$(dirname "${BASH_SOURCE[0]}")"
target=".${filename}.${sha256_hash}"
if [[ ! -f "$target" ]]; then
log "Downloading $filename"
curl -sSL "$url" -o "$target"
fi
sum="$(sha256sum "$target" | cut -d' ' -f1)"
if [[ "$sum" != "$sha256_hash" ]]; then
rm "$target"
error "Downloaded $filename has hash $sum, but expected $sha256_hash"
fi
cp "$target" "$tmpdir/$filename"
popd
done <<<"$resources"
terraform_coder_provider_version="$(yq e '.args.TERRAFORM_CODER_PROVIDER_VERSION' "$manifest_path")"
if [[ "$terraform_coder_provider_version" == "" ]]; then
error "TERRAFORM_CODER_PROVIDER_VERSION not found in hardening_manifest.yaml"
fi
# Build the image.
pushd "$tmpdir"
docker build \
--build-arg BASE_REGISTRY=registry.access.redhat.com \
--build-arg BASE_IMAGE=ubi8/ubi-minimal \
--build-arg BASE_TAG=8.7 \
--build-arg TERRAFORM_CODER_PROVIDER_VERSION="$terraform_coder_provider_version" \
-t "$image_tag" \
. >&2
popd
echo "$image_tag"

View File

@ -0,0 +1,65 @@
apiVersion: v1
# The repository name in registry1, excluding /ironbank/
name: "coder/coder-enterprise/coder-service-2"
# List of tags to push for the repository in registry1
# The most specific version should be the first tag and will be shown
# on ironbank.dso.mil
tags:
- "0.15.3"
- "latest"
# Build args passed to Dockerfile ARGs
args:
# Needs to be kept in sync with the resource below.
TERRAFORM_CODER_PROVIDER_VERSION: "0.6.10"
# Docker image labels
labels:
org.opencontainers.image.title: "coder-service-v2"
# Human-readable description of the software packaged in the image
org.opencontainers.image.description: "Coder server binary, includes REST API, Terraform, and dashboard"
# License(s) under which contained software is distributed
org.opencontainers.image.licenses: "AGPL"
# URL to find more information on the image
org.opencontainers.image.url: "https://coder.com/docs"
# Name of the distributing entity, organization or individual
org.opencontainers.image.vendor: "Coder Technologies"
org.opencontainers.image.version: "0.15.3"
# Keywords to help with search (ex. "cicd,gitops,golang")
mil.dso.ironbank.image.keywords: "remote, workspaces"
# List of resources to make available to the offline build context
resources:
# Coder binary
- url: "https://github.com/coder/coder/releases/download/v0.15.3/coder_0.15.3_linux_amd64.tar.gz"
filename: "coder.tar.gz"
validation:
type: sha256
value: 2c88555777f1d9cc77a8f049093f4002472dc43d52b026e6784ef477bdced4a2
# Terraform binary, bundled inside of Coder to support air-gapped installs.
- url: https://releases.hashicorp.com/terraform/1.3.7/terraform_1.3.7_linux_amd64.zip
filename: "terraform.zip"
validation:
type: sha256
value: b8cf184dee15dfa89713fe56085313ab23db22e17284a9a27c0999c67ce3021e
# Coder Terraform provider, bundled inside of Coder to support air-gapped
# installs.
#
# The version of this provider needs to be kept in sync with the
# TERRAFORM_CODER_PROVIDER_VERSION build arg.
- url: https://github.com/coder/terraform-provider-coder/releases/download/v0.6.10/terraform-provider-coder_0.6.10_linux_amd64.zip
filename: "terraform-provider-coder.zip"
validation:
type: sha256
value: 4c2a16010621e146251f6fb5e27105dde9213d85ca8f3c8866c3f5a4159b81b0
# List of project maintainers
maintainers:
- email: "eric@coder.com"
name: "Eric Paulsen"
username: "ericpaulsen"
- email: "dean@coder.com"
name: "Dean Sheather"
username: "cdrdean"

View File

@ -0,0 +1,5 @@
provider_installation {
filesystem_mirror {
path = "/opt/terraform/plugins"
}
}

View File

@ -39,7 +39,7 @@ realpath() {
}
# We have to define realpath before these otherwise it fails on Mac's bash.
SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[1]}")")"
PROJECT_ROOT="$(cd "$SCRIPT_DIR" && realpath "$(git rev-parse --show-toplevel)")"
# pushd is a silent alternative to the real pushd shell command.