diff --git a/changelog/v1.17.22/fix-gwp-fips-distroless.yaml b/changelog/v1.17.22/fix-gwp-fips-distroless.yaml new file mode 100644 index 00000000000..e34746f5d46 --- /dev/null +++ b/changelog/v1.17.22/fix-gwp-fips-distroless.yaml @@ -0,0 +1,5 @@ +changelog: +- type: FIX + issueLink: https://github.com/solo-io/gloo/issues/10602 + resolvesIssue: false + description: Fixes the gateway params image to respect the fips and distroless variants specified by global.image.variant. This only applies to the kubernetes gateway proxy. diff --git a/install/helm/gloo/templates/_gg-helpers.tpl b/install/helm/gloo/templates/_gg-helpers.tpl index 2a5241a76c2..55095a5a401 100644 --- a/install/helm/gloo/templates/_gg-helpers.tpl +++ b/install/helm/gloo/templates/_gg-helpers.tpl @@ -42,18 +42,18 @@ Images valid for the GatewayParameters ref Image api in projects/gateway2/api/v1alpha1/kube/container.proto */}} {{- define "gloo-gateway.gatewayParametersImage" -}} -{{- $image := . -}} +{{ $image := . }} {{- if $image.registry }} registry: {{ $image.registry }} {{- end -}}{{/* if $image.registry */}} {{- if $image.repository }} -repository: {{ $image.repository }} +repository: {{ template "gloo.image.repository" $image }} {{- end -}}{{/* if $image.repository */}} {{- if $image.tag }} -tag: {{ $image.tag }} +tag: {{ template "gloo.image.tag" $image }} {{- end -}}{{/* if $image.tag */}} {{- if $image.digest }} -digest: {{ $image.digest }} +digest: {{ template "gloo.image.digest" $image }} {{- end -}}{{/* if $image.digest */}} {{- if $image.pullPolicy }} pullPolicy: {{ $image.pullPolicy }} diff --git a/install/helm/gloo/templates/_helpers.tpl b/install/helm/gloo/templates/_helpers.tpl index af7bf19e4b8..cfb9454252a 100644 --- a/install/helm/gloo/templates/_helpers.tpl +++ b/install/helm/gloo/templates/_helpers.tpl @@ -25,59 +25,75 @@ ClusterRole {{- end -}} {{- end -}} -{{/* -Construct a container image name from a registry, repository, tag, and digest. -*/}} -{{- define "gloo.image" -}} -{{- $image := printf "%s/%s" .registry .repository -}} - +{{- define "gloo.image.repository" -}} {{- /* for fips or fips-distroless variants: add -fips to the image repo (name) */ -}} +{{- if .repository -}} +{{- $repository := .repository -}} {{- if or .fips (has .variant (list "fips" "fips-distroless")) -}} {{- $fipsSupportedImages := list "gloo-ee" "extauth-ee" "gloo-ee-envoy-wrapper" "rate-limit-ee" "discovery-ee" "sds-ee" -}} {{- if (has .repository $fipsSupportedImages) -}} -{{- $image = printf "%s-fips" $image -}} +{{- $repository = printf "%s-fips" $repository -}} {{- end -}}{{- /* if (has .repository $fipsSupportedImages) */ -}} {{- end -}}{{- /* if or .fips (has .variant (list "fips" "fips-distroless")) */ -}} +{{ $repository }} +{{- end -}}{{- /* if .repository */ -}} +{{- end -}}{{- /* define "gloo.image.repository" */ -}} -{{- /* -add tag, if it exists -*/ -}} +{{- define "gloo.image.tag" -}} {{- if .tag -}} -{{- $image = printf "%s:%s" $image .tag -}} -{{- end -}}{{- /* if .tag */ -}} - +{{- $tag := .tag -}} {{- /* for distroless or fips-distroless variants: add -distroless to the tag */ -}} {{- if and .tag (has .variant (list "distroless" "fips-distroless")) -}} {{- $distrolessSupportedImages := list "gloo" "gloo-envoy-wrapper" "discovery" "sds" "certgen" "kubectl" "access-logger" "ingress" "gloo-ee" "extauth-ee" "gloo-ee-envoy-wrapper" "rate-limit-ee" "discovery-ee" "sds-ee" "observability-ee" "caching-ee" -}} {{- if (has .repository $distrolessSupportedImages) -}} -{{- $image = printf "%s-distroless" $image -}} {{- /* Add distroless suffix to the tag since it contains the same binaries in a different container */ -}} +{{- $tag = printf "%s-distroless" $tag -}} {{- /* Add distroless suffix to the tag since it contains the same binaries in a different container */ -}} {{- end -}}{{- /* if (has .repository $distrolessSupportedImages) */ -}} {{- end -}}{{- /* if and .tag (has .variant (list "distroless" "fips-distroless")) */ -}} +{{ $tag }} +{{- end -}}{{- /* if .tag */ -}} +{{- end -}}{{- /* define "gloo.image.tag" */ -}} -{{- /* -add digest for the chosen variant, if it exists -*/ -}} +{{- define "gloo.image.digest" -}} +{{- $digest := "" -}} {{- if or .fips (eq .variant "fips") -}} {{- if .fipsDigest -}} - {{- $image = printf "%s@%s" $image .fipsDigest -}} + {{- $digest = .fipsDigest -}} {{- end -}}{{- /* if .fipsDigest */ -}} {{- else if eq .variant "distroless" -}} {{- if .distrolessDigest -}} - {{- $image = printf "%s@%s" $image .distrolessDigest -}} + {{- $digest = .distrolessDigest -}} {{- end -}}{{- /* if .distrolessDigest */ -}} {{- else if eq .variant "fips-distroless" -}} {{- if .fipsDistrolessDigest -}} - {{- $image = printf "%s@%s" $image .fipsDistrolessDigest -}} + {{- $digest = .fipsDistrolessDigest -}} {{- end -}}{{- /* if .fipsDistrolessDigest */ -}} {{- else -}} {{- if .digest -}}{{- /* standard image digest */ -}} - {{- $image = printf "%s@%s" $image .digest -}} + {{- $digest = .digest -}} {{- end -}}{{- /* if .digest */ -}} {{- end -}} +{{ $digest }} +{{- end -}}{{- /* define "gloo.image.digest" */ -}} + + +{{/* +Construct a container image name from a registry, repository, tag, and digest. +*/}} +{{- define "gloo.image" -}} +{{- $repository := include "gloo.image.repository" . -}} +{{- $image := printf "%s/%s" .registry $repository -}} +{{- $tag := include "gloo.image.tag" . -}} +{{- if $tag -}} +{{- $image = printf "%s:%s" $image $tag -}} +{{- end -}}{{- /* if .tag */ -}} +{{- $digest := include "gloo.image.digest" . -}} +{{- if $digest -}} +{{- $image = printf "%s@%s" $image $digest -}} +{{- end -}}{{- /* if .digest */ -}} {{ $image }} {{- end -}}{{- /* define "gloo.image" */ -}} @@ -170,7 +186,7 @@ It takes 4 values: .defaults - the default securityContext for the pod or container .globalSec - global security settings, usually from .Values.global.securitySettings .indent - the number of spaces to indent the output. If not set, the output will not be indented. - The indentation argument is necessary because it is possible that no output will be rendered. + The indentation argument is necessary because it is possible that no output will be rendered. If that happens and the caller handles the indentation the result will be a line of whitespace, which gets caught by the whitespace tests Depending upon the value of .values.merge, the securityContext will be merged with the defaults or completely replaced. @@ -234,7 +250,7 @@ It takes 4 values: .podSecurityStandards - podSecurityStandard from values.yaml .globalSec - global security settings, usually from .Values.global.securitySettings .indent - the number of spaces to indent the output. If not set, the output will not be indented. - The indentation argument is necessary because it is possible that no output will be rendered. + The indentation argument is necessary because it is possible that no output will be rendered. If that happens and the caller handles the indentation the result will be a line of whitespace, which gets caught by the whitespace tests If .podSecurityStandards.container.enableRestrictedContainerDefaults is true, the defaults will be set to a restricted set of values. @@ -260,7 +276,7 @@ It takes 4 values: {{- end -}} {{- /* set default seccompProfileType */ -}} -{{- $pss_restricted_defaults := dict +{{- $pss_restricted_defaults := dict "runAsNonRoot" true "capabilities" (dict "drop" (list "ALL")) "allowPrivilegeEscalation" false }} @@ -280,7 +296,7 @@ It takes 4 values: {{- end -}} {{- end -}} {{- /* call general securityContext template */ -}} -{{- include "gloo.securityContext" (dict +{{- include "gloo.securityContext" (dict "values" $values "defaults" $defaults "indent" $indent diff --git a/install/test/k8sgateway_test.go b/install/test/k8sgateway_test.go index 627f3732d42..7d5ca097dcc 100644 --- a/install/test/k8sgateway_test.go +++ b/install/test/k8sgateway_test.go @@ -359,6 +359,57 @@ var _ = Describe("Kubernetes Gateway API integration", func() { Entry("locally undefined, globally undefined", false), ) }) + + Context("distroless and fips", func() { + DescribeTable("Uses the correct image for the sds-ee container", func(variant string, expectedImage string) { + extraValueArgs := []string{ + "kubeGateway.gatewayParameters.glooGateway.sdsContainer.image.registry=my-sds-reg", + "kubeGateway.gatewayParameters.glooGateway.sdsContainer.image.tag=my-sds-tag", + "kubeGateway.gatewayParameters.glooGateway.sdsContainer.image.repository=sds-ee", + "global.image.variant=" + variant, + } + valuesArgs = append(valuesArgs, extraValueArgs...) + // Updated values so need to re-render + prepareHelmManifest(namespace, glootestutils.HelmValues{ValuesArgs: valuesArgs}) + + gwp := getDefaultGatewayParameters(testManifest) + gwpKube := gwp.Spec.Kube + Expect(gwpKube).ToNot(BeNil()) + sdsContainer := gwpKube.SdsContainer.Image + image := fmt.Sprintf("%s/%s:%s", *sdsContainer.Registry, *sdsContainer.Repository, *sdsContainer.Tag) + Expect(image).To(Equal(expectedImage)) + }, + Entry("No variant specified", "", "my-sds-reg/sds-ee:my-sds-tag"), + Entry("Standard variant", "standard", "my-sds-reg/sds-ee:my-sds-tag"), + Entry("Fips variant", "fips", "my-sds-reg/sds-ee-fips:my-sds-tag"), + Entry("Distroless variant", "distroless", "my-sds-reg/sds-ee:my-sds-tag-distroless"), + Entry("Fips-Distroless variant", "fips-distroless", "my-sds-reg/sds-ee-fips:my-sds-tag-distroless")) + + DescribeTable("Uses the correct image for the gloo-ee-envoy-wrapper container", func(variant string, expectedImage string) { + extraValueArgs := []string{ + "kubeGateway.gatewayParameters.glooGateway.envoyContainer.image.registry=my-gloo-ee-envoy-wrapper-reg", + "kubeGateway.gatewayParameters.glooGateway.envoyContainer.image.tag=my-gloo-ee-envoy-wrapper-tag", + "kubeGateway.gatewayParameters.glooGateway.envoyContainer.image.repository=gloo-ee-envoy-wrapper", + "global.image.variant=" + variant, + } + valuesArgs = append(valuesArgs, extraValueArgs...) + // Updated values so need to re-render + prepareHelmManifest(namespace, glootestutils.HelmValues{ValuesArgs: valuesArgs}) + + gwp := getDefaultGatewayParameters(testManifest) + gwpKube := gwp.Spec.Kube + Expect(gwpKube).ToNot(BeNil()) + envoyContainer := gwpKube.EnvoyContainer.Image + image := fmt.Sprintf("%s/%s:%s", *envoyContainer.Registry, *envoyContainer.Repository, *envoyContainer.Tag) + Expect(image).To(Equal(expectedImage)) + }, + Entry("No variant specified", "", "my-gloo-ee-envoy-wrapper-reg/gloo-ee-envoy-wrapper:my-gloo-ee-envoy-wrapper-tag"), + Entry("Standard variant", "standard", "my-gloo-ee-envoy-wrapper-reg/gloo-ee-envoy-wrapper:my-gloo-ee-envoy-wrapper-tag"), + Entry("Fips variant", "fips", "my-gloo-ee-envoy-wrapper-reg/gloo-ee-envoy-wrapper-fips:my-gloo-ee-envoy-wrapper-tag"), + Entry("Distroless variant", "distroless", "my-gloo-ee-envoy-wrapper-reg/gloo-ee-envoy-wrapper:my-gloo-ee-envoy-wrapper-tag-distroless"), + Entry("Fips-Distroless variant", "fips-distroless", "my-gloo-ee-envoy-wrapper-reg/gloo-ee-envoy-wrapper-fips:my-gloo-ee-envoy-wrapper-tag-distroless")) + + }) }) When("kube gateway integration is disabled (default)", func() { @@ -389,3 +440,13 @@ var _ = Describe("Kubernetes Gateway API integration", func() { } runTests(allTests) }) + +func getDefaultGatewayParameters(t TestManifest) *v1alpha1.GatewayParameters { + gwpUnstructured := t.ExpectCustomResource("GatewayParameters", namespace, wellknown.DefaultGatewayParametersName) + obj, err := kuberesource.ConvertUnstructured(gwpUnstructured) + Expect(err).NotTo(HaveOccurred()) + + gwp, ok := obj.(*v1alpha1.GatewayParameters) + Expect(ok).To(BeTrue()) + return gwp +}