This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new d31f66509df Fix Vault GCP auth for metadata credentials (#68069)
d31f66509df is described below
commit d31f66509df75351a75294f579cd033dcb541b6f
Author: Filip Popić <[email protected]>
AuthorDate: Thu Jun 11 10:54:44 2026 +0200
Fix Vault GCP auth for metadata credentials (#68069)
---
.../hashicorp/_internal_client/vault_client.py | 8 ++--
.../_internal_client/test_vault_client.py | 55 ++++++++++++++++++++++
2 files changed, 60 insertions(+), 3 deletions(-)
diff --git
a/providers/hashicorp/src/airflow/providers/hashicorp/_internal_client/vault_client.py
b/providers/hashicorp/src/airflow/providers/hashicorp/_internal_client/vault_client.py
index f52d08d574b..c5f3e4f8399 100644
---
a/providers/hashicorp/src/airflow/providers/hashicorp/_internal_client/vault_client.py
+++
b/providers/hashicorp/src/airflow/providers/hashicorp/_internal_client/vault_client.py
@@ -349,9 +349,9 @@ class _VaultClient(LoggingMixin):
import time
# Determine service account email
- service_account_email = getattr(credentials, "service_account_email",
None) or getattr(
- credentials, "client_email", None
- )
+ service_account_email = getattr(credentials, "service_account_email",
None)
+ if service_account_email in (None, "default"):
+ service_account_email = getattr(credentials, "client_email", None)
or None
if service_account_email is None:
# Fallback for Compute Engine credentials if email is not yet
populated
@@ -373,6 +373,8 @@ class _VaultClient(LoggingMixin):
f"Could not determine service account email from credentials. "
f"Expected string, got {type(service_account_email).__name__}"
)
+ if service_account_email == "default":
+ raise VaultError("Could not determine service account email from
Compute Engine credentials.")
# Generate a payload for subsequent "signJwt()" call.
# The 'sub' claim must be the service account email.
diff --git
a/providers/hashicorp/tests/unit/hashicorp/_internal_client/test_vault_client.py
b/providers/hashicorp/tests/unit/hashicorp/_internal_client/test_vault_client.py
index 0988062ca1e..7f701128a33 100644
---
a/providers/hashicorp/tests/unit/hashicorp/_internal_client/test_vault_client.py
+++
b/providers/hashicorp/tests/unit/hashicorp/_internal_client/test_vault_client.py
@@ -366,6 +366,61 @@ class TestVaultClient:
client.is_authenticated.assert_called_with()
assert vault_client.kv_engine_version == 2
+
@mock.patch("airflow.providers.google.cloud.utils.credentials_provider._get_scopes")
+
@mock.patch("airflow.providers.google.cloud.utils.credentials_provider.get_credentials_and_project_id")
+
@mock.patch("airflow.providers.hashicorp._internal_client.vault_client.hvac.Client")
+ @mock.patch("googleapiclient.discovery.build")
+ @mock.patch("time.time")
+ def test_gcp_adc_compute_engine_default_email_refresh(
+ self, mock_time, mock_google_build, mock_hvac_client,
mock_get_credentials, mock_get_scopes
+ ):
+ from google.auth import compute_engine
+
+ mock_client = mock.MagicMock()
+ mock_hvac_client.return_value = mock_client
+ mock_get_scopes.return_value = ["scope1", "scope2"]
+
+ mock_credentials = mock.MagicMock(spec=compute_engine.Credentials)
+ mock_credentials.service_account_email = "default"
+
+ def refresh(_request):
+ mock_credentials.service_account_email = "service_account_email"
+
+ mock_credentials.refresh.side_effect = refresh
+ mock_get_credentials.return_value = (mock_credentials, "project_id")
+
+ mock_sign_jwt = (
+
mock_google_build.return_value.projects.return_value.serviceAccounts.return_value.signJwt
+ )
+ mock_sign_jwt.return_value.execute.return_value = {"signedJwt":
"mocked_jwt"}
+
+ mock_time.return_value = 1234567890.0
+ iat = 1234567890
+ exp = iat + 900
+
+ vault_client = _VaultClient(
+ auth_type="gcp",
+ gcp_scopes="scope1,scope2",
+ role_id="role",
+ url="http://localhost:8180",
+ session=None,
+ )
+
+ client = vault_client.client
+
+ mock_credentials.refresh.assert_called_once()
+ args, kwargs = mock_sign_jwt.call_args
+ payload = json.loads(kwargs["body"]["payload"])
+
+ assert kwargs["name"] ==
"projects/project_id/serviceAccounts/service_account_email"
+ assert payload["iat"] == iat
+ assert payload["exp"] == exp
+ assert payload["sub"] == "service_account_email"
+
+ client.auth.gcp.login.assert_called_with(role="role", jwt="mocked_jwt")
+ client.is_authenticated.assert_called_with()
+ assert vault_client.kv_engine_version == 2
+
@mock.patch("airflow.providers.google.cloud.utils.credentials_provider._get_scopes")
@mock.patch("airflow.providers.google.cloud.utils.credentials_provider.get_credentials_and_project_id")
@mock.patch("airflow.providers.hashicorp._internal_client.vault_client.hvac.Client")