OLD | NEW |
(Empty) | |
| 1 # Copyright 2015 Google Inc. |
| 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at |
| 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 # See the License for the specific language governing permissions and |
| 13 # limitations under the License. |
| 14 |
| 15 """Helpers for reading the Google Cloud SDK's configuration.""" |
| 16 |
| 17 import json |
| 18 import os |
| 19 import subprocess |
| 20 |
| 21 import six |
| 22 |
| 23 from google.auth import environment_vars |
| 24 import google.oauth2.credentials |
| 25 |
| 26 # The Google OAuth 2.0 token endpoint. Used for authorized user credentials. |
| 27 _GOOGLE_OAUTH2_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token' |
| 28 |
| 29 # The ~/.config subdirectory containing gcloud credentials. |
| 30 _CONFIG_DIRECTORY = 'gcloud' |
| 31 # Windows systems store config at %APPDATA%\gcloud |
| 32 _WINDOWS_CONFIG_ROOT_ENV_VAR = 'APPDATA' |
| 33 # The name of the file in the Cloud SDK config that contains default |
| 34 # credentials. |
| 35 _CREDENTIALS_FILENAME = 'application_default_credentials.json' |
| 36 # The command to get the Cloud SDK configuration |
| 37 _CLOUD_SDK_CONFIG_COMMAND = ( |
| 38 'gcloud', 'config', 'config-helper', '--format', 'json') |
| 39 |
| 40 |
| 41 def get_config_path(): |
| 42 """Returns the absolute path the the Cloud SDK's configuration directory. |
| 43 |
| 44 Returns: |
| 45 str: The Cloud SDK config path. |
| 46 """ |
| 47 # If the path is explicitly set, return that. |
| 48 try: |
| 49 return os.environ[environment_vars.CLOUD_SDK_CONFIG_DIR] |
| 50 except KeyError: |
| 51 pass |
| 52 |
| 53 # Non-windows systems store this at ~/.config/gcloud |
| 54 if os.name != 'nt': |
| 55 return os.path.join( |
| 56 os.path.expanduser('~'), '.config', _CONFIG_DIRECTORY) |
| 57 # Windows systems store config at %APPDATA%\gcloud |
| 58 else: |
| 59 try: |
| 60 return os.path.join( |
| 61 os.environ[_WINDOWS_CONFIG_ROOT_ENV_VAR], |
| 62 _CONFIG_DIRECTORY) |
| 63 except KeyError: |
| 64 # This should never happen unless someone is really |
| 65 # messing with things, but we'll cover the case anyway. |
| 66 drive = os.environ.get('SystemDrive', 'C:') |
| 67 return os.path.join( |
| 68 drive, '\\', _CONFIG_DIRECTORY) |
| 69 |
| 70 |
| 71 def get_application_default_credentials_path(): |
| 72 """Gets the path to the application default credentials file. |
| 73 |
| 74 The path may or may not exist. |
| 75 |
| 76 Returns: |
| 77 str: The full path to application default credentials. |
| 78 """ |
| 79 config_path = get_config_path() |
| 80 return os.path.join(config_path, _CREDENTIALS_FILENAME) |
| 81 |
| 82 |
| 83 def load_authorized_user_credentials(info): |
| 84 """Loads an authorized user credential. |
| 85 |
| 86 Args: |
| 87 info (Mapping[str, str]): The loaded file's data. |
| 88 |
| 89 Returns: |
| 90 google.oauth2.credentials.Credentials: The constructed credentials. |
| 91 |
| 92 Raises: |
| 93 ValueError: if the info is in the wrong format or missing data. |
| 94 """ |
| 95 keys_needed = set(('refresh_token', 'client_id', 'client_secret')) |
| 96 missing = keys_needed.difference(six.iterkeys(info)) |
| 97 |
| 98 if missing: |
| 99 raise ValueError( |
| 100 'Authorized user info was not in the expected format, missing ' |
| 101 'fields {}.'.format(', '.join(missing))) |
| 102 |
| 103 return google.oauth2.credentials.Credentials( |
| 104 None, # No access token, must be refreshed. |
| 105 refresh_token=info['refresh_token'], |
| 106 token_uri=_GOOGLE_OAUTH2_TOKEN_ENDPOINT, |
| 107 client_id=info['client_id'], |
| 108 client_secret=info['client_secret']) |
| 109 |
| 110 |
| 111 def get_project_id(): |
| 112 """Gets the project ID from the Cloud SDK. |
| 113 |
| 114 Returns: |
| 115 Optional[str]: The project ID. |
| 116 """ |
| 117 |
| 118 try: |
| 119 output = subprocess.check_output( |
| 120 _CLOUD_SDK_CONFIG_COMMAND, |
| 121 stderr=subprocess.STDOUT) |
| 122 except (subprocess.CalledProcessError, OSError, IOError): |
| 123 return None |
| 124 |
| 125 try: |
| 126 configuration = json.loads(output.decode('utf-8')) |
| 127 except ValueError: |
| 128 return None |
| 129 |
| 130 try: |
| 131 return configuration['configuration']['properties']['core']['project'] |
| 132 except KeyError: |
| 133 return None |
OLD | NEW |