This is an automated email from the ASF dual-hosted git repository. potiuk pushed a commit to branch v1-10-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 05d033b5b53f2e1e48ab95941213e38d0dc5fcea Author: Aaron Son <[email protected]> AuthorDate: Sun May 3 16:10:25 2020 -0700 Support k8s auth method in Vault Secrets provider (#8640) (cherry picked from commit d8cb0b5ddb02d194742e374d9ac90dd8231f6e80) --- airflow/contrib/secrets/hashicorp_vault.py | 17 ++++++++++++++++- tests/contrib/secrets/test_hashicorp_vault.py | 27 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/airflow/contrib/secrets/hashicorp_vault.py b/airflow/contrib/secrets/hashicorp_vault.py index 8713733..8f6b53c 100644 --- a/airflow/contrib/secrets/hashicorp_vault.py +++ b/airflow/contrib/secrets/hashicorp_vault.py @@ -58,7 +58,7 @@ class VaultBackend(BaseSecretsBackend, LoggingMixin): :param url: Base URL for the Vault instance being addressed. :type url: str :param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 'userpass', 'approle', - 'github', 'gcp). Default is ``token``. + 'github', 'gcp', 'kubernetes'). Default is ``token``. :type auth_type: str :param mount_point: The "path" the secret engine was mounted on. (Default: ``secret``) :type mount_point: str @@ -73,6 +73,11 @@ class VaultBackend(BaseSecretsBackend, LoggingMixin): :type password: str :param role_id: Role ID for Authentication (for ``approle`` auth_type) :type role_id: str + :param kubernetes_role: Role for Authentication (for ``kubernetes`` auth_type) + :type kubernetes_role: str + :param kubernetes_jwt_path: Path for kubernetes jwt token (for ``kubernetes`` auth_type, deafult: + ``/var/run/secrets/kubernetes.io/serviceaccount/token``) + :type kubernetes_jwt_path: str :param secret_id: Secret ID for Authentication (for ``approle`` auth_type) :type secret_id: str :param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` auth_type) @@ -92,6 +97,8 @@ class VaultBackend(BaseSecretsBackend, LoggingMixin): username=None, # type: Optional[str] password=None, # type: Optional[str] role_id=None, # type: Optional[str] + kubernetes_role=None, # type: Optional[str] + kubernetes_jwt_path='/var/run/secrets/kubernetes.io/serviceaccount/token', # type: str secret_id=None, # type: Optional[str] gcp_key_path=None, # type: Optional[str] gcp_scopes=None, # type: Optional[str] @@ -107,6 +114,8 @@ class VaultBackend(BaseSecretsBackend, LoggingMixin): self.username = username self.password = password self.role_id = role_id + self.kubernetes_role = kubernetes_role + self.kubernetes_jwt_path = kubernetes_jwt_path self.secret_id = secret_id self.mount_point = mount_point self.kv_engine_version = kv_engine_version @@ -132,6 +141,12 @@ class VaultBackend(BaseSecretsBackend, LoggingMixin): _client.auth_userpass(username=self.username, password=self.password) elif self.auth_type == "approle": _client.auth_approle(role_id=self.role_id, secret_id=self.secret_id) + elif self.auth_type == "kubernetes": + if not self.kubernetes_role: + raise VaultError("kubernetes_role cannot be None for auth_type='kubernetes'") + with open(self.kubernetes_jwt_path) as f: + jwt = f.read() + _client.auth_kubernetes(role=self.kubernetes_role, jwt=jwt) elif self.auth_type == "github": _client.auth.github.login(token=self.token) elif self.auth_type == "gcp": diff --git a/tests/contrib/secrets/test_hashicorp_vault.py b/tests/contrib/secrets/test_hashicorp_vault.py index 0d52c3a..f027ad7 100644 --- a/tests/contrib/secrets/test_hashicorp_vault.py +++ b/tests/contrib/secrets/test_hashicorp_vault.py @@ -234,3 +234,30 @@ class TestVaultSecrets(TestCase): with six.assertRaisesRegex(self, VaultError, "token cannot be None for auth_type='token'"): VaultBackend(**kwargs).get_connections(conn_id='test') + + def test_auth_type_kubernetes_without_role_raises_error(self): + kwargs = { + "auth_type": "kubernetes", + "url": "http://127.0.0.1:8200", + } + + with six.assertRaisesRegex(self, VaultError, + "kubernetes_role cannot be None for auth_type='kubernetes'"): + VaultBackend(**kwargs).get_connections(conn_id='test') + + def test_auth_type_kubernetes_with_unreadable_jwt_raises_error(self): + path = "/var/tmp/this_does_not_exist/334e918ef11987d3ef2f9553458ea09f" + kwargs = { + "auth_type": "kubernetes", + "kubernetes_role": "default", + "kubernetes_jwt_path": path, + "url": "http://127.0.0.1:8200", + } + + if six.PY2: + error_ = IOError + else: + error_ = FileNotFoundError + + with six.assertRaisesRegex(self, error_, path): + VaultBackend(**kwargs).get_connections(conn_id='test')
