예제 #1
0
 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()
예제 #2
0
 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()
예제 #3
0
    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()
예제 #4
0
    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)