Skip to content
Closed
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
26 changes: 22 additions & 4 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
FROM golang:1.26.1-bookworm AS build
ARG TARGETARCH
RUN apt-get update && apt-get install -y \
jq \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY src/base/.devcontainer/scripts/install_cosign.sh /tmp/install_cosign.sh
COPY src/base/.devcontainer/scripts/install_trivy.sh /tmp/install_trivy.sh
RUN INSTALL_DIR=/usr/local/bin /tmp/install_cosign.sh
RUN case "${TARGETARCH}" in \
x86_64|amd64) TRIVY_ARCH=64bit ;; \
aarch64|arm64) TRIVY_ARCH=ARM64 ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" && exit 1 ;; \
esac \
&& INSTALL_DIR=/tmp/trivy/ ARCH="${TRIVY_ARCH}" /tmp/install_trivy.sh


FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04
ARG TARGETARCH
ENV TARGETARCH=${TARGETARCH}
Expand Down Expand Up @@ -64,11 +81,13 @@ RUN git clone https://github.com/awslabs/git-secrets.git /tmp/git-secrets && \
chmod 755 /usr/share/secrets-scanner && \
curl -L https://raw.githubusercontent.com/NHSDigital/software-engineering-quality-framework/main/tools/nhsd-git-secrets/nhsd-rules-deny.txt -o /usr/share/secrets-scanner/nhsd-rules-deny.txt

COPY --from=build /tmp/trivy/trivy /usr/local/bin/trivy

USER vscode

ENV PATH="/home/vscode/.asdf/shims/:$PATH:/workspaces/eps-devcontainers/node_modules/.bin"
ENV PATH="/home/vscode/.asdf/shims:/home/vscode/.local/bin:$PATH:/workspaces/eps-devcontainers/node_modules/.bin"
RUN \
echo 'PATH="/home/vscode/.asdf/shims/:$PATH:/workspaces/eps-devcontainers/node_modules/.bin"' >> ~/.bashrc; \
echo 'PATH="/home/vscode/.asdf/shims:/home/vscode/.local/bin:$PATH:/workspaces/eps-devcontainers/node_modules/.bin"' >> ~/.bashrc; \
echo '. <(asdf completion bash)' >> ~/.bashrc; \
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc; \
echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc; \
Expand All @@ -83,8 +102,7 @@ RUN asdf plugin add python; \
asdf plugin add actionlint; \
asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git; \
asdf plugin add trivy https://github.com/zufardhiyaulhaq/asdf-trivy.git; \
asdf plugin add yq https://github.com/sudermanjr/asdf-yq.git

asdf plugin add yq https://github.com/sudermanjr/asdf-yq.git;

WORKDIR /workspaces/eps-devcontainers
COPY .tool-versions /workspaces/eps-devcontainers/.tool-versions
Expand Down
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"source=${env:HOME}${env:USERPROFILE}/.aws,target=/home/vscode/.aws,type=bind",
"source=${env:HOME}${env:USERPROFILE}/.ssh,target=/home/vscode/.ssh,type=bind",
"source=${env:HOME}${env:USERPROFILE}/.gnupg,target=/home/vscode/.gnupg,type=bind",
"source=${env:HOME}${env:USERPROFILE}/.npmrc,target=/home/vscode/.npmrc,type=bind"
"source=${env:HOME}${env:USERPROFILE}/.npmrc,target=/home/vscode/.npmrc,type=bind",
"source=${env:HOME}${env:USERPROFILE}/.gitconfig,target=/home/vscode/.gitconfig,type=bind"
],
"runArgs": [
"--network=host"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build_all_images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
echo "node_24_languages=$node_24_language_folders"
echo "projects=$project_folders"
} >> "$GITHUB_OUTPUT"

