You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by po...@apache.org on 2020/06/29 13:21:22 UTC
[airflow] 16/37: Support k8s auth method in Vault Secrets provider
(#8640)
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 <aa...@liquidata.co>
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')