OLD | NEW |
(Empty) | |
| 1 # Copyright 2011 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 in gsutil.""" |
| 16 |
| 17 import sys |
| 18 import time |
| 19 import webbrowser |
| 20 |
| 21 import oauth2_client |
| 22 |
| 23 GSUTIL_CLIENT_ID = '909320924072.apps.googleusercontent.com' |
| 24 # Google OAuth2 clients always have a secret, even if the client is an installed |
| 25 # application/utility such as gsutil. Of course, in such cases the "secret" is |
| 26 # actually publicly known; security depends entirly on the secrecy of refresh |
| 27 # tokens, which effectively become bearer tokens. |
| 28 GSUTIL_CLIENT_NOTSOSECRET = 'p3RlpR10xMFh9ZXBS/ZNLYUu' |
| 29 |
| 30 GOOGLE_OAUTH2_PROVIDER_LABEL = 'Google' |
| 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 |
| 36 OOB_REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob' |
| 37 |
| 38 def OAuth2ClientFromBotoConfig(config): |
| 39 token_cache = None |
| 40 token_cache_type = config.get('OAuth2', 'token_cache', 'file_system') |
| 41 |
| 42 if token_cache_type == 'file_system': |
| 43 if config.has_option('OAuth2', 'token_cache_path_pattern'): |
| 44 token_cache = oauth2_client.FileSystemTokenCache( |
| 45 path_pattern=config.get('OAuth2', 'token_cache_path_pattern')) |
| 46 else: |
| 47 token_cache = oauth2_client.FileSystemTokenCache() |
| 48 elif token_cache_type == 'in_memory': |
| 49 token_cache = oauth2_client.InMemoryTokenCache() |
| 50 else: |
| 51 raise Exception( |
| 52 "Invalid value for config option OAuth2/token_cache: %s" % |
| 53 token_cache_type) |
| 54 |
| 55 proxy = None |
| 56 if (config.has_option('Boto', 'proxy') |
| 57 and config.has_option('Boto', 'proxy_port')): |
| 58 proxy = "%s:%s" % (config.get('Boto', 'proxy'), |
| 59 config.get('Boto', 'proxy_port')) |
| 60 |
| 61 provider_label = config.get( |
| 62 'OAuth2', 'provider_label', GOOGLE_OAUTH2_PROVIDER_LABEL) |
| 63 provider_authorization_uri = config.get( |
| 64 'OAuth2', 'provider_authorization_uri', |
| 65 GOOGLE_OAUTH2_PROVIDER_AUTHORIZATION_URI) |
| 66 provider_token_uri = config.get( |
| 67 'OAuth2', 'provider_token_uri', GOOGLE_OAUTH2_PROVIDER_TOKEN_URI) |
| 68 |
| 69 client_id = config.get('OAuth2', 'client_id', GSUTIL_CLIENT_ID) |
| 70 client_secret = config.get( |
| 71 'OAuth2', 'client_secret', GSUTIL_CLIENT_NOTSOSECRET) |
| 72 |
| 73 return oauth2_client.OAuth2Client( |
| 74 oauth2_client.OAuth2Provider( |
| 75 provider_label, provider_authorization_uri, provider_token_uri), |
| 76 client_id, client_secret, |
| 77 proxy=proxy, access_token_cache=token_cache) |
| 78 |
| 79 def OAuth2ApprovalFlow(oauth2_client, scopes, launch_browser=False): |
| 80 approval_url = oauth2_client.GetAuthorizationUri(OOB_REDIRECT_URI, scopes) |
| 81 if launch_browser: |
| 82 sys.stdout.write( |
| 83 'Attempting to launch a browser with the OAuth2 approval dialog at ' |
| 84 'URL: %s\n\n' |
| 85 '[Note: due to a Python bug, you may see a spurious error message "objec
t is not\n' |
| 86 'callable [...] in [...] Popen.__del__" which can be ignored.]\n\n' % ap
proval_url) |
| 87 else: |
| 88 sys.stdout.write( |
| 89 'Please navigate your browser to the following URL:\n%s\n' % |
| 90 approval_url) |
| 91 |
| 92 sys.stdout.write( |
| 93 'In your browser you should see a page that requests you to authorize ' |
| 94 'gsutil to access\nGoogle Cloud Storage on your behalf. After you ' |
| 95 'approve, an authorization code will be displayed.\n\n') |
| 96 if (launch_browser and |
| 97 not webbrowser.open(approval_url, new=1, autoraise=True)): |
| 98 sys.stdout.write( |
| 99 'Launching browser appears to have failed; please navigate a browser ' |
| 100 'to the following URL:\n%s\n' % approval_url) |
| 101 # Short delay; webbrowser.open on linux insists on printing out a message |
| 102 # which we don't want to run into the prompt for the auth code. |
| 103 time.sleep(2) |
| 104 code = raw_input('Enter the authorization code: ') |
| 105 |
| 106 refresh_token, access_token = oauth2_client.ExchangeAuthorizationCode( |
| 107 code, OOB_REDIRECT_URI, scopes) |
| 108 |
| 109 return refresh_token |
| 110 |
OLD | NEW |