package_base_docker_image:
uses: ./.github/workflows/build_multi_arch_image.yml
with:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/build_multi_arch_image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ jobs:
with:
fetch-depth: 0
- name: setup trivy
uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514
with:
version: v0.69.3
run: |
docker build --output=/usr/local/bin/ -f "src/base/.devcontainer/Dockerfile.trivy.${ARCH}" .
env:
ARCH: '${{ matrix.arch }}'
- name: setup node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ src/base/.devcontainer/language_versions/
.trivyignore_combined.yaml
.out/
.envrc
.trivy_out/
1 change: 0 additions & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ shellcheck 0.11.0
direnv 2.37.1
actionlint 1.7.10
ruby 3.3.0
trivy 0.69.3
yq 4.52.2
7 changes: 3 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ guard-%:
exit 1; \
fi

.PHONY: install install-python install-node install-hooks build-base-image build-node-24-image build-node-24-python-3-10-image build-node-24-python-3-12-image build-node-24-python-3-13-image build-node-24-python-3-14-image \
build-eps-storage-terraform-image build-fhir-facade-image build-node-24-python-3-14-golang-1-24-image build-node-24-python-3-14-java-24-image \
build-regression-tests-image build-all build-image build-githubactions-image scan-image scan-image-json shell-image lint test lint-githubactions lint-githubaction-scripts github-login clean
install: install-python install-node install-hooks

install-python:
Expand Down Expand Up @@ -129,13 +132,9 @@ test:
lint-githubactions:
actionlint

github-login:
gh auth login --scopes read:packages

