Skip to content
Merged
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
2 changes: 1 addition & 1 deletion deployment/chainloop/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Chainloop is an open source software supply chain control plane, a

type: application
# Bump the patch (not minor, not major) version on each change in the Chart Source code
version: 1.470.0
version: 1.470.1
# Do not update appVersion, this is handled automatically by the release process
appVersion: v1.127.0

Expand Down
34 changes: 24 additions & 10 deletions deployment/chainloop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ The existing gRPC ingress stays available. Existing clients can keep their curre
To test the shared endpoint, point a gRPC client to the control plane HTTP hostname on port 443.
The CAS shared endpoint mirrors the control plane (spec D-020): one standard HTTP listener dispatches each request, and native gRPC reaches the native transport through an in-process reverse proxy. `cas.ingress` is one catch-all route on the same hostname — one path `/` with an HTTP/2 (gRPC) upstream — so ByteStream uploads and downloads, browser downloads, and status probes share one Service port and one certificate, including mixed requests on one upstream connection.

Set gRPC transport annotations under `cas.ingress.annotations`, such as `backend-protocol: GRPCS` for TLS to the pod. The upload body-size annotations keep their existing defaults.
The chart selects gRPC transport annotations from the pod TLS configuration. You can override them under `cas.ingress.annotations`. The upload body-size annotations keep their existing defaults.

Enable the shared endpoint with a `cas.ingress` block — for example:

Expand Down Expand Up @@ -275,11 +275,25 @@ The chart configures HTTP/2 upstream traffic for these controllers:
Native gRPC clients normally use TLS on the ingress. Plaintext client HTTP/2 needs controller configuration too.
- Traefik: `controlplane.service.annotations` includes `traefik.ingress.kubernetes.io/service.serversscheme: h2c`.

These defaults apply to plaintext traffic between the ingress and the pod. Public ingress TLS still works as before.
If you enable TLS on the pod listener, configure the controller for encrypted HTTP/2 upstream traffic instead.
For ingress-nginx, use `GRPCS`. For F5 NGINX, also configure `nginx.org/ssl-services`.
For Traefik, use the `https` service scheme and configure certificate trust as required.
Other controllers need their own upstream protocol settings.
To enable pod TLS, provide each component with a Secret containing `tls.crt` and `tls.key`:

```yaml
controlplane:
tls:
existingSecret: cp-tls
cas:
tls:
existingSecret: cas-tls
```

With pod TLS enabled, direct HTTP clients must use HTTPS and direct gRPC clients must use TLS, whether or not an Ingress is enabled.
The legacy `tlsConfig.secret.name` setting is also supported; `tls.existingSecret` takes precedence when both are set.

The chart configures ingress-nginx, F5 NGINX, and Traefik to connect to the pods over TLS. Explicit annotation overrides take precedence.
Configure your ingress controller to trust the pod certificates. For other controllers or a Gateway, also configure TLS connections to the pods and certificate validation in your infrastructure.

Public TLS termination remains controlled by `ingress.tls` and `ingressAPI.tls`, independently of pod TLS.
When upgrading a deployment that already sets a pod TLS Secret for gRPC, the shared HTTP listener also switches to TLS. Direct clients of that listener must use TLS; HTTP requests must use HTTPS.

