From 4004a1035cc55515483ae36c8985a7c6004bdbdb Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 11 Apr 2025 15:45:45 +0100 Subject: [PATCH 01/23] accept otel configmap keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/version1/nginx-plus.tmpl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index 9b5a0738c5..8f9f2552f4 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -12,6 +12,9 @@ daemon off; error_log stderr {{.ErrorLogLevel}}; pid /var/lib/nginx/nginx.pid; +{{- if .MainOtelLoadModule}} +#load_module modules/ngx_otel_module.so; +{{- end}} {{- if .AppProtectLoadModule}} load_module modules/ngx_http_app_protect_module.so; {{- end}} @@ -142,6 +145,22 @@ http { {{- if .SSLDHParam}} ssl_dhparam {{.SSLDHParam}}; {{- end}} + + {{- if .MainOtelEnabled}} + # otel_exporter { + # endpoint {{ .MainOtelExporterEndpoint}}; + # header {{ .MainOtelExporterHeaderName }} {{ .MainOtelExporterHeaderValue }}; + {{ if .MainOtelExporterTrustedCA}} + # trusted_certificate ; + {{- end }} + {{ if .MainOtelServiceName}} + # otel_service_name {{ .MainOtelServiceName }}; + # } + {{- end }} + {{ if .MainOtelGlobalTraceEnabled }} + # otel_trace on; + {{- end}} + {{- end}} {{ $resolverIPV6HTTPBool := boolToPointerBool .ResolverIPV6 -}} {{ makeResolver .ResolverAddresses .ResolverValid $resolverIPV6HTTPBool }} From ab09179340399479d0081270af3a1d313e93fbbb Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Fri, 11 Apr 2025 14:45:29 +0100 Subject: [PATCH 02/23] add otel-module to NIC images Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- build/Dockerfile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 09ff7093c4..3d95082061 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -109,7 +109,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \ --mount=type=bind,from=nginx-files,src=tracking.info,target=/tmp/nginx/reporting/tracking.info \ export $(cat /tmp/user_agent) \ && printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check libcap libcurl \ + && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check libcap libcurl \ && mkdir -p /etc/nginx/reporting/ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ && ldconfig /usr/local/lib/ \ && sed -i -e '/nginx.com/d' /etc/apk/repositories @@ -151,7 +151,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \ && printf "%s\n" "https://${PACKAGE_REPO}/app-protect/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://pkgs.nginx.com/app-protect-security-updates/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \ @@ -187,7 +187,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \ printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \ @@ -226,7 +226,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && gpg --dearmor -o /usr/share/keyrings/app-protect-archive-keyring.gpg /tmp/app-protect-security-updates.key \ && cp /tmp/nginx-plus.sources /etc/apt/sources.list.d/nginx-plus.sources \ && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && apt-get purge --auto-remove -y gpg \ && mkdir -p /etc/nginx/reporting/ \ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ @@ -346,7 +346,7 @@ RUN --mount=type=bind,from=nginx-files,src=nginx_signing.key,target=/tmp/nginx_s printf "%s\n" "[nginx]" "name=nginx repo" \ "baseurl=https://nginx.org/packages/mainline/centos/9/\$basearch/" \ "gpgcheck=1" "enabled=1" "module_hotfixes=true" > /etc/yum.repos.d/nginx.repo \ - && microdnf --nodocs install -y nginx nginx-module-njs nginx-module-image-filter nginx-module-xslt \ + && microdnf --nodocs install -y nginx nginx-module-njs nginx-module-otel nginx-module-image-filter nginx-module-xslt \ && rm /etc/yum.repos.d/nginx.repo; \ fi \ && ubi-clean.sh @@ -368,7 +368,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode --mount=type=bind,from=nginx-files,src=tracking.info,target=/tmp/nginx/reporting/tracking.info \ mkdir -p /etc/nginx/reporting/ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ && ubi-setup.sh \ - && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && ubi-clean.sh @@ -447,7 +447,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode ############################################# Base image for UBI8 with NGINX Plus and App Protect WAF ############################################# -FROM redhat/ubi8@sha256:244e9858f9d8a2792a3dceb850b4fa8fdbd67babebfde42587bfa919d5d1ecef AS ubi-8-plus-nap +FROM redhat/ubi8@sha256:8bd1b6306f8164de7fb0974031a0f903bd3ab3e6bcab835854d3d9a1a74ea5db AS ubi-8-plus-nap ARG NAP_MODULES ARG NGINX_AGENT ARG NGINX_PLUS_VERSION @@ -473,7 +473,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ && rpm --import /tmp/nginx_signing.key \ - && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \ && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \ && subscription-manager register --org=${RHEL_ORGANIZATION} --activationkey=${RHEL_ACTIVATION_KEY} || true \ @@ -520,7 +520,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ && rpm --import /tmp/nginx_signing.key \ - && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \ ## end of duplicated code && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \ From fe8fd7a5e701b88d20a4f868d2212ed81c804fe8 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:15:53 +0100 Subject: [PATCH 03/23] remove unused config map keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/version1/nginx-plus.tmpl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index 8f9f2552f4..c637614df0 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -13,7 +13,7 @@ error_log stderr {{.ErrorLogLevel}}; pid /var/lib/nginx/nginx.pid; {{- if .MainOtelLoadModule}} -#load_module modules/ngx_otel_module.so; +load_module modules/ngx_otel_module.so; {{- end}} {{- if .AppProtectLoadModule}} load_module modules/ngx_http_app_protect_module.so; @@ -145,20 +145,23 @@ http { {{- if .SSLDHParam}} ssl_dhparam {{.SSLDHParam}}; {{- end}} - - {{- if .MainOtelEnabled}} - # otel_exporter { - # endpoint {{ .MainOtelExporterEndpoint}}; - # header {{ .MainOtelExporterHeaderName }} {{ .MainOtelExporterHeaderValue }}; + + {{- if .MainOtelLoadModule}} + otel_exporter { + endpoint {{ .MainOtelExporterEndpoint}}; + {{ if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; + {{- end }} {{ if .MainOtelExporterTrustedCA}} # trusted_certificate ; {{- end }} + } + {{ if .MainOtelServiceName}} - # otel_service_name {{ .MainOtelServiceName }}; - # } + otel_service_name {{ .MainOtelServiceName }}; {{- end }} {{ if .MainOtelGlobalTraceEnabled }} - # otel_trace on; + otel_trace on; {{- end}} {{- end}} From cf80a11d90a7b5b3cd6298d261b2bf23aca05a10 Mon Sep 17 00:00:00 2001 From: Paul Abel <128620221+pdabelf5@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:32:36 +0100 Subject: [PATCH 04/23] Remove OpenTracing Support from NIC (#7633) --- build/Dockerfile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 3d95082061..65c5349f5d 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -109,7 +109,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \ --mount=type=bind,from=nginx-files,src=tracking.info,target=/tmp/nginx/reporting/tracking.info \ export $(cat /tmp/user_agent) \ && printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check libcap libcurl \ + && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check libcap libcurl \ && mkdir -p /etc/nginx/reporting/ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ && ldconfig /usr/local/lib/ \ && sed -i -e '/nginx.com/d' /etc/apk/repositories @@ -151,7 +151,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \ && printf "%s\n" "https://${PACKAGE_REPO}/app-protect/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://pkgs.nginx.com/app-protect-security-updates/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ + && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \ @@ -187,7 +187,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \ printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ + && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \ @@ -226,7 +226,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && gpg --dearmor -o /usr/share/keyrings/app-protect-archive-keyring.gpg /tmp/app-protect-security-updates.key \ && cp /tmp/nginx-plus.sources /etc/apt/sources.list.d/nginx-plus.sources \ && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ + && apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ && apt-get purge --auto-remove -y gpg \ && mkdir -p /etc/nginx/reporting/ \ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ @@ -346,7 +346,7 @@ RUN --mount=type=bind,from=nginx-files,src=nginx_signing.key,target=/tmp/nginx_s printf "%s\n" "[nginx]" "name=nginx repo" \ "baseurl=https://nginx.org/packages/mainline/centos/9/\$basearch/" \ "gpgcheck=1" "enabled=1" "module_hotfixes=true" > /etc/yum.repos.d/nginx.repo \ - && microdnf --nodocs install -y nginx nginx-module-njs nginx-module-otel nginx-module-image-filter nginx-module-xslt \ + && microdnf --nodocs install -y nginx nginx-module-njs nginx-module-image-filter nginx-module-xslt \ && rm /etc/yum.repos.d/nginx.repo; \ fi \ && ubi-clean.sh @@ -368,7 +368,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode --mount=type=bind,from=nginx-files,src=tracking.info,target=/tmp/nginx/reporting/tracking.info \ mkdir -p /etc/nginx/reporting/ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ && ubi-setup.sh \ - && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ + && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ && ubi-clean.sh @@ -473,7 +473,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ && rpm --import /tmp/nginx_signing.key \ - && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ + && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \ && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \ && subscription-manager register --org=${RHEL_ORGANIZATION} --activationkey=${RHEL_ACTIVATION_KEY} || true \ @@ -520,7 +520,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ && rpm --import /tmp/nginx_signing.key \ - && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ + && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \ ## end of duplicated code && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \ From c1dc6e5189e6c8264f54edf17d6b51590981d0b4 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 11 Apr 2025 15:45:45 +0100 Subject: [PATCH 05/23] accept otel configmap keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/config_params.go | 8 ++++ internal/configs/configmaps.go | 73 +++++++++++++++++++++++++++++ internal/configs/version1/config.go | 8 ++++ 3 files changed, 89 insertions(+) diff --git a/internal/configs/config_params.go b/internal/configs/config_params.go index ec8d0c8a62..f4e0e99ec4 100644 --- a/internal/configs/config_params.go +++ b/internal/configs/config_params.go @@ -34,6 +34,14 @@ type ConfigParams struct { MainLogFormat []string MainLogFormatEscaping string MainMainSnippets []string + MainOtelEnabled bool + MainOtelLoadModule bool + MainOtelGlobalTraceEnabled bool + MainOtelExporterEndpoint string + MainOtelExporterTrustedCA string + MainOtelExporterHeaderName string + MainOtelExporterHeaderValue string + MainOtelServiceName string MainServerNamesHashBucketSize string MainServerNamesHashMaxSize string MainStreamLogFormat []string diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index 91a010c752..4cab3892ac 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -530,6 +530,71 @@ func ParseConfigMap(ctx context.Context, cfgm *v1.ConfigMap, nginxPlus bool, has } } + if otelExporterEndpoint, exists := cfgm.Data["otel-exporter-endpoint"]; exists { + otelExporterEndpoint = strings.TrimSpace(otelExporterEndpoint) + if otelExporterEndpoint != "" { + cfgParams.MainOtelExporterEndpoint = otelExporterEndpoint + } + } + + if otelExporterTrustedCA, exists := cfgm.Data["otel-exporter-trusted-ca"]; exists { + otelExporterTrustedCA = strings.TrimSpace(otelExporterTrustedCA) + if otelExporterTrustedCA != "" { + cfgParams.MainOtelExporterTrustedCA = otelExporterTrustedCA + } + } + + if otelExporterHeaderName, exists := cfgm.Data["otel-exporter-header-name"]; exists { + otelExporterHeaderName = strings.TrimSpace(otelExporterHeaderName) + if otelExporterHeaderName != "" { + cfgParams.MainOtelExporterHeaderName = otelExporterHeaderName + } + } + + if otelExporterHeaderValue, exists := cfgm.Data["otel-exporter-header-value"]; exists { + otelExporterHeaderValue = strings.TrimSpace(otelExporterHeaderValue) + if otelExporterHeaderValue != "" { + cfgParams.MainOtelExporterHeaderValue = otelExporterHeaderValue + } + } + + if otelServiceName, exists := cfgm.Data["otel-service-name"]; exists { + otelServiceName = strings.TrimSpace(otelServiceName) + if otelServiceName != "" { + cfgParams.MainOtelServiceName = otelServiceName + } + } + + if otelGlobalTraceEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-global-trace-enabled", cfgm); exists { + if err != nil { + nl.Error(l, err) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) + configOk = false + } + cfgParams.MainOtelGlobalTraceEnabled = otelGlobalTraceEnabled + } + + if cfgParams.MainOtelExporterEndpoint != "" { + cfgParams.MainOtelLoadModule = true + } + + if otelEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-enabled", cfgm); exists { + if err != nil { + nl.Error(l, err) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) + configOk = false + } else { + if cfgParams.MainOtelLoadModule { + cfgParams.MainOtelEnabled = otelEnabled + } else { + errorText := fmt.Sprintf("ConfigMap %s/%s: 'otel-enabled' is ignored because 'otel-exporter-endpoint' is not set, ignoring", cfgm.GetNamespace(), cfgm.GetName()) + nl.Error(l, errorText) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, errorText) + configOk = false + } + } + } + if hasAppProtect { if appProtectFailureModeAction, exists := cfgm.Data["app-protect-failure-mode-action"]; exists { if appProtectFailureModeAction == "pass" || appProtectFailureModeAction == "drop" { @@ -913,6 +978,14 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config NginxStatus: staticCfgParams.NginxStatus, NginxStatusAllowCIDRs: staticCfgParams.NginxStatusAllowCIDRs, NginxStatusPort: staticCfgParams.NginxStatusPort, + MainOtelEnabled: config.MainOtelEnabled, + MainOtelLoadModule: config.MainOtelLoadModule, + MainOtelGlobalTraceEnabled: config.MainOtelGlobalTraceEnabled, + MainOtelExporterEndpoint: config.MainOtelExporterEndpoint, + MainOtelExporterTrustedCA: config.MainOtelExporterTrustedCA, + MainOtelExporterHeaderName: config.MainOtelExporterHeaderName, + MainOtelExporterHeaderValue: config.MainOtelExporterHeaderValue, + MainOtelServiceName: config.MainOtelServiceName, ProxyProtocol: config.ProxyProtocol, ResolverAddresses: config.ResolverAddresses, ResolverIPV6: config.ResolverIPV6, diff --git a/internal/configs/version1/config.go b/internal/configs/version1/config.go index 8b510e315f..6ac8647ff9 100644 --- a/internal/configs/version1/config.go +++ b/internal/configs/version1/config.go @@ -240,6 +240,14 @@ type MainConfig struct { NginxStatus bool NginxStatusAllowCIDRs []string NginxStatusPort int + MainOtelEnabled bool + MainOtelLoadModule bool + MainOtelGlobalTraceEnabled bool + MainOtelExporterEndpoint string + MainOtelExporterTrustedCA string + MainOtelExporterHeaderName string + MainOtelExporterHeaderValue string + MainOtelServiceName string ProxyProtocol bool ResolverAddresses []string ResolverIPV6 bool From 5b7465c15b21323e2b36939494b4afee94bb6736 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Fri, 11 Apr 2025 14:45:29 +0100 Subject: [PATCH 06/23] add otel-module to NIC images Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- build/Dockerfile | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 65c5349f5d..79a6aa32b5 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -21,15 +21,26 @@ FROM golang:1.24-alpine@sha256:ef18ee7117463ac1055f5a370ed18b8750f01589f13ea0b48 ############################################# Base image for Alpine ############################################# FROM nginx:1.27.4-alpine@sha256:4ff102c5d78d254a6f0da062b3cf39eaf07f01eec0927fd21e219d0af8bc0591 AS alpine -RUN apk add --no-cache libcap libstdc++ +RUN apk add --no-cache libcap libstdc++ \ + && printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ + && apk add --no-cache libcap libstdc++ nginx-module-otel \ + && sed -i -e '/nginx.org/d' /etc/apk/repositories ############################################# Base image for Debian ############################################# FROM nginx:1.27.4@sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab AS debian RUN apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y libcap2-bin - + && apt-get install --no-install-recommends --no-install-suggests -y \ + libcap2-bin curl gnupg2 ca-certificates lsb-release debian-archive-keyring \ + && curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor > /usr/share/keyrings/nginx-archive-keyring.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ + http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" > /etc/apt/sources.list.d/nginx.list \ + && printf "%s" "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" > /etc/apt/preferences.d/99nginx \ + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y nginx-module-otel \ + && apt-get purge --auto-remove -y gnupg2 lsb-release curl \ + && rm -rf /var/lib/apt/lists/* /etc/apt/preferences.d/99nginx /etc/apt/sources.list.d/nginx.list ############################################# NGINX files ############################################# FROM scratch AS nginx-files @@ -109,7 +120,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \ --mount=type=bind,from=nginx-files,src=tracking.info,target=/tmp/nginx/reporting/tracking.info \ export $(cat /tmp/user_agent) \ && printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check libcap libcurl \ + && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check libcap libcurl \ && mkdir -p /etc/nginx/reporting/ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ && ldconfig /usr/local/lib/ \ && sed -i -e '/nginx.com/d' /etc/apk/repositories @@ -151,7 +162,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \ && printf "%s\n" "https://${PACKAGE_REPO}/app-protect/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://pkgs.nginx.com/app-protect-security-updates/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \ @@ -187,7 +198,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \ printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \ @@ -226,7 +237,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && gpg --dearmor -o /usr/share/keyrings/app-protect-archive-keyring.gpg /tmp/app-protect-security-updates.key \ && cp /tmp/nginx-plus.sources /etc/apt/sources.list.d/nginx-plus.sources \ && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && apt-get purge --auto-remove -y gpg \ && mkdir -p /etc/nginx/reporting/ \ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ @@ -346,7 +357,7 @@ RUN --mount=type=bind,from=nginx-files,src=nginx_signing.key,target=/tmp/nginx_s printf "%s\n" "[nginx]" "name=nginx repo" \ "baseurl=https://nginx.org/packages/mainline/centos/9/\$basearch/" \ "gpgcheck=1" "enabled=1" "module_hotfixes=true" > /etc/yum.repos.d/nginx.repo \ - && microdnf --nodocs install -y nginx nginx-module-njs nginx-module-image-filter nginx-module-xslt \ + && microdnf --nodocs install -y nginx nginx-module-njs nginx-module-otel nginx-module-image-filter nginx-module-xslt \ && rm /etc/yum.repos.d/nginx.repo; \ fi \ && ubi-clean.sh @@ -368,7 +379,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode --mount=type=bind,from=nginx-files,src=tracking.info,target=/tmp/nginx/reporting/tracking.info \ mkdir -p /etc/nginx/reporting/ && cp -av /tmp/nginx/reporting/tracking.info /etc/nginx/reporting/tracking.info \ && ubi-setup.sh \ - && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && ubi-clean.sh @@ -473,7 +484,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ && rpm --import /tmp/nginx_signing.key \ - && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \ && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \ && subscription-manager register --org=${RHEL_ORGANIZATION} --activationkey=${RHEL_ACTIVATION_KEY} || true \ @@ -520,7 +531,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode && groupadd --system --gid 101 nginx \ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ && rpm --import /tmp/nginx_signing.key \ - && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \ + && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-otel nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \ ## end of duplicated code && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \ From 13d62045539606090c9d07c5f3df9ddfbacde3be Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:15:53 +0100 Subject: [PATCH 07/23] remove unused config map keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/configmaps.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index 4cab3892ac..d509769118 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -578,23 +578,6 @@ func ParseConfigMap(ctx context.Context, cfgm *v1.ConfigMap, nginxPlus bool, has cfgParams.MainOtelLoadModule = true } - if otelEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-enabled", cfgm); exists { - if err != nil { - nl.Error(l, err) - eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) - configOk = false - } else { - if cfgParams.MainOtelLoadModule { - cfgParams.MainOtelEnabled = otelEnabled - } else { - errorText := fmt.Sprintf("ConfigMap %s/%s: 'otel-enabled' is ignored because 'otel-exporter-endpoint' is not set, ignoring", cfgm.GetNamespace(), cfgm.GetName()) - nl.Error(l, errorText) - eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, errorText) - configOk = false - } - } - } - if hasAppProtect { if appProtectFailureModeAction, exists := cfgm.Data["app-protect-failure-mode-action"]; exists { if appProtectFailureModeAction == "pass" || appProtectFailureModeAction == "drop" { From f6f680842f161aecd11105d8057df45c3210b08b Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Mon, 14 Apr 2025 13:02:40 +0100 Subject: [PATCH 08/23] update templates to add OSS support --- internal/configs/version1/nginx-plus.tmpl | 8 ++++---- internal/configs/version1/nginx.tmpl | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index c637614df0..eefd0a98e5 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -149,18 +149,18 @@ http { {{- if .MainOtelLoadModule}} otel_exporter { endpoint {{ .MainOtelExporterEndpoint}}; - {{ if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{ if .MainOtelExporterTrustedCA}} + {{- if .MainOtelExporterTrustedCA}} # trusted_certificate ; {{- end }} } - {{ if .MainOtelServiceName}} + {{- if .MainOtelServiceName}} otel_service_name {{ .MainOtelServiceName }}; {{- end }} - {{ if .MainOtelGlobalTraceEnabled }} + {{- if .MainOtelGlobalTraceEnabled }} otel_trace on; {{- end}} {{- end}} diff --git a/internal/configs/version1/nginx.tmpl b/internal/configs/version1/nginx.tmpl index 5b290b381d..b54acefa66 100644 --- a/internal/configs/version1/nginx.tmpl +++ b/internal/configs/version1/nginx.tmpl @@ -11,6 +11,10 @@ daemon off; error_log stderr {{.ErrorLogLevel}}; pid /var/lib/nginx/nginx.pid; +{{- if .MainOtelLoadModule}} +load_module modules/ngx_otel_module.so; +{{- end}} + {{- if .MainSnippets}} {{range $value := .MainSnippets}} {{$value}}{{end}} @@ -104,6 +108,25 @@ http { ssl_dhparam {{.SSLDHParam}}; {{- end}} + {{- if .MainOtelLoadModule}} + otel_exporter { + endpoint {{ .MainOtelExporterEndpoint}}; + {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; + {{- end }} + {{- if .MainOtelExporterTrustedCA}} + # trusted_certificate ; + {{- end }} + } + + {{- if .MainOtelServiceName}} + otel_service_name {{ .MainOtelServiceName }}; + {{- end }} + {{- if .MainOtelGlobalTraceEnabled }} + otel_trace on; + {{- end}} + {{- end}} + server { # required to support the Websocket protocol in VirtualServer/VirtualServerRoutes set $default_connection_header ""; From 13fc8fea7e0e7f3f61db5601591be65239fa9818 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Fri, 11 Apr 2025 14:45:29 +0100 Subject: [PATCH 09/23] add otel-module to NIC images Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- build/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 79a6aa32b5..6441863e30 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -21,8 +21,7 @@ FROM golang:1.24-alpine@sha256:ef18ee7117463ac1055f5a370ed18b8750f01589f13ea0b48 ############################################# Base image for Alpine ############################################# FROM nginx:1.27.4-alpine@sha256:4ff102c5d78d254a6f0da062b3cf39eaf07f01eec0927fd21e219d0af8bc0591 AS alpine -RUN apk add --no-cache libcap libstdc++ \ - && printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ +RUN printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ && apk add --no-cache libcap libstdc++ nginx-module-otel \ && sed -i -e '/nginx.org/d' /etc/apk/repositories From 7ea1716a13875c27d9bedea19715f116fa795967 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Fri, 11 Apr 2025 14:45:29 +0100 Subject: [PATCH 10/23] add otel-module to NIC images Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- build/Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 6441863e30..39bd9f5d50 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -14,14 +14,15 @@ ARG PACKAGE_REPO=pkgs.nginx.com FROM ghcr.io/nginx/dependencies/nginx-ubi-ppc64le:nginx-1.27.4@sha256:fff4dde599b89cb22e5cea5d8cfba8c47bcedaa8e6fa549f5fe74a89c733aa2f AS ubi-ppc64le FROM ghcr.io/nginx/alpine-fips:0.2.4-alpine3.19@sha256:2a7f8451110b588b733e4cb8727a48153057b1debac5c78ef8a539ff63712fa1 AS alpine-fips-3.19 FROM ghcr.io/nginx/alpine-fips:0.2.4-alpine3.21@sha256:5221dec2e33436f2586c743c7aa3ef4626c0ec54184dc3364d101036d4f4a060 AS alpine-fips-3.21 -FROM redhat/ubi9-minimal:9.5@sha256:a50731d3397a4ee28583f1699842183d4d24fadcc565c4688487af9ee4e13a44 AS ubi-minimal -FROM golang:1.24-alpine@sha256:ef18ee7117463ac1055f5a370ed18b8750f01589f13ea0b48642f5792b234044 AS golang-builder +FROM redhat/ubi9-minimal:9.5@sha256:e1c4703364c5cb58f5462575dc90345bcd934ddc45e6c32f9c162f2b5617681c AS ubi-minimal +FROM golang:1.24-alpine@sha256:7772cb5322baa875edd74705556d08f0eeca7b9c4b5367754ce3f2f00041ccee AS golang-builder ############################################# Base image for Alpine ############################################# FROM nginx:1.27.4-alpine@sha256:4ff102c5d78d254a6f0da062b3cf39eaf07f01eec0927fd21e219d0af8bc0591 AS alpine -RUN printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ +RUN apk add --no-cache libcap libstdc++ \ + && printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ && apk add --no-cache libcap libstdc++ nginx-module-otel \ && sed -i -e '/nginx.org/d' /etc/apk/repositories @@ -41,6 +42,7 @@ RUN apt-get update \ && apt-get purge --auto-remove -y gnupg2 lsb-release curl \ && rm -rf /var/lib/apt/lists/* /etc/apt/preferences.d/99nginx /etc/apt/sources.list.d/nginx.list + ############################################# NGINX files ############################################# FROM scratch AS nginx-files ARG IC_VERSION @@ -457,7 +459,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode ############################################# Base image for UBI8 with NGINX Plus and App Protect WAF ############################################# -FROM redhat/ubi8@sha256:8bd1b6306f8164de7fb0974031a0f903bd3ab3e6bcab835854d3d9a1a74ea5db AS ubi-8-plus-nap +FROM redhat/ubi8@sha256:244e9858f9d8a2792a3dceb850b4fa8fdbd67babebfde42587bfa919d5d1ecef AS ubi-8-plus-nap ARG NAP_MODULES ARG NGINX_AGENT ARG NGINX_PLUS_VERSION From 1a90b428cd2f68aa222796c73e5a3e5f4f969107 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:15:53 +0100 Subject: [PATCH 11/23] remove unused config map keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/version1/nginx-plus.tmpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index eefd0a98e5..c637614df0 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -149,18 +149,18 @@ http { {{- if .MainOtelLoadModule}} otel_exporter { endpoint {{ .MainOtelExporterEndpoint}}; - {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + {{ if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{- if .MainOtelExporterTrustedCA}} + {{ if .MainOtelExporterTrustedCA}} # trusted_certificate ; {{- end }} } - {{- if .MainOtelServiceName}} + {{ if .MainOtelServiceName}} otel_service_name {{ .MainOtelServiceName }}; {{- end }} - {{- if .MainOtelGlobalTraceEnabled }} + {{ if .MainOtelGlobalTraceEnabled }} otel_trace on; {{- end}} {{- end}} From fc0c97964b974aecf872c1f009fbbcd10819e862 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Mon, 14 Apr 2025 13:02:40 +0100 Subject: [PATCH 12/23] update templates to add OSS support --- internal/configs/version1/nginx-plus.tmpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index c637614df0..eefd0a98e5 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -149,18 +149,18 @@ http { {{- if .MainOtelLoadModule}} otel_exporter { endpoint {{ .MainOtelExporterEndpoint}}; - {{ if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{ if .MainOtelExporterTrustedCA}} + {{- if .MainOtelExporterTrustedCA}} # trusted_certificate ; {{- end }} } - {{ if .MainOtelServiceName}} + {{- if .MainOtelServiceName}} otel_service_name {{ .MainOtelServiceName }}; {{- end }} - {{ if .MainOtelGlobalTraceEnabled }} + {{- if .MainOtelGlobalTraceEnabled }} otel_trace on; {{- end}} {{- end}} From 790e93192367d832832a9711a868cc30db60ad16 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 11 Apr 2025 15:45:45 +0100 Subject: [PATCH 13/23] accept otel configmap keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/configmaps.go | 65 +++++++++++++++++++++++ internal/configs/version1/nginx-plus.tmpl | 16 ++++++ 2 files changed, 81 insertions(+) diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index d509769118..8d05b6b09a 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -578,6 +578,71 @@ func ParseConfigMap(ctx context.Context, cfgm *v1.ConfigMap, nginxPlus bool, has cfgParams.MainOtelLoadModule = true } + if otelExporterEndpoint, exists := cfgm.Data["otel-exporter-endpoint"]; exists { + otelExporterEndpoint = strings.TrimSpace(otelExporterEndpoint) + if otelExporterEndpoint != "" { + cfgParams.MainOtelExporterEndpoint = otelExporterEndpoint + } + } + + if otelExporterTrustedCA, exists := cfgm.Data["otel-exporter-trusted-ca"]; exists { + otelExporterTrustedCA = strings.TrimSpace(otelExporterTrustedCA) + if otelExporterTrustedCA != "" { + cfgParams.MainOtelExporterTrustedCA = otelExporterTrustedCA + } + } + + if otelExporterHeaderName, exists := cfgm.Data["otel-exporter-header-name"]; exists { + otelExporterHeaderName = strings.TrimSpace(otelExporterHeaderName) + if otelExporterHeaderName != "" { + cfgParams.MainOtelExporterHeaderName = otelExporterHeaderName + } + } + + if otelExporterHeaderValue, exists := cfgm.Data["otel-exporter-header-value"]; exists { + otelExporterHeaderValue = strings.TrimSpace(otelExporterHeaderValue) + if otelExporterHeaderValue != "" { + cfgParams.MainOtelExporterHeaderValue = otelExporterHeaderValue + } + } + + if otelServiceName, exists := cfgm.Data["otel-service-name"]; exists { + otelServiceName = strings.TrimSpace(otelServiceName) + if otelServiceName != "" { + cfgParams.MainOtelServiceName = otelServiceName + } + } + + if otelGlobalTraceEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-global-trace-enabled", cfgm); exists { + if err != nil { + nl.Error(l, err) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) + configOk = false + } + cfgParams.MainOtelGlobalTraceEnabled = otelGlobalTraceEnabled + } + + if cfgParams.MainOtelExporterEndpoint != "" { + cfgParams.MainOtelLoadModule = true + } + + if otelEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-enabled", cfgm); exists { + if err != nil { + nl.Error(l, err) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) + configOk = false + } else { + if cfgParams.MainOtelLoadModule { + cfgParams.MainOtelEnabled = otelEnabled + } else { + errorText := fmt.Sprintf("ConfigMap %s/%s: 'otel-enabled' is ignored because 'otel-exporter-endpoint' is not set, ignoring", cfgm.GetNamespace(), cfgm.GetName()) + nl.Error(l, errorText) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, errorText) + configOk = false + } + } + } + if hasAppProtect { if appProtectFailureModeAction, exists := cfgm.Data["app-protect-failure-mode-action"]; exists { if appProtectFailureModeAction == "pass" || appProtectFailureModeAction == "drop" { diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index eefd0a98e5..cc0be3e5c9 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -145,6 +145,22 @@ http { {{- if .SSLDHParam}} ssl_dhparam {{.SSLDHParam}}; {{- end}} + + {{- if .MainOtelEnabled}} + # otel_exporter { + # endpoint {{ .MainOtelExporterEndpoint}}; + # header {{ .MainOtelExporterHeaderName }} {{ .MainOtelExporterHeaderValue }}; + {{ if .MainOtelExporterTrustedCA}} + # trusted_certificate ; + {{- end }} + {{ if .MainOtelServiceName}} + # otel_service_name {{ .MainOtelServiceName }}; + # } + {{- end }} + {{ if .MainOtelGlobalTraceEnabled }} + # otel_trace on; + {{- end}} + {{- end}} {{- if .MainOtelLoadModule}} otel_exporter { From 32633ea132452410a18b7a9d038bb12f251dc264 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Fri, 11 Apr 2025 14:45:29 +0100 Subject: [PATCH 14/23] add otel-module to NIC images Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- build/Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 39bd9f5d50..958b54bfec 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -21,14 +21,13 @@ FROM golang:1.24-alpine@sha256:7772cb5322baa875edd74705556d08f0eeca7b9c4b5367754 ############################################# Base image for Alpine ############################################# FROM nginx:1.27.4-alpine@sha256:4ff102c5d78d254a6f0da062b3cf39eaf07f01eec0927fd21e219d0af8bc0591 AS alpine -RUN apk add --no-cache libcap libstdc++ \ - && printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ +RUN printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release` "/main" >> /etc/apk/repositories \ && apk add --no-cache libcap libstdc++ nginx-module-otel \ && sed -i -e '/nginx.org/d' /etc/apk/repositories ############################################# Base image for Debian ############################################# -FROM nginx:1.27.4@sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab AS debian +FROM nginx:1.27.4@sha256:124b44bfc9ccd1f3cedf4b592d4d1e8bddb78b51ec2ed5056c52d3692baebc19 AS debian RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ From 8d0decdc62779629e68389953297cd03f1d4e4e3 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:15:53 +0100 Subject: [PATCH 15/23] remove unused config map keys Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/configmaps.go | 17 ----------------- internal/configs/version1/nginx-plus.tmpl | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index 8d05b6b09a..f193c00123 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -626,23 +626,6 @@ func ParseConfigMap(ctx context.Context, cfgm *v1.ConfigMap, nginxPlus bool, has cfgParams.MainOtelLoadModule = true } - if otelEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-enabled", cfgm); exists { - if err != nil { - nl.Error(l, err) - eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) - configOk = false - } else { - if cfgParams.MainOtelLoadModule { - cfgParams.MainOtelEnabled = otelEnabled - } else { - errorText := fmt.Sprintf("ConfigMap %s/%s: 'otel-enabled' is ignored because 'otel-exporter-endpoint' is not set, ignoring", cfgm.GetNamespace(), cfgm.GetName()) - nl.Error(l, errorText) - eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, errorText) - configOk = false - } - } - } - if hasAppProtect { if appProtectFailureModeAction, exists := cfgm.Data["app-protect-failure-mode-action"]; exists { if appProtectFailureModeAction == "pass" || appProtectFailureModeAction == "drop" { diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index cc0be3e5c9..ca779514f6 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -145,20 +145,23 @@ http { {{- if .SSLDHParam}} ssl_dhparam {{.SSLDHParam}}; {{- end}} - - {{- if .MainOtelEnabled}} - # otel_exporter { - # endpoint {{ .MainOtelExporterEndpoint}}; - # header {{ .MainOtelExporterHeaderName }} {{ .MainOtelExporterHeaderValue }}; + + {{- if .MainOtelLoadModule}} + otel_exporter { + endpoint {{ .MainOtelExporterEndpoint}}; + {{ if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; + {{- end }} {{ if .MainOtelExporterTrustedCA}} # trusted_certificate ; {{- end }} + } + {{ if .MainOtelServiceName}} - # otel_service_name {{ .MainOtelServiceName }}; - # } + otel_service_name {{ .MainOtelServiceName }}; {{- end }} {{ if .MainOtelGlobalTraceEnabled }} - # otel_trace on; + otel_trace on; {{- end}} {{- end}} From fc7c76472f220ba0ecb37ec8fc50199d297bc358 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Tue, 29 Apr 2025 13:28:57 +0100 Subject: [PATCH 16/23] remove unused otel flag --- internal/configs/config_params.go | 1 - internal/configs/configmaps.go | 1 - 2 files changed, 2 deletions(-) diff --git a/internal/configs/config_params.go b/internal/configs/config_params.go index f4e0e99ec4..5c904ef5e3 100644 --- a/internal/configs/config_params.go +++ b/internal/configs/config_params.go @@ -34,7 +34,6 @@ type ConfigParams struct { MainLogFormat []string MainLogFormatEscaping string MainMainSnippets []string - MainOtelEnabled bool MainOtelLoadModule bool MainOtelGlobalTraceEnabled bool MainOtelExporterEndpoint string diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index f193c00123..fe37f58de1 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -1009,7 +1009,6 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config NginxStatus: staticCfgParams.NginxStatus, NginxStatusAllowCIDRs: staticCfgParams.NginxStatusAllowCIDRs, NginxStatusPort: staticCfgParams.NginxStatusPort, - MainOtelEnabled: config.MainOtelEnabled, MainOtelLoadModule: config.MainOtelLoadModule, MainOtelGlobalTraceEnabled: config.MainOtelGlobalTraceEnabled, MainOtelExporterEndpoint: config.MainOtelExporterEndpoint, From b9e4652b8573e42fe0be11c3017b71d1d6f3ccbb Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Tue, 29 Apr 2025 13:51:51 +0100 Subject: [PATCH 17/23] rename mgmt trusted secret function --- cmd/nginx-ingress/main.go | 4 ++-- internal/configs/version1/config.go | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go index 30f4cfa0cf..4678e1ea97 100644 --- a/cmd/nginx-ingress/main.go +++ b/cmd/nginx-ingress/main.go @@ -166,7 +166,7 @@ func main() { logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) } - if err := processTrustedCertSecret(kubeClient, nginxManager, mgmtCfgParams, controllerNamespace); err != nil { + if err := processMgmtTrustedCertSecret(kubeClient, nginxManager, mgmtCfgParams, controllerNamespace); err != nil { logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) } @@ -371,7 +371,7 @@ func processClientAuthSecret(kubeClient *kubernetes.Clientset, nginxManager ngin return nil } -func processTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, mgmtCfgParams *configs.MGMTConfigParams, controllerNamespace string) error { +func processMgmtTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, mgmtCfgParams *configs.MGMTConfigParams, controllerNamespace string) error { if mgmtCfgParams.Secrets.TrustedCert == "" { return nil } diff --git a/internal/configs/version1/config.go b/internal/configs/version1/config.go index 6ac8647ff9..a42730058a 100644 --- a/internal/configs/version1/config.go +++ b/internal/configs/version1/config.go @@ -240,7 +240,6 @@ type MainConfig struct { NginxStatus bool NginxStatusAllowCIDRs []string NginxStatusPort int - MainOtelEnabled bool MainOtelLoadModule bool MainOtelGlobalTraceEnabled bool MainOtelExporterEndpoint string From 69d2855e4d79179d4fb27d56a647e877c063191e Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Tue, 29 Apr 2025 15:27:39 +0100 Subject: [PATCH 18/23] add CA to Otel exporter on startup --- cmd/nginx-ingress/main.go | 22 ++++++++++++++++++++++ internal/configs/configmaps.go | 2 +- internal/configs/version1/nginx-plus.tmpl | 10 +++++----- internal/configs/version1/nginx.tmpl | 8 ++++---- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go index 4678e1ea97..262647ffc5 100644 --- a/cmd/nginx-ingress/main.go +++ b/cmd/nginx-ingress/main.go @@ -189,6 +189,7 @@ func main() { if err != nil { logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) } + globalConfigurationValidator := createGlobalConfigurationValidator() mustProcessGlobalConfiguration(ctx) @@ -196,6 +197,10 @@ func main() { cfgParams := configs.NewDefaultConfigParams(ctx, *nginxPlus) cfgParams = processConfigMaps(kubeClient, cfgParams, nginxManager, templateExecutor, eventRecorder) + if err := processOtelTrustedCertSecret(kubeClient, nginxManager, cfgParams, controllerNamespace); err != nil { + logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) + } + staticCfgParams := &configs.StaticConfigParams{ DisableIPV6: *disableIPV6, DefaultHTTPListenerPort: *defaultHTTPListenerPort, @@ -392,6 +397,23 @@ func processMgmtTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager return nil } +func processOtelTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, cfgParams *configs.ConfigParams, controllerNamespace string) error { + if cfgParams.MainOtelExporterTrustedCA == "" { + return nil + } + + trustedCertSecretNsName := controllerNamespace + "/" + cfgParams.MainOtelExporterTrustedCA + + secret, err := getAndValidateSecret(kubeClient, trustedCertSecretNsName, secrets.SecretTypeCA) + if err != nil { + return fmt.Errorf("error trying to get the trusted cert secret %v: %w", trustedCertSecretNsName, err) + } + + caBytes, _ := configs.GenerateCAFileContent(secret) + nginxManager.CreateSecret(fmt.Sprintf("%s-%s-%s", controllerNamespace, cfgParams.MainOtelExporterTrustedCA, configs.CACrtKey), caBytes, nginx.ReadWriteOnlyFileMode) + return nil +} + func mustCreateConfigAndKubeClient(ctx context.Context) (*rest.Config, *kubernetes.Clientset) { l := nl.LoggerFromContext(ctx) var config *rest.Config diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index fe37f58de1..4554e828d7 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -1012,7 +1012,7 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config MainOtelLoadModule: config.MainOtelLoadModule, MainOtelGlobalTraceEnabled: config.MainOtelGlobalTraceEnabled, MainOtelExporterEndpoint: config.MainOtelExporterEndpoint, - MainOtelExporterTrustedCA: config.MainOtelExporterTrustedCA, + MainOtelExporterTrustedCA: fmt.Sprintf("%s-%s-%s", os.Getenv("POD_NAMESPACE"), config.MainOtelExporterTrustedCA, CACrtKey), MainOtelExporterHeaderName: config.MainOtelExporterHeaderName, MainOtelExporterHeaderValue: config.MainOtelExporterHeaderValue, MainOtelServiceName: config.MainOtelServiceName, diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index ca779514f6..40f414373b 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -146,14 +146,14 @@ http { ssl_dhparam {{.SSLDHParam}}; {{- end}} - {{- if .MainOtelLoadModule}} + {{- if .MainOtelLoadModule }} otel_exporter { - endpoint {{ .MainOtelExporterEndpoint}}; - {{ if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} + endpoint {{ .MainOtelExporterEndpoint }}; + {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{ if .MainOtelExporterTrustedCA}} - # trusted_certificate ; + {{- if .MainOtelExporterTrustedCA }} + trusted_certificate /etc/nginx/secrets/{{ .MainOtelExporterTrustedCA }}; {{- end }} } diff --git a/internal/configs/version1/nginx.tmpl b/internal/configs/version1/nginx.tmpl index b54acefa66..2d1822c8ee 100644 --- a/internal/configs/version1/nginx.tmpl +++ b/internal/configs/version1/nginx.tmpl @@ -108,14 +108,14 @@ http { ssl_dhparam {{.SSLDHParam}}; {{- end}} - {{- if .MainOtelLoadModule}} + {{- if .MainOtelLoadModule }} otel_exporter { - endpoint {{ .MainOtelExporterEndpoint}}; + endpoint {{ .MainOtelExporterEndpoint }}; {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{- if .MainOtelExporterTrustedCA}} - # trusted_certificate ; + {{- if .MainOtelExporterTrustedCA }} + trusted_certificate /etc/nginx/secrets/{{ .MainOtelExporterTrustedCA }}; {{- end }} } From f9afb47442b1cbca62fe227d10deadd137932c55 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Tue, 29 Apr 2025 17:47:18 +0100 Subject: [PATCH 19/23] add runtime config for Otel CA cert updates --- internal/configs/configmaps.go | 7 +++- internal/configs/configurator.go | 5 ++- internal/k8s/controller.go | 61 +++++++++++++++++++++++++------- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index 4554e828d7..cd63bd4767 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -988,6 +988,11 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config ResolverValid: config.ZoneSync.ResolverValid, } + mainOtelExporterTrustedCA := "" + if config.MainOtelExporterTrustedCA != "" { + mainOtelExporterTrustedCA = fmt.Sprintf("%s-%s-%s", os.Getenv("POD_NAMESPACE"), config.MainOtelExporterTrustedCA, CACrtKey) + } + nginxCfg := &version1.MainConfig{ AccessLog: config.MainAccessLog, DefaultServerAccessLogOff: config.DefaultServerAccessLogOff, @@ -1012,7 +1017,7 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config MainOtelLoadModule: config.MainOtelLoadModule, MainOtelGlobalTraceEnabled: config.MainOtelGlobalTraceEnabled, MainOtelExporterEndpoint: config.MainOtelExporterEndpoint, - MainOtelExporterTrustedCA: fmt.Sprintf("%s-%s-%s", os.Getenv("POD_NAMESPACE"), config.MainOtelExporterTrustedCA, CACrtKey), + MainOtelExporterTrustedCA: mainOtelExporterTrustedCA, MainOtelExporterHeaderName: config.MainOtelExporterHeaderName, MainOtelExporterHeaderValue: config.MainOtelExporterHeaderValue, MainOtelServiceName: config.MainOtelServiceName, diff --git a/internal/configs/configurator.go b/internal/configs/configurator.go index 110ab16d6f..ba370848e8 100644 --- a/internal/configs/configurator.go +++ b/internal/configs/configurator.go @@ -826,8 +826,11 @@ func generateTLSPassthroughHostsConfig(tlsPassthroughPairs map[string]tlsPassthr // AddOrUpdateCASecret writes the secret content to disk returning the files added/updated func (cnf *Configurator) AddOrUpdateCASecret(secret *api_v1.Secret, crtFileName, crlFileName string) string { crtData, crlData := GenerateCAFileContent(secret) + crlFilePath := "" crtFilePath := cnf.nginxManager.CreateSecret(crtFileName, crtData, nginx.ReadWriteOnlyFileMode) - crlFilePath := cnf.nginxManager.CreateSecret(crlFileName, crlData, nginx.ReadWriteOnlyFileMode) + if len(crlData) > 0 { + crlFilePath = cnf.nginxManager.CreateSecret(crlFileName, crlData, nginx.ReadWriteOnlyFileMode) + } return fmt.Sprintf("%s %s", crtFilePath, crlFilePath) } diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index 28a7ff9899..e3077de541 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -102,11 +102,12 @@ type podEndpoint struct { } type specialSecrets struct { - defaultServerSecret string - wildcardTLSSecret string - licenseSecret string - clientAuthSecret string - trustedCertSecret string + defaultServerSecret string + wildcardTLSSecret string + licenseSecret string + clientAuthSecret string + mgmtTrustedCertSecret string + otelTrustedCertSecret string } type controllerMetadata struct { @@ -247,14 +248,19 @@ type NewLoadBalancerControllerInput struct { // NewLoadBalancerController creates a controller func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalancerController { + otelTrustedCertSecret := "" + if input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA != "" { + otelTrustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA) + } specialSecrets := specialSecrets{ - defaultServerSecret: input.DefaultServerSecret, - wildcardTLSSecret: input.WildcardTLSSecret, + defaultServerSecret: input.DefaultServerSecret, + wildcardTLSSecret: input.WildcardTLSSecret, + otelTrustedCertSecret: otelTrustedCertSecret, } if input.IsNginxPlus { specialSecrets.licenseSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.License) specialSecrets.clientAuthSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.ClientAuth) - specialSecrets.trustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.TrustedCert) + specialSecrets.mgmtTrustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.TrustedCert) } lbc := &LoadBalancerController{ client: input.KubeClient, @@ -924,7 +930,7 @@ func (lbc *LoadBalancerController) updateAllConfigs() { if _, hasCRL := secret.Data[configs.CACrlKey]; hasCRL { lbc.configurator.MgmtCfgParams.Secrets.TrustedCRL = secret.Name } - lbc.specialSecrets.trustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) + lbc.specialSecrets.mgmtTrustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) lbc.handleSpecialSecretUpdate(secret, reloadNginx) } // update special ClientAuth secret in mgmtConfigParams @@ -937,6 +943,15 @@ func (lbc *LoadBalancerController) updateAllConfigs() { lbc.handleSpecialSecretUpdate(secret, reloadNginx) } } + // update special Otel CA secret in configParams + if cfgParams.MainOtelExporterTrustedCA != "" { + secret, err := lbc.client.CoreV1().Secrets(lbc.configMap.GetNamespace()).Get(context.TODO(), cfgParams.MainOtelExporterTrustedCA, meta_v1.GetOptions{}) + if err != nil { + nl.Errorf(lbc.Logger, "secret %s/%s: %v", lbc.configMap.GetNamespace(), cfgParams.MainOtelExporterTrustedCA, err) + } + lbc.specialSecrets.otelTrustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) + lbc.handleSpecialSecretUpdate(secret, reloadNginx) + } resources := lbc.configuration.GetResources() nl.Debugf(lbc.Logger, "Updating %v resources", len(resources)) resourceExes := lbc.createExtendedResources(resources) @@ -1843,7 +1858,9 @@ func (lbc *LoadBalancerController) isSpecialSecret(secretName string) bool { return true case lbc.specialSecrets.clientAuthSecret: return true - case lbc.specialSecrets.trustedCertSecret: + case lbc.specialSecrets.mgmtTrustedCertSecret: + return true + case lbc.specialSecrets.otelTrustedCertSecret: return true default: return false @@ -1918,7 +1935,12 @@ func (lbc *LoadBalancerController) handleSpecialSecretUpdate(secret *api_v1.Secr if ok := lbc.performNGINXReload(secret); !ok { return } - case lbc.specialSecrets.trustedCertSecret: + case lbc.specialSecrets.mgmtTrustedCertSecret: + lbc.updateAllConfigs() + if ok := lbc.performNGINXReload(secret); !ok { + return + } + case lbc.specialSecrets.otelTrustedCertSecret: lbc.updateAllConfigs() if ok := lbc.performNGINXReload(secret); !ok { return @@ -1944,7 +1966,12 @@ func (lbc *LoadBalancerController) writeSpecialSecrets(secret *api_v1.Secret, sp return false } case secrets.SecretTypeCA: - lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("mgmt/%s", configs.CACrtKey), fmt.Sprintf("mgmt/%s", configs.CACrlKey)) + if lbc.specialSecrets.mgmtTrustedCertSecret != "" { + lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("mgmt/%s", configs.CACrtKey), fmt.Sprintf("mgmt/%s", configs.CACrlKey)) + } + if lbc.specialSecrets.otelTrustedCertSecret != "" { + lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("%s-%s-%s", lbc.metadata.namespace, lbc.configurator.CfgParams.MainOtelExporterTrustedCA, configs.CACrtKey), "") + } case api_v1.SecretTypeTLS: // if the secret name matches the specified if secretNsName == mgmtClientAuthNamespaceName { @@ -1981,7 +2008,7 @@ func (lbc *LoadBalancerController) specialSecretValidation(secretNsName string, return false } } - if secretNsName == lbc.specialSecrets.trustedCertSecret { + if secretNsName == lbc.specialSecrets.mgmtTrustedCertSecret { err := secrets.ValidateCASecret(secret) if err != nil { nl.Errorf(lbc.Logger, "Couldn't validate the special Secret %v: %v", secretNsName, err) @@ -1997,6 +2024,14 @@ func (lbc *LoadBalancerController) specialSecretValidation(secretNsName string, return false } } + if secretNsName == lbc.specialSecrets.otelTrustedCertSecret { + err := secrets.ValidateCASecret(secret) + if err != nil { + nl.Errorf(lbc.Logger, "Couldn't validate the special Secret %v: %v", secretNsName, err) + lbc.recorder.Eventf(lbc.metadata.pod, api_v1.EventTypeWarning, nl.EventReasonRejected, "the special Secret %v was rejected, using the previous version: %v", secretNsName, err) + return false + } + } return true } From 8c67c43ec30d53482aa2437b45ed646a8f934049 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Tue, 29 Apr 2025 20:12:31 +0100 Subject: [PATCH 20/23] add nil check --- internal/k8s/controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index e3077de541..2ebf145b8e 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -249,7 +249,7 @@ type NewLoadBalancerControllerInput struct { // NewLoadBalancerController creates a controller func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalancerController { otelTrustedCertSecret := "" - if input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA != "" { + if input.NginxConfigurator != nil && input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA != "" { otelTrustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA) } specialSecrets := specialSecrets{ From 1d581b53d37940d4d3ce93aee58b03908450ff59 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Thu, 15 May 2025 15:57:00 +0100 Subject: [PATCH 21/23] Remove cert processing, rename configmap keys, fix tests Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- cmd/nginx-ingress/main.go | 26 +--- internal/configs/config_params.go | 2 +- internal/configs/configmaps.go | 178 ++++++++++------------ internal/configs/configmaps_test.go | 176 +++++++++++++++++++++ internal/configs/configurator.go | 5 +- internal/configs/version1/nginx-plus.tmpl | 22 --- internal/configs/version1/nginx.tmpl | 3 - internal/k8s/controller.go | 61 ++------ 8 files changed, 270 insertions(+), 203 deletions(-) diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go index 262647ffc5..30f4cfa0cf 100644 --- a/cmd/nginx-ingress/main.go +++ b/cmd/nginx-ingress/main.go @@ -166,7 +166,7 @@ func main() { logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) } - if err := processMgmtTrustedCertSecret(kubeClient, nginxManager, mgmtCfgParams, controllerNamespace); err != nil { + if err := processTrustedCertSecret(kubeClient, nginxManager, mgmtCfgParams, controllerNamespace); err != nil { logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) } @@ -189,7 +189,6 @@ func main() { if err != nil { logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) } - globalConfigurationValidator := createGlobalConfigurationValidator() mustProcessGlobalConfiguration(ctx) @@ -197,10 +196,6 @@ func main() { cfgParams := configs.NewDefaultConfigParams(ctx, *nginxPlus) cfgParams = processConfigMaps(kubeClient, cfgParams, nginxManager, templateExecutor, eventRecorder) - if err := processOtelTrustedCertSecret(kubeClient, nginxManager, cfgParams, controllerNamespace); err != nil { - logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err) - } - staticCfgParams := &configs.StaticConfigParams{ DisableIPV6: *disableIPV6, DefaultHTTPListenerPort: *defaultHTTPListenerPort, @@ -376,7 +371,7 @@ func processClientAuthSecret(kubeClient *kubernetes.Clientset, nginxManager ngin return nil } -func processMgmtTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, mgmtCfgParams *configs.MGMTConfigParams, controllerNamespace string) error { +func processTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, mgmtCfgParams *configs.MGMTConfigParams, controllerNamespace string) error { if mgmtCfgParams.Secrets.TrustedCert == "" { return nil } @@ -397,23 +392,6 @@ func processMgmtTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager return nil } -func processOtelTrustedCertSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, cfgParams *configs.ConfigParams, controllerNamespace string) error { - if cfgParams.MainOtelExporterTrustedCA == "" { - return nil - } - - trustedCertSecretNsName := controllerNamespace + "/" + cfgParams.MainOtelExporterTrustedCA - - secret, err := getAndValidateSecret(kubeClient, trustedCertSecretNsName, secrets.SecretTypeCA) - if err != nil { - return fmt.Errorf("error trying to get the trusted cert secret %v: %w", trustedCertSecretNsName, err) - } - - caBytes, _ := configs.GenerateCAFileContent(secret) - nginxManager.CreateSecret(fmt.Sprintf("%s-%s-%s", controllerNamespace, cfgParams.MainOtelExporterTrustedCA, configs.CACrtKey), caBytes, nginx.ReadWriteOnlyFileMode) - return nil -} - func mustCreateConfigAndKubeClient(ctx context.Context) (*rest.Config, *kubernetes.Clientset) { l := nl.LoggerFromContext(ctx) var config *rest.Config diff --git a/internal/configs/config_params.go b/internal/configs/config_params.go index 5c904ef5e3..44f65d3e3a 100644 --- a/internal/configs/config_params.go +++ b/internal/configs/config_params.go @@ -35,7 +35,7 @@ type ConfigParams struct { MainLogFormatEscaping string MainMainSnippets []string MainOtelLoadModule bool - MainOtelGlobalTraceEnabled bool + MainOtelTraceInHTTP bool MainOtelExporterEndpoint string MainOtelExporterTrustedCA string MainOtelExporterHeaderName string diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index cd63bd4767..148f8e9a62 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -530,100 +530,9 @@ func ParseConfigMap(ctx context.Context, cfgm *v1.ConfigMap, nginxPlus bool, has } } - if otelExporterEndpoint, exists := cfgm.Data["otel-exporter-endpoint"]; exists { - otelExporterEndpoint = strings.TrimSpace(otelExporterEndpoint) - if otelExporterEndpoint != "" { - cfgParams.MainOtelExporterEndpoint = otelExporterEndpoint - } - } - - if otelExporterTrustedCA, exists := cfgm.Data["otel-exporter-trusted-ca"]; exists { - otelExporterTrustedCA = strings.TrimSpace(otelExporterTrustedCA) - if otelExporterTrustedCA != "" { - cfgParams.MainOtelExporterTrustedCA = otelExporterTrustedCA - } - } - - if otelExporterHeaderName, exists := cfgm.Data["otel-exporter-header-name"]; exists { - otelExporterHeaderName = strings.TrimSpace(otelExporterHeaderName) - if otelExporterHeaderName != "" { - cfgParams.MainOtelExporterHeaderName = otelExporterHeaderName - } - } - - if otelExporterHeaderValue, exists := cfgm.Data["otel-exporter-header-value"]; exists { - otelExporterHeaderValue = strings.TrimSpace(otelExporterHeaderValue) - if otelExporterHeaderValue != "" { - cfgParams.MainOtelExporterHeaderValue = otelExporterHeaderValue - } - } - - if otelServiceName, exists := cfgm.Data["otel-service-name"]; exists { - otelServiceName = strings.TrimSpace(otelServiceName) - if otelServiceName != "" { - cfgParams.MainOtelServiceName = otelServiceName - } - } - - if otelGlobalTraceEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-global-trace-enabled", cfgm); exists { - if err != nil { - nl.Error(l, err) - eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) - configOk = false - } - cfgParams.MainOtelGlobalTraceEnabled = otelGlobalTraceEnabled - } - - if cfgParams.MainOtelExporterEndpoint != "" { - cfgParams.MainOtelLoadModule = true - } - - if otelExporterEndpoint, exists := cfgm.Data["otel-exporter-endpoint"]; exists { - otelExporterEndpoint = strings.TrimSpace(otelExporterEndpoint) - if otelExporterEndpoint != "" { - cfgParams.MainOtelExporterEndpoint = otelExporterEndpoint - } - } - - if otelExporterTrustedCA, exists := cfgm.Data["otel-exporter-trusted-ca"]; exists { - otelExporterTrustedCA = strings.TrimSpace(otelExporterTrustedCA) - if otelExporterTrustedCA != "" { - cfgParams.MainOtelExporterTrustedCA = otelExporterTrustedCA - } - } - - if otelExporterHeaderName, exists := cfgm.Data["otel-exporter-header-name"]; exists { - otelExporterHeaderName = strings.TrimSpace(otelExporterHeaderName) - if otelExporterHeaderName != "" { - cfgParams.MainOtelExporterHeaderName = otelExporterHeaderName - } - } - - if otelExporterHeaderValue, exists := cfgm.Data["otel-exporter-header-value"]; exists { - otelExporterHeaderValue = strings.TrimSpace(otelExporterHeaderValue) - if otelExporterHeaderValue != "" { - cfgParams.MainOtelExporterHeaderValue = otelExporterHeaderValue - } - } - - if otelServiceName, exists := cfgm.Data["otel-service-name"]; exists { - otelServiceName = strings.TrimSpace(otelServiceName) - if otelServiceName != "" { - cfgParams.MainOtelServiceName = otelServiceName - } - } - - if otelGlobalTraceEnabled, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-global-trace-enabled", cfgm); exists { - if err != nil { - nl.Error(l, err) - eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) - configOk = false - } - cfgParams.MainOtelGlobalTraceEnabled = otelGlobalTraceEnabled - } - - if cfgParams.MainOtelExporterEndpoint != "" { - cfgParams.MainOtelLoadModule = true + _, otelErr := parseConfigMapOpenTelemetry(l, cfgm, cfgParams, eventLog) + if otelErr != nil { + configOk = false } if hasAppProtect { @@ -836,6 +745,79 @@ func parseConfigMapZoneSync(l *slog.Logger, cfgm *v1.ConfigMap, cfgParams *Confi return &cfgParams.ZoneSync, nil } +//nolint:gocyclo +func parseConfigMapOpenTelemetry(l *slog.Logger, cfgm *v1.ConfigMap, cfgParams *ConfigParams, eventLog record.EventRecorder) (*ConfigParams, error) { + if otelExporterEndpoint, exists := cfgm.Data["otel-exporter-endpoint"]; exists { + otelExporterEndpoint = strings.TrimSpace(otelExporterEndpoint) + if otelExporterEndpoint != "" { + cfgParams.MainOtelExporterEndpoint = otelExporterEndpoint + } + } + + if otelExporterHeaderName, exists := cfgm.Data["otel-exporter-header-name"]; exists { + otelExporterHeaderName = strings.TrimSpace(otelExporterHeaderName) + if otelExporterHeaderName != "" { + cfgParams.MainOtelExporterHeaderName = otelExporterHeaderName + } + } + + if otelExporterHeaderValue, exists := cfgm.Data["otel-exporter-header-value"]; exists { + otelExporterHeaderValue = strings.TrimSpace(otelExporterHeaderValue) + if otelExporterHeaderValue != "" { + cfgParams.MainOtelExporterHeaderValue = otelExporterHeaderValue + } + } + + if otelServiceName, exists := cfgm.Data["otel-service-name"]; exists { + otelServiceName = strings.TrimSpace(otelServiceName) + if otelServiceName != "" { + cfgParams.MainOtelServiceName = otelServiceName + } + } + + otelValid := true + + if otelTraceInHTTP, exists, err := GetMapKeyAsBool(cfgm.Data, "otel-trace-in-http", cfgm); exists { + if err != nil { + nl.Error(l, err) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, err.Error()) + otelValid = false + } + cfgParams.MainOtelTraceInHTTP = otelTraceInHTTP + } + + if (cfgParams.MainOtelExporterHeaderName != "" && cfgParams.MainOtelExporterHeaderValue == "") || + (cfgParams.MainOtelExporterHeaderName == "" && cfgParams.MainOtelExporterHeaderValue != "") { + errorText := "Both 'otel-exporter-header-name' and 'otel-exporter-header-value' must be set or neither" + nl.Error(l, errorText) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, errorText) + otelValid = false + } + + if cfgParams.MainOtelExporterEndpoint != "" { + cfgParams.MainOtelLoadModule = true + } + + if cfgParams.MainOtelExporterEndpoint == "" && + (cfgParams.MainOtelExporterTrustedCA != "" || + cfgParams.MainOtelExporterHeaderName != "" || + cfgParams.MainOtelExporterHeaderValue != "" || + cfgParams.MainOtelServiceName != "" || + cfgParams.MainOtelTraceInHTTP) { + errorText := "ConfigMap key 'otel-exporter-endpoint' is required when other otel fields are set" + nl.Error(l, errorText) + eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, errorText) + otelValid = false + cfgParams.MainOtelTraceInHTTP = false + } + + if !otelValid { + return nil, errors.New("invalid OpenTelemetry configuration") + } + + return cfgParams, nil +} + // ParseMGMTConfigMap parses the mgmt block ConfigMap into MGMTConfigParams. // //nolint:gocyclo @@ -988,11 +970,6 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config ResolverValid: config.ZoneSync.ResolverValid, } - mainOtelExporterTrustedCA := "" - if config.MainOtelExporterTrustedCA != "" { - mainOtelExporterTrustedCA = fmt.Sprintf("%s-%s-%s", os.Getenv("POD_NAMESPACE"), config.MainOtelExporterTrustedCA, CACrtKey) - } - nginxCfg := &version1.MainConfig{ AccessLog: config.MainAccessLog, DefaultServerAccessLogOff: config.DefaultServerAccessLogOff, @@ -1015,9 +992,8 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config NginxStatusAllowCIDRs: staticCfgParams.NginxStatusAllowCIDRs, NginxStatusPort: staticCfgParams.NginxStatusPort, MainOtelLoadModule: config.MainOtelLoadModule, - MainOtelGlobalTraceEnabled: config.MainOtelGlobalTraceEnabled, + MainOtelGlobalTraceEnabled: config.MainOtelTraceInHTTP, MainOtelExporterEndpoint: config.MainOtelExporterEndpoint, - MainOtelExporterTrustedCA: mainOtelExporterTrustedCA, MainOtelExporterHeaderName: config.MainOtelExporterHeaderName, MainOtelExporterHeaderValue: config.MainOtelExporterHeaderValue, MainOtelServiceName: config.MainOtelServiceName, diff --git a/internal/configs/configmaps_test.go b/internal/configs/configmaps_test.go index 517c384780..e62e63c431 100644 --- a/internal/configs/configmaps_test.go +++ b/internal/configs/configmaps_test.go @@ -1376,6 +1376,182 @@ func TestParseZoneSyncResolverIPV6MapResolverIPV6(t *testing.T) { }) } } +func TestOpenTelemetryConfigurationSuccess(t *testing.T) { + t.Parallel() + tests := []struct { + configMap *v1.ConfigMap + expectedLoadModule bool + expectedExporterEndpoint string + //expectedExporterTrustedCA string + expectedExporterHeaderName string + expectedExporterHeaderValue string + expectedServiceName string + expectedTraceInHTTP bool + msg string + }{ + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-endpoint": "https://otel-collector:4317", + "otel-service-name": "nginx-ingress-controller", + }, + }, + expectedLoadModule: true, + expectedExporterEndpoint: "https://otel-collector:4317", + expectedExporterHeaderName: "", + expectedExporterHeaderValue: "", + expectedServiceName: "nginx-ingress-controller", + msg: "endpoint set, minimal config", + }, + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-endpoint": "https://otel-collector:4317", + "otel-exporter-trusted-ca": "otel-ca-secret", + "otel-exporter-header-name": "X-Custom-Header", + "otel-exporter-header-value": "custom-value", + "otel-service-name": "nginx-ingress-controller", + "otel-trace-in-http": "true", + }, + }, + expectedLoadModule: true, + expectedExporterEndpoint: "https://otel-collector:4317", + expectedExporterHeaderName: "X-Custom-Header", + expectedExporterHeaderValue: "custom-value", + expectedServiceName: "nginx-ingress-controller", + expectedTraceInHTTP: true, + msg: "endpoint set, full config", + }, + { + configMap: &v1.ConfigMap{ + Data: map[string]string{}, + }, + expectedLoadModule: false, + expectedExporterEndpoint: "", + expectedExporterHeaderName: "", + expectedExporterHeaderValue: "", + expectedServiceName: "", + expectedTraceInHTTP: false, + msg: "no config", + }, + } + + isPlus := true + hasAppProtect := false + hasAppProtectDos := false + hasTLSPassthrough := false + const expectedConfigOk = true + + for _, test := range tests { + t.Run(test.msg, func(t *testing.T) { + result, configOk := ParseConfigMap(context.Background(), test.configMap, isPlus, + hasAppProtect, hasAppProtectDos, hasTLSPassthrough, makeEventLogger()) + if configOk != expectedConfigOk { + t.Errorf("configOk: want %v, got %v", expectedConfigOk, configOk) + } + if result.MainOtelLoadModule != test.expectedLoadModule { + t.Errorf("MainOtelLoadModule: want %v, got %v", test.expectedLoadModule, result.MainOtelLoadModule) + } + if result.MainOtelExporterEndpoint != test.expectedExporterEndpoint { + t.Errorf("MainOtelExporterEndpoint: want %q, got %q", test.expectedExporterEndpoint, result.MainOtelExporterEndpoint) + } + if result.MainOtelExporterHeaderName != test.expectedExporterHeaderName { + t.Errorf("MainOtelExporterHeaderName: want %q, got %q", test.expectedExporterHeaderName, result.MainOtelExporterHeaderName) + } + if result.MainOtelExporterHeaderValue != test.expectedExporterHeaderValue { + t.Errorf("MainOtelExporterHeaderValue: want %q, got %q", test.expectedExporterHeaderValue, result.MainOtelExporterHeaderValue) + } + if result.MainOtelServiceName != test.expectedServiceName { + t.Errorf("MainOtelServiceName: want %q, got %q", test.expectedServiceName, result.MainOtelServiceName) + } + if result.MainOtelTraceInHTTP != test.expectedTraceInHTTP { + t.Errorf("MainOtelTraceInHTTP: want %v, got %v", test.expectedTraceInHTTP, result.MainOtelTraceInHTTP) + } + }) + } +} + +func TestOpenTelemetryConfigurationInvalid(t *testing.T) { + t.Parallel() + tests := []struct { + configMap *v1.ConfigMap + expectedLoadModule bool + msg string + }{ + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-endpoint": " ", + "otel-service-name": "nginx-ingress-controller", + }, + }, + expectedLoadModule: false, + msg: "empty endpoint, service name set", + }, + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-endpoint": "https://otel-collector:4317", + "otel-exporter-header-name": "X-Custom-Header", + "otel-service-name": "nginx-ingress-controller", + }, + }, + expectedLoadModule: true, + msg: "endpoint set, header name only", + }, + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-endpoint": "https://otel-collector:4317", + "otel-exporter-header-value": "custom-value", + "otel-service-name": "nginx-ingress-controller", + }, + }, + expectedLoadModule: true, + msg: "endpoint set, header value only", + }, + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-header-name": "X-Custom-Header", + "otel-exporter-header-value": "custom-value", + }, + }, + expectedLoadModule: false, + msg: "no endpoint, headers set", + }, + { + configMap: &v1.ConfigMap{ + Data: map[string]string{ + "otel-exporter-endpoint": "https://otel-collector:4317", + "otel-service-name": "nginx-ingress-controller", + "otel-trace-in-http": "invalid", + }, + }, + expectedLoadModule: true, + msg: "endpoint set, invalid trace flag", + }, + } + + isPlus := true + hasAppProtect := false + hasAppProtectDos := false + hasTLSPassthrough := false + expectedConfigOk := false + + for _, test := range tests { + t.Run(test.msg, func(t *testing.T) { + result, configOk := ParseConfigMap(context.Background(), test.configMap, isPlus, + hasAppProtect, hasAppProtectDos, hasTLSPassthrough, makeEventLogger()) + if configOk != expectedConfigOk { + t.Errorf("configOk: want %v, got %v", expectedConfigOk, configOk) + } + if result.MainOtelLoadModule != test.expectedLoadModule { + t.Errorf("MainOtelLoadModule: want %v, got %v", test.expectedLoadModule, result.MainOtelLoadModule) + } + }) + } +} func makeEventLogger() record.EventRecorder { return record.NewFakeRecorder(1024) diff --git a/internal/configs/configurator.go b/internal/configs/configurator.go index ba370848e8..110ab16d6f 100644 --- a/internal/configs/configurator.go +++ b/internal/configs/configurator.go @@ -826,11 +826,8 @@ func generateTLSPassthroughHostsConfig(tlsPassthroughPairs map[string]tlsPassthr // AddOrUpdateCASecret writes the secret content to disk returning the files added/updated func (cnf *Configurator) AddOrUpdateCASecret(secret *api_v1.Secret, crtFileName, crlFileName string) string { crtData, crlData := GenerateCAFileContent(secret) - crlFilePath := "" crtFilePath := cnf.nginxManager.CreateSecret(crtFileName, crtData, nginx.ReadWriteOnlyFileMode) - if len(crlData) > 0 { - crlFilePath = cnf.nginxManager.CreateSecret(crlFileName, crlData, nginx.ReadWriteOnlyFileMode) - } + crlFilePath := cnf.nginxManager.CreateSecret(crlFileName, crlData, nginx.ReadWriteOnlyFileMode) return fmt.Sprintf("%s %s", crtFilePath, crlFilePath) } diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index 40f414373b..b9ae81b126 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -152,9 +152,6 @@ http { {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{- if .MainOtelExporterTrustedCA }} - trusted_certificate /etc/nginx/secrets/{{ .MainOtelExporterTrustedCA }}; - {{- end }} } {{ if .MainOtelServiceName}} @@ -165,25 +162,6 @@ http { {{- end}} {{- end}} - {{- if .MainOtelLoadModule}} - otel_exporter { - endpoint {{ .MainOtelExporterEndpoint}}; - {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} - header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; - {{- end }} - {{- if .MainOtelExporterTrustedCA}} - # trusted_certificate ; - {{- end }} - } - - {{- if .MainOtelServiceName}} - otel_service_name {{ .MainOtelServiceName }}; - {{- end }} - {{- if .MainOtelGlobalTraceEnabled }} - otel_trace on; - {{- end}} - {{- end}} - {{ $resolverIPV6HTTPBool := boolToPointerBool .ResolverIPV6 -}} {{ makeResolver .ResolverAddresses .ResolverValid $resolverIPV6HTTPBool }} {{if .ResolverTimeout}}resolver_timeout {{.ResolverTimeout}};{{end}} diff --git a/internal/configs/version1/nginx.tmpl b/internal/configs/version1/nginx.tmpl index 2d1822c8ee..a5f8d7760b 100644 --- a/internal/configs/version1/nginx.tmpl +++ b/internal/configs/version1/nginx.tmpl @@ -114,9 +114,6 @@ http { {{- if and .MainOtelExporterHeaderName .MainOtelExporterHeaderValue }} header {{ .MainOtelExporterHeaderName }} "{{ .MainOtelExporterHeaderValue }}"; {{- end }} - {{- if .MainOtelExporterTrustedCA }} - trusted_certificate /etc/nginx/secrets/{{ .MainOtelExporterTrustedCA }}; - {{- end }} } {{- if .MainOtelServiceName}} diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index 2ebf145b8e..28a7ff9899 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -102,12 +102,11 @@ type podEndpoint struct { } type specialSecrets struct { - defaultServerSecret string - wildcardTLSSecret string - licenseSecret string - clientAuthSecret string - mgmtTrustedCertSecret string - otelTrustedCertSecret string + defaultServerSecret string + wildcardTLSSecret string + licenseSecret string + clientAuthSecret string + trustedCertSecret string } type controllerMetadata struct { @@ -248,19 +247,14 @@ type NewLoadBalancerControllerInput struct { // NewLoadBalancerController creates a controller func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalancerController { - otelTrustedCertSecret := "" - if input.NginxConfigurator != nil && input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA != "" { - otelTrustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.CfgParams.MainOtelExporterTrustedCA) - } specialSecrets := specialSecrets{ - defaultServerSecret: input.DefaultServerSecret, - wildcardTLSSecret: input.WildcardTLSSecret, - otelTrustedCertSecret: otelTrustedCertSecret, + defaultServerSecret: input.DefaultServerSecret, + wildcardTLSSecret: input.WildcardTLSSecret, } if input.IsNginxPlus { specialSecrets.licenseSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.License) specialSecrets.clientAuthSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.ClientAuth) - specialSecrets.mgmtTrustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.TrustedCert) + specialSecrets.trustedCertSecret = fmt.Sprintf("%s/%s", input.ControllerNamespace, input.NginxConfigurator.MgmtCfgParams.Secrets.TrustedCert) } lbc := &LoadBalancerController{ client: input.KubeClient, @@ -930,7 +924,7 @@ func (lbc *LoadBalancerController) updateAllConfigs() { if _, hasCRL := secret.Data[configs.CACrlKey]; hasCRL { lbc.configurator.MgmtCfgParams.Secrets.TrustedCRL = secret.Name } - lbc.specialSecrets.mgmtTrustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) + lbc.specialSecrets.trustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) lbc.handleSpecialSecretUpdate(secret, reloadNginx) } // update special ClientAuth secret in mgmtConfigParams @@ -943,15 +937,6 @@ func (lbc *LoadBalancerController) updateAllConfigs() { lbc.handleSpecialSecretUpdate(secret, reloadNginx) } } - // update special Otel CA secret in configParams - if cfgParams.MainOtelExporterTrustedCA != "" { - secret, err := lbc.client.CoreV1().Secrets(lbc.configMap.GetNamespace()).Get(context.TODO(), cfgParams.MainOtelExporterTrustedCA, meta_v1.GetOptions{}) - if err != nil { - nl.Errorf(lbc.Logger, "secret %s/%s: %v", lbc.configMap.GetNamespace(), cfgParams.MainOtelExporterTrustedCA, err) - } - lbc.specialSecrets.otelTrustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) - lbc.handleSpecialSecretUpdate(secret, reloadNginx) - } resources := lbc.configuration.GetResources() nl.Debugf(lbc.Logger, "Updating %v resources", len(resources)) resourceExes := lbc.createExtendedResources(resources) @@ -1858,9 +1843,7 @@ func (lbc *LoadBalancerController) isSpecialSecret(secretName string) bool { return true case lbc.specialSecrets.clientAuthSecret: return true - case lbc.specialSecrets.mgmtTrustedCertSecret: - return true - case lbc.specialSecrets.otelTrustedCertSecret: + case lbc.specialSecrets.trustedCertSecret: return true default: return false @@ -1935,12 +1918,7 @@ func (lbc *LoadBalancerController) handleSpecialSecretUpdate(secret *api_v1.Secr if ok := lbc.performNGINXReload(secret); !ok { return } - case lbc.specialSecrets.mgmtTrustedCertSecret: - lbc.updateAllConfigs() - if ok := lbc.performNGINXReload(secret); !ok { - return - } - case lbc.specialSecrets.otelTrustedCertSecret: + case lbc.specialSecrets.trustedCertSecret: lbc.updateAllConfigs() if ok := lbc.performNGINXReload(secret); !ok { return @@ -1966,12 +1944,7 @@ func (lbc *LoadBalancerController) writeSpecialSecrets(secret *api_v1.Secret, sp return false } case secrets.SecretTypeCA: - if lbc.specialSecrets.mgmtTrustedCertSecret != "" { - lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("mgmt/%s", configs.CACrtKey), fmt.Sprintf("mgmt/%s", configs.CACrlKey)) - } - if lbc.specialSecrets.otelTrustedCertSecret != "" { - lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("%s-%s-%s", lbc.metadata.namespace, lbc.configurator.CfgParams.MainOtelExporterTrustedCA, configs.CACrtKey), "") - } + lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("mgmt/%s", configs.CACrtKey), fmt.Sprintf("mgmt/%s", configs.CACrlKey)) case api_v1.SecretTypeTLS: // if the secret name matches the specified if secretNsName == mgmtClientAuthNamespaceName { @@ -2008,7 +1981,7 @@ func (lbc *LoadBalancerController) specialSecretValidation(secretNsName string, return false } } - if secretNsName == lbc.specialSecrets.mgmtTrustedCertSecret { + if secretNsName == lbc.specialSecrets.trustedCertSecret { err := secrets.ValidateCASecret(secret) if err != nil { nl.Errorf(lbc.Logger, "Couldn't validate the special Secret %v: %v", secretNsName, err) @@ -2024,14 +1997,6 @@ func (lbc *LoadBalancerController) specialSecretValidation(secretNsName string, return false } } - if secretNsName == lbc.specialSecrets.otelTrustedCertSecret { - err := secrets.ValidateCASecret(secret) - if err != nil { - nl.Errorf(lbc.Logger, "Couldn't validate the special Secret %v: %v", secretNsName, err) - lbc.recorder.Eventf(lbc.metadata.pod, api_v1.EventTypeWarning, nl.EventReasonRejected, "the special Secret %v was rejected, using the previous version: %v", secretNsName, err) - return false - } - } return true } From 1753df346ff35bdb8066ea9deb6118816df3578a Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Thu, 15 May 2025 16:20:12 +0100 Subject: [PATCH 22/23] fix rebase Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- build/Dockerfile | 7 +++---- internal/configs/config_params.go | 1 - internal/configs/configmaps.go | 3 +-- internal/configs/configmaps_test.go | 7 +++---- internal/configs/version1/config.go | 1 - 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 958b54bfec..2e54241801 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -14,8 +14,8 @@ ARG PACKAGE_REPO=pkgs.nginx.com FROM ghcr.io/nginx/dependencies/nginx-ubi-ppc64le:nginx-1.27.4@sha256:fff4dde599b89cb22e5cea5d8cfba8c47bcedaa8e6fa549f5fe74a89c733aa2f AS ubi-ppc64le FROM ghcr.io/nginx/alpine-fips:0.2.4-alpine3.19@sha256:2a7f8451110b588b733e4cb8727a48153057b1debac5c78ef8a539ff63712fa1 AS alpine-fips-3.19 FROM ghcr.io/nginx/alpine-fips:0.2.4-alpine3.21@sha256:5221dec2e33436f2586c743c7aa3ef4626c0ec54184dc3364d101036d4f4a060 AS alpine-fips-3.21 -FROM redhat/ubi9-minimal:9.5@sha256:e1c4703364c5cb58f5462575dc90345bcd934ddc45e6c32f9c162f2b5617681c AS ubi-minimal -FROM golang:1.24-alpine@sha256:7772cb5322baa875edd74705556d08f0eeca7b9c4b5367754ce3f2f00041ccee AS golang-builder +FROM redhat/ubi9-minimal:9.5@sha256:a50731d3397a4ee28583f1699842183d4d24fadcc565c4688487af9ee4e13a44 AS ubi-minimal +FROM golang:1.24-alpine@sha256:ef18ee7117463ac1055f5a370ed18b8750f01589f13ea0b48642f5792b234044 AS golang-builder ############################################# Base image for Alpine ############################################# @@ -27,7 +27,7 @@ RUN printf "%s%s%s\n" "http://nginx.org/packages/mainline/alpine/v" `egrep -o '^ ############################################# Base image for Debian ############################################# -FROM nginx:1.27.4@sha256:124b44bfc9ccd1f3cedf4b592d4d1e8bddb78b51ec2ed5056c52d3692baebc19 AS debian +FROM nginx:1.27.4@sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab AS debian RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ @@ -41,7 +41,6 @@ RUN apt-get update \ && apt-get purge --auto-remove -y gnupg2 lsb-release curl \ && rm -rf /var/lib/apt/lists/* /etc/apt/preferences.d/99nginx /etc/apt/sources.list.d/nginx.list - ############################################# NGINX files ############################################# FROM scratch AS nginx-files ARG IC_VERSION diff --git a/internal/configs/config_params.go b/internal/configs/config_params.go index 44f65d3e3a..c73310056d 100644 --- a/internal/configs/config_params.go +++ b/internal/configs/config_params.go @@ -37,7 +37,6 @@ type ConfigParams struct { MainOtelLoadModule bool MainOtelTraceInHTTP bool MainOtelExporterEndpoint string - MainOtelExporterTrustedCA string MainOtelExporterHeaderName string MainOtelExporterHeaderValue string MainOtelServiceName string diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go index 148f8e9a62..54c7cfc39c 100644 --- a/internal/configs/configmaps.go +++ b/internal/configs/configmaps.go @@ -799,8 +799,7 @@ func parseConfigMapOpenTelemetry(l *slog.Logger, cfgm *v1.ConfigMap, cfgParams * } if cfgParams.MainOtelExporterEndpoint == "" && - (cfgParams.MainOtelExporterTrustedCA != "" || - cfgParams.MainOtelExporterHeaderName != "" || + (cfgParams.MainOtelExporterHeaderName != "" || cfgParams.MainOtelExporterHeaderValue != "" || cfgParams.MainOtelServiceName != "" || cfgParams.MainOtelTraceInHTTP) { diff --git a/internal/configs/configmaps_test.go b/internal/configs/configmaps_test.go index e62e63c431..ddc57d0b13 100644 --- a/internal/configs/configmaps_test.go +++ b/internal/configs/configmaps_test.go @@ -1379,10 +1379,9 @@ func TestParseZoneSyncResolverIPV6MapResolverIPV6(t *testing.T) { func TestOpenTelemetryConfigurationSuccess(t *testing.T) { t.Parallel() tests := []struct { - configMap *v1.ConfigMap - expectedLoadModule bool - expectedExporterEndpoint string - //expectedExporterTrustedCA string + configMap *v1.ConfigMap + expectedLoadModule bool + expectedExporterEndpoint string expectedExporterHeaderName string expectedExporterHeaderValue string expectedServiceName string diff --git a/internal/configs/version1/config.go b/internal/configs/version1/config.go index a42730058a..106470b865 100644 --- a/internal/configs/version1/config.go +++ b/internal/configs/version1/config.go @@ -243,7 +243,6 @@ type MainConfig struct { MainOtelLoadModule bool MainOtelGlobalTraceEnabled bool MainOtelExporterEndpoint string - MainOtelExporterTrustedCA string MainOtelExporterHeaderName string MainOtelExporterHeaderValue string MainOtelServiceName string From d7bce3274550d137ed5464a8eea2541bbd6d84b1 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Thu, 15 May 2025 16:23:43 +0100 Subject: [PATCH 23/23] fix linting Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/configmaps_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/configs/configmaps_test.go b/internal/configs/configmaps_test.go index ddc57d0b13..0d5c46ad80 100644 --- a/internal/configs/configmaps_test.go +++ b/internal/configs/configmaps_test.go @@ -1376,6 +1376,7 @@ func TestParseZoneSyncResolverIPV6MapResolverIPV6(t *testing.T) { }) } } + func TestOpenTelemetryConfigurationSuccess(t *testing.T) { t.Parallel() tests := []struct {