lint-githubaction-scripts:
shellcheck .github/scripts/*.sh

clean:
rm -rf .out
find . -type f -name '.trivyignore_combined.yaml' -delete

1 change: 0 additions & 1 deletion src/base/.devcontainer/.tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ shellcheck 0.11.0
direnv 2.37.1
actionlint 1.7.11
ruby 3.3.0
trivy 0.69.3
yq 4.52.4
18 changes: 18 additions & 0 deletions src/base/.devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
FROM golang:1.26.1-bookworm AS build
ARG TARGETARCH
RUN apt-get update && apt-get install -y \
jq \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/install_cosign.sh /tmp/install_cosign.sh
COPY scripts/install_trivy.sh /tmp/install_trivy.sh
RUN INSTALL_DIR=/usr/local/bin /tmp/install_cosign.sh
RUN case "${TARGETARCH}" in \
x86_64|amd64) TRIVY_ARCH=64bit ;; \
aarch64|arm64) TRIVY_ARCH=ARM64 ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" && exit 1 ;; \
esac \
&& INSTALL_DIR=/tmp/trivy/ ARCH="${TRIVY_ARCH}" /tmp/install_trivy.sh

FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04

ARG SCRIPTS_DIR=/usr/local/share/eps
Expand All @@ -16,6 +32,8 @@ COPY --chmod=755 Mk ${SCRIPTS_DIR}/Mk
WORKDIR ${SCRIPTS_DIR}/${CONTAINER_NAME}
RUN ./root_install.sh

COPY --from=build /tmp/trivy/trivy /usr/local/bin/trivy

COPY --chmod=755 scripts/vscode_install.sh ${SCRIPTS_DIR}/${CONTAINER_NAME}/vscode_install.sh
USER vscode
COPY --chown=vscode:vscode .tool-versions.asdf /home/vscode/.tool-versions.asdf
Expand Down
13 changes: 13 additions & 0 deletions src/base/.devcontainer/Dockerfile.trivy.amd64
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.26.1-bookworm AS build
RUN apt-get update && apt-get install -y \
jq \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY src/base/.devcontainer/scripts/install_cosign.sh /tmp/install_cosign.sh
COPY src/base/.devcontainer/scripts/install_trivy.sh /tmp/install_trivy.sh
RUN INSTALL_DIR=/usr/local/bin /tmp/install_cosign.sh
RUN INSTALL_DIR=/tmp/trivy/ ARCH=64bit /tmp/install_trivy.sh

FROM scratch
COPY --from=build /tmp/trivy/trivy /
ENTRYPOINT ["/trivy"]
13 changes: 13 additions & 0 deletions src/base/.devcontainer/Dockerfile.trivy.arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.26.1-bookworm AS build
RUN apt-get update && apt-get install -y \
jq \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/install_cosign.sh /tmp/install_cosign.sh
COPY scripts/install_trivy.sh /tmp/install_trivy.sh
RUN INSTALL_DIR=/usr/local/bin /tmp/install_cosign.sh
RUN INSTALL_DIR=/tmp/trivy/ ARCH=ARM64 /tmp/install_trivy.sh

FROM scratch
COPY --from=build /tmp/trivy/trivy /
ENTRYPOINT ["/trivy"]
109 changes: 109 additions & 0 deletions src/base/.devcontainer/scripts/install_cosign.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env bash
set -euo pipefail

DEFAULT_INSTALL_DIR="/usr/local/bin"
INSTALL_DIR="${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}"
REQUESTED_VERSION="${1:-latest}"
OS="$(uname -s)"
ARCH="$(uname -m)"
API_URL="https://api.github.com/repos/sigstore/cosign/releases"

usage() {
cat <<'EOF'
Usage: install_cosign.sh [version]

Downloads the requested cosign release (default: latest) for Linux amd64, verifies
its signature, and installs it into $INSTALL_DIR (override via INSTALL_DIR env var).
EOF
}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi

if [[ "$OS" != "Linux" ]]; then
echo "Error: This installer currently supports Linux only" >&2
exit 1
fi

case "$ARCH" in
x86_64|amd64)
BINARY_NAME="cosign-linux-amd64"
;;
aarch64|arm64)
BINARY_NAME="cosign-linux-arm64"
;;
*)
echo "Error: Unsupported architecture $ARCH" >&2
exit 1
;;
esac

for cmd in curl openssl install go jq; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: $cmd is required but not found in PATH" >&2
exit 1
fi
done

get_latest_tag() {
local response
response="$(curl -fsSL "$API_URL/latest")"
awk -F'"' '/tag_name/ {print $4; exit}' <<<"$response"
}

VERSION="$REQUESTED_VERSION"
if [[ "$VERSION" == "latest" ]]; then
VERSION="$(get_latest_tag)"
fi

if [[ -z "$VERSION" ]]; then
echo "Error: Unable to determine cosign version" >&2
exit 1
fi

BASE_URL="https://github.com/sigstore/cosign/releases/download/${VERSION}"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

download() {
local url="${1}" dest="${2}"
echo "Downloading ${dest} ..."
curl -fsSL "${url}" -o "${dest}"
}

BIN_PATH="$TMP_DIR/${BINARY_NAME}"
SIGSTORE_PATH="$TMP_DIR/${BINARY_NAME}-kms.sigstore.json"
ARTIFACT_PATH="$TMP_DIR/artifact.pub"
DECODED_SIGSTORE_PATH="$TMP_DIR/cosign-kms.sig.decoded"

download "${BASE_URL}/${BINARY_NAME}" "$BIN_PATH"
download "${BASE_URL}/${BINARY_NAME}-kms.sigstore.json" "$SIGSTORE_PATH"

# install tuf-client
go install github.com/theupdateframework/go-tuf/cmd/tuf-client@latest

# setup tuf-client
SIGSTORE_ROOT_PATH="$TMP_DIR/sigstore-root.json"
curl -o "$SIGSTORE_ROOT_PATH" https://raw.githubusercontent.com/sigstore/root-signing/refs/heads/main/metadata/root_history/10.root.json
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trusted Sigstore root is fetched from refs/heads/main (10.root.json). Pulling trust material from a moving branch makes verification less reproducible and increases supply-chain risk. Prefer pinning this URL to a specific commit SHA (or a signed, versioned release artifact) so the installer always uses a known root.

Suggested change
curl -o "$SIGSTORE_ROOT_PATH" https://raw.githubusercontent.com/sigstore/root-signing/refs/heads/main/metadata/root_history/10.root.json
curl -o "$SIGSTORE_ROOT_PATH" https://raw.githubusercontent.com/sigstore/root-signing/39c787b931c9791667235b3a5229ae58f12f1b4a/metadata/root_history/10.root.json

Copilot uses AI. Check for mistakes.
tuf-client init https://tuf-repo-cdn.sigstore.dev "$SIGSTORE_ROOT_PATH"

tuf-client get https://tuf-repo-cdn.sigstore.dev artifact.pub > "$ARTIFACT_PATH"

cat "$SIGSTORE_PATH" | jq -r .messageSignature.signature | base64 -d > "$DECODED_SIGSTORE_PATH"
pushd "$TMP_DIR" >/dev/null
echo "verifying signature with artifact.pub"
openssl dgst -sha256 -verify "$ARTIFACT_PATH" -signature "$DECODED_SIGSTORE_PATH" "$BIN_PATH"
popd >/dev/null

echo "verifying signature with cosign verify-blob"
chmod +x "$BIN_PATH"
${BIN_PATH} verify-blob --bundle "${SIGSTORE_PATH}" --key "$ARTIFACT_PATH" "$BIN_PATH"

mkdir -p "$INSTALL_DIR"
install -m 0755 "$BIN_PATH" "${INSTALL_DIR}/cosign"

"${INSTALL_DIR}/cosign" version

echo "cosign ${VERSION} installed to ${INSTALL_DIR}"
62 changes: 62 additions & 0 deletions src/base/.devcontainer/scripts/install_trivy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail

DEFAULT_INSTALL_DIR="/usr/local/bin"
INSTALL_DIR="${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}"
VERSION="v0.69.3"
DEFAULT_ARCH="64bit"
ARCH="${ARCH:-$DEFAULT_ARCH}"
RELEASE_NUMBER="${VERSION#v}"
BASE_URL="https://github.com/aquasecurity/trivy/releases/download/${VERSION}"
ARCHIVE="trivy_${RELEASE_NUMBER}_Linux-${ARCH}.tar.gz"
BUNDLE="${ARCHIVE}.sigstore.json"
CERT_IDENTITY="https://github.com/aquasecurity/trivy/.github/workflows/reusable-release.yaml@refs/tags/${VERSION}"

usage() {
cat <<'EOF'
Usage: install_trivy.sh [output_dir]

Downloads Trivy, its sigstore bundle, and checksum into output_dir (default: current directory),
then verifies the checksum and the sigstore bundle, following
https://github.com/aquasecurity/trivy/blob/main/docs/getting-started/signature-verification.md.
EOF
}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi

for cmd in curl cosign sha256sum; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: $cmd is required but not found in PATH" >&2
exit 1
fi
Comment on lines +15 to +34
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

install_trivy.sh help text and dependencies don't match the implementation: the script doesn't accept an output_dir argument (it only uses INSTALL_DIR env var), it claims to download/verify a checksum but never downloads any checksum file, and sha256sum is required but never used. Align the usage text + required commands with reality, or implement checksum download + verification if that's intended.

Copilot uses AI. Check for mistakes.
done

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

download() {
local url="${1}" dest="${2}"
echo "Downloading ${dest} ..."
curl -fsSL "${url}" -o "${dest}"
}
ARCHIVE_PATH="${TMP_DIR}/${ARCHIVE}"
BUNDLE_PATH="${TMP_DIR}/${BUNDLE}"
download "${BASE_URL}/${ARCHIVE}" "${ARCHIVE_PATH}"
download "${BASE_URL}/${BUNDLE}" "${BUNDLE_PATH}"


cosign verify-blob-attestation "${ARCHIVE_PATH}" \
--bundle "${BUNDLE_PATH}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
--certificate-identity "${CERT_IDENTITY}"

echo "Sigstore verification passed"
tar -xzf "${ARCHIVE_PATH}" -C "${TMP_DIR}"

mkdir -p "$INSTALL_DIR"
install -m 0755 "$TMP_DIR/trivy" "${INSTALL_DIR}/trivy"

echo "trivy ${VERSION} installed to ${INSTALL_DIR}"
Loading