The NGINX gRPC module path supports the shared endpoint without path or content-type rules.
The regression suite checks that path with NGINX Open Source. It does not certify every controller or NGINX Plus release.
Expand Down Expand Up @@ -616,7 +630,7 @@ Once done, you can access with [two predefined users](https://github.com/chainlo
| `controlplane.containerPorts.grpc` | controlplane gRPC container port | `9000` |
| `controlplane.containerPorts.metrics` | controlplane prometheus metrics container port | `5000` |
| `controlplane.enableProfiler` | Enable pprof profiling on port 6060 | `false` |
| `controlplane.tls.existingSecret` | Existing secret name containing TLS certificate to be used by the controlplane grpc server. NOTE: When it's set it will disable secret creation. The secret must contains 2 keys: tls.crt and tls.key respectively containing the certificate and private key. | `""` |
| `controlplane.tls.existingSecret` | Secret with tls.crt and tls.key for both listeners. Direct clients must use TLS. Public Ingress TLS termination remains separate. The legacy tlsConfig.secret.name value is also supported. | `""` |
| `controlplane.pluginsDir` | Directory where to look for plugins | `/plugins` |
| `controlplane.pluginsNetworkPolicy` | Outbound network policy for the plugins that accept an arbitrary target URL, currently the generic webhook and Dependency-Track plugins. Plugins whose destination is a known public service, such as the Slack and Discord webhooks, always refuse non-public destinations. | |
| `controlplane.pluginsNetworkPolicy.blockPrivateTargets` | Refuse requests to destinations that are not publicly routable, such as loopback, private ranges and cloud metadata endpoints | `false` |
Expand Down Expand Up @@ -679,7 +693,7 @@ Once done, you can access with [two predefined users](https://github.com/chainlo
| `controlplane.service.loadBalancerIP` | controlplane service Load Balancer IP | `""` |
| `controlplane.service.loadBalancerSourceRanges` | controlplane service Load Balancer sources | `[]` |
| `controlplane.service.externalTrafficPolicy` | controlplane service external traffic policy | `Cluster` |
| `controlplane.service.annotations` | Annotations for the shared HTTP and gRPC service. Traefik uses h2c upstream. | See values.yaml |
| `controlplane.service.annotations` | Annotations for the shared HTTP and gRPC service. Traefik uses h2c or HTTPS to match shared listener TLS. | See values.yaml |
| `controlplane.service.extraPorts` | Extra ports to expose in controlplane service (normally used with the `sidecars` value) | `[]` |
| `controlplane.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` |
| `controlplane.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` |
Expand Down Expand Up @@ -846,7 +860,7 @@ Once done, you can access with [two predefined users](https://github.com/chainlo
| `cas.containerPorts.http` | controlplane HTTP container port | `8000` |
| `cas.containerPorts.grpc` | controlplane gRPC container port | `9000` |
| `cas.containerPorts.metrics` | controlplane prometheus metrics container port | `5000` |
| `cas.tls.existingSecret` | Existing secret name containing TLS certificate to be used by the cas grpc server. NOTE: When it's set it will disable secret creation. The secret must contains 2 keys: tls.crt and tls.key respectively containing the certificate and private key. | `""` |
| `cas.tls.existingSecret` | Secret with tls.crt and tls.key for both listeners. Direct clients must use TLS. Public Ingress TLS termination remains separate. The legacy tlsConfig.secret.name value is also supported. | `""` |

### CAS Networking

Expand All @@ -861,7 +875,7 @@ Once done, you can access with [two predefined users](https://github.com/chainlo
| `cas.service.loadBalancerIP` | cas service Load Balancer IP | `""` |
| `cas.service.loadBalancerSourceRanges` | cas service Load Balancer sources | `[]` |
| `cas.service.externalTrafficPolicy` | cas service external traffic policy | `Cluster` |
| `cas.service.annotations` | Annotations for the shared HTTP and gRPC service. Traefik uses h2c for HTTP/2 upstream traffic. | See values.yaml |
| `cas.service.annotations` | Annotations for the shared HTTP and gRPC service. Traefik uses h2c or HTTPS to match shared listener TLS. | See values.yaml |
| `cas.service.extraPorts` | Extra ports to expose in cas service (normally used with the `sidecars` value) | `[]` |
| `cas.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` |
| `cas.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` |
Expand Down
39 changes: 35 additions & 4 deletions deployment/chainloop/chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,21 @@ func testSharedCASIngress(t *testing.T) {
}

type chartResource struct {
Kind string `yaml:"kind"`
Kind string `yaml:"kind"`
Data map[string]string `yaml:"data"`
Metadata struct {
Name string `yaml:"name"`
Annotations map[string]string `yaml:"annotations"`
} `yaml:"metadata"`
Spec struct {
Template struct {
Spec chartPodSpec `yaml:"spec"`
} `yaml:"template"`
Ports []struct {
Name string `yaml:"name"`
Port int `yaml:"port"`
TargetPort string `yaml:"targetPort"`
Name string `yaml:"name"`
Port int `yaml:"port"`
TargetPort string `yaml:"targetPort"`
AppProtocol string `yaml:"appProtocol"`
} `yaml:"ports"`
TLS []struct {
Hosts []string `yaml:"hosts"`
Expand All @@ -246,6 +251,32 @@ type chartResource struct {
} `yaml:"spec"`
}

type chartPodSpec struct {
Containers []struct {
StartupProbe chartProbe `yaml:"startupProbe"`
LivenessProbe chartProbe `yaml:"livenessProbe"`
ReadinessProbe chartProbe `yaml:"readinessProbe"`
VolumeMounts []struct {
Name string `yaml:"name"`
MountPath string `yaml:"mountPath"`
} `yaml:"volumeMounts"`
} `yaml:"containers"`
Volumes []struct {
Name string `yaml:"name"`
Secret *struct {
SecretName string `yaml:"secretName"`
} `yaml:"secret"`
} `yaml:"volumes"`
}

type chartProbe struct {
HTTPGet struct {
Path string `yaml:"path"`
Port string `yaml:"port"`
Scheme string `yaml:"scheme"`
} `yaml:"httpGet"`
}

func TestCASSharedIngressTLS(t *testing.T) {
resources := renderChart(t, []string{helmSet, casIngressEnabled, helmSet, "cas.ingress.tls=true",
helmSetString, `cas.ingress.annotations.cert-manager\.io/cluster-issuer=test-issuer`})
Expand Down
5 changes: 5 additions & 0 deletions deployment/chainloop/templates/cas/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ data:
staging_dir: {{ include "chainloop.cas.staging_dir" . | quote }}
server:
http:
{{- if include "cas.tls-secret-name" . }}
tls_config:
certificate: /data/server-certs/tls.crt
private_key: /data/server-certs/tls.key
{{- end }}
addr: "0.0.0.0:{{ .Values.cas.containerPorts.http }}"
# Timeouts for http downloads
# grpc downloads/uploads don't require this because they don't have timeouts
Expand Down
11 changes: 10 additions & 1 deletion deployment/chainloop/templates/cas/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,24 @@ spec:
httpGet:
path: /statusz
port: http
{{- if include "cas.tls-secret-name" . }}
scheme: HTTPS
{{- end }}
periodSeconds: 5
livenessProbe:
httpGet:
path: /statusz
port: http
{{- if include "cas.tls-secret-name" . }}
scheme: HTTPS
{{- end }}
readinessProbe:
httpGet:
path: /statusz?readiness=1
port: http
{{- if include "cas.tls-secret-name" . }}
scheme: HTTPS
{{- end }}
{{- if .Values.cas.resources }}
resources: {{- toYaml .Values.cas.resources | nindent 12 }}
{{- else if ne .Values.cas.resourcesPreset "none" }}
Expand Down Expand Up @@ -186,4 +195,4 @@ spec:
{{- end }}
{{- if .Values.cas.extraVolumes }}
{{- include "common.tplvalues.render" (dict "value" .Values.cas.extraVolumes "context" $) | nindent 8 }}
{{- end }}
{{- end }}
10 changes: 7 additions & 3 deletions deployment/chainloop/templates/cas/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ metadata:
name: {{ $fullName }}
namespace: {{ include "common.names.namespace" . | quote }}
labels: {{- include "chainloop.cas.labels" . | nindent 4 }}
{{- if or .Values.cas.ingress.annotations .Values.commonAnnotations }}
{{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.cas.ingress.annotations .Values.commonAnnotations) "context" .) }}
{{- $tlsAnnotations := dict }}
{{- if include "cas.tls-secret-name" . }}
{{- $_ := set $tlsAnnotations "nginx.org/ssl-services" $fullName }}
{{- end }}
{{- if or .Values.cas.ingress.annotations .Values.commonAnnotations $tlsAnnotations }}
{{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.cas.ingress.annotations .Values.commonAnnotations $tlsAnnotations) "context" .) }}
annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
spec:
Expand Down Expand Up @@ -57,4 +61,4 @@ spec:
{{- include "common.tplvalues.render" (dict "value" .Values.cas.ingress.extraTls "context" $) | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
1 change: 1 addition & 0 deletions deployment/chainloop/templates/cas/service-http.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ spec:
port: {{ $port }}
targetPort: http
protocol: TCP
appProtocol: {{ if include "cas.tls-secret-name" . }}kubernetes.io/h2{{ else }}kubernetes.io/h2c{{ end }}
{{- if and (or (eq .Values.cas.service.type "NodePort") (eq .Values.cas.service.type "LoadBalancer")) (not (empty .Values.cas.service.nodePorts.http)) }}
nodePort: {{ .Values.cas.service.nodePorts.http }}
{{- else if eq .Values.cas.service.type "ClusterIP" }}
Expand Down
5 changes: 5 additions & 0 deletions deployment/chainloop/templates/controlplane/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ data:
enable_profiler: {{ .Values.controlplane.enableProfiler }}
server:
http:
{{- if include "controlplane.tls-secret-name" . }}
tls_config:
certificate: /data/server-certs/tls.crt
private_key: /data/server-certs/tls.key
{{- end }}
addr: "0.0.0.0:{{ .Values.controlplane.containerPorts.http }}"
timeout: 10s
external_url: {{ include "chainloop.controlplane.external_url" . }}
Expand Down
11 changes: 10 additions & 1 deletion deployment/chainloop/templates/controlplane/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,29 @@ spec:
httpGet:
path: /statusz
port: http
{{- if include "controlplane.tls-secret-name" . }}
scheme: HTTPS
{{- end }}
failureThreshold: 10
periodSeconds: 5
initialDelaySeconds: 10
livenessProbe:
httpGet:
path: /statusz
port: http
{{- if include "controlplane.tls-secret-name" . }}
scheme: HTTPS
{{- end }}
failureThreshold: 10
periodSeconds: 5
initialDelaySeconds: 10
readinessProbe:
httpGet:
path: /statusz?readiness=1
port: http
{{- if include "controlplane.tls-secret-name" . }}
scheme: HTTPS
{{- end }}
periodSeconds: 5
{{- if .Values.controlplane.lifecycleHooks }}
lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.controlplane.lifecycleHooks "context" $) | nindent 12 }}
Expand Down Expand Up @@ -249,4 +258,4 @@ spec:
- name: tsa-roots
configMap:
name: {{ include "chainloop.controlplane.fullname" $ }}-tsa
{{- end }}
{{- end }}
8 changes: 6 additions & 2 deletions deployment/chainloop/templates/controlplane/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ metadata:
name: {{ $fullName }}
namespace: {{ include "common.names.namespace" . | quote }}
labels: {{- include "chainloop.controlplane.labels" . | nindent 4 }}
{{- if or .Values.controlplane.ingress.annotations .Values.commonAnnotations }}
{{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.controlplane.ingress.annotations .Values.commonAnnotations) "context" .) }}
{{- $tlsAnnotations := dict }}
{{- if include "controlplane.tls-secret-name" . }}
{{- $_ := set $tlsAnnotations "nginx.org/ssl-services" $fullName }}
{{- end }}
{{- if or .Values.controlplane.ingress.annotations .Values.commonAnnotations $tlsAnnotations }}
{{- $annotations := include "common.tplvalues.merge" (dict "values" (list .Values.controlplane.ingress.annotations .Values.commonAnnotations $tlsAnnotations) "context" .) }}
annotations: {{- include "common.tplvalues.render" (dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
spec:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ spec:
targetPort: {{ .Values.controlplane.containerPorts.http }}
{{- end }}
protocol: TCP
appProtocol: {{ if include "controlplane.tls-secret-name" . }}kubernetes.io/h2{{ else }}kubernetes.io/h2c{{ end }}
{{- if and (or (eq .Values.controlplane.service.type "NodePort") (eq .Values.controlplane.service.type "LoadBalancer")) (not (empty .Values.controlplane.service.nodePorts.http)) }}
nodePort: {{ .Values.controlplane.service.nodePorts.http }}
{{- else if eq .Values.controlplane.service.type "ClusterIP" }}
Expand Down
Loading
Loading