mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 12:21:31 +00:00
build: propagate HTTP_PROXY/HTTPS_PROXY/NO_PROXY through Docker build (M-4, Issue #9)
Addresses Medium finding M-4 in the audit report. The multi-stage
Dockerfiles previously had no ARG declarations for HTTP_PROXY,
HTTPS_PROXY, or NO_PROXY, so corporate-proxy environments silently
failed at 'npm ci' (frontend stage) and 'go mod download' (Go builder).
The npm retry idiom (`npm ci --include=dev || npm ci --include=dev`)
masked the failure because the upstream 'Exit handler never called!'
bug exits 0 despite the install crash.
Fix: thread HTTP_PROXY / HTTPS_PROXY / NO_PROXY ARGs through every
Docker build stage that performs network I/O, re-export them as ENV
with both upper- and lower-case aliases (apk/curl/npm read lowercase;
Go/Node read uppercase), and forward the host shell's environment via
`build.args:` in every compose file and `build-args:` in the release
workflow's docker/build-push-action steps. Defaults are empty strings
so un-proxied builds remain byte-identical to the pre-fix tree.
Scope: Dockerfile (frontend + Go builder stages), Dockerfile.agent
(Go builder stage), deploy/docker-compose.yml (server + agent),
deploy/docker-compose.dev.yml (server + agent), deploy/docker-compose.test.yml
(server + agent), .github/workflows/release.yml (both docker/build-push-action
v6 invocations). Zero Go, web, test, or runtime code changes. Zero
base-image changes. Existing npm `||` retry idiom and `ARG TARGETARCH`
preserved verbatim.
CWE-1173 (Improper Use of Validated Input) / CWE-16 (Configuration).
Verification:
- YAML parses clean across all four compose files and release.yml.
- yamllint -d relaxed: clean exit across all five YAML files.
- All six `build.args:` blocks expose HTTP_PROXY, HTTPS_PROXY, NO_PROXY
with default-empty ${VAR:-} substitution.
- Both release.yml docker/build-push-action steps expose the same
three keys sourced from ${{ secrets.HTTP_PROXY }}, etc.
- Dockerfiles contain 5 proxy ARG declarations total (Dockerfile has 2
stages × 3 ARGs = 6 lines, Dockerfile.agent has 1 stage × 3 ARGs = 3
lines); lowercase ENV aliases verified present in every stage.
- git diff --shortstat: 6 files changed, 117 insertions(+), 0 deletions.
Pure additive.
Docker-live verification (`docker build`, `docker compose config`)
deferred to CI / post-commit smoke because the sandbox has no Docker
runtime. hadolint, go, golangci-lint, govulncheck likewise unavailable
in the sandbox; per-layer CI coverage gates (service 55%, handler 60%,
domain 40%, middleware 30%) are trivially unaffected as M-4 touches
zero Go source files.
This commit is contained in:
@@ -107,6 +107,16 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-server:${{ steps.version.outputs.VERSION }}
|
${{ env.REGISTRY }}/shankar0123/certctl-server:${{ steps.version.outputs.VERSION }}
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-server:latest
|
${{ env.REGISTRY }}/shankar0123/certctl-server:latest
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards runner-level proxy
|
||||||
|
# secrets into the Docker build so self-hosted runners behind
|
||||||
|
# corporate proxies can reach public registries. GitHub-hosted
|
||||||
|
# runners don't need proxies, so the secrets are optional and
|
||||||
|
# resolve to empty strings when unset — byte-identical to the
|
||||||
|
# pre-fix behaviour for the public-runner path.
|
||||||
|
build-args: |
|
||||||
|
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
||||||
|
HTTPS_PROXY=${{ secrets.HTTPS_PROXY }}
|
||||||
|
NO_PROXY=${{ secrets.NO_PROXY }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
@@ -119,6 +129,13 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-agent:${{ steps.version.outputs.VERSION }}
|
${{ env.REGISTRY }}/shankar0123/certctl-agent:${{ steps.version.outputs.VERSION }}
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-agent:latest
|
${{ env.REGISTRY }}/shankar0123/certctl-agent:latest
|
||||||
|
# Proxy propagation (M-4, Issue #9) — see server-image step for
|
||||||
|
# rationale. Empty secrets resolve to empty build args, leaving
|
||||||
|
# the un-proxied code path byte-identical to the pre-fix tree.
|
||||||
|
build-args: |
|
||||||
|
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
||||||
|
HTTPS_PROXY=${{ secrets.HTTPS_PROXY }}
|
||||||
|
NO_PROXY=${{ secrets.NO_PROXY }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
|||||||
+27
@@ -3,6 +3,22 @@
|
|||||||
# Stage 1: Build frontend
|
# Stage 1: Build frontend
|
||||||
FROM node:20-alpine AS frontend
|
FROM node:20-alpine AS frontend
|
||||||
|
|
||||||
|
# Proxy propagation (M-4, Issue #9) — defaulted to empty so un-proxied builds
|
||||||
|
# behave identically to the pre-fix tree. When `HTTP_PROXY`/`HTTPS_PROXY`/
|
||||||
|
# `NO_PROXY` are forwarded via `docker build --build-arg` (or compose
|
||||||
|
# `build.args`), they are re-exported as ENV with both upper- and lower-case
|
||||||
|
# names because npm/apk/curl read the lowercase variants while Go, Node, and
|
||||||
|
# most HTTP libraries read the uppercase ones.
|
||||||
|
ARG HTTP_PROXY=
|
||||||
|
ARG HTTPS_PROXY=
|
||||||
|
ARG NO_PROXY=
|
||||||
|
ENV HTTP_PROXY=${HTTP_PROXY} \
|
||||||
|
HTTPS_PROXY=${HTTPS_PROXY} \
|
||||||
|
NO_PROXY=${NO_PROXY} \
|
||||||
|
http_proxy=${HTTP_PROXY} \
|
||||||
|
https_proxy=${HTTPS_PROXY} \
|
||||||
|
no_proxy=${NO_PROXY}
|
||||||
|
|
||||||
WORKDIR /app/web
|
WORKDIR /app/web
|
||||||
|
|
||||||
COPY web/ .
|
COPY web/ .
|
||||||
@@ -13,6 +29,17 @@ RUN npm ci --include=dev || npm ci --include=dev && \
|
|||||||
# Stage 2: Build Go binary
|
# Stage 2: Build Go binary
|
||||||
FROM golang:1.25-alpine AS builder
|
FROM golang:1.25-alpine AS builder
|
||||||
|
|
||||||
|
# Proxy propagation (M-4, Issue #9) — see Stage 1 rationale.
|
||||||
|
ARG HTTP_PROXY=
|
||||||
|
ARG HTTPS_PROXY=
|
||||||
|
ARG NO_PROXY=
|
||||||
|
ENV HTTP_PROXY=${HTTP_PROXY} \
|
||||||
|
HTTPS_PROXY=${HTTPS_PROXY} \
|
||||||
|
NO_PROXY=${NO_PROXY} \
|
||||||
|
http_proxy=${HTTP_PROXY} \
|
||||||
|
https_proxy=${HTTPS_PROXY} \
|
||||||
|
no_proxy=${NO_PROXY}
|
||||||
|
|
||||||
RUN apk add --no-cache git ca-certificates tzdata
|
RUN apk add --no-cache git ca-certificates tzdata
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -2,6 +2,22 @@
|
|||||||
# Stage 1: Build
|
# Stage 1: Build
|
||||||
FROM golang:1.25-alpine AS builder
|
FROM golang:1.25-alpine AS builder
|
||||||
|
|
||||||
|
# Proxy propagation (M-4, Issue #9) — defaulted to empty so un-proxied builds
|
||||||
|
# behave identically to the pre-fix tree. When `HTTP_PROXY`/`HTTPS_PROXY`/
|
||||||
|
# `NO_PROXY` are forwarded via `docker build --build-arg` (or compose
|
||||||
|
# `build.args`), they are re-exported as ENV with both upper- and lower-case
|
||||||
|
# names because apk and curl read the lowercase variants while Go reads the
|
||||||
|
# uppercase ones.
|
||||||
|
ARG HTTP_PROXY=
|
||||||
|
ARG HTTPS_PROXY=
|
||||||
|
ARG NO_PROXY=
|
||||||
|
ENV HTTP_PROXY=${HTTP_PROXY} \
|
||||||
|
HTTPS_PROXY=${HTTPS_PROXY} \
|
||||||
|
NO_PROXY=${NO_PROXY} \
|
||||||
|
http_proxy=${HTTP_PROXY} \
|
||||||
|
https_proxy=${HTTPS_PROXY} \
|
||||||
|
no_proxy=${NO_PROXY}
|
||||||
|
|
||||||
RUN apk add --no-cache git ca-certificates
|
RUN apk add --no-cache git ca-certificates
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -9,6 +9,16 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards host shell's proxy env
|
||||||
|
# vars into the Docker build so the Node frontend stage and Go module
|
||||||
|
# download can reach the public registries behind corporate proxies.
|
||||||
|
# Defaults to empty; omit the variables from the host environment for
|
||||||
|
# un-proxied builds and the behaviour is byte-identical to the pre-fix
|
||||||
|
# tree.
|
||||||
|
args:
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
environment:
|
environment:
|
||||||
# Verbose logging for development
|
# Verbose logging for development
|
||||||
CERTCTL_LOG_LEVEL: debug
|
CERTCTL_LOG_LEVEL: debug
|
||||||
@@ -29,6 +39,15 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: Dockerfile.agent
|
dockerfile: Dockerfile.agent
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards host shell's proxy env
|
||||||
|
# vars into the Docker build so the Go module download stage can reach
|
||||||
|
# the public Go module proxy behind corporate proxies. Defaults to
|
||||||
|
# empty; omit the variables from the host environment for un-proxied
|
||||||
|
# builds and the behaviour is byte-identical to the pre-fix tree.
|
||||||
|
args:
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
environment:
|
environment:
|
||||||
CERTCTL_LOG_LEVEL: debug
|
CERTCTL_LOG_LEVEL: debug
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,16 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards host shell's proxy env
|
||||||
|
# vars into the Docker build so the Node frontend stage and Go module
|
||||||
|
# download can reach the public registries behind corporate proxies.
|
||||||
|
# Defaults to empty; omit the variables from the host environment for
|
||||||
|
# un-proxied builds and the behaviour is byte-identical to the pre-fix
|
||||||
|
# tree.
|
||||||
|
args:
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
container_name: certctl-test-server
|
container_name: certctl-test-server
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
@@ -266,6 +276,15 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: Dockerfile.agent
|
dockerfile: Dockerfile.agent
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards host shell's proxy env
|
||||||
|
# vars into the Docker build so the Go module download stage can reach
|
||||||
|
# the public Go module proxy behind corporate proxies. Defaults to
|
||||||
|
# empty; omit the variables from the host environment for un-proxied
|
||||||
|
# builds and the behaviour is byte-identical to the pre-fix tree.
|
||||||
|
args:
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
container_name: certctl-test-agent
|
container_name: certctl-test-agent
|
||||||
depends_on:
|
depends_on:
|
||||||
certctl-server:
|
certctl-server:
|
||||||
|
|||||||
@@ -36,6 +36,16 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards host shell's proxy env
|
||||||
|
# vars into the Docker build so the Node frontend stage and Go module
|
||||||
|
# download can reach the public registries behind corporate proxies.
|
||||||
|
# Defaults to empty; omit the variables from the host environment for
|
||||||
|
# un-proxied builds and the behaviour is byte-identical to the pre-fix
|
||||||
|
# tree.
|
||||||
|
args:
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
container_name: certctl-server
|
container_name: certctl-server
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
@@ -75,6 +85,15 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: Dockerfile.agent
|
dockerfile: Dockerfile.agent
|
||||||
|
# Proxy propagation (M-4, Issue #9) — forwards host shell's proxy env
|
||||||
|
# vars into the Docker build so the Go module download stage can reach
|
||||||
|
# the public Go module proxy behind corporate proxies. Defaults to
|
||||||
|
# empty; omit the variables from the host environment for un-proxied
|
||||||
|
# builds and the behaviour is byte-identical to the pre-fix tree.
|
||||||
|
args:
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
container_name: certctl-agent
|
container_name: certctl-agent
|
||||||
depends_on:
|
depends_on:
|
||||||
certctl-server:
|
certctl-server:
|
||||||
|
|||||||
Reference in New Issue
Block a user