This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch chart/v1-2x-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/chart/v1-2x-test by this push:
     new 6b92f1535e2 [chart/v1-2x-test] Apply Default Security Context to OTel 
Collector Container (#74268) (#76896)
6b92f1535e2 is described below

commit 6b92f1535e2d8d72157bcc6a0a6e8750560081a8
Author: Deep <[email protected]>
AuthorDate: Thu Nov 12 19:51:52 2026 +0530

    [chart/v1-2x-test] Apply Default Security Context to OTel Collector 
Container (#74268) (#76896)
    
    (cherry picked from commit 73fae2472c721e887e6eebb72a68408bcead024c)
    
    Signed-off-by: Subhadeep Maity 
<[email protected]>
    Co-authored-by: Cursor <[email protected]>
---
 chart/README.md                                     |  1 +
 .../otel-collector/otel-collector-deployment.yaml   |  5 ++++-
 chart/values.schema.json                            |  2 +-
 chart/values.yaml                                   |  2 ++
 .../otel_collector/test_otel_collector.py           | 21 +++++++++++++++++++++
 .../helm_tests/security/test_security_context.py    | 16 ++++++++++++----
 6 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/chart/README.md b/chart/README.md
index 248e0b7a15f..7b39fdd6a7c 100644
--- a/chart/README.md
+++ b/chart/README.md
@@ -52,6 +52,7 @@ cluster using the [Helm](https://helm.sh) package manager.
    * Container-specific Service Account Token Volume configuration 
implementing Principle of Least Privilege
    * Only scheduler containers receive API access; init and sidecar containers 
operate without tokens
    * Defense-in-depth security with both ServiceAccount and Pod-level controls
+   * Default container hardening with security contexts set
    * Compatibility with security policies like Kyverno and compliance 
frameworks
 * Monitoring:
    * StatsD/Prometheus metrics for Airflow
diff --git a/chart/templates/otel-collector/otel-collector-deployment.yaml 
b/chart/templates/otel-collector/otel-collector-deployment.yaml
index 0bea8a53109..a5ad072efbc 100644
--- a/chart/templates/otel-collector/otel-collector-deployment.yaml
+++ b/chart/templates/otel-collector/otel-collector-deployment.yaml
@@ -26,6 +26,7 @@
 {{- $tolerations := or .Values.otelCollector.tolerations .Values.tolerations }}
 {{- $topologySpreadConstraints := or 
.Values.otelCollector.topologySpreadConstraints 
.Values.topologySpreadConstraints }}
 {{- $revisionHistoryLimit := include "airflow.revisionHistoryLimit" (list 
.Values.otelCollector.revisionHistoryLimit .Values.revisionHistoryLimit) }}
+{{- $containerSecurityContext := include "externalContainerSecurityContext" 
(list .Values.otelCollector .Values) }}
 apiVersion: apps/v1
 kind: Deployment
 metadata:
@@ -83,7 +84,9 @@ spec:
         - name: otel-collector
           image: {{ template "otel_collector_image" . }}
           imagePullPolicy: {{ .Values.images.otelCollector.pullPolicy }}
-          securityContext: {{- toYaml 
.Values.otelCollector.securityContexts.container | nindent 12 }}
+          {{- if $containerSecurityContext }}
+          securityContext: {{ $containerSecurityContext | nindent 12 }}
+          {{- end }}
           args: {{- tpl (toYaml .Values.otelCollector.args) . | nindent 12 }}
           ports:
             - name: otlp-grpc
diff --git a/chart/values.schema.json b/chart/values.schema.json
index b0baac49808..d850333b1be 100644
--- a/chart/values.schema.json
+++ b/chart/values.schema.json
@@ -9896,7 +9896,7 @@
                             "x-docsSection": "Kubernetes"
                         },
                         "container": {
-                            "description": "Container security context 
definition for the OTel Collector.",
+                            "description": "Container security context 
definition for the OTel Collector. By default, privilege escalation is disabled 
and all capabilities are dropped unless `securityContexts.disableDefaults` is 
enabled.",
                             "type": "object",
                             "$ref": 
"#/definitions/io.k8s.api.core.v1.SecurityContext",
                             "default": {},
diff --git a/chart/values.yaml b/chart/values.yaml
index 6e0cc035d0b..f1bbcd33b55 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -3767,6 +3767,8 @@ otelCollector:
   labels: {}
   podAnnotations: {}
 
+  # Detailed security contexts for the OTel Collector.
+  # By default, the container disallows privilege escalation and drops all 
capabilities.
   securityContexts:
     pod: {}
     container: {}
diff --git a/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py 
b/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py
index b7d84347fb9..73698d6b54e 100644
--- a/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py
+++ b/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py
@@ -159,6 +159,27 @@ class TestOtelCollectorDeployment:
             "--config=/etc/otel-collector/config.yml"
         ]
 
+    def test_default_container_security_context(self):
+        docs = render_chart(
+            values={"otelCollector": {"tracesEnabled": True}}, 
show_only=[DEPLOYMENT_TEMPLATE]
+        )
+
+        assert 
jmespath.search("spec.template.spec.containers[0].securityContext", docs[0]) == 
{
+            "allowPrivilegeEscalation": False,
+            "capabilities": {"drop": ["ALL"]},
+        }
+
+    def test_container_security_context_disable_defaults(self):
+        docs = render_chart(
+            values={
+                "securityContexts": {"disableDefaults": True},
+                "otelCollector": {"tracesEnabled": True},
+            },
+            show_only=[DEPLOYMENT_TEMPLATE],
+        )
+
+        assert 
jmespath.search("spec.template.spec.containers[0].securityContext", docs[0]) is 
None
+
     def test_args_override(self):
         custom = ["--config=/etc/otel-collector/config.yml", 
"--feature-gates=+foo"]
         docs = render_chart(
diff --git a/helm-tests/tests/helm_tests/security/test_security_context.py 
b/helm-tests/tests/helm_tests/security/test_security_context.py
index b8fc29cb0dd..8574c7a70d5 100644
--- a/helm-tests/tests/helm_tests/security/test_security_context.py
+++ b/helm-tests/tests/helm_tests/security/test_security_context.py
@@ -383,6 +383,7 @@ class TestSecurityContext:
                 "executor": "CeleryExecutor,KubernetesExecutor",
                 "cleanup": {"enabled": True},
                 "flower": {"enabled": True},
+                "otelCollector": {"tracesEnabled": True},
                 "pgbouncer": {"enabled": True},
             },
             show_only=[
@@ -394,6 +395,7 @@ class TestSecurityContext:
                 "templates/jobs/create-user-job.yaml",
                 "templates/jobs/migrate-database-job.yaml",
                 "templates/triggerer/triggerer-deployment.yaml",
+                "templates/otel-collector/otel-collector-deployment.yaml",
                 "templates/pgbouncer/pgbouncer-deployment.yaml",
                 "templates/statsd/statsd-deployment.yaml",
                 "templates/redis/redis-statefulset.yaml",
@@ -407,18 +409,19 @@ class TestSecurityContext:
             "spec.jobTemplate.spec.template.spec.securityContext", docs[0]
         )
 
-        for doc in docs[1:-3]:
+        for doc in docs[1:-4]:
             assert ctx_value_container == jmespath.search(
                 "spec.template.spec.containers[0].securityContext", doc
             )
             assert ctx_value_pod == 
jmespath.search("spec.template.spec.securityContext", doc)
 
-        # Global security context is not propagated to pgbouncer, redis and 
statsd, so we test default value
+        # Global security context is not propagated to otel collector, 
pgbouncer, redis and statsd,
+        # so we test default value
         default_ctx_value_container = {"allowPrivilegeEscalation": False, 
"capabilities": {"drop": ["ALL"]}}
         default_ctx_value_pod_pgbouncer = {"runAsUser": 65534}
         default_ctx_value_pod_statsd = {"runAsUser": 65534}
         default_ctx_value_pod_redis = {"runAsUser": 0}
-        for doc in docs[-3:]:
+        for doc in docs[-4:]:
             assert default_ctx_value_container == jmespath.search(
                 "spec.template.spec.containers[0].securityContext", doc
             )
@@ -523,6 +526,7 @@ class TestSecurityContext:
                 "apiServer": security_context,
                 "workers": workers_values,
                 "flower": {"enabled": True, **security_context},
+                "otelCollector": {"tracesEnabled": True, **security_context},
                 "statsd": security_context,
                 "createUserJob": security_context,
                 "migrateDatabaseJob": security_context,
@@ -537,6 +541,7 @@ class TestSecurityContext:
                 "templates/api-server/api-server-deployment.yaml",
                 "templates/dag-processor/dag-processor-deployment.yaml",
                 "templates/workers/worker-deployment.yaml",
+                "templates/otel-collector/otel-collector-deployment.yaml",
                 "templates/statsd/statsd-deployment.yaml",
                 "templates/jobs/create-user-job.yaml",
                 "templates/jobs/migrate-database-job.yaml",
@@ -1108,6 +1113,7 @@ class TestSecurityContext:
             values={
                 "securityContexts": {"disableDefaults": True},
                 "flower": {"enabled": True},
+                "otelCollector": {"tracesEnabled": True},
                 "pgbouncer": {"enabled": True},
                 "statsd": {"enabled": True},
             },
@@ -1123,10 +1129,12 @@ class TestSecurityContext:
                 "templates/pgbouncer/pgbouncer-deployment.yaml",
                 "templates/statsd/statsd-deployment.yaml",
                 "templates/redis/redis-statefulset.yaml",
+                "templates/otel-collector/otel-collector-deployment.yaml",
             ],
         )
 
-        assert all(v is None for v in 
jmespath.search("[].spec.template.spec.securityContext", docs))
+        assert all(v is None for v in 
jmespath.search("[].spec.template.spec.securityContext", docs[:-1]))
+        assert jmespath.search("spec.template.spec.securityContext", docs[-1]) 
== {}
         assert all(
             v is None for v in 
jmespath.search("[].spec.template.spec.containers[0].securityContext", docs)
         )

Reply via email to