Skip to content

Commit 31cc5dc

Browse files
dan-osterrathTempestShaw
authored andcommitted
Add support for disabling SA token automount for Scheduler (apache#59156)
* Add support for manual mounting of Service Account tokens in Scheduler when using Pod launching executors (apache#59099) * fix bug in helper function for determining if executor is Pod launching (apache#59099) * Remove emojis in production guide (apache#59099) * Auto formatting by prek and some manual cleanup (apache#59099) * Removed the detailed security enhancements from the main documentation page and created newsfragment 59156.significant.rst to properly document these changes in the changelog as suggested. (apache#59099) * Reduced redundancy by removing detailed examples and linking to the dedicated service-account-token-examples.rst document for comprehensive configuration examples and use cases. (apache#59099) * Add support for manual mounting of Service Account tokens in Scheduler when using Pod launching executors (apache#59099) * fix bug in helper function for determining if executor is Pod launching (apache#59099) * Remove emojis in production guide (apache#59099) * Auto formatting by prek and some manual cleanup (apache#59099) * Removed the detailed security enhancements from the main documentation page and created newsfragment 59156.significant.rst to properly document these changes in the changelog as suggested. (apache#59099) * Reduced redundancy by removing detailed examples and linking to the dedicated service-account-token-examples.rst document for comprehensive configuration examples and use cases. (apache#59099) * Fix title underlines in SA token examples RST file. (apache#59099) * Fix spell checks and removed wrong Helm values schema spec for Worker. (apache#59099) * Minor fix in descriptions. (apache#59099) --------- Co-authored-by: Dan Osterrath <9108541+dan-osterrath@users.noreply.github.com>
1 parent cbb3ab9 commit 31cc5dc

13 files changed

Lines changed: 1354 additions & 19 deletions

File tree

chart/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ cluster using the [Helm](https://helm.sh) package manager.
4747
* Supported database backend: ``PostgreSQL``, ``MySQL``
4848
* Autoscaling for ``CeleryExecutor`` provided by KEDA
4949
* ``PostgreSQL`` and ``PgBouncer`` with a battle-tested configuration
50+
* **Security enhancements**:
51+
* Container-specific Service Account Token Volume configuration implementing Principle of Least Privilege
52+
* Only scheduler containers receive API access; init and sidecar containers operate without tokens
53+
* Defense-in-depth security with both ServiceAccount and Pod-level controls
54+
* Compatibility with security policies like Kyverno and compliance frameworks
5055
* Monitoring:
5156
* StatsD/Prometheus metrics for Airflow
5257
* Prometheus metrics for PgBouncer

chart/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Helm Chart for Apache Airflow
4444
:caption: Guides
4545

4646
production-guide
47+
service-account-token-examples
4748

4849
.. toctree::
4950
:hidden:

chart/docs/production-guide.rst

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,3 +703,174 @@ this behavior is deprecated in favor of explicitly defining ``.Values.imagePullS
703703

704704
You can read more about advanced ways of setting configuration variables in the
705705
:doc:`apache-airflow:howto/set-config`.
706+
707+
Service Account Token Volume Configuration
708+
------------------------------------------
709+
710+
When using pod-launching executors (``CeleryExecutor``, ``CeleryKubernetesExecutor``, ``KubernetesExecutor``, ``LocalKubernetesExecutor``),
711+
you can configure how Kubernetes service account tokens are mounted into pods. This provides enhanced security control
712+
and compatibility with security policies like Kyverno.
713+
714+
Background
715+
^^^^^^^^^^
716+
717+
By default, Kubernetes automatically mounts service account tokens into pods via the ``automountServiceAccountToken`` setting.
718+
However, for security reasons, you might want to disable automatic mounting and manually configure service account token volumes instead.
719+
720+
This feature addresses Bug #59099 where ``scheduler.serviceAccount.automountServiceAccountToken: false`` was ignored
721+
when using the KubernetesExecutor. The solution implements a defense-in-depth approach with both ServiceAccount-level
722+
and Pod-level controls.
723+
724+
Container-Specific Security
725+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
726+
727+
The Service Account Token Volume is mounted **only** in containers that require Kubernetes API access, implementing the
728+
**Principle of Least Privilege**:
729+
730+
* **Scheduler Container**: Receives Service Account Token (needs API access for pod management)
731+
* **Init Container "wait-for-airflow-migrations"**: No Service Account Token (only performs database migrations)
732+
* **Sidecar Container "scheduler-log-groomer"**: No Service Account Token (only performs log cleanup operations)
733+
734+
This container-specific approach ensures that:
735+
736+
- **Database Migration Container**: Only accesses the database for schema updates, no Kubernetes API access required
737+
- **Log Groomer Container**: Only performs filesystem operations for log cleanup, no API access required
738+
- **Scheduler Container**: Requires API access for launching and managing pods with pod-launching executors
739+
740+
**Security Benefits:**
741+
742+
* **Reduced Attack Surface**: Containers without API access cannot interact with the Kubernetes API even if compromised
743+
* **Compliance**: Meets security policy requirements that mandate minimal privilege assignment
744+
* **Audit Trail**: Clear separation of which containers have API access for security auditing
745+
* **Defense-in-Depth**: Multiple layers of security controls at both ServiceAccount and container levels
746+
747+
Configuration Options
748+
^^^^^^^^^^^^^^^^^^^^^
749+
750+
The service account token volume configuration is available for the scheduler component and includes the following options:
751+
752+
.. code-block:: yaml
753+
754+
scheduler:
755+
serviceAccount:
756+
automountServiceAccountToken: false # Disable automatic token mounting
757+
serviceAccountTokenVolume:
758+
enabled: true # Enable manual token volume
759+
mountPath: /var/run/secrets/kubernetes.io/serviceaccount # Mount path for the token
760+
volumeName: kube-api-access # Name of the projected volume
761+
expirationSeconds: 3600 # Token expiration time in seconds
762+
audience: ~ # Token audience (optional)
763+
764+
Security Implications
765+
^^^^^^^^^^^^^^^^^^^^^
766+
767+
**When to use manual token volumes:**
768+
769+
* When security policies require explicit control over service account token mounting
770+
* When using security policy engines like Kyverno that restrict automatic token mounting
771+
* When implementing defense-in-depth security strategies
772+
* When you need custom token expiration times or audiences
773+
* When compliance frameworks mandate container-specific privilege assignment
774+
775+
**Security benefits:**
776+
777+
* **Explicit control**: Manual configuration makes token mounting intentional and visible
778+
* **Policy compliance**: Compatible with security policies that restrict ``automountServiceAccountToken: true``
779+
* **Defense-in-depth**: Provides both ServiceAccount-level and Pod-level security controls
780+
* **Custom expiration**: Allows setting shorter token lifetimes for enhanced security
781+
* **Container isolation**: Only scheduler container receives API access, reducing attack surface
782+
* **Principle of Least Privilege**: Each container receives only the minimum required permissions
783+
784+
**Why Init and Sidecar Containers Don't Need API Access:**
785+
786+
* **Init Container (wait-for-airflow-migrations)**:
787+
788+
- **Purpose**: Performs database schema migrations using ``airflow db migrate``
789+
- **Required Access**: Database connection only
790+
- **Security Rationale**: Database operations don't require Kubernetes API interaction
791+
792+
* **Sidecar Container (scheduler-log-groomer)**:
793+
794+
- **Purpose**: Cleans up old log files from the filesystem
795+
- **Required Access**: Local filesystem access only
796+
- **Security Rationale**: Log cleanup is purely filesystem-based, no API calls needed
797+
798+
* **Scheduler Container**:
799+
800+
- **Purpose**: Manages DAG scheduling and launches task pods
801+
- **Required Access**: Kubernetes API for pod creation, monitoring, and cleanup
802+
- **Security Rationale**: Pod-launching executors require API access for container orchestration
803+
804+
Use Cases and Examples
805+
^^^^^^^^^^^^^^^^^^^^^^
806+
807+
For comprehensive configuration examples, security scenarios, and detailed use cases,
808+
see :doc:`service-account-token-examples`.
809+
810+
Supported Executors
811+
^^^^^^^^^^^^^^^^^^^
812+
813+
The service account token volume configuration is only effective for pod-launching executors:
814+
815+
* ``CeleryExecutor`` - When launching Celery worker pods
816+
* ``CeleryKubernetesExecutor`` - For both Celery workers and Kubernetes task pods
817+
* ``KubernetesExecutor`` - When launching task pods in Kubernetes
818+
* ``LocalKubernetesExecutor`` - For Kubernetes task pods in local mode
819+
820+
For other executors (``LocalExecutor``, ``SequentialExecutor``), this configuration has no effect
821+
as they don't launch additional pods.
822+
823+
Migration from Automatic to Manual Token Mounting
824+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
825+
826+
To migrate from automatic to manual token mounting:
827+
828+
1. **Test the configuration** in a non-production environment first
829+
2. **Update your values.yaml**:
830+
831+
.. code-block:: yaml
832+
833+
scheduler:
834+
serviceAccount:
835+
automountServiceAccountToken: false # Disable automatic mounting
836+
serviceAccountTokenVolume:
837+
enabled: true # Enable manual mounting
838+
839+
3. **Deploy the changes** using Helm upgrade
840+
4. **Verify** that the scheduler can still launch pods successfully
841+
5. **Monitor** for any authentication issues in the logs
842+
843+
Troubleshooting
844+
^^^^^^^^^^^^^^^
845+
846+
**Common Issues:**
847+
848+
* **Authentication failures**: Ensure ``serviceAccountTokenVolume.enabled`` is set to ``true`` when ``automountServiceAccountToken`` is ``false``
849+
* **Permission denied**: Verify that the service account has the necessary RBAC permissions
850+
* **Token expiration**: Check if ``expirationSeconds`` is too short for your workload patterns
851+
852+
**Debugging:**
853+
854+
Check the scheduler logs for authentication-related errors:
855+
856+
.. code-block:: bash
857+
858+
kubectl logs deployment/airflow-scheduler -n <namespace>
859+
860+
Verify the projected volume is mounted correctly:
861+
862+
.. code-block:: bash
863+
864+
kubectl describe pod <scheduler-pod-name> -n <namespace>
865+
866+
Backward Compatibility
867+
^^^^^^^^^^^^^^^^^^^^^^
868+
869+
This feature maintains full backward compatibility:
870+
871+
* Existing deployments with ``automountServiceAccountToken: true`` (default) continue to work unchanged
872+
* The ``serviceAccountTokenVolume`` configuration is only applied when explicitly enabled
873+
* Default values ensure no breaking changes for existing installations
874+
875+
For more information about Kubernetes service account tokens and projected volumes, see the
876+
`Kubernetes documentation on service account tokens <https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection>`_.

0 commit comments

Comments
 (0)