From 08e8c937090ae73e8cc9d9fb7ab6244717b12260 Mon Sep 17 00:00:00 2001 From: Jose Manuel Palomares Date: Mon, 22 Dec 2025 09:58:29 +0100 Subject: [PATCH 01/21] feat: inf-3308 adapt charts to support Envoy Gateway --- parcellab/common/Chart.yaml | 2 +- parcellab/common/templates/_httproute.tpl | 38 ++++ .../common/templates/_referencegrant.tpl | 57 ++++++ parcellab/common/templates/_routing.tpl | 11 + .../common/templates/_securitypolicy.tpl | 189 ++++++++++++++++++ parcellab/common/values.yaml | 73 +++++++ parcellab/cronjob/Chart.yaml | 2 +- parcellab/microservice/Chart.yaml | 2 +- parcellab/microservice/README.md | 6 + .../microservice/templates/httproute.yaml | 1 + .../templates/referencegrant.yaml | 1 + .../templates/securitypolicy.yaml | 1 + parcellab/microservice/values.yaml | 81 ++++++++ parcellab/monolith/Chart.yaml | 2 +- parcellab/monolith/README.md | 6 + parcellab/monolith/templates/httproute.yaml | 1 + .../monolith/templates/referencegrant.yaml | 1 + .../monolith/templates/securitypolicy.yaml | 1 + parcellab/monolith/values.yaml | 81 ++++++++ parcellab/worker-group/Chart.yaml | 2 +- 20 files changed, 553 insertions(+), 5 deletions(-) create mode 100644 parcellab/common/templates/_httproute.tpl create mode 100644 parcellab/common/templates/_referencegrant.tpl create mode 100644 parcellab/common/templates/_routing.tpl create mode 100644 parcellab/common/templates/_securitypolicy.tpl create mode 100644 parcellab/microservice/templates/httproute.yaml create mode 100644 parcellab/microservice/templates/referencegrant.yaml create mode 100644 parcellab/microservice/templates/securitypolicy.yaml create mode 100644 parcellab/monolith/templates/httproute.yaml create mode 100644 parcellab/monolith/templates/referencegrant.yaml create mode 100644 parcellab/monolith/templates/securitypolicy.yaml diff --git a/parcellab/common/Chart.yaml b/parcellab/common/Chart.yaml index da7e0dbe..e093e500 100644 --- a/parcellab/common/Chart.yaml +++ b/parcellab/common/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: common description: A Helm chart library for parcelLab charts type: library -version: 1.2.2 +version: 1.3.2 maintainers: - name: parcelLab email: engineering@parcellab.com diff --git a/parcellab/common/templates/_httproute.tpl b/parcellab/common/templates/_httproute.tpl new file mode 100644 index 00000000..4f7d465c --- /dev/null +++ b/parcellab/common/templates/_httproute.tpl @@ -0,0 +1,38 @@ +{{/* vim: set filetype=mustache: */}} +{{/* + Common httproute definition: + {{ include "common.httproute" ( + dict + "Values" "the values scope" + ) }} +*/}} + +{{- define "common.httproute" -}} +{{- $httproute := .Values.httproute | default dict -}} +{{- if $httproute.enabled }} +{{- $name := include "common.fullname" . }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "common.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "common.labels" . | nindent 4 }} +spec: + parentRefs: + - name: {{ $httproute.parentGateway }} + namespace: {{ $httproute.parentGatewayNamespace | default "envoy-gateway" }} + hostnames: + {{- range $httproute.hosts }} + - {{ . | quote }} + {{- end }} + rules: + - matches: + - path: + type: PathPrefix + value: {{ $httproute.path | default "/" }} + backendRefs: + - name: {{ include "common.fullname" . }} + port: {{ .Values.service.port }} +{{- end }} +{{- end -}} diff --git a/parcellab/common/templates/_referencegrant.tpl b/parcellab/common/templates/_referencegrant.tpl new file mode 100644 index 00000000..e9bbd27d --- /dev/null +++ b/parcellab/common/templates/_referencegrant.tpl @@ -0,0 +1,57 @@ +{{/* vim: set filetype=mustache: */}} +{{/* + Common ReferenceGrant definition: + {{ include "common.referencegrant" ( + dict + "Values" "the values scope" + "Release" .Release + ) }} +*/}} + +{{- define "common.referencegrant" -}} +{{- $referenceGrant := .Values.referenceGrant | default dict -}} +{{- if $referenceGrant.enabled }} +{{- $name := include "common.fullname" . }} +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: {{ $referenceGrant.name | default (printf "%s-grant" $name) }} + namespace: {{ $referenceGrant.namespace | default .Release.Namespace }} + labels: + {{- include "common.labels" . | nindent 4 }} + {{- with $referenceGrant.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + from: + {{- if $referenceGrant.from }} + {{- range $referenceGrant.from }} + - group: {{ .group | quote }} + kind: {{ .kind | quote }} + namespace: {{ .namespace | quote }} + {{- with .name }} + name: {{ . | quote }} + {{- end }} + {{- end }} + {{- else }} + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: {{ .Release.Namespace | quote }} + {{- end }} + to: + {{- if $referenceGrant.to }} + {{- range $referenceGrant.to }} + - group: {{ .group | quote }} + kind: {{ .kind | quote }} + {{- with .name }} + name: {{ . | quote }} + {{- end }} + {{- end }} + {{- else }} + - group: "" + kind: Service + {{- end }} +{{- end }} +{{- end -}} diff --git a/parcellab/common/templates/_routing.tpl b/parcellab/common/templates/_routing.tpl new file mode 100644 index 00000000..d71941a0 --- /dev/null +++ b/parcellab/common/templates/_routing.tpl @@ -0,0 +1,11 @@ +{{- define "common.routing" -}} +{{- $httproute := .Values.httproute | default dict -}} +{{- $ingress := .Values.ingress | default dict -}} + +{{- if $httproute.enabled }} + {{- include "common.httproute" . }} +{{- else if $ingress.enabled }} + {{- include "common.ingress" . }} +{{- end }} + +{{- end -}} diff --git a/parcellab/common/templates/_securitypolicy.tpl b/parcellab/common/templates/_securitypolicy.tpl new file mode 100644 index 00000000..3f7d9923 --- /dev/null +++ b/parcellab/common/templates/_securitypolicy.tpl @@ -0,0 +1,189 @@ +{{/* vim: set filetype=mustache: */}} +{{/* + Common SecurityPolicy definition: + {{ include "common.securitypolicy" ( + dict + "Values" "the values scope" + "Release" .Release + ) }} +*/}} + +{{- define "common.securitypolicy" -}} +{{- $securityPolicy := .Values.securityPolicy | default dict -}} +{{- if $securityPolicy.enabled }} +{{- $name := include "common.fullname" . }} +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: {{ $securityPolicy.name | default (printf "%s-security" $name) }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "common.labels" . | nindent 4 }} + {{- with $securityPolicy.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + targetRef: + group: {{ $securityPolicy.targetRef.group | default "gateway.networking.k8s.io" }} + kind: {{ $securityPolicy.targetRef.kind | default "HTTPRoute" }} + name: {{ $securityPolicy.targetRef.name | default $name }} + {{- with $securityPolicy.targetRef.namespace }} + namespace: {{ . }} + {{- end }} + {{- if $securityPolicy.oidc }} + oidc: + provider: + issuer: {{ required "securityPolicy.oidc.provider.issuer is required" $securityPolicy.oidc.provider.issuer | quote }} + {{- with $securityPolicy.oidc.provider.authorizationEndpoint }} + authorizationEndpoint: {{ . | quote }} + {{- end }} + {{- with $securityPolicy.oidc.provider.tokenEndpoint }} + tokenEndpoint: {{ . | quote }} + {{- end }} + clientID: {{ required "securityPolicy.oidc.clientID is required" $securityPolicy.oidc.clientID | quote }} + clientSecret: + {{- if $securityPolicy.oidc.clientSecret }} + name: {{ $securityPolicy.oidc.clientSecret.name | quote }} + {{- with $securityPolicy.oidc.clientSecret.namespace }} + namespace: {{ . | quote }} + {{- end }} + {{- else }} + name: "keycloak-oidc-secret" + {{- end }} + redirectURL: {{ required "securityPolicy.oidc.redirectURL is required" $securityPolicy.oidc.redirectURL | quote }} + {{- with $securityPolicy.oidc.logoutPath }} + logoutPath: {{ . | quote }} + {{- end }} + {{- if $securityPolicy.oidc.scopes }} + scopes: + {{- toYaml $securityPolicy.oidc.scopes | nindent 6 }} + {{- else }} + scopes: + - openid + - profile + - email + {{- end }} + {{- with $securityPolicy.oidc.cookieDomain }} + cookieDomain: {{ . | quote }} + {{- end }} + {{- with $securityPolicy.oidc.cookieNames }} + cookieNames: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if hasKey $securityPolicy.oidc "forwardAccessToken" }} + forwardAccessToken: {{ $securityPolicy.oidc.forwardAccessToken }} + {{- end }} + {{- if hasKey $securityPolicy.oidc "passThroughAuthHeader" }} + passThroughAuthHeader: {{ $securityPolicy.oidc.passThroughAuthHeader }} + {{- end }} + {{- with $securityPolicy.oidc.refreshToken }} + refreshToken: {{ . }} + {{- end }} + {{- end }} + {{- if $securityPolicy.jwt }} + jwt: + {{- if hasKey $securityPolicy.jwt "optional" }} + optional: {{ $securityPolicy.jwt.optional }} + {{- end }} + providers: + {{- range $securityPolicy.jwt.providers }} + - name: {{ .name | quote }} + issuer: {{ .issuer | quote }} + {{- with .audiences }} + audiences: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .remoteJWKS }} + remoteJWKS: + uri: {{ .remoteJWKS.uri | quote }} + {{- with .remoteJWKS.cacheDuration }} + cacheDuration: {{ . }} + {{- end }} + {{- end }} + {{- if .claimToHeaders }} + claimToHeaders: + {{- range .claimToHeaders }} + - header: {{ .header | quote }} + claim: {{ .claim | quote }} + {{- end }} + {{- end }} + {{- with .extractFrom }} + extractFrom: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + {{- if $securityPolicy.basicAuth }} + basicAuth: + users: + name: {{ $securityPolicy.basicAuth.users.name | quote }} + {{- with $securityPolicy.basicAuth.users.namespace }} + namespace: {{ . | quote }} + {{- end }} + {{- end }} + {{- if $securityPolicy.authorization }} + authorization: + defaultAction: {{ $securityPolicy.authorization.defaultAction | default "Deny" }} + {{- if $securityPolicy.authorization.rules }} + rules: + {{- range $securityPolicy.authorization.rules }} + - name: {{ .name | quote }} + action: {{ .action | default "Allow" }} + {{- if .principal }} + principal: + {{- if .principal.clientCIDRs }} + clientCIDRs: + {{- toYaml .principal.clientCIDRs | nindent 12 }} + {{- end }} + {{- if .principal.jwt }} + jwt: + provider: {{ .principal.jwt.provider | quote }} + {{- if .principal.jwt.scopes }} + scopes: + {{- toYaml .principal.jwt.scopes | nindent 14 }} + {{- end }} + {{- if .principal.jwt.claims }} + claims: + {{- range .principal.jwt.claims }} + - name: {{ .name | quote }} + {{- with .valueType }} + valueType: {{ . }} + {{- end }} + {{- if .values }} + values: + {{- toYaml .values | nindent 18 }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if $securityPolicy.cors }} + cors: + allowOrigins: + {{- toYaml $securityPolicy.cors.allowOrigins | nindent 6 }} + {{- with $securityPolicy.cors.allowMethods }} + allowMethods: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $securityPolicy.cors.allowHeaders }} + allowHeaders: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $securityPolicy.cors.exposeHeaders }} + exposeHeaders: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if hasKey $securityPolicy.cors "allowCredentials" }} + allowCredentials: {{ $securityPolicy.cors.allowCredentials }} + {{- end }} + {{- with $securityPolicy.cors.maxAge }} + maxAge: {{ . }} + {{- end }} + {{- end }} +{{- end }} +{{- end -}} diff --git a/parcellab/common/values.yaml b/parcellab/common/values.yaml index 2e495bc4..ee333bd0 100644 --- a/parcellab/common/values.yaml +++ b/parcellab/common/values.yaml @@ -23,6 +23,79 @@ image: tag: stable ingress: enabled: false + +## +## Envoy Gateway Resources +## + +# HTTPRoute - Configure routing through Envoy Gateway +httproute: + enabled: false + # parentGateway: gateway-api + # parentGatewayNamespace: envoy-gateway + # hosts: + # - myapp.gateway.test.parcellab.dev + # path: / + +# ReferenceGrant - Allow cross-namespace references +referenceGrant: + enabled: false + # Automatically allows HTTPRoute and SecurityPolicy from current namespace + # to reference Gateway and Secret in envoy-gateway namespace + +# SecurityPolicy - OIDC Authentication with Group-Based Authorization +# Example: Employee-Only App +securityPolicy: + enabled: false + # name: employee-only # Optional: custom name + # targetRef: + # kind: HTTPRoute + # name: myapp # Optional: defaults to release name + # oidc: + # provider: + # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" + # clientID: "envoy-gateway-client" + # clientSecret: + # name: "keycloak-oidc-secret" + # namespace: "envoy-gateway" + # redirectURL: "https://myapp.gateway.test.parcellab.dev/oauth2/callback" + # logoutPath: "/logout" + # scopes: + # - openid + # - profile + # - email + # cookieDomain: "myapp.gateway.test.parcellab.dev" + # forwardAccessToken: true + # passThroughAuthHeader: true + # jwt: + # optional: false + # providers: + # - name: keycloak + # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" + # remoteJWKS: + # uri: "https://auth.test.parcellab.dev/realms/parcellab-internal/protocol/openid-connect/certs" + # cacheDuration: 300s + # claimToHeaders: + # - header: "x-user-email" + # claim: "email" + # - header: "x-user-groups" + # claim: "groups" + # - header: "x-user-id" + # claim: "sub" + # authorization: + # defaultAction: Deny + # rules: + # - name: allow-employees + # action: Allow + # principal: + # jwt: + # provider: keycloak + # claims: + # - name: groups + # valueType: StringArray + # values: + # - "/parcellab-employee" + name: common terminationGracePeriodSeconds: 30 nodeSelector: {} diff --git a/parcellab/cronjob/Chart.yaml b/parcellab/cronjob/Chart.yaml index 7eff6a05..3ba4d4c0 100644 --- a/parcellab/cronjob/Chart.yaml +++ b/parcellab/cronjob/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: cronjob description: Single cron job -version: 0.4.1 +version: 0.4.2 dependencies: - name: common version: "*" diff --git a/parcellab/microservice/Chart.yaml b/parcellab/microservice/Chart.yaml index 9445b295..b32100fb 100644 --- a/parcellab/microservice/Chart.yaml +++ b/parcellab/microservice/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: microservice description: Simple microservice -version: 0.4.1 +version: 0.5.1 dependencies: - name: common version: "*" diff --git a/parcellab/microservice/README.md b/parcellab/microservice/README.md index 5e268d3b..01136f96 100644 --- a/parcellab/microservice/README.md +++ b/parcellab/microservice/README.md @@ -31,10 +31,16 @@ needs. Its generated secret's data values will be loaded as environment variables to the target pod. - `hpa` - Horizontal automatic scaling rules of pods. Can be defined with the `autoscaling` setting. +- `httproute` + - Configure routing through Envoy Gateway. Defined with `httproute`. - `ingress` - Rules to open external access to the workload. Can be defined with `ingress`. - `poddisruptionbudget` - Limit the number of concurrent disruptions for the application. Defined with `podDisruptionBudget`. +- `referencegrant` + - Allow cross-namespace references for Envoy Gateway (e.g., HTTPRoute → Gateway). Defined with `referenceGrant`. +- `securitypolicy` + - Configure authentication and authorization with Envoy Gateway. Defined with `securityPolicy`. - `serviceaccount` - Configure a service account for the pods. Defined with `serviceAccount`. - `vpa` diff --git a/parcellab/microservice/templates/httproute.yaml b/parcellab/microservice/templates/httproute.yaml new file mode 100644 index 00000000..e0cd8f4d --- /dev/null +++ b/parcellab/microservice/templates/httproute.yaml @@ -0,0 +1 @@ +{{ include "common.httproute" . }} diff --git a/parcellab/microservice/templates/referencegrant.yaml b/parcellab/microservice/templates/referencegrant.yaml new file mode 100644 index 00000000..d64fae3a --- /dev/null +++ b/parcellab/microservice/templates/referencegrant.yaml @@ -0,0 +1 @@ +{{- include "common.referencegrant" . }} diff --git a/parcellab/microservice/templates/securitypolicy.yaml b/parcellab/microservice/templates/securitypolicy.yaml new file mode 100644 index 00000000..c62fbe00 --- /dev/null +++ b/parcellab/microservice/templates/securitypolicy.yaml @@ -0,0 +1 @@ +{{- include "common.securitypolicy" . }} diff --git a/parcellab/microservice/values.yaml b/parcellab/microservice/values.yaml index 8657c787..dc208c2b 100644 --- a/parcellab/microservice/values.yaml +++ b/parcellab/microservice/values.yaml @@ -46,6 +46,87 @@ ingress: # hosts: # - chart-example.local +## +## Envoy Gateway Resources +## + +# HTTPRoute - Configure routing through Envoy Gateway +httproute: + enabled: false + # parentGateway: gateway-api + # parentGatewayNamespace: envoy-gateway + # hosts: + # - myapp.gateway.test.parcellab.dev + # path: / + +# ReferenceGrant - Allow cross-namespace references +referenceGrant: + enabled: false + # name: custom-grant # Optional: custom name + # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) + # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) + # - group: gateway.networking.k8s.io + # kind: HTTPRoute + # namespace: myapp + # to: # Optional: specify what can be referenced (default: Service) + # - group: "" + # kind: Service + # - group: "" + # kind: Secret + +# SecurityPolicy - OIDC Authentication with Group-Based Authorization +# Example: Employee-Only App +securityPolicy: + enabled: false + # name: employee-only # Optional: custom name + # targetRef: + # kind: HTTPRoute + # name: myapp # Optional: defaults to release name + # oidc: + # provider: + # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" + # clientID: "envoy-gateway-client" + # clientSecret: + # name: "keycloak-oidc-secret" + # namespace: "envoy-gateway" + # redirectURL: "https://myapp.gateway.test.parcellab.dev/oauth2/callback" + # logoutPath: "/logout" + # scopes: + # - openid + # - profile + # - email + # cookieDomain: "myapp.gateway.test.parcellab.dev" + # forwardAccessToken: true + # passThroughAuthHeader: true + # jwt: + # optional: false + # providers: + # - name: keycloak + # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" + # remoteJWKS: + # uri: "https://auth.test.parcellab.dev/realms/parcellab-internal/protocol/openid-connect/certs" + # cacheDuration: 300s + # claimToHeaders: + # - header: "x-user-email" + # claim: "email" + # - header: "x-user-groups" + # claim: "groups" + # - header: "x-user-id" + # claim: "sub" + # authorization: + # defaultAction: Deny + # rules: + # - name: allow-employees + # action: Allow + # principal: + # jwt: + # provider: keycloak + # claims: + # - name: groups + # valueType: StringArray + # values: + # - "/parcellab-employee" + ## ## Cronjob ## diff --git a/parcellab/monolith/Chart.yaml b/parcellab/monolith/Chart.yaml index be349dfb..1de13c65 100644 --- a/parcellab/monolith/Chart.yaml +++ b/parcellab/monolith/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: monolith description: Application that may define multiple services and cronjobs -version: 0.4.0 +version: 0.5.0 dependencies: - name: common version: "*" diff --git a/parcellab/monolith/README.md b/parcellab/monolith/README.md index 678dee32..c44c7789 100644 --- a/parcellab/monolith/README.md +++ b/parcellab/monolith/README.md @@ -31,10 +31,16 @@ needs. Its generated secret's data values will be loaded as environment variables to the target pod. - `hpa` - Horizontal automatic scaling rules of pods. Can be defined with the `autoscaling` setting. +- `httproute` + - Configure routing through Envoy Gateway. Defined with `httproute`. - `ingress` - Rules to open external access to the workload. Can be defined with `ingress`. - `poddisruptionbudget` - Limit the number of concurrent disruptions for the application. Defined with `podDisruptionBudget`. +- `referencegrant` + - Allow cross-namespace references for Envoy Gateway (e.g., HTTPRoute → Gateway). Defined with `referenceGrant`. +- `securitypolicy` + - Configure authentication and authorization with Envoy Gateway. Defined with `securityPolicy`. - `serviceaccount` - Configure a service account for the pods. Defined with `serviceAccount`. - `vpa` diff --git a/parcellab/monolith/templates/httproute.yaml b/parcellab/monolith/templates/httproute.yaml new file mode 100644 index 00000000..e0cd8f4d --- /dev/null +++ b/parcellab/monolith/templates/httproute.yaml @@ -0,0 +1 @@ +{{ include "common.httproute" . }} diff --git a/parcellab/monolith/templates/referencegrant.yaml b/parcellab/monolith/templates/referencegrant.yaml new file mode 100644 index 00000000..d64fae3a --- /dev/null +++ b/parcellab/monolith/templates/referencegrant.yaml @@ -0,0 +1 @@ +{{- include "common.referencegrant" . }} diff --git a/parcellab/monolith/templates/securitypolicy.yaml b/parcellab/monolith/templates/securitypolicy.yaml new file mode 100644 index 00000000..c62fbe00 --- /dev/null +++ b/parcellab/monolith/templates/securitypolicy.yaml @@ -0,0 +1 @@ +{{- include "common.securitypolicy" . }} diff --git a/parcellab/monolith/values.yaml b/parcellab/monolith/values.yaml index a4e9df5c..3b94e11c 100644 --- a/parcellab/monolith/values.yaml +++ b/parcellab/monolith/values.yaml @@ -75,6 +75,87 @@ ingress: # hosts: # - chart-example.local +## +## Envoy Gateway Resources +## + +# HTTPRoute - Configure routing through Envoy Gateway +httproute: + enabled: false + # parentGateway: gateway-api + # parentGatewayNamespace: envoy-gateway + # hosts: + # - myapp.gateway.test.parcellab.dev + # path: / + +# ReferenceGrant - Allow cross-namespace references +referenceGrant: + enabled: false + # name: custom-grant # Optional: custom name + # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) + # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) + # - group: gateway.networking.k8s.io + # kind: HTTPRoute + # namespace: myapp + # to: # Optional: specify what can be referenced (default: Service) + # - group: "" + # kind: Service + # - group: "" + # kind: Secret + +# SecurityPolicy - OIDC Authentication with Group-Based Authorization +# Example: Employee-Only App +securityPolicy: + enabled: false + # name: employee-only # Optional: custom name + # targetRef: + # kind: HTTPRoute + # name: myapp # Optional: defaults to release name + # oidc: + # provider: + # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" + # clientID: "envoy-gateway-client" + # clientSecret: + # name: "keycloak-oidc-secret" + # namespace: "envoy-gateway" + # redirectURL: "https://myapp.gateway.test.parcellab.dev/oauth2/callback" + # logoutPath: "/logout" + # scopes: + # - openid + # - profile + # - email + # cookieDomain: "myapp.gateway.test.parcellab.dev" + # forwardAccessToken: true + # passThroughAuthHeader: true + # jwt: + # optional: false + # providers: + # - name: keycloak + # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" + # remoteJWKS: + # uri: "https://auth.test.parcellab.dev/realms/parcellab-internal/protocol/openid-connect/certs" + # cacheDuration: 300s + # claimToHeaders: + # - header: "x-user-email" + # claim: "email" + # - header: "x-user-groups" + # claim: "groups" + # - header: "x-user-id" + # claim: "sub" + # authorization: + # defaultAction: Deny + # rules: + # - name: allow-employees + # action: Allow + # principal: + # jwt: + # provider: keycloak + # claims: + # - name: groups + # valueType: StringArray + # values: + # - "/parcellab-employee" + ## ## Cronjob ## diff --git a/parcellab/worker-group/Chart.yaml b/parcellab/worker-group/Chart.yaml index 533d6ede..da9c5926 100644 --- a/parcellab/worker-group/Chart.yaml +++ b/parcellab/worker-group/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: worker-group description: Set of workers that do not expose a service -version: 0.3.1 +version: 0.3.2 dependencies: - name: common version: "*" From 96d39ebe7b6c9c106ac2f11baf7f027c891c16be Mon Sep 17 00:00:00 2001 From: Jose Manuel Palomares Date: Tue, 23 Dec 2025 10:03:17 +0100 Subject: [PATCH 02/21] feat: inf-3308 adapt charts to support Envoy Gateway --- parcellab/common/templates/_httproute.tpl | 6 ++++-- parcellab/common/templates/_referencegrant.tpl | 10 +++++----- parcellab/common/templates/_securitypolicy.tpl | 9 +++++---- parcellab/common/values.yaml | 13 +++++++++++-- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/parcellab/common/templates/_httproute.tpl b/parcellab/common/templates/_httproute.tpl index 4f7d465c..3769fe0f 100644 --- a/parcellab/common/templates/_httproute.tpl +++ b/parcellab/common/templates/_httproute.tpl @@ -20,12 +20,14 @@ metadata: {{- include "common.labels" . | nindent 4 }} spec: parentRefs: - - name: {{ $httproute.parentGateway }} + - name: {{ required "httproute.parentGateway is required" $httproute.parentGateway }} namespace: {{ $httproute.parentGatewayNamespace | default "envoy-gateway" }} + {{- with $httproute.hosts }} hostnames: - {{- range $httproute.hosts }} + {{- range . }} - {{ . | quote }} {{- end }} + {{- end }} rules: - matches: - path: diff --git a/parcellab/common/templates/_referencegrant.tpl b/parcellab/common/templates/_referencegrant.tpl index e9bbd27d..84960137 100644 --- a/parcellab/common/templates/_referencegrant.tpl +++ b/parcellab/common/templates/_referencegrant.tpl @@ -28,9 +28,9 @@ spec: from: {{- if $referenceGrant.from }} {{- range $referenceGrant.from }} - - group: {{ .group | quote }} - kind: {{ .kind | quote }} - namespace: {{ .namespace | quote }} + - group: {{ .group | default "gateway.networking.k8s.io" | quote }} + kind: {{ required "referenceGrant.from.kind is required" .kind | quote }} + namespace: {{ .namespace | default $.Release.Namespace | quote }} {{- with .name }} name: {{ . | quote }} {{- end }} @@ -43,8 +43,8 @@ spec: to: {{- if $referenceGrant.to }} {{- range $referenceGrant.to }} - - group: {{ .group | quote }} - kind: {{ .kind | quote }} + - group: {{ .group | default "" | quote }} + kind: {{ required "referenceGrant.to.kind is required" .kind | quote }} {{- with .name }} name: {{ . | quote }} {{- end }} diff --git a/parcellab/common/templates/_securitypolicy.tpl b/parcellab/common/templates/_securitypolicy.tpl index 3f7d9923..6d398536 100644 --- a/parcellab/common/templates/_securitypolicy.tpl +++ b/parcellab/common/templates/_securitypolicy.tpl @@ -12,6 +12,7 @@ {{- $securityPolicy := .Values.securityPolicy | default dict -}} {{- if $securityPolicy.enabled }} {{- $name := include "common.fullname" . }} +{{- $targetRef := $securityPolicy.targetRef | default dict -}} --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy @@ -26,10 +27,10 @@ metadata: {{- end }} spec: targetRef: - group: {{ $securityPolicy.targetRef.group | default "gateway.networking.k8s.io" }} - kind: {{ $securityPolicy.targetRef.kind | default "HTTPRoute" }} - name: {{ $securityPolicy.targetRef.name | default $name }} - {{- with $securityPolicy.targetRef.namespace }} + group: {{ $targetRef.group | default "gateway.networking.k8s.io" }} + kind: {{ $targetRef.kind | default "HTTPRoute" }} + name: {{ $targetRef.name | default $name }} + {{- with $targetRef.namespace }} namespace: {{ . }} {{- end }} {{- if $securityPolicy.oidc }} diff --git a/parcellab/common/values.yaml b/parcellab/common/values.yaml index ee333bd0..c19c10ed 100644 --- a/parcellab/common/values.yaml +++ b/parcellab/common/values.yaml @@ -40,8 +40,17 @@ httproute: # ReferenceGrant - Allow cross-namespace references referenceGrant: enabled: false - # Automatically allows HTTPRoute and SecurityPolicy from current namespace - # to reference Gateway and Secret in envoy-gateway namespace + # name: custom-grant # Optional: custom name + # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) + # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) + # - group: gateway.networking.k8s.io + # kind: HTTPRoute + # namespace: myapp + # to: # Optional: specify what can be referenced (default: Service) + # - group: "" + # kind: Service + # - group: "" + # kind: Secret # SecurityPolicy - OIDC Authentication with Group-Based Authorization # Example: Employee-Only App From 9f2f436de62d285bd650bf15b698160c3a9dad08 Mon Sep 17 00:00:00 2001 From: Jose Manuel Palomares Date: Tue, 23 Dec 2025 10:12:12 +0100 Subject: [PATCH 03/21] feat: inf-3308 adapt charts to support Envoy Gateway --- parcellab/microservice/templates/httproute.yaml | 4 ++++ parcellab/microservice/templates/referencegrant.yaml | 4 ++++ parcellab/microservice/templates/securitypolicy.yaml | 4 ++++ parcellab/monolith/templates/httproute.yaml | 4 ++++ parcellab/monolith/templates/referencegrant.yaml | 4 ++++ parcellab/monolith/templates/securitypolicy.yaml | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/parcellab/microservice/templates/httproute.yaml b/parcellab/microservice/templates/httproute.yaml index e0cd8f4d..579f4a86 100644 --- a/parcellab/microservice/templates/httproute.yaml +++ b/parcellab/microservice/templates/httproute.yaml @@ -1 +1,5 @@ +{{- if .Values.httproute }} +{{- if .Values.httproute.enabled }} {{ include "common.httproute" . }} +{{- end }} +{{- end }} diff --git a/parcellab/microservice/templates/referencegrant.yaml b/parcellab/microservice/templates/referencegrant.yaml index d64fae3a..45c9b4bb 100644 --- a/parcellab/microservice/templates/referencegrant.yaml +++ b/parcellab/microservice/templates/referencegrant.yaml @@ -1 +1,5 @@ +{{- if .Values.referenceGrant }} +{{- if .Values.referenceGrant.enabled }} {{- include "common.referencegrant" . }} +{{- end }} +{{- end }} diff --git a/parcellab/microservice/templates/securitypolicy.yaml b/parcellab/microservice/templates/securitypolicy.yaml index c62fbe00..90b407f0 100644 --- a/parcellab/microservice/templates/securitypolicy.yaml +++ b/parcellab/microservice/templates/securitypolicy.yaml @@ -1 +1,5 @@ +{{- if .Values.securityPolicy }} +{{- if .Values.securityPolicy.enabled }} {{- include "common.securitypolicy" . }} +{{- end }} +{{- end }} diff --git a/parcellab/monolith/templates/httproute.yaml b/parcellab/monolith/templates/httproute.yaml index e0cd8f4d..579f4a86 100644 --- a/parcellab/monolith/templates/httproute.yaml +++ b/parcellab/monolith/templates/httproute.yaml @@ -1 +1,5 @@ +{{- if .Values.httproute }} +{{- if .Values.httproute.enabled }} {{ include "common.httproute" . }} +{{- end }} +{{- end }} diff --git a/parcellab/monolith/templates/referencegrant.yaml b/parcellab/monolith/templates/referencegrant.yaml index d64fae3a..45c9b4bb 100644 --- a/parcellab/monolith/templates/referencegrant.yaml +++ b/parcellab/monolith/templates/referencegrant.yaml @@ -1 +1,5 @@ +{{- if .Values.referenceGrant }} +{{- if .Values.referenceGrant.enabled }} {{- include "common.referencegrant" . }} +{{- end }} +{{- end }} diff --git a/parcellab/monolith/templates/securitypolicy.yaml b/parcellab/monolith/templates/securitypolicy.yaml index c62fbe00..90b407f0 100644 --- a/parcellab/monolith/templates/securitypolicy.yaml +++ b/parcellab/monolith/templates/securitypolicy.yaml @@ -1 +1,5 @@ +{{- if .Values.securityPolicy }} +{{- if .Values.securityPolicy.enabled }} {{- include "common.securitypolicy" . }} +{{- end }} +{{- end }} From 69214205fcd4a38dcd127f6674df49c1587866f5 Mon Sep 17 00:00:00 2001 From: Jose Manuel Palomares Date: Wed, 24 Dec 2025 14:27:00 +0100 Subject: [PATCH 04/21] feat: inf-3308 adapt charts to support Envoy Gateway --- parcellab/common/templates/_httproute.tpl | 3 +- .../common/templates/_referencegrant.tpl | 3 +- parcellab/common/templates/_routing.tpl | 3 +- .../common/templates/_securitypolicy.tpl | 190 ------------------ parcellab/common/values.yaml | 100 +++------ parcellab/microservice/README.md | 8 +- .../microservice/templates/httproute.yaml | 6 +- .../templates/referencegrant.yaml | 4 - .../templates/securitypolicy.yaml | 5 - parcellab/microservice/values.yaml | 98 ++------- parcellab/monolith/README.md | 8 +- parcellab/monolith/templates/httproute.yaml | 6 +- .../monolith/templates/referencegrant.yaml | 4 - .../monolith/templates/securitypolicy.yaml | 5 - parcellab/monolith/values.yaml | 98 ++------- 15 files changed, 82 insertions(+), 459 deletions(-) delete mode 100644 parcellab/common/templates/_securitypolicy.tpl delete mode 100644 parcellab/microservice/templates/securitypolicy.yaml delete mode 100644 parcellab/monolith/templates/securitypolicy.yaml diff --git a/parcellab/common/templates/_httproute.tpl b/parcellab/common/templates/_httproute.tpl index 3769fe0f..4c4f758f 100644 --- a/parcellab/common/templates/_httproute.tpl +++ b/parcellab/common/templates/_httproute.tpl @@ -8,7 +8,8 @@ */}} {{- define "common.httproute" -}} -{{- $httproute := .Values.httproute | default dict -}} +{{- $envoy := .Values.envoy | default dict -}} +{{- $httproute := $envoy.httpRoute | default dict -}} {{- if $httproute.enabled }} {{- $name := include "common.fullname" . }} apiVersion: gateway.networking.k8s.io/v1 diff --git a/parcellab/common/templates/_referencegrant.tpl b/parcellab/common/templates/_referencegrant.tpl index 84960137..8072bc67 100644 --- a/parcellab/common/templates/_referencegrant.tpl +++ b/parcellab/common/templates/_referencegrant.tpl @@ -9,7 +9,8 @@ */}} {{- define "common.referencegrant" -}} -{{- $referenceGrant := .Values.referenceGrant | default dict -}} +{{- $envoy := .Values.envoy | default dict -}} +{{- $referenceGrant := $envoy.referenceGrant | default dict -}} {{- if $referenceGrant.enabled }} {{- $name := include "common.fullname" . }} --- diff --git a/parcellab/common/templates/_routing.tpl b/parcellab/common/templates/_routing.tpl index d71941a0..b89cc803 100644 --- a/parcellab/common/templates/_routing.tpl +++ b/parcellab/common/templates/_routing.tpl @@ -1,5 +1,6 @@ {{- define "common.routing" -}} -{{- $httproute := .Values.httproute | default dict -}} +{{- $envoy := .Values.envoy | default dict -}} +{{- $httproute := $envoy.httpRoute | default dict -}} {{- $ingress := .Values.ingress | default dict -}} {{- if $httproute.enabled }} diff --git a/parcellab/common/templates/_securitypolicy.tpl b/parcellab/common/templates/_securitypolicy.tpl deleted file mode 100644 index 6d398536..00000000 --- a/parcellab/common/templates/_securitypolicy.tpl +++ /dev/null @@ -1,190 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* - Common SecurityPolicy definition: - {{ include "common.securitypolicy" ( - dict - "Values" "the values scope" - "Release" .Release - ) }} -*/}} - -{{- define "common.securitypolicy" -}} -{{- $securityPolicy := .Values.securityPolicy | default dict -}} -{{- if $securityPolicy.enabled }} -{{- $name := include "common.fullname" . }} -{{- $targetRef := $securityPolicy.targetRef | default dict -}} ---- -apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: SecurityPolicy -metadata: - name: {{ $securityPolicy.name | default (printf "%s-security" $name) }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "common.labels" . | nindent 4 }} - {{- with $securityPolicy.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - targetRef: - group: {{ $targetRef.group | default "gateway.networking.k8s.io" }} - kind: {{ $targetRef.kind | default "HTTPRoute" }} - name: {{ $targetRef.name | default $name }} - {{- with $targetRef.namespace }} - namespace: {{ . }} - {{- end }} - {{- if $securityPolicy.oidc }} - oidc: - provider: - issuer: {{ required "securityPolicy.oidc.provider.issuer is required" $securityPolicy.oidc.provider.issuer | quote }} - {{- with $securityPolicy.oidc.provider.authorizationEndpoint }} - authorizationEndpoint: {{ . | quote }} - {{- end }} - {{- with $securityPolicy.oidc.provider.tokenEndpoint }} - tokenEndpoint: {{ . | quote }} - {{- end }} - clientID: {{ required "securityPolicy.oidc.clientID is required" $securityPolicy.oidc.clientID | quote }} - clientSecret: - {{- if $securityPolicy.oidc.clientSecret }} - name: {{ $securityPolicy.oidc.clientSecret.name | quote }} - {{- with $securityPolicy.oidc.clientSecret.namespace }} - namespace: {{ . | quote }} - {{- end }} - {{- else }} - name: "keycloak-oidc-secret" - {{- end }} - redirectURL: {{ required "securityPolicy.oidc.redirectURL is required" $securityPolicy.oidc.redirectURL | quote }} - {{- with $securityPolicy.oidc.logoutPath }} - logoutPath: {{ . | quote }} - {{- end }} - {{- if $securityPolicy.oidc.scopes }} - scopes: - {{- toYaml $securityPolicy.oidc.scopes | nindent 6 }} - {{- else }} - scopes: - - openid - - profile - - email - {{- end }} - {{- with $securityPolicy.oidc.cookieDomain }} - cookieDomain: {{ . | quote }} - {{- end }} - {{- with $securityPolicy.oidc.cookieNames }} - cookieNames: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- if hasKey $securityPolicy.oidc "forwardAccessToken" }} - forwardAccessToken: {{ $securityPolicy.oidc.forwardAccessToken }} - {{- end }} - {{- if hasKey $securityPolicy.oidc "passThroughAuthHeader" }} - passThroughAuthHeader: {{ $securityPolicy.oidc.passThroughAuthHeader }} - {{- end }} - {{- with $securityPolicy.oidc.refreshToken }} - refreshToken: {{ . }} - {{- end }} - {{- end }} - {{- if $securityPolicy.jwt }} - jwt: - {{- if hasKey $securityPolicy.jwt "optional" }} - optional: {{ $securityPolicy.jwt.optional }} - {{- end }} - providers: - {{- range $securityPolicy.jwt.providers }} - - name: {{ .name | quote }} - issuer: {{ .issuer | quote }} - {{- with .audiences }} - audiences: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- if .remoteJWKS }} - remoteJWKS: - uri: {{ .remoteJWKS.uri | quote }} - {{- with .remoteJWKS.cacheDuration }} - cacheDuration: {{ . }} - {{- end }} - {{- end }} - {{- if .claimToHeaders }} - claimToHeaders: - {{- range .claimToHeaders }} - - header: {{ .header | quote }} - claim: {{ .claim | quote }} - {{- end }} - {{- end }} - {{- with .extractFrom }} - extractFrom: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- end }} - {{- end }} - {{- if $securityPolicy.basicAuth }} - basicAuth: - users: - name: {{ $securityPolicy.basicAuth.users.name | quote }} - {{- with $securityPolicy.basicAuth.users.namespace }} - namespace: {{ . | quote }} - {{- end }} - {{- end }} - {{- if $securityPolicy.authorization }} - authorization: - defaultAction: {{ $securityPolicy.authorization.defaultAction | default "Deny" }} - {{- if $securityPolicy.authorization.rules }} - rules: - {{- range $securityPolicy.authorization.rules }} - - name: {{ .name | quote }} - action: {{ .action | default "Allow" }} - {{- if .principal }} - principal: - {{- if .principal.clientCIDRs }} - clientCIDRs: - {{- toYaml .principal.clientCIDRs | nindent 12 }} - {{- end }} - {{- if .principal.jwt }} - jwt: - provider: {{ .principal.jwt.provider | quote }} - {{- if .principal.jwt.scopes }} - scopes: - {{- toYaml .principal.jwt.scopes | nindent 14 }} - {{- end }} - {{- if .principal.jwt.claims }} - claims: - {{- range .principal.jwt.claims }} - - name: {{ .name | quote }} - {{- with .valueType }} - valueType: {{ . }} - {{- end }} - {{- if .values }} - values: - {{- toYaml .values | nindent 18 }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- if $securityPolicy.cors }} - cors: - allowOrigins: - {{- toYaml $securityPolicy.cors.allowOrigins | nindent 6 }} - {{- with $securityPolicy.cors.allowMethods }} - allowMethods: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with $securityPolicy.cors.allowHeaders }} - allowHeaders: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with $securityPolicy.cors.exposeHeaders }} - exposeHeaders: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- if hasKey $securityPolicy.cors "allowCredentials" }} - allowCredentials: {{ $securityPolicy.cors.allowCredentials }} - {{- end }} - {{- with $securityPolicy.cors.maxAge }} - maxAge: {{ . }} - {{- end }} - {{- end }} -{{- end }} -{{- end -}} diff --git a/parcellab/common/values.yaml b/parcellab/common/values.yaml index 54c13dcb..e5382eae 100644 --- a/parcellab/common/values.yaml +++ b/parcellab/common/values.yaml @@ -28,82 +28,34 @@ ingress: ## Envoy Gateway Resources ## -# HTTPRoute - Configure routing through Envoy Gateway -httproute: - enabled: false - # parentGateway: gateway-api - # parentGatewayNamespace: envoy-gateway - # hosts: - # - myapp.gateway.test.parcellab.dev - # path: / +# Configure Envoy Gateway resources under a single parent: +# +# envoy: +# httpRoute: {...} +# referenceGrant: {...} -# ReferenceGrant - Allow cross-namespace references -referenceGrant: - enabled: false - # name: custom-grant # Optional: custom name - # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) - # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) - # - group: gateway.networking.k8s.io - # kind: HTTPRoute - # namespace: myapp - # to: # Optional: specify what can be referenced (default: Service) - # - group: "" - # kind: Service - # - group: "" - # kind: Secret +envoy: + httpRoute: + enabled: false + # parentGateway: gateway-api + # parentGatewayNamespace: envoy-gateway + # hosts: + # - myapp.gateway.test.parcellab.dev + # path: / -# SecurityPolicy - OIDC Authentication with Group-Based Authorization -# Example: Employee-Only App -securityPolicy: - enabled: false - # name: employee-only # Optional: custom name - # targetRef: - # kind: HTTPRoute - # name: myapp # Optional: defaults to release name - # oidc: - # provider: - # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" - # clientID: "envoy-gateway-client" - # clientSecret: - # name: "keycloak-oidc-secret" - # namespace: "envoy-gateway" - # redirectURL: "https://myapp.gateway.test.parcellab.dev/oauth2/callback" - # logoutPath: "/logout" - # scopes: - # - openid - # - profile - # - email - # cookieDomain: "myapp.gateway.test.parcellab.dev" - # forwardAccessToken: true - # passThroughAuthHeader: true - # jwt: - # optional: false - # providers: - # - name: keycloak - # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" - # remoteJWKS: - # uri: "https://auth.test.parcellab.dev/realms/parcellab-internal/protocol/openid-connect/certs" - # cacheDuration: 300s - # claimToHeaders: - # - header: "x-user-email" - # claim: "email" - # - header: "x-user-groups" - # claim: "groups" - # - header: "x-user-id" - # claim: "sub" - # authorization: - # defaultAction: Deny - # rules: - # - name: allow-employees - # action: Allow - # principal: - # jwt: - # provider: keycloak - # claims: - # - name: groups - # valueType: StringArray - # values: - # - "/parcellab-employee" + referenceGrant: + enabled: false + # name: custom-grant # Optional: custom name + # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) + # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) + # - group: gateway.networking.k8s.io + # kind: HTTPRoute + # namespace: myapp + # to: # Optional: specify what can be referenced (default: Service) + # - group: "" + # kind: Service + # - group: "" + # kind: Secret name: common terminationGracePeriodSeconds: 30 diff --git a/parcellab/microservice/README.md b/parcellab/microservice/README.md index 01136f96..a53956d8 100644 --- a/parcellab/microservice/README.md +++ b/parcellab/microservice/README.md @@ -31,16 +31,12 @@ needs. Its generated secret's data values will be loaded as environment variables to the target pod. - `hpa` - Horizontal automatic scaling rules of pods. Can be defined with the `autoscaling` setting. -- `httproute` - - Configure routing through Envoy Gateway. Defined with `httproute`. +- `envoy` + - Envoy Gateway resources (HTTPRoute, ReferenceGrant). Defined under `envoy.*`. - `ingress` - Rules to open external access to the workload. Can be defined with `ingress`. - `poddisruptionbudget` - Limit the number of concurrent disruptions for the application. Defined with `podDisruptionBudget`. -- `referencegrant` - - Allow cross-namespace references for Envoy Gateway (e.g., HTTPRoute → Gateway). Defined with `referenceGrant`. -- `securitypolicy` - - Configure authentication and authorization with Envoy Gateway. Defined with `securityPolicy`. - `serviceaccount` - Configure a service account for the pods. Defined with `serviceAccount`. - `vpa` diff --git a/parcellab/microservice/templates/httproute.yaml b/parcellab/microservice/templates/httproute.yaml index 579f4a86..56066a75 100644 --- a/parcellab/microservice/templates/httproute.yaml +++ b/parcellab/microservice/templates/httproute.yaml @@ -1,5 +1 @@ -{{- if .Values.httproute }} -{{- if .Values.httproute.enabled }} -{{ include "common.httproute" . }} -{{- end }} -{{- end }} +{{- include "common.httproute" . }} diff --git a/parcellab/microservice/templates/referencegrant.yaml b/parcellab/microservice/templates/referencegrant.yaml index 45c9b4bb..d64fae3a 100644 --- a/parcellab/microservice/templates/referencegrant.yaml +++ b/parcellab/microservice/templates/referencegrant.yaml @@ -1,5 +1 @@ -{{- if .Values.referenceGrant }} -{{- if .Values.referenceGrant.enabled }} {{- include "common.referencegrant" . }} -{{- end }} -{{- end }} diff --git a/parcellab/microservice/templates/securitypolicy.yaml b/parcellab/microservice/templates/securitypolicy.yaml deleted file mode 100644 index 90b407f0..00000000 --- a/parcellab/microservice/templates/securitypolicy.yaml +++ /dev/null @@ -1,5 +0,0 @@ -{{- if .Values.securityPolicy }} -{{- if .Values.securityPolicy.enabled }} -{{- include "common.securitypolicy" . }} -{{- end }} -{{- end }} diff --git a/parcellab/microservice/values.yaml b/parcellab/microservice/values.yaml index ed31e0a1..61272323 100644 --- a/parcellab/microservice/values.yaml +++ b/parcellab/microservice/values.yaml @@ -50,82 +50,28 @@ ingress: ## Envoy Gateway Resources ## -# HTTPRoute - Configure routing through Envoy Gateway -httproute: - enabled: false - # parentGateway: gateway-api - # parentGatewayNamespace: envoy-gateway - # hosts: - # - myapp.gateway.test.parcellab.dev - # path: / - -# ReferenceGrant - Allow cross-namespace references -referenceGrant: - enabled: false - # name: custom-grant # Optional: custom name - # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) - # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) - # - group: gateway.networking.k8s.io - # kind: HTTPRoute - # namespace: myapp - # to: # Optional: specify what can be referenced (default: Service) - # - group: "" - # kind: Service - # - group: "" - # kind: Secret - -# SecurityPolicy - OIDC Authentication with Group-Based Authorization -# Example: Employee-Only App -securityPolicy: - enabled: false - # name: employee-only # Optional: custom name - # targetRef: - # kind: HTTPRoute - # name: myapp # Optional: defaults to release name - # oidc: - # provider: - # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" - # clientID: "envoy-gateway-client" - # clientSecret: - # name: "keycloak-oidc-secret" - # namespace: "envoy-gateway" - # redirectURL: "https://myapp.gateway.test.parcellab.dev/oauth2/callback" - # logoutPath: "/logout" - # scopes: - # - openid - # - profile - # - email - # cookieDomain: "myapp.gateway.test.parcellab.dev" - # forwardAccessToken: true - # passThroughAuthHeader: true - # jwt: - # optional: false - # providers: - # - name: keycloak - # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" - # remoteJWKS: - # uri: "https://auth.test.parcellab.dev/realms/parcellab-internal/protocol/openid-connect/certs" - # cacheDuration: 300s - # claimToHeaders: - # - header: "x-user-email" - # claim: "email" - # - header: "x-user-groups" - # claim: "groups" - # - header: "x-user-id" - # claim: "sub" - # authorization: - # defaultAction: Deny - # rules: - # - name: allow-employees - # action: Allow - # principal: - # jwt: - # provider: keycloak - # claims: - # - name: groups - # valueType: StringArray - # values: - # - "/parcellab-employee" +envoy: + httpRoute: + enabled: false + # parentGateway: gateway-api + # parentGatewayNamespace: envoy-gateway + # hosts: + # - myapp.gateway.test.parcellab.dev + # path: / + + referenceGrant: + enabled: false + # name: custom-grant # Optional: custom name + # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) + # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) + # - group: gateway.networking.k8s.io + # kind: HTTPRoute + # namespace: myapp + # to: # Optional: specify what can be referenced (default: Service) + # - group: "" + # kind: Service + # - group: "" + # kind: Secret ## ## Cronjob diff --git a/parcellab/monolith/README.md b/parcellab/monolith/README.md index c44c7789..f9e27133 100644 --- a/parcellab/monolith/README.md +++ b/parcellab/monolith/README.md @@ -31,16 +31,12 @@ needs. Its generated secret's data values will be loaded as environment variables to the target pod. - `hpa` - Horizontal automatic scaling rules of pods. Can be defined with the `autoscaling` setting. -- `httproute` - - Configure routing through Envoy Gateway. Defined with `httproute`. +- `envoy` + - Envoy Gateway resources (HTTPRoute, ReferenceGrant). Defined under `envoy.*`. - `ingress` - Rules to open external access to the workload. Can be defined with `ingress`. - `poddisruptionbudget` - Limit the number of concurrent disruptions for the application. Defined with `podDisruptionBudget`. -- `referencegrant` - - Allow cross-namespace references for Envoy Gateway (e.g., HTTPRoute → Gateway). Defined with `referenceGrant`. -- `securitypolicy` - - Configure authentication and authorization with Envoy Gateway. Defined with `securityPolicy`. - `serviceaccount` - Configure a service account for the pods. Defined with `serviceAccount`. - `vpa` diff --git a/parcellab/monolith/templates/httproute.yaml b/parcellab/monolith/templates/httproute.yaml index 579f4a86..56066a75 100644 --- a/parcellab/monolith/templates/httproute.yaml +++ b/parcellab/monolith/templates/httproute.yaml @@ -1,5 +1 @@ -{{- if .Values.httproute }} -{{- if .Values.httproute.enabled }} -{{ include "common.httproute" . }} -{{- end }} -{{- end }} +{{- include "common.httproute" . }} diff --git a/parcellab/monolith/templates/referencegrant.yaml b/parcellab/monolith/templates/referencegrant.yaml index 45c9b4bb..d64fae3a 100644 --- a/parcellab/monolith/templates/referencegrant.yaml +++ b/parcellab/monolith/templates/referencegrant.yaml @@ -1,5 +1 @@ -{{- if .Values.referenceGrant }} -{{- if .Values.referenceGrant.enabled }} {{- include "common.referencegrant" . }} -{{- end }} -{{- end }} diff --git a/parcellab/monolith/templates/securitypolicy.yaml b/parcellab/monolith/templates/securitypolicy.yaml deleted file mode 100644 index 90b407f0..00000000 --- a/parcellab/monolith/templates/securitypolicy.yaml +++ /dev/null @@ -1,5 +0,0 @@ -{{- if .Values.securityPolicy }} -{{- if .Values.securityPolicy.enabled }} -{{- include "common.securitypolicy" . }} -{{- end }} -{{- end }} diff --git a/parcellab/monolith/values.yaml b/parcellab/monolith/values.yaml index df069ddb..253c8d36 100644 --- a/parcellab/monolith/values.yaml +++ b/parcellab/monolith/values.yaml @@ -79,82 +79,28 @@ ingress: ## Envoy Gateway Resources ## -# HTTPRoute - Configure routing through Envoy Gateway -httproute: - enabled: false - # parentGateway: gateway-api - # parentGatewayNamespace: envoy-gateway - # hosts: - # - myapp.gateway.test.parcellab.dev - # path: / - -# ReferenceGrant - Allow cross-namespace references -referenceGrant: - enabled: false - # name: custom-grant # Optional: custom name - # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) - # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) - # - group: gateway.networking.k8s.io - # kind: HTTPRoute - # namespace: myapp - # to: # Optional: specify what can be referenced (default: Service) - # - group: "" - # kind: Service - # - group: "" - # kind: Secret - -# SecurityPolicy - OIDC Authentication with Group-Based Authorization -# Example: Employee-Only App -securityPolicy: - enabled: false - # name: employee-only # Optional: custom name - # targetRef: - # kind: HTTPRoute - # name: myapp # Optional: defaults to release name - # oidc: - # provider: - # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" - # clientID: "envoy-gateway-client" - # clientSecret: - # name: "keycloak-oidc-secret" - # namespace: "envoy-gateway" - # redirectURL: "https://myapp.gateway.test.parcellab.dev/oauth2/callback" - # logoutPath: "/logout" - # scopes: - # - openid - # - profile - # - email - # cookieDomain: "myapp.gateway.test.parcellab.dev" - # forwardAccessToken: true - # passThroughAuthHeader: true - # jwt: - # optional: false - # providers: - # - name: keycloak - # issuer: "https://auth.test.parcellab.dev/realms/parcellab-internal" - # remoteJWKS: - # uri: "https://auth.test.parcellab.dev/realms/parcellab-internal/protocol/openid-connect/certs" - # cacheDuration: 300s - # claimToHeaders: - # - header: "x-user-email" - # claim: "email" - # - header: "x-user-groups" - # claim: "groups" - # - header: "x-user-id" - # claim: "sub" - # authorization: - # defaultAction: Deny - # rules: - # - name: allow-employees - # action: Allow - # principal: - # jwt: - # provider: keycloak - # claims: - # - name: groups - # valueType: StringArray - # values: - # - "/parcellab-employee" +envoy: + httpRoute: + enabled: false + # parentGateway: gateway-api + # parentGatewayNamespace: envoy-gateway + # hosts: + # - myapp.gateway.test.parcellab.dev + # path: / + + referenceGrant: + enabled: false + # name: custom-grant # Optional: custom name + # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) + # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) + # - group: gateway.networking.k8s.io + # kind: HTTPRoute + # namespace: myapp + # to: # Optional: specify what can be referenced (default: Service) + # - group: "" + # kind: Service + # - group: "" + # kind: Secret ## ## Cronjob From 3a40b7c361faab556d8393743716e9b18610027c Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Wed, 28 Jan 2026 11:57:51 +0100 Subject: [PATCH 05/21] chore: updates based on tests with FBA --- parcellab/common/templates/_httproute.tpl | 41 ------ parcellab/common/templates/_httproutes.tpl | 56 ++++++++ .../common/templates/_referencegrant.tpl | 25 ++-- .../common/templates/_securitypolicy.tpl | 124 ++++++++++++++++++ parcellab/common/values.yaml | 35 +---- .../microservice/templates/httproute.yaml | 1 - .../microservice/templates/httproutes.yaml | 1 + .../templates/securitypolicies.yaml | 1 + parcellab/microservice/values.yaml | 48 +++---- 9 files changed, 213 insertions(+), 119 deletions(-) delete mode 100644 parcellab/common/templates/_httproute.tpl create mode 100644 parcellab/common/templates/_httproutes.tpl create mode 100644 parcellab/common/templates/_securitypolicy.tpl delete mode 100644 parcellab/microservice/templates/httproute.yaml create mode 100644 parcellab/microservice/templates/httproutes.yaml create mode 100644 parcellab/microservice/templates/securitypolicies.yaml diff --git a/parcellab/common/templates/_httproute.tpl b/parcellab/common/templates/_httproute.tpl deleted file mode 100644 index 4c4f758f..00000000 --- a/parcellab/common/templates/_httproute.tpl +++ /dev/null @@ -1,41 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* - Common httproute definition: - {{ include "common.httproute" ( - dict - "Values" "the values scope" - ) }} -*/}} - -{{- define "common.httproute" -}} -{{- $envoy := .Values.envoy | default dict -}} -{{- $httproute := $envoy.httpRoute | default dict -}} -{{- if $httproute.enabled }} -{{- $name := include "common.fullname" . }} -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: {{ include "common.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "common.labels" . | nindent 4 }} -spec: - parentRefs: - - name: {{ required "httproute.parentGateway is required" $httproute.parentGateway }} - namespace: {{ $httproute.parentGatewayNamespace | default "envoy-gateway" }} - {{- with $httproute.hosts }} - hostnames: - {{- range . }} - - {{ . | quote }} - {{- end }} - {{- end }} - rules: - - matches: - - path: - type: PathPrefix - value: {{ $httproute.path | default "/" }} - backendRefs: - - name: {{ include "common.fullname" . }} - port: {{ .Values.service.port }} -{{- end }} -{{- end -}} diff --git a/parcellab/common/templates/_httproutes.tpl b/parcellab/common/templates/_httproutes.tpl new file mode 100644 index 00000000..4968f8af --- /dev/null +++ b/parcellab/common/templates/_httproutes.tpl @@ -0,0 +1,56 @@ +{{/* vim: set filetype=mustache: */}} +{{/* + Common HTTPRoute definition with deterministic names and labels: + {{ include "common.httproutes" . }} +*/}} + +{{- define "common.httproutes" -}} +{{- $envoy := .Values.envoy | default dict -}} +{{- if $envoy.enabled -}} +{{- $gateway := default (dict "name" "gateway-api" "namespace" "envoy-gateway") $envoy.gateway -}} +{{- $httproutes := default (list) $envoy.httpRoutes -}} +{{- $baseName := include "common.fullname" . -}} +{{- $globalLabels := include "common.labels" . -}} +{{- $serviceNamespace := .Release.Namespace -}} +{{- $security := default dict $envoy.security -}} +{{- $securityEnabled := default false $security.enabled -}} +{{- $securityLabelKey := printf "%s/security-required" (include "common.parcellabtagsdomain" .) -}} + +{{- range $index, $route := $httproutes }} +{{- $rawRouteName := default (printf "%s-%d" $baseName $index) $route.name -}} +{{- $sanitizedRouteName := trunc 63 (trimSuffix "-" (regexReplaceAll "[^a-z0-9-]" (lower $rawRouteName) "-")) -}} +{{- $routeName := default (printf "%s-%d" $baseName $index) $sanitizedRouteName }} +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ $routeName }} + namespace: {{ $serviceNamespace }} + labels: + {{- $globalLabels | nindent 4 }} + {{ $securityLabelKey }}: {{ (ternary "true" "false" $securityEnabled) | quote }} + {{- with $route.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + external-dns.alpha.kubernetes.io/hostname: | + {{- range $route.hosts }} + {{ . }} + {{- end }} +spec: + parentRefs: + - name: {{ $gateway.name }} + namespace: {{ $gateway.namespace }} + group: gateway.networking.k8s.io + kind: Gateway + hostnames: + {{- range $route.hosts }} + - {{ . | quote }} + {{- end }} + {{- with $route.rules }} + rules: + {{ toYaml . | nindent 4 }} + {{ end }} +{{ end }} +{{- end }} +{{- end }} diff --git a/parcellab/common/templates/_referencegrant.tpl b/parcellab/common/templates/_referencegrant.tpl index 8072bc67..92512bc0 100644 --- a/parcellab/common/templates/_referencegrant.tpl +++ b/parcellab/common/templates/_referencegrant.tpl @@ -10,15 +10,17 @@ {{- define "common.referencegrant" -}} {{- $envoy := .Values.envoy | default dict -}} -{{- $referenceGrant := $envoy.referenceGrant | default dict -}} -{{- if $referenceGrant.enabled }} +{{- $referenceGrant := .Values.envoy.referenceGrant | default dict -}} +{{- $gateway := $envoy.gateway | default dict -}} {{- $name := include "common.fullname" . }} +{{- $serviceNamespace := .Release.Namespace }} +{{- if $envoy.enabled -}} --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: - name: {{ $referenceGrant.name | default (printf "%s-grant" $name) }} - namespace: {{ $referenceGrant.namespace | default .Release.Namespace }} + name: {{ (printf "%s-reference-grant" $name) }} + namespace: {{ $serviceNamespace | quote }} labels: {{- include "common.labels" . | nindent 4 }} {{- with $referenceGrant.annotations }} @@ -27,22 +29,15 @@ metadata: {{- end }} spec: from: - {{- if $referenceGrant.from }} {{- range $referenceGrant.from }} - group: {{ .group | default "gateway.networking.k8s.io" | quote }} kind: {{ required "referenceGrant.from.kind is required" .kind | quote }} - namespace: {{ .namespace | default $.Release.Namespace | quote }} + namespace: {{ $serviceNamespace | quote }} {{- with .name }} name: {{ . | quote }} {{- end }} {{- end }} - {{- else }} - - group: gateway.networking.k8s.io - kind: HTTPRoute - namespace: {{ .Release.Namespace | quote }} - {{- end }} to: - {{- if $referenceGrant.to }} {{- range $referenceGrant.to }} - group: {{ .group | default "" | quote }} kind: {{ required "referenceGrant.to.kind is required" .kind | quote }} @@ -50,9 +45,5 @@ spec: name: {{ . | quote }} {{- end }} {{- end }} - {{- else }} - - group: "" - kind: Service - {{- end }} -{{- end }} +{{- end -}} {{- end -}} diff --git a/parcellab/common/templates/_securitypolicy.tpl b/parcellab/common/templates/_securitypolicy.tpl new file mode 100644 index 00000000..b8ef6c3d --- /dev/null +++ b/parcellab/common/templates/_securitypolicy.tpl @@ -0,0 +1,124 @@ +{{/* vim: set filetype=mustache: */}} +{{/* + Render Envoy Gateway SecurityPolicy resources defined under + .Values.envoy.security.policies. Each policy renders as a complete resource + (OIDC, JWT, authorization) while inheriting defaults from envoy.security.*. +*/}} +{{- define "common.securitypolicies" -}} +{{- $values := .Values -}} +{{- if .Values.microservice }} +{{- $values = .Values.microservice -}} +{{- end -}} +{{- $envoy := default (dict "enabled" false) $values.envoy -}} +{{- if $envoy.enabled }} +{{- $security := default dict $envoy.security -}} +{{- $policies := default (list) $security.policies -}} +{{- if $policies }} +{{- $scope := dict "Values" $values "Release" .Release -}} +{{- $serviceName := default (include "common.fullname" $scope) $values.name -}} +{{- $policyNamespace := default "infra" $security.namespace -}} +{{- $securityLabelKey := printf "%s/security-required" (include "common.parcellabtagsdomain" .) -}} +{{- $globalIssuer := $security.issuer -}} +{{- $globalRedirectURL := $security.redirectURL -}} +{{- $globalCookieDomain := $security.cookieDomain -}} +{{- $globalLogoutPath := $security.logoutPath -}} +{{- $globalClientID := $security.clientID -}} +{{- $globalClientSecretName := $security.clientSecretName -}} +{{- $globalScopes := $security.scopes -}} +{{- $globalClaimHeaders := $security.claimToHeaders -}} +{{- $globalJwtProviderName := $security.jwtProviderName -}} +{{- $globalJwksURI := $security.jwksURI -}} + +{{ range $policyIndex, $policy := $policies }} +{{- $policyName := required (printf "envoy.security.policies[%d].name is required" $policyIndex) $policy.name -}} +{{- $issuer := required (printf "SecurityPolicy %q requires envoy.security.issuer or policies[].issuer" $policyName) (coalesce $policy.issuer $globalIssuer) -}} +{{- $redirectURL := required (printf "SecurityPolicy %q requires redirectURL (set envoy.security.redirectURL or policies[].redirectURL)" $policyName) (coalesce $policy.redirectURL $globalRedirectURL) -}} +{{- $cookieDomain := required (printf "SecurityPolicy %q requires cookieDomain (set envoy.security.cookieDomain or policies[].cookieDomain)" $policyName) (coalesce $policy.cookieDomain $globalCookieDomain) -}} +{{- $logoutPath := coalesce $policy.logoutPath $globalLogoutPath "/logout" -}} +{{- $clientID := coalesce $policy.clientID $globalClientID $serviceName -}} +{{- $defaultSecretName := printf "%s-oidc-secret" $serviceName -}} +{{- $clientSecretName := coalesce $policy.clientSecretName $globalClientSecretName $defaultSecretName -}} +{{- $scopes := coalesce $policy.scopes $globalScopes -}} +{{- $claimToHeaders := coalesce $policy.claimToHeaders $globalClaimHeaders -}} +{{- $jwtProviderName := coalesce $policy.jwtProviderName $globalJwtProviderName "keycloak" -}} +{{- $jwksURI := coalesce $policy.jwksURI $globalJwksURI (printf "%s/protocol/openid-connect/certs" $issuer) -}} +{{- $targetRef := $policy.targetRef -}} +{{- $targetRefs := $policy.targetRefs -}} +{{- $rawSelectors := list -}} +{{- if $policy.targetSelectors }} + {{- if kindIs "slice" $policy.targetSelectors }} + {{- $rawSelectors = $policy.targetSelectors -}} + {{- else }} + {{- $rawSelectors = list $policy.targetSelectors -}} + {{- end }} +{{- else if $policy.targetSelector }} + {{- $rawSelectors = list $policy.targetSelector -}} +{{- end }} +{{- if and (not $targetRef) (not $targetRefs) (eq (len $rawSelectors) 0) }} + {{- $rawSelectors = list (dict "matchLabels" (dict $securityLabelKey "true")) -}} +{{- end }} +{{- $targetSelectors := list -}} +{{- range $rawSelectors }} + {{- $group := default "gateway.networking.k8s.io" .group -}} + {{- $kind := default "HTTPRoute" .kind -}} + {{- $matchLabels := default (dict) .matchLabels -}} + {{- $targetSelectors = append $targetSelectors (dict "group" $group "kind" $kind "matchLabels" $matchLabels) -}} +{{- end }} +{{- $defaultAction := default "Deny" $policy.defaultAction -}} +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: {{ $policyName }} + namespace: {{ $policyNamespace | quote }} + annotations: + oidc.autoregistrar.parcellab.dev/sync-enabled: 'true' +spec: + {{- if $targetRef }} + targetRef: + {{- toYaml $targetRef | nindent 4 }} + {{- else if $targetRefs }} + targetRefs: + {{- toYaml $targetRefs | nindent 4 }} + {{- else }} + targetSelectors: + {{- toYaml $targetSelectors | nindent 4 }} + {{- end }} + oidc: + provider: + issuer: {{ $issuer | quote }} + clientID: {{ $clientID | quote }} + clientSecret: + name: {{ $clientSecretName | quote }} + redirectURL: {{ $redirectURL | quote }} + logoutPath: {{ $logoutPath | quote }} + {{- with $scopes }} + scopes: + {{ toYaml . | nindent 6 }} + {{- end }} + cookieDomain: {{ $cookieDomain | quote }} + forwardAccessToken: true + passThroughAuthHeader: true + jwt: + optional: false + providers: + - name: {{ $jwtProviderName | quote }} + issuer: {{ $issuer | quote }} + remoteJWKS: + cacheDuration: 300s + uri: {{ $jwksURI | quote }} + {{- with $claimToHeaders }} + claimToHeaders: + {{ toYaml . | nindent 8 }} + {{- end }} + + authorization: + defaultAction: {{ $defaultAction }} + {{- with $policy.authorizationRules }} + rules: + {{ toYaml . | nindent 6 }} + {{- end }} +{{ end }} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/parcellab/common/values.yaml b/parcellab/common/values.yaml index e5382eae..63b2d135 100644 --- a/parcellab/common/values.yaml +++ b/parcellab/common/values.yaml @@ -24,38 +24,11 @@ image: ingress: enabled: false -## -## Envoy Gateway Resources -## - -# Configure Envoy Gateway resources under a single parent: -# -# envoy: -# httpRoute: {...} -# referenceGrant: {...} - envoy: - httpRoute: - enabled: false - # parentGateway: gateway-api - # parentGatewayNamespace: envoy-gateway - # hosts: - # - myapp.gateway.test.parcellab.dev - # path: / - - referenceGrant: - enabled: false - # name: custom-grant # Optional: custom name - # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) - # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) - # - group: gateway.networking.k8s.io - # kind: HTTPRoute - # namespace: myapp - # to: # Optional: specify what can be referenced (default: Service) - # - group: "" - # kind: Service - # - group: "" - # kind: Secret + enabled: false + gateway: {} + referenceGrant: {} + httpRoutes: [] name: common terminationGracePeriodSeconds: 30 diff --git a/parcellab/microservice/templates/httproute.yaml b/parcellab/microservice/templates/httproute.yaml deleted file mode 100644 index 56066a75..00000000 --- a/parcellab/microservice/templates/httproute.yaml +++ /dev/null @@ -1 +0,0 @@ -{{- include "common.httproute" . }} diff --git a/parcellab/microservice/templates/httproutes.yaml b/parcellab/microservice/templates/httproutes.yaml new file mode 100644 index 00000000..d4687b9e --- /dev/null +++ b/parcellab/microservice/templates/httproutes.yaml @@ -0,0 +1 @@ +{{- include "common.httproutes" . }} diff --git a/parcellab/microservice/templates/securitypolicies.yaml b/parcellab/microservice/templates/securitypolicies.yaml new file mode 100644 index 00000000..6022ef10 --- /dev/null +++ b/parcellab/microservice/templates/securitypolicies.yaml @@ -0,0 +1 @@ +{{- include "common.securitypolicies" . }} diff --git a/parcellab/microservice/values.yaml b/parcellab/microservice/values.yaml index 61272323..3a1743a5 100644 --- a/parcellab/microservice/values.yaml +++ b/parcellab/microservice/values.yaml @@ -35,8 +35,7 @@ ingress: className: "nginx" annotations: # kubernetes.io/tls-acme: "true" - hosts: - [] + hosts: [] # - host: app # paths: # - path: / @@ -47,31 +46,25 @@ ingress: # - chart-example.local ## -## Envoy Gateway Resources +## Envoy Gateway ## envoy: - httpRoute: - enabled: false - # parentGateway: gateway-api - # parentGatewayNamespace: envoy-gateway - # hosts: - # - myapp.gateway.test.parcellab.dev - # path: / - + enabled: false + gateway: + namespace: envoy-gateway + name: gateway-api referenceGrant: - enabled: false - # name: custom-grant # Optional: custom name - # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) - # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) - # - group: gateway.networking.k8s.io - # kind: HTTPRoute - # namespace: myapp - # to: # Optional: specify what can be referenced (default: Service) - # - group: "" - # kind: Service - # - group: "" - # kind: Secret + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: SecurityPolicy + to: + - group: gateway.networking.k8s.io + kind: Gateway + name: gateway-api + httpRoutes: [] ## ## Cronjob @@ -104,8 +97,7 @@ config: {} # environment variables using the external-secrets project and an already # configured secret store reference # See https://external-secrets.io/latest/spec/#external-secrets.io/v1beta1.ExternalSecretSpec -externalSecret: - {} +externalSecret: {} # dataFrom: # - extract: # key: app-key-in-secrets-manager @@ -230,8 +222,7 @@ terminationGracePeriodSeconds: 30 nodeSelector: {} -securityContext: - {} +securityContext: {} # capabilities: # drop: # - ALL @@ -280,8 +271,7 @@ containerEnv: [] # - name: MY_ENV_VAR # value: "myvalue" -podSecurityContext: - {} +podSecurityContext: {} # fsGroup: 2000 resources: From 32a6f3aea2223cd295dbe7e853587fd9daedb9ec Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Wed, 28 Jan 2026 12:03:46 +0100 Subject: [PATCH 06/21] chore: updatae monolith --- parcellab/monolith/templates/httproute.yaml | 1 - parcellab/monolith/templates/httproutes.yaml | 1 + .../monolith/templates/securitypolicies.yaml | 1 + parcellab/monolith/values.yaml | 34 ++++++++----------- 4 files changed, 16 insertions(+), 21 deletions(-) delete mode 100644 parcellab/monolith/templates/httproute.yaml create mode 100644 parcellab/monolith/templates/httproutes.yaml create mode 100644 parcellab/monolith/templates/securitypolicies.yaml diff --git a/parcellab/monolith/templates/httproute.yaml b/parcellab/monolith/templates/httproute.yaml deleted file mode 100644 index 56066a75..00000000 --- a/parcellab/monolith/templates/httproute.yaml +++ /dev/null @@ -1 +0,0 @@ -{{- include "common.httproute" . }} diff --git a/parcellab/monolith/templates/httproutes.yaml b/parcellab/monolith/templates/httproutes.yaml new file mode 100644 index 00000000..d4687b9e --- /dev/null +++ b/parcellab/monolith/templates/httproutes.yaml @@ -0,0 +1 @@ +{{- include "common.httproutes" . }} diff --git a/parcellab/monolith/templates/securitypolicies.yaml b/parcellab/monolith/templates/securitypolicies.yaml new file mode 100644 index 00000000..6022ef10 --- /dev/null +++ b/parcellab/monolith/templates/securitypolicies.yaml @@ -0,0 +1 @@ +{{- include "common.securitypolicies" . }} diff --git a/parcellab/monolith/values.yaml b/parcellab/monolith/values.yaml index 253c8d36..86d6ab03 100644 --- a/parcellab/monolith/values.yaml +++ b/parcellab/monolith/values.yaml @@ -80,27 +80,21 @@ ingress: ## envoy: - httpRoute: - enabled: false - # parentGateway: gateway-api - # parentGatewayNamespace: envoy-gateway - # hosts: - # - myapp.gateway.test.parcellab.dev - # path: / - + enabled: false + gateway: + namespace: envoy-gateway + name: gateway-api referenceGrant: - enabled: false - # name: custom-grant # Optional: custom name - # namespace: envoy-gateway # Optional: where to create the grant (default: current namespace) - # from: # Optional: specify what can reference (default: HTTPRoute from current namespace) - # - group: gateway.networking.k8s.io - # kind: HTTPRoute - # namespace: myapp - # to: # Optional: specify what can be referenced (default: Service) - # - group: "" - # kind: Service - # - group: "" - # kind: Secret + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: SecurityPolicy + to: + - group: gateway.networking.k8s.io + kind: Gateway + name: gateway-api + httpRoutes: [] ## ## Cronjob From 7d961498535117ea94e8714411d703aebe192e9e Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Thu, 29 Jan 2026 23:37:15 +0100 Subject: [PATCH 07/21] chore: linted and added sample values to microservice for gateway --- package.json | 1 + parcellab/microservice/values.yaml | 56 +++++++++++++++++++++++++++--- parcellab/worker-group/README.md | 2 +- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5ad07f94..3622b85d 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "lint": "npm run lint:helm && npm run lint:prettier", "lint:helm": "npm run deps && find parcellab -type d -maxdepth 1 -mindepth 1 | xargs -I {} helm lint {}", "lint:prettier": "prettier --check --ignore-unknown .", + "lint:prettier:fix": "prettier --check --ignore-unknown --write .", "lint:staged": "lint-staged", "format": "prettier --write --ignore-unknown .", "prepare": "husky install", diff --git a/parcellab/microservice/values.yaml b/parcellab/microservice/values.yaml index 3a1743a5..b8c89794 100644 --- a/parcellab/microservice/values.yaml +++ b/parcellab/microservice/values.yaml @@ -35,7 +35,8 @@ ingress: className: "nginx" annotations: # kubernetes.io/tls-acme: "true" - hosts: [] + hosts: + [] # - host: app # paths: # - path: / @@ -65,6 +66,50 @@ envoy: kind: Gateway name: gateway-api httpRoutes: [] + # - name: my-default-route + # hosts: + # - my-app.example.com + # rules: + # - name: default-route + # matches: + # - path: + # type: PathPrefix + # value: "/" + # backendRefs: + # - name: my-app + # port: 5000 + # group: "" + # kind: Service + # labels: + # foo: bar # optional + security: + enabled: false +# enabled: true +# issuer: "https://my-issuer-domain.example.com" +# redirectURL: "https://my-app.example.com/oauth2/callback" +# cookieDomain: "my-app.example.com" +# scopes: +# - profile +# - email +# claimToHeaders: +# - header: "x-user-email" +# claim: "email" +# policies: +# - name: staff-only +# targetRef: +# kind: HTTPRoute +# name: my-default-route +# group: "gateway.networking.k8s.io" +# authorizationRules: +# - name: member-of-staff-group +# action: Allow +# principal: +# jwt: +# provider: my-provider +# claims: +# - name: groups +# valueType: StringArray +# values: ["staff"] ## ## Cronjob @@ -97,7 +142,8 @@ config: {} # environment variables using the external-secrets project and an already # configured secret store reference # See https://external-secrets.io/latest/spec/#external-secrets.io/v1beta1.ExternalSecretSpec -externalSecret: {} +externalSecret: + {} # dataFrom: # - extract: # key: app-key-in-secrets-manager @@ -222,7 +268,8 @@ terminationGracePeriodSeconds: 30 nodeSelector: {} -securityContext: {} +securityContext: + {} # capabilities: # drop: # - ALL @@ -271,7 +318,8 @@ containerEnv: [] # - name: MY_ENV_VAR # value: "myvalue" -podSecurityContext: {} +podSecurityContext: + {} # fsGroup: 2000 resources: diff --git a/parcellab/worker-group/README.md b/parcellab/worker-group/README.md index a2a083bc..f678ab1f 100644 --- a/parcellab/worker-group/README.md +++ b/parcellab/worker-group/README.md @@ -24,7 +24,7 @@ a service, as such workloads are expected to run indefinitely without network tr These resources can be configured or totally skipped depending on your business needs. - + - `configmap` - The attributes defined in `config` will automatically be loaded as environment variables to the target pod. From 849373b8b3eeb9754b348114f4ee514206faf9b1 Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Thu, 29 Jan 2026 23:38:26 +0100 Subject: [PATCH 08/21] chore: added value samples to monolith --- parcellab/monolith/values.yaml | 46 +++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/parcellab/monolith/values.yaml b/parcellab/monolith/values.yaml index 86d6ab03..d8d94825 100644 --- a/parcellab/monolith/values.yaml +++ b/parcellab/monolith/values.yaml @@ -76,7 +76,7 @@ ingress: # - chart-example.local ## -## Envoy Gateway Resources +## Envoy Gateway ## envoy: @@ -95,6 +95,50 @@ envoy: kind: Gateway name: gateway-api httpRoutes: [] + # - name: my-default-route + # hosts: + # - my-app.example.com + # rules: + # - name: default-route + # matches: + # - path: + # type: PathPrefix + # value: "/" + # backendRefs: + # - name: my-app + # port: 5000 + # group: "" + # kind: Service + # labels: + # foo: bar # optional + security: + enabled: false +# enabled: true +# issuer: "https://my-issuer-domain.example.com" +# redirectURL: "https://my-app.example.com/oauth2/callback" +# cookieDomain: "my-app.example.com" +# scopes: +# - profile +# - email +# claimToHeaders: +# - header: "x-user-email" +# claim: "email" +# policies: +# - name: staff-only +# targetRef: +# kind: HTTPRoute +# name: my-default-route +# group: "gateway.networking.k8s.io" +# authorizationRules: +# - name: member-of-staff-group +# action: Allow +# principal: +# jwt: +# provider: my-provider +# claims: +# - name: groups +# valueType: StringArray +# values: ["staff"] ## ## Cronjob From f74644d899053009f6e7d004b22c43f266d0480b Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Thu, 29 Jan 2026 23:44:01 +0100 Subject: [PATCH 09/21] chore: rename file --- .../common/templates/_securitypolicy.tpl | 124 ------------------ 1 file changed, 124 deletions(-) delete mode 100644 parcellab/common/templates/_securitypolicy.tpl diff --git a/parcellab/common/templates/_securitypolicy.tpl b/parcellab/common/templates/_securitypolicy.tpl deleted file mode 100644 index b8ef6c3d..00000000 --- a/parcellab/common/templates/_securitypolicy.tpl +++ /dev/null @@ -1,124 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* - Render Envoy Gateway SecurityPolicy resources defined under - .Values.envoy.security.policies. Each policy renders as a complete resource - (OIDC, JWT, authorization) while inheriting defaults from envoy.security.*. -*/}} -{{- define "common.securitypolicies" -}} -{{- $values := .Values -}} -{{- if .Values.microservice }} -{{- $values = .Values.microservice -}} -{{- end -}} -{{- $envoy := default (dict "enabled" false) $values.envoy -}} -{{- if $envoy.enabled }} -{{- $security := default dict $envoy.security -}} -{{- $policies := default (list) $security.policies -}} -{{- if $policies }} -{{- $scope := dict "Values" $values "Release" .Release -}} -{{- $serviceName := default (include "common.fullname" $scope) $values.name -}} -{{- $policyNamespace := default "infra" $security.namespace -}} -{{- $securityLabelKey := printf "%s/security-required" (include "common.parcellabtagsdomain" .) -}} -{{- $globalIssuer := $security.issuer -}} -{{- $globalRedirectURL := $security.redirectURL -}} -{{- $globalCookieDomain := $security.cookieDomain -}} -{{- $globalLogoutPath := $security.logoutPath -}} -{{- $globalClientID := $security.clientID -}} -{{- $globalClientSecretName := $security.clientSecretName -}} -{{- $globalScopes := $security.scopes -}} -{{- $globalClaimHeaders := $security.claimToHeaders -}} -{{- $globalJwtProviderName := $security.jwtProviderName -}} -{{- $globalJwksURI := $security.jwksURI -}} - -{{ range $policyIndex, $policy := $policies }} -{{- $policyName := required (printf "envoy.security.policies[%d].name is required" $policyIndex) $policy.name -}} -{{- $issuer := required (printf "SecurityPolicy %q requires envoy.security.issuer or policies[].issuer" $policyName) (coalesce $policy.issuer $globalIssuer) -}} -{{- $redirectURL := required (printf "SecurityPolicy %q requires redirectURL (set envoy.security.redirectURL or policies[].redirectURL)" $policyName) (coalesce $policy.redirectURL $globalRedirectURL) -}} -{{- $cookieDomain := required (printf "SecurityPolicy %q requires cookieDomain (set envoy.security.cookieDomain or policies[].cookieDomain)" $policyName) (coalesce $policy.cookieDomain $globalCookieDomain) -}} -{{- $logoutPath := coalesce $policy.logoutPath $globalLogoutPath "/logout" -}} -{{- $clientID := coalesce $policy.clientID $globalClientID $serviceName -}} -{{- $defaultSecretName := printf "%s-oidc-secret" $serviceName -}} -{{- $clientSecretName := coalesce $policy.clientSecretName $globalClientSecretName $defaultSecretName -}} -{{- $scopes := coalesce $policy.scopes $globalScopes -}} -{{- $claimToHeaders := coalesce $policy.claimToHeaders $globalClaimHeaders -}} -{{- $jwtProviderName := coalesce $policy.jwtProviderName $globalJwtProviderName "keycloak" -}} -{{- $jwksURI := coalesce $policy.jwksURI $globalJwksURI (printf "%s/protocol/openid-connect/certs" $issuer) -}} -{{- $targetRef := $policy.targetRef -}} -{{- $targetRefs := $policy.targetRefs -}} -{{- $rawSelectors := list -}} -{{- if $policy.targetSelectors }} - {{- if kindIs "slice" $policy.targetSelectors }} - {{- $rawSelectors = $policy.targetSelectors -}} - {{- else }} - {{- $rawSelectors = list $policy.targetSelectors -}} - {{- end }} -{{- else if $policy.targetSelector }} - {{- $rawSelectors = list $policy.targetSelector -}} -{{- end }} -{{- if and (not $targetRef) (not $targetRefs) (eq (len $rawSelectors) 0) }} - {{- $rawSelectors = list (dict "matchLabels" (dict $securityLabelKey "true")) -}} -{{- end }} -{{- $targetSelectors := list -}} -{{- range $rawSelectors }} - {{- $group := default "gateway.networking.k8s.io" .group -}} - {{- $kind := default "HTTPRoute" .kind -}} - {{- $matchLabels := default (dict) .matchLabels -}} - {{- $targetSelectors = append $targetSelectors (dict "group" $group "kind" $kind "matchLabels" $matchLabels) -}} -{{- end }} -{{- $defaultAction := default "Deny" $policy.defaultAction -}} ---- -apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: SecurityPolicy -metadata: - name: {{ $policyName }} - namespace: {{ $policyNamespace | quote }} - annotations: - oidc.autoregistrar.parcellab.dev/sync-enabled: 'true' -spec: - {{- if $targetRef }} - targetRef: - {{- toYaml $targetRef | nindent 4 }} - {{- else if $targetRefs }} - targetRefs: - {{- toYaml $targetRefs | nindent 4 }} - {{- else }} - targetSelectors: - {{- toYaml $targetSelectors | nindent 4 }} - {{- end }} - oidc: - provider: - issuer: {{ $issuer | quote }} - clientID: {{ $clientID | quote }} - clientSecret: - name: {{ $clientSecretName | quote }} - redirectURL: {{ $redirectURL | quote }} - logoutPath: {{ $logoutPath | quote }} - {{- with $scopes }} - scopes: - {{ toYaml . | nindent 6 }} - {{- end }} - cookieDomain: {{ $cookieDomain | quote }} - forwardAccessToken: true - passThroughAuthHeader: true - jwt: - optional: false - providers: - - name: {{ $jwtProviderName | quote }} - issuer: {{ $issuer | quote }} - remoteJWKS: - cacheDuration: 300s - uri: {{ $jwksURI | quote }} - {{- with $claimToHeaders }} - claimToHeaders: - {{ toYaml . | nindent 8 }} - {{- end }} - - authorization: - defaultAction: {{ $defaultAction }} - {{- with $policy.authorizationRules }} - rules: - {{ toYaml . | nindent 6 }} - {{- end }} -{{ end }} -{{- end -}} -{{- end -}} -{{- end -}} From dd3fbcc8fee482cd39f2ed5b1db656376c1fb747 Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Thu, 29 Jan 2026 23:44:33 +0100 Subject: [PATCH 10/21] chore: rename file --- .../common/templates/_securitypolicies.tpl | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 parcellab/common/templates/_securitypolicies.tpl diff --git a/parcellab/common/templates/_securitypolicies.tpl b/parcellab/common/templates/_securitypolicies.tpl new file mode 100644 index 00000000..b8ef6c3d --- /dev/null +++ b/parcellab/common/templates/_securitypolicies.tpl @@ -0,0 +1,124 @@ +{{/* vim: set filetype=mustache: */}} +{{/* + Render Envoy Gateway SecurityPolicy resources defined under + .Values.envoy.security.policies. Each policy renders as a complete resource + (OIDC, JWT, authorization) while inheriting defaults from envoy.security.*. +*/}} +{{- define "common.securitypolicies" -}} +{{- $values := .Values -}} +{{- if .Values.microservice }} +{{- $values = .Values.microservice -}} +{{- end -}} +{{- $envoy := default (dict "enabled" false) $values.envoy -}} +{{- if $envoy.enabled }} +{{- $security := default dict $envoy.security -}} +{{- $policies := default (list) $security.policies -}} +{{- if $policies }} +{{- $scope := dict "Values" $values "Release" .Release -}} +{{- $serviceName := default (include "common.fullname" $scope) $values.name -}} +{{- $policyNamespace := default "infra" $security.namespace -}} +{{- $securityLabelKey := printf "%s/security-required" (include "common.parcellabtagsdomain" .) -}} +{{- $globalIssuer := $security.issuer -}} +{{- $globalRedirectURL := $security.redirectURL -}} +{{- $globalCookieDomain := $security.cookieDomain -}} +{{- $globalLogoutPath := $security.logoutPath -}} +{{- $globalClientID := $security.clientID -}} +{{- $globalClientSecretName := $security.clientSecretName -}} +{{- $globalScopes := $security.scopes -}} +{{- $globalClaimHeaders := $security.claimToHeaders -}} +{{- $globalJwtProviderName := $security.jwtProviderName -}} +{{- $globalJwksURI := $security.jwksURI -}} + +{{ range $policyIndex, $policy := $policies }} +{{- $policyName := required (printf "envoy.security.policies[%d].name is required" $policyIndex) $policy.name -}} +{{- $issuer := required (printf "SecurityPolicy %q requires envoy.security.issuer or policies[].issuer" $policyName) (coalesce $policy.issuer $globalIssuer) -}} +{{- $redirectURL := required (printf "SecurityPolicy %q requires redirectURL (set envoy.security.redirectURL or policies[].redirectURL)" $policyName) (coalesce $policy.redirectURL $globalRedirectURL) -}} +{{- $cookieDomain := required (printf "SecurityPolicy %q requires cookieDomain (set envoy.security.cookieDomain or policies[].cookieDomain)" $policyName) (coalesce $policy.cookieDomain $globalCookieDomain) -}} +{{- $logoutPath := coalesce $policy.logoutPath $globalLogoutPath "/logout" -}} +{{- $clientID := coalesce $policy.clientID $globalClientID $serviceName -}} +{{- $defaultSecretName := printf "%s-oidc-secret" $serviceName -}} +{{- $clientSecretName := coalesce $policy.clientSecretName $globalClientSecretName $defaultSecretName -}} +{{- $scopes := coalesce $policy.scopes $globalScopes -}} +{{- $claimToHeaders := coalesce $policy.claimToHeaders $globalClaimHeaders -}} +{{- $jwtProviderName := coalesce $policy.jwtProviderName $globalJwtProviderName "keycloak" -}} +{{- $jwksURI := coalesce $policy.jwksURI $globalJwksURI (printf "%s/protocol/openid-connect/certs" $issuer) -}} +{{- $targetRef := $policy.targetRef -}} +{{- $targetRefs := $policy.targetRefs -}} +{{- $rawSelectors := list -}} +{{- if $policy.targetSelectors }} + {{- if kindIs "slice" $policy.targetSelectors }} + {{- $rawSelectors = $policy.targetSelectors -}} + {{- else }} + {{- $rawSelectors = list $policy.targetSelectors -}} + {{- end }} +{{- else if $policy.targetSelector }} + {{- $rawSelectors = list $policy.targetSelector -}} +{{- end }} +{{- if and (not $targetRef) (not $targetRefs) (eq (len $rawSelectors) 0) }} + {{- $rawSelectors = list (dict "matchLabels" (dict $securityLabelKey "true")) -}} +{{- end }} +{{- $targetSelectors := list -}} +{{- range $rawSelectors }} + {{- $group := default "gateway.networking.k8s.io" .group -}} + {{- $kind := default "HTTPRoute" .kind -}} + {{- $matchLabels := default (dict) .matchLabels -}} + {{- $targetSelectors = append $targetSelectors (dict "group" $group "kind" $kind "matchLabels" $matchLabels) -}} +{{- end }} +{{- $defaultAction := default "Deny" $policy.defaultAction -}} +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: {{ $policyName }} + namespace: {{ $policyNamespace | quote }} + annotations: + oidc.autoregistrar.parcellab.dev/sync-enabled: 'true' +spec: + {{- if $targetRef }} + targetRef: + {{- toYaml $targetRef | nindent 4 }} + {{- else if $targetRefs }} + targetRefs: + {{- toYaml $targetRefs | nindent 4 }} + {{- else }} + targetSelectors: + {{- toYaml $targetSelectors | nindent 4 }} + {{- end }} + oidc: + provider: + issuer: {{ $issuer | quote }} + clientID: {{ $clientID | quote }} + clientSecret: + name: {{ $clientSecretName | quote }} + redirectURL: {{ $redirectURL | quote }} + logoutPath: {{ $logoutPath | quote }} + {{- with $scopes }} + scopes: + {{ toYaml . | nindent 6 }} + {{- end }} + cookieDomain: {{ $cookieDomain | quote }} + forwardAccessToken: true + passThroughAuthHeader: true + jwt: + optional: false + providers: + - name: {{ $jwtProviderName | quote }} + issuer: {{ $issuer | quote }} + remoteJWKS: + cacheDuration: 300s + uri: {{ $jwksURI | quote }} + {{- with $claimToHeaders }} + claimToHeaders: + {{ toYaml . | nindent 8 }} + {{- end }} + + authorization: + defaultAction: {{ $defaultAction }} + {{- with $policy.authorizationRules }} + rules: + {{ toYaml . | nindent 6 }} + {{- end }} +{{ end }} +{{- end -}} +{{- end -}} +{{- end -}} From 4fc9a1162e6ad5e94227768ab3f64e04a45fe449 Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Fri, 30 Jan 2026 09:25:56 +0100 Subject: [PATCH 11/21] chore: delete unused tempalte --- parcellab/common/templates/_routing.tpl | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 parcellab/common/templates/_routing.tpl diff --git a/parcellab/common/templates/_routing.tpl b/parcellab/common/templates/_routing.tpl deleted file mode 100644 index b89cc803..00000000 --- a/parcellab/common/templates/_routing.tpl +++ /dev/null @@ -1,12 +0,0 @@ -{{- define "common.routing" -}} -{{- $envoy := .Values.envoy | default dict -}} -{{- $httproute := $envoy.httpRoute | default dict -}} -{{- $ingress := .Values.ingress | default dict -}} - -{{- if $httproute.enabled }} - {{- include "common.httproute" . }} -{{- else if $ingress.enabled }} - {{- include "common.ingress" . }} -{{- end }} - -{{- end -}} From b8c6478cb76091cd0161a7cecfde6ba22b5f28ff Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:35:22 +0100 Subject: [PATCH 12/21] fix: add validation to prevent invalid ReferenceGrant resources (#418) * Initial plan * fix: add validation to ReferenceGrant template to prevent invalid resources Co-authored-by: andibeuge <97287249+andibeuge@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: andibeuge <97287249+andibeuge@users.noreply.github.com> --- parcellab/common/templates/_referencegrant.tpl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/parcellab/common/templates/_referencegrant.tpl b/parcellab/common/templates/_referencegrant.tpl index 92512bc0..95f4bd33 100644 --- a/parcellab/common/templates/_referencegrant.tpl +++ b/parcellab/common/templates/_referencegrant.tpl @@ -14,7 +14,9 @@ {{- $gateway := $envoy.gateway | default dict -}} {{- $name := include "common.fullname" . }} {{- $serviceNamespace := .Release.Namespace }} -{{- if $envoy.enabled -}} +{{- $from := $referenceGrant.from | default list -}} +{{- $to := $referenceGrant.to | default list -}} +{{- if and $envoy.enabled (gt (len $from) 0) (gt (len $to) 0) -}} --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant @@ -29,7 +31,7 @@ metadata: {{- end }} spec: from: - {{- range $referenceGrant.from }} + {{- range $from }} - group: {{ .group | default "gateway.networking.k8s.io" | quote }} kind: {{ required "referenceGrant.from.kind is required" .kind | quote }} namespace: {{ $serviceNamespace | quote }} @@ -38,7 +40,7 @@ spec: {{- end }} {{- end }} to: - {{- range $referenceGrant.to }} + {{- range $to }} - group: {{ .group | default "" | quote }} kind: {{ required "referenceGrant.to.kind is required" .kind | quote }} {{- with .name }} From ecea7dd3fe02ae520294e696b0a139154c2e68b3 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:36:00 +0100 Subject: [PATCH 13/21] fix: enhance charts to support Envoy Gateway based on feedback (#417) * Initial plan * Add validation for HTTPRoute hosts requirement Co-authored-by: andibeuge <97287249+andibeuge@users.noreply.github.com> * Use idiomatic len check for empty hosts validation Co-authored-by: andibeuge <97287249+andibeuge@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: andibeuge <97287249+andibeuge@users.noreply.github.com> --- parcellab/common/templates/_httproutes.tpl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/parcellab/common/templates/_httproutes.tpl b/parcellab/common/templates/_httproutes.tpl index 4968f8af..7a5ad9fe 100644 --- a/parcellab/common/templates/_httproutes.tpl +++ b/parcellab/common/templates/_httproutes.tpl @@ -17,6 +17,10 @@ {{- $securityLabelKey := printf "%s/security-required" (include "common.parcellabtagsdomain" .) -}} {{- range $index, $route := $httproutes }} +{{- $hosts := required (printf "envoy.httpRoutes[%d].hosts is required" $index) $route.hosts -}} +{{- if eq (len $hosts) 0 -}} +{{- fail (printf "envoy.httpRoutes[%d].hosts cannot be empty" $index) -}} +{{- end -}} {{- $rawRouteName := default (printf "%s-%d" $baseName $index) $route.name -}} {{- $sanitizedRouteName := trunc 63 (trimSuffix "-" (regexReplaceAll "[^a-z0-9-]" (lower $rawRouteName) "-")) -}} {{- $routeName := default (printf "%s-%d" $baseName $index) $sanitizedRouteName }} @@ -34,7 +38,7 @@ metadata: {{- end }} annotations: external-dns.alpha.kubernetes.io/hostname: | - {{- range $route.hosts }} + {{- range $hosts }} {{ . }} {{- end }} spec: @@ -44,7 +48,7 @@ spec: group: gateway.networking.k8s.io kind: Gateway hostnames: - {{- range $route.hosts }} + {{- range $hosts }} - {{ . | quote }} {{- end }} {{- with $route.rules }} From d6edbbc44af864cf72e5f1ffdb6225c42c61d6d9 Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Fri, 30 Jan 2026 09:40:59 +0100 Subject: [PATCH 14/21] chore: remove invalid block --- parcellab/common/templates/_securitypolicies.tpl | 3 --- 1 file changed, 3 deletions(-) diff --git a/parcellab/common/templates/_securitypolicies.tpl b/parcellab/common/templates/_securitypolicies.tpl index b8ef6c3d..723c0218 100644 --- a/parcellab/common/templates/_securitypolicies.tpl +++ b/parcellab/common/templates/_securitypolicies.tpl @@ -6,9 +6,6 @@ */}} {{- define "common.securitypolicies" -}} {{- $values := .Values -}} -{{- if .Values.microservice }} -{{- $values = .Values.microservice -}} -{{- end -}} {{- $envoy := default (dict "enabled" false) $values.envoy -}} {{- if $envoy.enabled }} {{- $security := default dict $envoy.security -}} From c9562ca547cd4de430447dd3c2d3435a049e6dbb Mon Sep 17 00:00:00 2001 From: andibeuge <97287249+andibeuge@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:46:53 +0100 Subject: [PATCH 15/21] Update parcellab/monolith/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- parcellab/monolith/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parcellab/monolith/README.md b/parcellab/monolith/README.md index f9e27133..465e252a 100644 --- a/parcellab/monolith/README.md +++ b/parcellab/monolith/README.md @@ -32,7 +32,7 @@ needs. - `hpa` - Horizontal automatic scaling rules of pods. Can be defined with the `autoscaling` setting. - `envoy` - - Envoy Gateway resources (HTTPRoute, ReferenceGrant). Defined under `envoy.*`. + - Envoy Gateway resources (HTTPRoute, ReferenceGrant, SecurityPolicy). Defined under `envoy.*`. - `ingress` - Rules to open external access to the workload. Can be defined with `ingress`. - `poddisruptionbudget` From a6fd86fbd549d1c5996f97e5feaaea82bba7a660 Mon Sep 17 00:00:00 2001 From: andibeuge <97287249+andibeuge@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:49:11 +0100 Subject: [PATCH 16/21] Update parcellab/common/templates/_referencegrant.tpl Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- parcellab/common/templates/_referencegrant.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parcellab/common/templates/_referencegrant.tpl b/parcellab/common/templates/_referencegrant.tpl index 95f4bd33..0224b12a 100644 --- a/parcellab/common/templates/_referencegrant.tpl +++ b/parcellab/common/templates/_referencegrant.tpl @@ -22,7 +22,7 @@ apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: {{ (printf "%s-reference-grant" $name) }} - namespace: {{ $serviceNamespace | quote }} + namespace: {{ $gateway.namespace | quote }} labels: {{- include "common.labels" . | nindent 4 }} {{- with $referenceGrant.annotations }} From 66a3d812227e7540c9060e88d407c178596cf19d Mon Sep 17 00:00:00 2001 From: Andreas Beuge Date: Fri, 30 Jan 2026 09:52:27 +0100 Subject: [PATCH 17/21] fix: correct policy namespace --- parcellab/common/templates/_securitypolicies.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parcellab/common/templates/_securitypolicies.tpl b/parcellab/common/templates/_securitypolicies.tpl index 723c0218..3e0666f4 100644 --- a/parcellab/common/templates/_securitypolicies.tpl +++ b/parcellab/common/templates/_securitypolicies.tpl @@ -13,7 +13,7 @@ {{- if $policies }} {{- $scope := dict "Values" $values "Release" .Release -}} {{- $serviceName := default (include "common.fullname" $scope) $values.name -}} -{{- $policyNamespace := default "infra" $security.namespace -}} +{{- $policyNamespace := .Release.Namespace -}} {{- $securityLabelKey := printf "%s/security-required" (include "common.parcellabtagsdomain" .) -}} {{- $globalIssuer := $security.issuer -}} {{- $globalRedirectURL := $security.redirectURL -}} From 90acd657ae62a1b12aec0155ab760e161015e538 Mon Sep 17 00:00:00 2001 From: andibeuge <97287249+andibeuge@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:58:16 +0100 Subject: [PATCH 18/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- parcellab/common/templates/_httproutes.tpl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/parcellab/common/templates/_httproutes.tpl b/parcellab/common/templates/_httproutes.tpl index 7a5ad9fe..9d539cee 100644 --- a/parcellab/common/templates/_httproutes.tpl +++ b/parcellab/common/templates/_httproutes.tpl @@ -37,10 +37,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} annotations: - external-dns.alpha.kubernetes.io/hostname: | - {{- range $hosts }} - {{ . }} - {{- end }} + external-dns.alpha.kubernetes.io/hostname: "{{ join "," $route.hosts }}" spec: parentRefs: - name: {{ $gateway.name }} From 29521defb31d7b77a215b52ffca7af4ee2cd5184 Mon Sep 17 00:00:00 2001 From: andibeuge <97287249+andibeuge@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:59:25 +0100 Subject: [PATCH 19/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- parcellab/microservice/values.yaml | 52 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/parcellab/microservice/values.yaml b/parcellab/microservice/values.yaml index b8c89794..e55fb28f 100644 --- a/parcellab/microservice/values.yaml +++ b/parcellab/microservice/values.yaml @@ -84,32 +84,32 @@ envoy: # foo: bar # optional security: enabled: false -# enabled: true -# issuer: "https://my-issuer-domain.example.com" -# redirectURL: "https://my-app.example.com/oauth2/callback" -# cookieDomain: "my-app.example.com" -# scopes: -# - profile -# - email -# claimToHeaders: -# - header: "x-user-email" -# claim: "email" -# policies: -# - name: staff-only -# targetRef: -# kind: HTTPRoute -# name: my-default-route -# group: "gateway.networking.k8s.io" -# authorizationRules: -# - name: member-of-staff-group -# action: Allow -# principal: -# jwt: -# provider: my-provider -# claims: -# - name: groups -# valueType: StringArray -# values: ["staff"] + # enabled: true + # issuer: "https://my-issuer-domain.example.com" + # redirectURL: "https://my-app.example.com/oauth2/callback" + # cookieDomain: "my-app.example.com" + # scopes: + # - profile + # - email + # claimToHeaders: + # - header: "x-user-email" + # claim: "email" + # policies: + # - name: staff-only + # targetRef: + # kind: HTTPRoute + # name: my-default-route + # group: "gateway.networking.k8s.io" + # authorizationRules: + # - name: member-of-staff-group + # action: Allow + # principal: + # jwt: + # provider: my-provider + # claims: + # - name: groups + # valueType: StringArray + # values: ["staff"] ## ## Cronjob From f82ace12281325e3e362ab0efbad8a6bd4fccc67 Mon Sep 17 00:00:00 2001 From: andibeuge <97287249+andibeuge@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:59:42 +0100 Subject: [PATCH 20/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- parcellab/monolith/values.yaml | 52 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/parcellab/monolith/values.yaml b/parcellab/monolith/values.yaml index d8d94825..71a3b983 100644 --- a/parcellab/monolith/values.yaml +++ b/parcellab/monolith/values.yaml @@ -113,32 +113,32 @@ envoy: # foo: bar # optional security: enabled: false -# enabled: true -# issuer: "https://my-issuer-domain.example.com" -# redirectURL: "https://my-app.example.com/oauth2/callback" -# cookieDomain: "my-app.example.com" -# scopes: -# - profile -# - email -# claimToHeaders: -# - header: "x-user-email" -# claim: "email" -# policies: -# - name: staff-only -# targetRef: -# kind: HTTPRoute -# name: my-default-route -# group: "gateway.networking.k8s.io" -# authorizationRules: -# - name: member-of-staff-group -# action: Allow -# principal: -# jwt: -# provider: my-provider -# claims: -# - name: groups -# valueType: StringArray -# values: ["staff"] + # enabled: true + # issuer: "https://my-issuer-domain.example.com" + # redirectURL: "https://my-app.example.com/oauth2/callback" + # cookieDomain: "my-app.example.com" + # scopes: + # - profile + # - email + # claimToHeaders: + # - header: "x-user-email" + # claim: "email" + # policies: + # - name: staff-only + # targetRef: + # kind: HTTPRoute + # name: my-default-route + # group: "gateway.networking.k8s.io" + # authorizationRules: + # - name: member-of-staff-group + # action: Allow + # principal: + # jwt: + # provider: my-provider + # claims: + # - name: groups + # valueType: StringArray + # values: ["staff"] ## ## Cronjob From ba4705f225eb19a55df96a1ab6e5d686edb9e227 Mon Sep 17 00:00:00 2001 From: andibeuge <97287249+andibeuge@users.noreply.github.com> Date: Fri, 30 Jan 2026 10:00:06 +0100 Subject: [PATCH 21/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3622b85d..2245b80c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "lint": "npm run lint:helm && npm run lint:prettier", "lint:helm": "npm run deps && find parcellab -type d -maxdepth 1 -mindepth 1 | xargs -I {} helm lint {}", "lint:prettier": "prettier --check --ignore-unknown .", - "lint:prettier:fix": "prettier --check --ignore-unknown --write .", + "lint:prettier:fix": "prettier --write --ignore-unknown .", "lint:staged": "lint-staged", "format": "prettier --write --ignore-unknown .", "prepare": "husky install",