Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,12 @@ the controller rather than by Helm.
{{- printf "%s.${metadata.componentNamespace}-${metadata.environmentName}" $svc -}}
{{- end -}}
{{- end -}}

{{/*
Stamped onto build-stage pods (Argo applies templates[].metadata to the pod), and the only
thing build-workflow-networkpolicy.yaml's podSelector can match — CR labels never reach the pod.
*/}}
{{- define "amp.buildWorkflowPodLabels" -}}
app.kubernetes.io/name: amp-build
app.kubernetes.io/component: build-workflow
{{- end -}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{{- if .Values.networkPolicy.buildWorkflows.enabled }}
{{- $bw := .Values.networkPolicy.buildWorkflows }}
{{- $namespaces := without ($bw.namespaces | default list) "" nil }}
{{- if not $namespaces }}
{{- $namespaces = list (printf "workflows-%s" (.Values.environment.name | default "default")) }}
{{- end }}
{{- range $namespace := $namespaces }}
{{- if ne $namespace $.Release.Namespace }}
{{- if not (lookup "v1" "Namespace" "" $namespace) }}
---
# OpenChoreo does not create this namespace until a workflow first runs there, so rendering
# only the NetworkPolicy fails a fresh install with `namespaces "<name>" not found`.
#
# Only when it is absent: Helm refuses to adopt a resource lacking its ownership metadata,
# so rendering unconditionally fails with `invalid ownership metadata` wherever OpenChoreo,
# an installer, or the evaluation chart created it first. The lookup needs a live cluster;
# a path without one (helm template, GitOps dry-run) emits it, which is correct for a first
# install and the safe direction to be wrong in.
#
# resource-policy: keep — OpenChoreo owns this namespace's lifecycle and it holds running
# workflows, so uninstalling this chart must never delete it.
apiVersion: v1
kind: Namespace
metadata:
name: {{ $namespace }}
annotations:
helm.sh/resource-policy: keep
labels:
{{- include "amp-build-extension.labels" $ | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{{- if .Values.networkPolicy.buildWorkflows.enabled }}
{{- $bw := .Values.networkPolicy.buildWorkflows }}
{{- $namespaces := without ($bw.namespaces | default list) "" nil }}
{{- if not $namespaces }}
{{- $namespaces = list (printf "workflows-%s" (.Values.environment.name | default "default")) }}
{{- end }}
{{- range $namespace := $namespaces }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: amp-build-workflow-egress
namespace: {{ $namespace }}
labels:
{{- include "amp-build-extension.labels" $ | nindent 4 }}
spec:
# generate-workload-cr is unlabelled and so unselected: it calls the OpenChoreo API and
# Thunder, and runs no user content.
podSelector:
matchLabels:
{{- include "amp.buildWorkflowPodLabels" $ | nindent 6 }}
policyTypes: [Egress]
egress:
# Matched post-DNAT: every rule names the backing pod's address and containerPort, not the Service's.

# Scoped to the DNS workload, not left open — build pods run untrusted code.
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: {{ $bw.dns.namespace }}
podSelector:
matchLabels:
{{ $bw.dns.podLabel.key }}: {{ $bw.dns.podLabel.value }}
ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP

# The point of the policy: builds keep the internet, lose the private network. No
# `ports`, so a mirror or registry on a non-standard port cannot break.
- to:
- ipBlock:
cidr: 0.0.0.0/0
{{- with without ($bw.internet.excludedCidrs | default list) "" nil }}
except:
{{- range . }}
- {{ . }}
{{- end }}
{{- end }}
{{- if $bw.internet.ipv6 }}
# A policy with only an IPv4 block denies all IPv6 egress, so dual-stack builds fail.
- ipBlock:
cidr: ::/0
{{- with without ($bw.internet.excludedCidrsV6 | default list) "" nil }}
except:
{{- range . }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}

{{- with $bw.apiServer }}
{{- $cidrs := without (.cidrs | default list) "" nil }}
{{- if and $cidrs .ports }}
# wait reports WorkflowTaskResults here; no pod backs the API server, so ipBlock. Pods
# are the unit of policy, so this reaches the build container too — workflow-sa can only
# create/patch workflowtaskresults.
- to:
{{- range $cidrs }}
- ipBlock:
cidr: {{ . }}
{{- end }}
ports:
{{- range .ports }}
- port: {{ . }}
protocol: TCP
{{- end }}
{{- end }}
{{- end }}

{{- with $bw.registry }}
{{- $cidrs := without (.cidrs | default list) "" nil }}
{{- if and $cidrs .ports }}
# publish-image pushes here and build-image pulls cached buildpacks; reached on the node
# network, which the internet rule's except withholds. registry.<baseDomain> needs no rule.
- to:
{{- range $cidrs }}
- ipBlock:
cidr: {{ . }}
{{- end }}
ports:
{{- range .ports }}
- port: {{ . }}
protocol: TCP
{{- end }}
{{- end }}

{{- with .inCluster }}
{{- if and .namespace .ports }}
# A registry addressed by Service DNS is matched post-DNAT, so this names the registry
# pod's namespace and its containerPort — the Service's own port never matches. Without
# podLabels this reaches every pod in that namespace on those ports.
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: {{ .namespace }}
{{- with .podLabels }}
podSelector:
matchLabels:
{{- toYaml . | nindent 14 }}
{{- end }}
ports:
{{- range .ports }}
- port: {{ . }}
protocol: TCP
{{- end }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{{- end }}
{{- end }}
{{- end }}

{{- with $bw.extraEgress }}
# Private-network destinations a build needs: self-hosted git, internal registry, proxy.
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ metadata:
spec:
templates:
- name: build-image
metadata:
labels:
{{- include "amp.buildWorkflowPodLabels" . | nindent 10 }}
inputs:
parameters:
- name: git-revision
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ metadata:
spec:
templates:
- name: checkout
metadata:
labels:
{{- include "amp.buildWorkflowPodLabels" . | nindent 10 }}
outputs:
parameters:
- name: git-revision
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ metadata:
spec:
templates:
- name: build-image
metadata:
labels:
{{- include "amp.buildWorkflowPodLabels" . | nindent 10 }}
# User-namespaced builds need idmapped-mount kernel support (~6.3+);
# buildWorkflows.userNamespaces in values.yaml documents the trade-off.
podSpecPatch: '{{ if .Values.buildWorkflows.userNamespaces }}{"hostUsers": false}{{ else }}{}{{ end }}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ metadata:
spec:
templates:
- name: build-image
metadata:
labels:
{{- include "amp.buildWorkflowPodLabels" . | nindent 10 }}
# User-namespaced builds need idmapped-mount kernel support (~6.3+);
# buildWorkflows.userNamespaces in values.yaml documents the trade-off.
podSpecPatch: '{{ if .Values.buildWorkflows.userNamespaces }}{"hostUsers": false}{{ else }}{}{{ end }}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ metadata:
spec:
templates:
- name: publish-image
metadata:
labels:
{{- include "amp.buildWorkflowPodLabels" . | nindent 10 }}
inputs:
parameters:
- name: git-revision
Expand Down
Loading
Loading