Skip to content
Draft
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
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,28 @@ The implementation is based on the cosign CLI's output transformation:

- [cosign verify.go - transformOutput](https://github.com/sigstore/cosign/blob/b7462fb60764850a789392429d3ba40f969d07db/cmd/cosign/cli/verify/verify.go#L263)

## Proxy for internet registries

When images are hosted on registries reachable only through a forward proxy
(e.g. public internet registries), the webhook can route its outbound image and
signature requests through that proxy. The verification path honors the standard
`HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables
(via `http.ProxyFromEnvironment`).

Enable it in the Helm chart and use `noProxy` to keep internal registries direct,
so only non-`*.telekom.de` images are sent through the proxy:

```yaml
proxy:
enabled: true
httpsProxy: "http://proxy.telekom.de:8080"
httpProxy: "http://proxy.telekom.de:8080"
noProxy: ".telekom.de"
```

These values are injected into both the webhook container (runtime admission
verification) and the image-verification init containers.

## Credits

* Bruno Bressi <bruno.bressi@telekom.de>
Expand Down
8 changes: 8 additions & 0 deletions chart/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ spec:
env:
- name: COSIGNPUBKEY
value: {{- toYaml .Values.cosign.key | indent 12 }}
{{- if .Values.proxy.enabled }}
- name: HTTP_PROXY
value: {{ .Values.proxy.httpProxy | quote }}
- name: HTTPS_PROXY
value: {{ .Values.proxy.httpsProxy | quote }}
- name: NO_PROXY
value: {{ .Values.proxy.noProxy | quote }}
{{- end }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
Expand Down
6 changes: 5 additions & 1 deletion chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ tolerations: []

affinity: {}

# proxy configuration for outbound connections
# proxy configuration for outbound connections (image and signature pulls).
# When enabled, these env vars are injected into the webhook container and the
# image-verification init containers. The verification path honors them via
# http.ProxyFromEnvironment. Set noProxy to reach internal registries directly,
# e.g. noProxy: ".telekom.de" routes only non-*.telekom.de images via the proxy.
proxy:
enabled: false
httpProxy: ""
Expand Down
20 changes: 19 additions & 1 deletion webhook/cosignwebhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,10 @@ func (csh *CosignServerHandler) parseImageAndVerifier(image, pubKey string) (nam
// buildRemoteOpts constructs the remote options for registry access.
func (*CosignServerHandler) buildRemoteOpts(kc authn.Keychain, env []corev1.EnvVar) ([]ociremote.Option, error) {
remoteOpts := []ociremote.Option{
ociremote.WithRemoteOptions(remote.WithAuthFromKeychain(kc)),
ociremote.WithRemoteOptions(
remote.WithAuthFromKeychain(kc),
remote.WithTransport(proxyTransport()),
),
}

if r := getCosignRepository(env); r != "" {
Expand Down Expand Up @@ -455,6 +458,21 @@ func (*CosignServerHandler) newVerifierForKey(publicKey crypto.PublicKey) (signa
}
}

// proxyTransport returns an http.RoundTripper based on go-containerregistry's
// DefaultTransport. It honors the standard HTTP_PROXY, HTTPS_PROXY and NO_PROXY
// environment variables via http.ProxyFromEnvironment. This allows outbound
// registry and signature traffic to be routed through a forward proxy for
// images hosted on internet registries, while internal domains listed in
// NO_PROXY (e.g. ".telekom.de") are reached directly.
func proxyTransport() http.RoundTripper {
if t, ok := remote.DefaultTransport.(*http.Transport); ok {
tc := t.Clone()
tc.Proxy = http.ProxyFromEnvironment
return tc
}
return remote.DefaultTransport
}

// getCosignRepository returns the repository specified by the COSIGN_REPOSITORY environment variable
// of the container, or nil if not set.
func getCosignRepository(env []corev1.EnvVar) string {
Expand Down
Loading