def __init__(self, path, config, provider): self.oauth2_client = None if (provider.name == 'google'): if config.has_option('Credentials', 'gs_oauth2_refresh_token'): self.oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig( config) elif config.has_option('GoogleCompute', 'service_account'): self.oauth2_client = oauth2_client.CreateOAuth2GCEClient() if not self.oauth2_client: raise NotReadyToAuthenticate()
def __init__(self, path, config, provider): self.oauth2_client = None if (provider.name == 'google'): if config.has_option('GoogleCompute', 'service_account'): self.oauth2_client = oauth2_client.CreateOAuth2GCEClient() else: self.oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig(config) self.oauth2_client.cache_key_base = oauth.CLIENT_ID if not self.oauth2_client: raise auth_handler.NotReadyToAuthenticate()
def __init__(self, path, config, provider): if (provider.name == 'google' and config.has_option('Credentials', 'gs_service_key_file')): self.oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig( config, cred_type=oauth2_client.CredTypes.OAUTH2_SERVICE_ACCOUNT) # If we make it to this point, then we will later attempt to authenticate # as a service account based on how the boto auth plugins work. This is # global so that command.py can access this value once it's set. # TODO: replace this approach with a way to get the current plugin # from boto so that we don't have to have global variables. global IS_SERVICE_ACCOUNT IS_SERVICE_ACCOUNT = True else: raise NotReadyToAuthenticate()
def _WriteBotoConfigFile(self, config_file, launch_browser=True, oauth2_scopes=[SCOPE_FULL_CONTROL], cred_type=CredTypes.OAUTH2_USER_ACCOUNT): """Creates a boto config file interactively. Needed credentials are obtained interactively, either by asking the user for access key and secret, or by walking the user through the OAuth2 approval flow. Args: config_file: File object to which the resulting config file will be written. launch_browser: In the OAuth2 approval flow, attempt to open a browser window and navigate to the approval URL. oauth2_scopes: A list of OAuth2 scopes to request authorization for, when using OAuth2. cred_type: There are three options: - for HMAC, ask the user for access key and secret - for OAUTH2_USER_ACCOUNT, walk the user through OAuth2 approval flow and produce a config with an oauth2_refresh_token credential. - for OAUTH2_SERVICE_ACCOUNT, prompt the user for OAuth2 for service account email address and private key file (and password for that file). """ # Collect credentials provider_map = {'aws': 'aws', 'google': 'gs'} uri_map = {'aws': 's3', 'google': 'gs'} key_ids = {} sec_keys = {} if cred_type == CredTypes.OAUTH2_SERVICE_ACCOUNT: gs_service_client_id = raw_input( 'What is your service account email ' 'address? ') gs_service_key_file = raw_input( 'What is the full path to your private ' 'key file? ') gs_service_key_file_password = raw_input('\n'.join( textwrap.wrap( 'What is the password for your service key file [if you haven\'t ' 'set one explicitly, leave this line blank]?')) + ' ') self._CheckPrivateKeyFilePermissions(gs_service_key_file) elif cred_type == CredTypes.OAUTH2_USER_ACCOUNT: oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig( boto.config, cred_type) try: oauth2_refresh_token = oauth2_helper.OAuth2ApprovalFlow( oauth2_client, oauth2_scopes, launch_browser) except (ResponseNotReady, ServerNotFoundError, socket.error): # TODO: Determine condition to check for in the ResponseNotReady # exception so we only run proxy config flow if failure was caused by # request being blocked because it wasn't sent through proxy. (This # error could also happen if gsutil or the oauth2 client had a bug that # attempted to incorrectly reuse an HTTP connection, for example.) sys.stdout.write('\n'.join( textwrap.wrap( "Unable to connect to accounts.google.com during OAuth2 flow. This " "can happen if your site uses a proxy. If you are using gsutil " "through a proxy, please enter the proxy's information; otherwise " "leave the following fields blank.")) + '\n') self._PromptForProxyConfig() oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig( boto.config, cred_type) oauth2_refresh_token = oauth2_helper.OAuth2ApprovalFlow( oauth2_client, oauth2_scopes, launch_browser) elif cred_type == CredTypes.HMAC: got_creds = False for provider in provider_map: if provider == 'google': key_ids[provider] = raw_input( 'What is your %s access key ID? ' % provider) sec_keys[provider] = raw_input( 'What is your %s secret access key? ' % provider) got_creds = True if not key_ids[provider] or not sec_keys[provider]: raise CommandException( 'Incomplete credentials provided. Please try again.' ) if not got_creds: raise CommandException( 'No credentials provided. Please try again.') # Write the config file prelude. config_file.write(CONFIG_PRELUDE_CONTENT.lstrip()) config_file.write( '# This file was created by gsutil version %s at %s.\n' % (gslib.VERSION, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) config_file.write( '#\n# You can create additional configuration files by ' 'running\n# gsutil config [options] [-o <config-file>]\n\n\n') # Write the config file Credentials section. config_file.write('[Credentials]\n\n') if cred_type == CredTypes.OAUTH2_SERVICE_ACCOUNT: config_file.write('# Google OAuth2 service account credentials ' '(for "gs://" URIs):\n') config_file.write('gs_service_client_id = %s\n' % gs_service_client_id) config_file.write('gs_service_key_file = %s\n' % gs_service_key_file) if not gs_service_key_file_password: config_file.write( '# If you would like to set your password, you can do so using\n' '# the following commands (replaced with your information):\n' '# "openssl pkcs12 -in cert1.p12 -out temp_cert.pem"\n' '# "openssl pkcs12 -export -in temp_cert.pem -out cert2.p12"\n' '# "rm -f temp_cert.pem"\n' '# Your initial password is "notasecret" - for more information,' '\n# please see http://www.openssl.org/docs/apps/pkcs12.html.\n' ) config_file.write('#gs_service_key_file_password =\n\n') else: config_file.write('gs_service_key_file_password = %s\n\n' % gs_service_key_file_password) elif cred_type == CredTypes.OAUTH2_USER_ACCOUNT: config_file.write( '# Google OAuth2 credentials (for "gs://" URIs):\n' '# The following OAuth2 account is authorized for scope(s):\n') for scope in oauth2_scopes: config_file.write('# %s\n' % scope) config_file.write('gs_oauth2_refresh_token = %s\n\n' % oauth2_refresh_token) else: config_file.write( '# To add Google OAuth2 credentials ("gs://" URIs), ' 'edit and uncomment the\n# following line:\n' '#gs_oauth2_refresh_token = <your OAuth2 refresh token>\n\n') for provider in provider_map: key_prefix = provider_map[provider] uri_scheme = uri_map[provider] if provider in key_ids and provider in sec_keys: config_file.write('# %s credentials ("%s://" URIs):\n' % (provider, uri_scheme)) config_file.write('%s_access_key_id = %s\n' % (key_prefix, key_ids[provider])) config_file.write('%s_secret_access_key = %s\n' % (key_prefix, sec_keys[provider])) else: config_file.write( '# To add %s credentials ("%s://" URIs), edit and ' 'uncomment the\n# following two lines:\n' '#%s_access_key_id = <your %s access key ID>\n' '#%s_secret_access_key = <your %s secret access key>\n' % (provider, uri_scheme, key_prefix, provider, key_prefix, provider)) host_key = Provider.HostKeyMap[provider] config_file.write( '# The ability to specify an alternate storage host and port\n' '# is primarily for cloud storage service developers.\n' '# Setting a non-default gs_host only works if prefer_api=xml.\n' '#%s_host = <alternate storage host address>\n' '#%s_port = <alternate storage host port>\n' % (host_key, host_key)) if host_key == 'gs': config_file.write( '#%s_json_host = <alternate JSON API storage host address>\n' '#%s_json_port = <alternate JSON API storage host port>\n\n' % (host_key, host_key)) config_file.write('\n') # Write the config file Boto section. config_file.write('%s\n' % CONFIG_BOTO_SECTION_CONTENT) self._WriteProxyConfigFileSection(config_file) # Write the config file GSUtil section that doesn't depend on user input. config_file.write(CONFIG_INPUTLESS_GSUTIL_SECTION_CONTENT) # Write the default API version. config_file.write(""" # 'default_api_version' specifies the default Google Cloud Storage XML API # version to use. If not set below gsutil defaults to API version 1. """) api_version = 2 if cred_type == CredTypes.HMAC: api_version = 1 config_file.write('default_api_version = %d\n' % api_version) # Write the config file GSUtil section that includes the default # project ID input from the user. if launch_browser: sys.stdout.write( 'Attempting to launch a browser to open the Google Cloud Console at ' 'URL: %s\n\n' '[Note: due to a Python bug, you may see a spurious error message ' '"object is not\ncallable [...] in [...] Popen.__del__" which can ' 'be ignored.]\n\n' % GOOG_CLOUD_CONSOLE_URI) sys.stdout.write( 'In your browser you should see the Cloud Console. Find the project ' 'you will\nuse, and then copy the Project ID string from the second ' 'column. Older projects do\nnot have Project ID strings. For such ' 'projects, click the project and then copy the\nProject Number ' 'listed under that project.\n\n') if not webbrowser.open( GOOG_CLOUD_CONSOLE_URI, new=1, autoraise=True): sys.stdout.write( 'Launching browser appears to have failed; please navigate a ' 'browser to the following URL:\n%s\n' % GOOG_CLOUD_CONSOLE_URI) # Short delay; webbrowser.open on linux insists on printing out a message # which we don't want to run into the prompt for the auth code. time.sleep(2) else: sys.stdout.write( '\nPlease navigate your browser to %s,\nthen find the project you ' 'will use, and copy the Project ID string from the\nsecond column. ' 'Older projects do not have Project ID strings. For such projects,\n' 'click the project and then copy the Project Number listed under ' 'that project.\n\n' % GOOG_CLOUD_CONSOLE_URI) default_project_id = raw_input('What is your project-id? ').strip() project_id_section_prelude = """ # 'default_project_id' specifies the default Google Cloud Storage project ID to # use with the 'mb' and 'ls' commands. This default can be overridden by # specifying the -p option to the 'mb' and 'ls' commands. """ if not default_project_id: raise CommandException( 'No default project ID entered. The default project ID is needed by ' 'the\nls and mb commands; please try again.') config_file.write('%sdefault_project_id = %s\n\n\n' % (project_id_section_prelude, default_project_id)) # Write the config file OAuth2 section. config_file.write(CONFIG_OAUTH2_CONFIG_CONTENT)