| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2014 Google Inc. All Rights Reserved. |
| 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 """Helper routines to facilitate use of oauth2_client.""" |
| 16 |
| 17 from __future__ import absolute_import |
| 18 |
| 19 import os |
| 20 import sys |
| 21 import time |
| 22 import webbrowser |
| 23 |
| 24 from oauth2client.client import OAuth2WebServerFlow |
| 25 |
| 26 from gcs_oauth2_boto_plugin import oauth2_client |
| 27 |
| 28 CLIENT_ID = None |
| 29 CLIENT_SECRET = None |
| 30 |
| 31 GOOGLE_OAUTH2_PROVIDER_AUTHORIZATION_URI = ( |
| 32 'https://accounts.google.com/o/oauth2/auth') |
| 33 GOOGLE_OAUTH2_PROVIDER_TOKEN_URI = ( |
| 34 'https://accounts.google.com/o/oauth2/token') |
| 35 GOOGLE_OAUTH2_DEFAULT_FILE_PASSWORD = 'notasecret' |
| 36 |
| 37 OOB_REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob' |
| 38 |
| 39 def OAuth2ClientFromBotoConfig(config, |
| 40 cred_type=oauth2_client.CredTypes.OAUTH2_USER_ACCOUNT): |
| 41 token_cache = None |
| 42 token_cache_type = config.get('OAuth2', 'token_cache', 'file_system') |
| 43 if token_cache_type == 'file_system': |
| 44 if config.has_option('OAuth2', 'token_cache_path_pattern'): |
| 45 token_cache = oauth2_client.FileSystemTokenCache( |
| 46 path_pattern=config.get('OAuth2', 'token_cache_path_pattern')) |
| 47 else: |
| 48 token_cache = oauth2_client.FileSystemTokenCache() |
| 49 elif token_cache_type == 'in_memory': |
| 50 token_cache = oauth2_client.InMemoryTokenCache() |
| 51 else: |
| 52 raise Exception( |
| 53 "Invalid value for config option OAuth2/token_cache: %s" % |
| 54 token_cache_type) |
| 55 |
| 56 proxy_host = None |
| 57 proxy_port = None |
| 58 proxy_user = None |
| 59 proxy_pass = None |
| 60 if (config.has_option('Boto', 'proxy') |
| 61 and config.has_option('Boto', 'proxy_port')): |
| 62 proxy_host = config.get('Boto', 'proxy') |
| 63 proxy_port = int(config.get('Boto', 'proxy_port')) |
| 64 proxy_user = config.get('Boto', 'proxy_user', None) |
| 65 proxy_pass = config.get('Boto', 'proxy_pass', None) |
| 66 |
| 67 provider_authorization_uri = config.get( |
| 68 'OAuth2', 'provider_authorization_uri', |
| 69 GOOGLE_OAUTH2_PROVIDER_AUTHORIZATION_URI) |
| 70 provider_token_uri = config.get( |
| 71 'OAuth2', 'provider_token_uri', GOOGLE_OAUTH2_PROVIDER_TOKEN_URI) |
| 72 |
| 73 if cred_type == oauth2_client.CredTypes.OAUTH2_SERVICE_ACCOUNT: |
| 74 service_client_id = config.get('Credentials', 'gs_service_client_id', '') |
| 75 private_key_filename = config.get('Credentials', 'gs_service_key_file', '') |
| 76 key_file_pass = config.get('Credentials', 'gs_service_key_file_password', |
| 77 GOOGLE_OAUTH2_DEFAULT_FILE_PASSWORD) |
| 78 with open(private_key_filename, 'rb') as private_key_file: |
| 79 private_key = private_key_file.read() |
| 80 |
| 81 return oauth2_client.OAuth2ServiceAccountClient( |
| 82 service_client_id, private_key, key_file_pass, |
| 83 access_token_cache=token_cache, auth_uri=provider_authorization_uri, |
| 84 token_uri=provider_token_uri, |
| 85 disable_ssl_certificate_validation=not(config.getbool( |
| 86 'Boto', 'https_validate_certificates', True)), |
| 87 proxy_host=proxy_host, proxy_port=proxy_port, |
| 88 proxy_user=proxy_user, proxy_pass=proxy_pass) |
| 89 |
| 90 elif cred_type == oauth2_client.CredTypes.OAUTH2_USER_ACCOUNT: |
| 91 client_id = config.get('OAuth2', 'client_id', |
| 92 os.environ.get('OAUTH2_CLIENT_ID', CLIENT_ID)) |
| 93 if not client_id: |
| 94 raise Exception( |
| 95 'client_id for your application obtained from ' |
| 96 'https://console.developers.google.com must be set in a boto config ' |
| 97 'or with OAUTH2_CLIENT_ID environment variable or with ' |
| 98 'gcs_oauth2_boto_plugin.SetFallbackClientIdAndSecret function.') |
| 99 |
| 100 client_secret = config.get('OAuth2', 'client_secret', |
| 101 os.environ.get('OAUTH2_CLIENT_SECRET', |
| 102 CLIENT_SECRET)) |
| 103 if not client_secret: |
| 104 raise Exception( |
| 105 'client_secret for your application obtained from ' |
| 106 'https://console.developers.google.com must be set in a boto config ' |
| 107 'or with OAUTH2_CLIENT_SECRET environment variable or with ' |
| 108 'gcs_oauth2_boto_plugin.SetFallbackClientIdAndSecret function.') |
| 109 return oauth2_client.OAuth2UserAccountClient( |
| 110 provider_token_uri, client_id, client_secret, |
| 111 config.get('Credentials', 'gs_oauth2_refresh_token'), |
| 112 auth_uri=provider_authorization_uri, access_token_cache=token_cache, |
| 113 disable_ssl_certificate_validation=not(config.getbool( |
| 114 'Boto', 'https_validate_certificates', True)), |
| 115 proxy_host=proxy_host, proxy_port=proxy_port, |
| 116 proxy_user=proxy_user, proxy_pass=proxy_pass, |
| 117 ca_certs_file=config.get_value('Boto', 'ca_certificates_file')) |
| 118 else: |
| 119 raise Exception('You have attempted to create an OAuth2 client without ' |
| 120 'setting up OAuth2 credentials.') |
| 121 |
| 122 |
| 123 def OAuth2ApprovalFlow(client, scopes, launch_browser=False): |
| 124 flow = OAuth2WebServerFlow( |
| 125 client.client_id, client.client_secret, scopes, auth_uri=client.auth_uri, |
| 126 token_uri=client.token_uri, redirect_uri=OOB_REDIRECT_URI) |
| 127 approval_url = flow.step1_get_authorize_url() |
| 128 |
| 129 if launch_browser: |
| 130 sys.stdout.write( |
| 131 'Attempting to launch a browser with the OAuth2 approval dialog at ' |
| 132 'URL: %s\n\n' |
| 133 '[Note: due to a Python bug, you may see a spurious error message ' |
| 134 '"object is not\ncallable [...] in [...] Popen.__del__" which can be ' |
| 135 'ignored.]\n\n' % approval_url) |
| 136 else: |
| 137 sys.stdout.write( |
| 138 'Please navigate your browser to the following URL:\n%s\n' % |
| 139 approval_url) |
| 140 |
| 141 sys.stdout.write( |
| 142 'In your browser you should see a page that requests you to authorize ' |
| 143 'access to Google Cloud Platform APIs and Services on your behalf. ' |
| 144 'After you approve, an authorization code will be displayed.\n\n') |
| 145 if (launch_browser and |
| 146 not webbrowser.open(approval_url, new=1, autoraise=True)): |
| 147 sys.stdout.write( |
| 148 'Launching browser appears to have failed; please navigate a browser ' |
| 149 'to the following URL:\n%s\n' % approval_url) |
| 150 # Short delay; webbrowser.open on linux insists on printing out a message |
| 151 # which we don't want to run into the prompt for the auth code. |
| 152 time.sleep(2) |
| 153 code = raw_input('Enter the authorization code: ') |
| 154 credentials = flow.step2_exchange(code, http=client.CreateHttpRequest()) |
| 155 return credentials.refresh_token |
| 156 |
| 157 |
| 158 def SetFallbackClientIdAndSecret(client_id, client_secret): |
| 159 global CLIENT_ID |
| 160 global CLIENT_SECRET |
| 161 |
| 162 CLIENT_ID = client_id |
| 163 CLIENT_SECRET = client_secret |
| 164 |
| 165 |
| 166 def SetLock(lock): |
| 167 oauth2_client.token_exchange_lock = lock |
| 168 |
| OLD | NEW |