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/08/14 15:26:54 UTC

[airflow] branch master updated: Catch Permission Denied exception when getting secret from GCP Secret Manager. (#10326)

This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/master by this push:
     new 47387a6  Catch Permission Denied exception when getting secret from GCP Secret Manager. (#10326)
47387a6 is described below

commit 47387a69e623676b57b6d42ff07e729da2d21bff
Author: mhenc <mh...@google.com>
AuthorDate: Fri Aug 14 17:26:05 2020 +0200

    Catch Permission Denied exception when getting secret from GCP Secret Manager. (#10326)
---
 .../cloud/_internal_client/secret_manager_client.py     |  8 +++++++-
 .../_internal_client/test_secret_manager_client.py      | 17 ++++++++++++++++-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/airflow/providers/google/cloud/_internal_client/secret_manager_client.py b/airflow/providers/google/cloud/_internal_client/secret_manager_client.py
index 36d0891..59714d2 100644
--- a/airflow/providers/google/cloud/_internal_client/secret_manager_client.py
+++ b/airflow/providers/google/cloud/_internal_client/secret_manager_client.py
@@ -20,7 +20,7 @@ from typing import Optional
 
 import google
 from cached_property import cached_property
-from google.api_core.exceptions import NotFound
+from google.api_core.exceptions import NotFound, PermissionDenied
 from google.api_core.gapic_v1.client_info import ClientInfo
 from google.cloud.secretmanager_v1 import SecretManagerServiceClient
 
@@ -92,3 +92,9 @@ class _SecretManagerClient(LoggingMixin):
                 "GCP API Call Error (NotFound): Secret ID %s not found.", secret_id
             )
             return None
+        except PermissionDenied:
+            self.log.error(
+                """GCP API Call Error (PermissionDenied): No access for Secret ID %s.
+                Did you add 'secretmanager.versions.access' permission?""", secret_id
+            )
+            return None
diff --git a/tests/providers/google/cloud/_internal_client/test_secret_manager_client.py b/tests/providers/google/cloud/_internal_client/test_secret_manager_client.py
index c3d977a..cad3d7b 100644
--- a/tests/providers/google/cloud/_internal_client/test_secret_manager_client.py
+++ b/tests/providers/google/cloud/_internal_client/test_secret_manager_client.py
@@ -18,7 +18,7 @@
 
 from unittest import TestCase, mock
 
-from google.api_core.exceptions import NotFound
+from google.api_core.exceptions import NotFound, PermissionDenied
 from google.cloud.secretmanager_v1.types import AccessSecretVersionResponse
 
 from airflow.providers.google.cloud._internal_client.secret_manager_client import _SecretManagerClient  # noqa
@@ -63,6 +63,21 @@ class TestSecretManagerClient(TestCase):
 
     @mock.patch(INTERNAL_CLIENT_MODULE + ".SecretManagerServiceClient")
     @mock.patch(INTERNAL_CLIENT_MODULE + ".ClientInfo")
+    def test_get_no_permissions(self, mock_client_info, mock_secrets_client):
+        mock_client = mock.MagicMock()
+        mock_client_info.return_value = mock.MagicMock()
+        mock_secrets_client.return_value = mock_client
+        mock_client.secret_version_path.return_value = "full-path"
+        # No permissions for requested secret id
+        mock_client.access_secret_version.side_effect = PermissionDenied('test-msg')
+        secrets_client = _SecretManagerClient(credentials="credentials")
+        secret = secrets_client.get_secret(secret_id="missing", project_id="project_id")
+        mock_client.secret_version_path.assert_called_once_with("project_id", 'missing', 'latest')
+        self.assertIsNone(secret)
+        mock_client.access_secret_version.assert_called_once_with('full-path')
+
+    @mock.patch(INTERNAL_CLIENT_MODULE + ".SecretManagerServiceClient")
+    @mock.patch(INTERNAL_CLIENT_MODULE + ".ClientInfo")
     def test_get_existing_key(self, mock_client_info, mock_secrets_client):
         mock_client = mock.MagicMock()
         mock_client_info.return_value = mock.MagicMock()