|
|
|
@ -21,6 +21,7 @@ import os |
|
|
|
|
# TODO(sergiitk): Remove after #24897 is solved |
|
|
|
|
import grpc |
|
|
|
|
from absl import flags |
|
|
|
|
from google.cloud import secretmanager_v1 |
|
|
|
|
from google.longrunning import operations_pb2 |
|
|
|
|
from google.protobuf import json_format |
|
|
|
|
from google.rpc import code_pb2 |
|
|
|
@ -29,6 +30,11 @@ import googleapiclient.errors |
|
|
|
|
import tenacity |
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
PRIVATE_API_KEY_SECRET_NAME = flags.DEFINE_string( |
|
|
|
|
"private_api_key_secret_name", |
|
|
|
|
default=None, |
|
|
|
|
help="Load Private API access key from the latest version of the secret " |
|
|
|
|
"with the given name, in the format projects/*/secrets/*") |
|
|
|
|
V1_DISCOVERY_URI = flags.DEFINE_string("v1_discovery_uri", |
|
|
|
|
default=discovery.V1_DISCOVERY_URI, |
|
|
|
|
help="Override v1 Discovery URI") |
|
|
|
@ -51,17 +57,43 @@ class GcpApiManager: |
|
|
|
|
v1_discovery_uri=None, |
|
|
|
|
v2_discovery_uri=None, |
|
|
|
|
compute_v1_discovery_file=None, |
|
|
|
|
private_api_key=None): |
|
|
|
|
private_api_key_secret_name=None): |
|
|
|
|
self.v1_discovery_uri = v1_discovery_uri or V1_DISCOVERY_URI.value |
|
|
|
|
self.v2_discovery_uri = v2_discovery_uri or V2_DISCOVERY_URI.value |
|
|
|
|
self.compute_v1_discovery_file = (compute_v1_discovery_file or |
|
|
|
|
COMPUTE_V1_DISCOVERY_FILE.value) |
|
|
|
|
self.private_api_key = private_api_key or os.getenv('PRIVATE_API_KEY') |
|
|
|
|
self.private_api_key_secret_name = (private_api_key_secret_name or |
|
|
|
|
PRIVATE_API_KEY_SECRET_NAME.value) |
|
|
|
|
self._exit_stack = contextlib.ExitStack() |
|
|
|
|
|
|
|
|
|
def close(self): |
|
|
|
|
self._exit_stack.close() |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
@functools.lru_cache(None) |
|
|
|
|
def private_api_key(self): |
|
|
|
|
""" |
|
|
|
|
Private API key. |
|
|
|
|
|
|
|
|
|
Return API key credential that identifies a GCP project allow-listed for |
|
|
|
|
accessing private API discovery documents. |
|
|
|
|
https://pantheon.corp.google.com/apis/credentials |
|
|
|
|
|
|
|
|
|
This method lazy-loads the content of the key from the Secret Manager. |
|
|
|
|
https://pantheon.corp.google.com/security/secret-manager |
|
|
|
|
""" |
|
|
|
|
if not self.private_api_key_secret_name: |
|
|
|
|
raise ValueError('private_api_key_secret_name must be set to ' |
|
|
|
|
'access private_api_key.') |
|
|
|
|
|
|
|
|
|
secrets_api = self.secrets('v1') |
|
|
|
|
version_resource_path = secrets_api.secret_version_path( |
|
|
|
|
**secrets_api.parse_secret_path(self.private_api_key_secret_name), |
|
|
|
|
secret_version='latest') |
|
|
|
|
secret: secretmanager_v1.AccessSecretVersionResponse |
|
|
|
|
secret = secrets_api.access_secret_version(name=version_resource_path) |
|
|
|
|
return secret.payload.data.decode() |
|
|
|
|
|
|
|
|
|
@functools.lru_cache(None) |
|
|
|
|
def compute(self, version): |
|
|
|
|
api_name = 'compute' |
|
|
|
@ -93,6 +125,13 @@ class GcpApiManager: |
|
|
|
|
|
|
|
|
|
raise NotImplementedError(f'Network Services {version} not supported') |
|
|
|
|
|
|
|
|
|
@functools.lru_cache(None) |
|
|
|
|
def secrets(self, version): |
|
|
|
|
if version == 'v1': |
|
|
|
|
return secretmanager_v1.SecretManagerServiceClient() |
|
|
|
|
|
|
|
|
|
raise NotImplementedError(f'Secrets Manager {version} not supported') |
|
|
|
|
|
|
|
|
|
def _build_from_discovery_v1(self, api_name, version): |
|
|
|
|
api = discovery.build(api_name, |
|
|
|
|
version, |
|
|
|
|