diff --git a/paasta_tools/kubernetes_tools.py b/paasta_tools/kubernetes_tools.py index 1ef5e36097..02c013cc77 100644 --- a/paasta_tools/kubernetes_tools.py +++ b/paasta_tools/kubernetes_tools.py @@ -21,6 +21,7 @@ import re from datetime import datetime from enum import Enum +from functools import lru_cache from inspect import currentframe from pathlib import Path from typing import Any @@ -2552,6 +2553,19 @@ def get_topology_spread_constraints( "topology_spread_constraints", default_pod_topology_spread_constraints ) + def get_projected_sa_volumes(self) -> List[ProjectedSAVolume]: + config_volumes = super().get_projected_sa_volumes() + token_config = ( + load_system_paasta_config().get_service_auth_token_volume_config() + ) + if ( + self.service in get_authenticating_services(self.soa_dir) + and token_config + and not any(volume == token_config for volume in config_volumes) + ): + config_volumes = [token_config, *config_volumes] + return config_volumes + def get_kubernetes_secret_hashes( environment_variables: Mapping[str, str], service: str, namespace: str @@ -4406,3 +4420,11 @@ def get_kubernetes_secret_volumes( ] = secret_contents return secret_volumes + + +@lru_cache() +def get_authenticating_services(soa_dir: str = DEFAULT_SOA_DIR) -> Set[str]: + """Load list of services partecipating in authenticated traffic""" + authenticating_services_conf_path = os.path.join(soa_dir, "authenticating.yaml") + config = service_configuration_lib.read_yaml_file(authenticating_services_conf_path) + return set(config.get("services", [])) diff --git a/paasta_tools/utils.py b/paasta_tools/utils.py index 4e31bb7dbe..88129aee35 100644 --- a/paasta_tools/utils.py +++ b/paasta_tools/utils.py @@ -2017,6 +2017,7 @@ class SystemPaastaConfigDict(TypedDict, total=False): sidecar_requirements_config: Dict[str, KubeContainerResourceRequest] eks_cluster_aliases: Dict[str, str] secret_sync_delay_seconds: float + service_auth_token_settings: ProjectedSAVolume def load_system_paasta_config( @@ -2703,6 +2704,9 @@ def get_spark_kubeconfig(self) -> str: def get_kube_clusters(self) -> Dict: return self.config_dict.get("kube_clusters", {}) + def get_service_auth_token_volume_config(self) -> ProjectedSAVolume: + return self.config_dict.get("service_auth_token_settings", {}) + def _run( command: Union[str, List[str]], diff --git a/tests/test_kubernetes_tools.py b/tests/test_kubernetes_tools.py index 3f9425040e..138fd3f488 100644 --- a/tests/test_kubernetes_tools.py +++ b/tests/test_kubernetes_tools.py @@ -906,6 +906,9 @@ def test_get_kubernetes_containers(self, prometheus_port, expected_ports): "paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_sidecar_containers", autospec=True, return_value=["mock_sidecar"], + ), mock.patch( + "paasta_tools.kubernetes_tools.load_system_paasta_config", + autospec=True, ): if prometheus_port: self.deployment.config_dict["prometheus_port"] = prometheus_port @@ -1611,6 +1614,10 @@ def test_format_kubernetes_app_dict(self, _): in ret.spec.template.metadata.labels.__setitem__.mock_calls ) + @mock.patch( + "paasta_tools.kubernetes_tools.load_system_paasta_config", + autospec=True, + ) @mock.patch( "paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_volumes", autospec=True, @@ -1695,6 +1702,7 @@ def test_get_pod_template_spec( mock_get_pod_volumes, mock_get_kubernetes_containers, mock_get_volumes, + mock_load_system_paasta_config, in_smtstk, routable_ip, pod_topology, @@ -2773,6 +2781,25 @@ def test_get_persistent_volume_name(self): ) assert pv_name == "pv--slash-blahslash-what" + @mock.patch( + "paasta_tools.kubernetes_tools.load_system_paasta_config", autospec=None + ) + @mock.patch( + "paasta_tools.kubernetes_tools.get_authenticating_services", autospec=None + ) + def test_get_projected_sa_volumes_token_automount( + self, mock_get_auth_services, mock_system_config + ): + mock_get_auth_services.return_value = {"service_a", "service_b", "kurupt"} + mock_system_config.return_value.get_service_auth_token_volume_config.return_value = { + "audience": "foo.bar", + "container_path": "/var/secret/something", + } + assert self.deployment.get_projected_sa_volumes() == [ + {"audience": "foo.bar", "container_path": "/var/secret/something"}, + ] + mock_get_auth_services.assert_called_once_with("/nail/blah") + def test_get_kubernetes_services_running_here(): with mock.patch(