예제 #1
0
    def Run(self, args):
        """This is what ts called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      InvalidImageNameError: If the user specified an invalid image name.
    Returns:
      A list of the deleted docker_name.Tag and docker_name.Digest objects
    """
        # IMAGE_NAME: The fully-qualified image name to delete (with a digest).
        # Deletes the layers. Ex. gcr.io/google-appengine/java(@DIGEST|:TAG).

        http_obj = http.Http()
        # collect input/validate
        digests, tags = self._ProcessImageNames(args.image_names)
        # print
        if digests:
            log.status.Print('Digests:')
        for digest in digests:
            self._PrintDigest(digest, http_obj)

        if tags:
            log.status.Print('Tags:')
        for tag in tags:
            log.status.Print('- ' + str(tag))
        for digest in digests:
            tags.update(util.GetDockerTagsForDigest(digest, http_obj))
        # prompt
        console_io.PromptContinue(
            'This operation will delete the above tags '
            'and/or digests. Tag deletions only delete the'
            'tag. Digest deletions also delete the '
            'underlying image layers.',
            default=True,
            cancel_on_no=True)
        # delete and collect output
        result = []
        for tag in tags:  # tags must be deleted before digests
            self._DeleteDockerTagOrDigest(tag, http_obj)
            result.append({'name': str(tag)})
        for digest in digests:
            self._DeleteDockerTagOrDigest(digest, http_obj)
            result.append({'name': str(digest)})
        return result
예제 #2
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      exceptions.Error: If the repository could not be found, or access was
      denied.
      docker_http.V2DiagnosticException: Any other error occured while
      accessing GCR.
    """
        repository_arg = args.repository
        self._epilog = None
        if not repository_arg:
            repository_arg = 'gcr.io/{0}'.format(
                properties.VALUES.core.project.Get(required=True))
            self._epilog = 'Only listing images in {0}. '.format(
                repository_arg)
            self._epilog += 'Use --repository to list images in other repositories.'

        # Throws if invalid.
        repository = util.ValidateRepositoryPath(repository_arg)

        def _DisplayName(c):
            """Display the fully-qualified name."""
            return '{0}/{1}'.format(repository, c)

        http_obj = http.Http()
        with docker_image.FromRegistry(basic_creds=util.CredentialProvider(),
                                       name=repository,
                                       transport=http_obj) as r:
            try:
                images = [{'name': _DisplayName(c)} for c in r.children()]
                return images
            except docker_http.V2DiagnosticException as err:
                if err.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]:
                    raise exceptions.Error(
                        'Access denied: {0}'.format(repository))
                elif err.status == httplib.NOT_FOUND:
                    raise exceptions.Error('Not found: {0}'.format(repository))
                else:
                    raise
예제 #3
0
def _Refresh(credentials,
             http_client=None,
             is_impersonated_credential=False,
             include_email=False,
             gce_token_format='standard',
             gce_include_license=False):
    """Refreshes oauth2client credentials."""
    response_encoding = None if six.PY2 else 'utf-8'
    request_client = http_client or http.Http(
        response_encoding=response_encoding)
    try:
        credentials.refresh(request_client)

        id_token = None
        # Service accounts require an additional request to receive a fresh id_token
        if is_impersonated_credential:
            if not IMPERSONATION_TOKEN_PROVIDER:
                raise AccountImpersonationError(
                    'gcloud is configured to impersonate a service account but '
                    'impersonation support is not available.')
            if not IMPERSONATION_TOKEN_PROVIDER.IsImpersonationCredential(
                    credentials):
                raise AccountImpersonationError(
                    'Invalid impersonation account for refresh {}'.format(
                        credentials))
            id_token = _RefreshImpersonatedAccountIdToken(
                credentials, include_email=include_email)
        # Service accounts require an additional request to receive a fresh id_token
        elif isinstance(credentials,
                        service_account.ServiceAccountCredentials):
            id_token = _RefreshServiceAccountIdToken(credentials,
                                                     request_client)
        elif isinstance(credentials, oauth2client_gce.AppAssertionCredentials):
            id_token = c_gce.Metadata().GetIdToken(
                config.CLOUDSDK_CLIENT_ID,
                token_format=gce_token_format,
                include_license=gce_include_license)

        if id_token:
            if credentials.token_response:
                credentials.token_response['id_token'] = id_token
            credentials.id_tokenb64 = id_token

    except (client.AccessTokenRefreshError, httplib2.ServerNotFoundError) as e:
        raise TokenRefreshError(six.text_type(e))
    except reauth_errors.ReauthError as e:
        raise TokenRefreshReauthError(str(e))
예제 #4
0
def Http(timeout='unset', enable_resource_quota=True):
    """Get an httplib2.Http client for working with the Google API.

  Args:
    timeout: double, The timeout in seconds to pass to httplib2.  This is the
        socket level timeout.  If timeout is None, timeout is infinite.  If
        default argument 'unset' is given, a sensible default is selected.
    enable_resource_quota: bool, By default, we are going to tell APIs to use
        the quota of the project being operated on. For some APIs we want to use
        gcloud's quota, so you can explicitly disable that behavior by passing
        False here.

  Returns:
    An authorized httplib2.Http client object, or a regular httplib2.Http object
    if no credentials are available.

  Raises:
    c_store.Error: If an error loading the credentials occurs.
  """
    http_client = http.Http(timeout=timeout)

    # Wrappers for IAM header injection.
    authority_selector = properties.VALUES.auth.authority_selector.Get()
    authorization_token_file = (
        properties.VALUES.auth.authorization_token_file.Get())
    handlers = _GetIAMAuthHandlers(authority_selector,
                                   authorization_token_file)

    creds = store.LoadIfEnabled()
    if creds:
        # Inject the resource project header for quota unless explicitly disabled.
        if enable_resource_quota:
            quota_project = _GetQuotaProject(creds)
            if quota_project:
                handlers.append(
                    http.Modifiers.Handler(
                        http.Modifiers.SetHeader('X-Goog-User-Project',
                                                 quota_project)))

        http_client = creds.authorize(http_client)
        # Wrap the request method to put in our own error handling.
        http_client = http.Modifiers.WrapRequest(
            http_client, handlers, _HandleAuthError,
            client.AccessTokenRefreshError)

    return http_client
예제 #5
0
    def Run(self, args):
        # pylint: disable=missing-docstring
        def Push(image, dest_name, creds, http_obj, src_name,
                 session_push_type):
            with session_push_type(dest_name, creds, http_obj) as push:
                push.upload(image)
                log.CreatedResource(dest_name)
            log.UpdatedResource(src_name)

        http_obj = http.Http()

        src_name = util.GetDockerImageFromTagOrDigest(args.src_image)
        dest_name = docker_name.Tag(args.dest_image)

        if '/' not in dest_name.repository:
            raise exceptions.Error(
                'Pushing to project root-level images is disabled. '
                'Please designate an image within a project, '
                'e.g. gcr.io/project-id/my-image:tag')

        console_io.PromptContinue('This will tag {0} with {1}'.format(
            src_name, dest_name),
                                  default=True,
                                  cancel_on_no=True)
        creds = util.CredentialProvider()
        with util.WrapExpectedDockerlessErrors():
            with docker_image_list.FromRegistry(src_name, creds,
                                                http_obj) as manifest_list:
                if manifest_list.exists():
                    Push(manifest_list, dest_name, creds, http_obj, src_name,
                         v2_2_session.Push)
                    return

            with v2_2_image.FromRegistry(src_name,
                                         creds,
                                         http_obj,
                                         accepted_mimes=docker_http.
                                         SUPPORTED_MANIFEST_MIMES) as v2_2_img:
                if v2_2_img.exists():
                    Push(v2_2_img, dest_name, creds, http_obj, src_name,
                         v2_2_session.Push)
                    return

            with v2_image.FromRegistry(src_name, creds, http_obj) as v2_img:
                Push(v2_img, dest_name, creds, http_obj, src_name,
                     v2_session.Push)
예제 #6
0
  def Run(self, args):
    """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      ArgumentError: If the user provided the flag --show-occurrences-from but
        --show-occurrences=False.
      InvalidImageNameError: If the user specified an invalid image name.
    Returns:
      Some value that we want to have printed later.
    """
    # Verify that --show-occurrences-from is set iff --show-occurrences=True.
    if args.IsSpecified('show_occurrences_from') and not args.show_occurrences:
      raise ArgumentError(
          '--show-occurrences-from may only be set if --show-occurrences=True')

    repository = util.ValidateRepositoryPath(args.image_name)
    http_obj = http.Http()
    with util.WrapExpectedDockerlessErrors(repository):
      with docker_image.FromRegistry(
          basic_creds=util.CredentialProvider(),
          name=repository,
          transport=http_obj) as image:
        manifests = image.manifests()
        # Only consider the top _DEFAULT_SHOW_OCCURRENCES_FROM images
        # to reduce computation time.
        most_recent_resource_urls = None
        if args.show_occurrences_from:
          # This block is skipped when the user provided
          # --show-occurrences-from=unlimited on the CLI.
          most_recent_resource_urls = [
              'https://%s@%s' % (args.image_name, k) for k in heapq.nlargest(
                  args.show_occurrences_from,
                  manifests,
                  key=lambda k: manifests[k]['timeCreatedMs'])
          ]
        return util.TransformManifests(
            manifests,
            repository,
            show_occurrences=args.show_occurrences,
            occurrence_filter=args.occurrence_filter,
            resource_urls=most_recent_resource_urls)
예제 #7
0
def RevokeCredentials(credentials):
    """Revokes the token on the server.

  Args:
    credentials: user account credentials from either google-auth or
      oauth2client.
  Raises:
    RevokeError: If credentials to revoke is not user account credentials.
  """
    if not c_creds.IsUserAccountCredentials(credentials):
        raise RevokeError(
            'The token cannot be revoked from server because it is '
            'not user account credentials.')
    http_client = http.Http()
    if c_creds.IsOauth2ClientCredentials(credentials):
        credentials.revoke(http_client)
    else:
        credentials.revoke(http.GoogleAuthRequest(http_client))
예제 #8
0
 def run(url, extra_headers):
     request_mock.return_value = ({
         'header1': 'value1',
         'header2': 'value2'
     }, b'response content')
     properties.VALUES.core.log_http.Set(True)
     http_client = http.Http()
     http_client.request(url,
                         method='GET',
                         body='request content',
                         headers=extra_headers)
     request_mock.assert_called_once_with(
         url,
         method='GET',
         headers=mock.ANY,
         body='request content',
     )
     request_mock.reset_mock()
예제 #9
0
  def _WebRequest(self, method, url, headers=None):
    """Internal method to make requests against web URLs.

    Args:
      method: request method, e.g. GET
      url: request URL
      headers: dictionary of request headers

    Returns:
      Response body as a string

    Raises:
      Error: If the response has a status code >= 400.
    """
    r, content = http.Http().request(url, method, headers=headers)
    if r.status >= 400:
      raise exceptions.Error(
          'status: {}, reason: {}'.format(r.status, r.reason))
    return content
예제 #10
0
def Refresh(credentials, http_client=None):
  """Refresh credentials.

  Calls credentials.refresh(), unless they're SignedJwtAssertionCredentials.

  Args:
    credentials: oauth2client.client.Credentials, The credentials to refresh.
    http_client: httplib2.Http, The http transport to refresh with.

  Raises:
    TokenRefreshError: If the credentials fail to refresh.
    TokenRefreshReauthError: If the credentials fail to refresh due to reauth.
  """
  try:
    credentials.refresh(http_client or http.Http())
  except (client.AccessTokenRefreshError, httplib2.ServerNotFoundError) as e:
    raise TokenRefreshError(e.message)
  except reauth_errors.ReauthError as e:
    raise TokenRefreshReauthError(e.message)
예제 #11
0
 def HttpClient(self):
     assert self.active
     if not self.client_key and self.client_cert and self.client_cert_domain:
         raise ValueError(
             'Kubeconfig authentication requires a client certificate '
             'authentication method.')
     if self.client_cert_domain:
         # Import http only when needed, as it depends on credential infrastructure
         # which is not needed in all cases.
         from googlecloudsdk.core import http as http_core  # pylint: disable=g-import-not-at-top
         http_client = http_core.Http(response_encoding=http_core.ENCODING,
                                      ca_certs=self.ca_certs)
         http_client.add_certificate(self.client_key, self.client_cert,
                                     self.client_cert_domain)
         return http_client
     from googlecloudsdk.core.credentials import http as http_creds  # pylint: disable=g-import-not-at-top
     http_client = http_creds.Http(response_encoding=http_creds.ENCODING,
                                   ca_certs=self.ca_certs)
     return http_client
예제 #12
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      exceptions.Error: If the repository could not be found, or access was
      denied.
      docker_http.V2DiagnosticException: Any other error occurred while
      accessing GCR.
    """
        repository_arg = args.repository
        self._epilog = None
        if not repository_arg:
            project_id = properties.VALUES.core.project.Get(required=True)
            # Handle domain-scoped projects...
            project_id = project_id.replace(':', '/', 1)
            repository_arg = 'gcr.io/{0}'.format(project_id)
            self._epilog = 'Only listing images in {0}. '.format(
                repository_arg)
            self._epilog += 'Use --repository to list images in other repositories.'

        # Throws if invalid.
        repository = util.ValidateRepositoryPath(repository_arg)

        def _DisplayName(c):
            """Display the fully-qualified name."""
            return '{0}/{1}'.format(repository, c)

        http_obj = http.Http()
        with util.WrapExpectedDockerlessErrors(repository):
            with docker_image.FromRegistry(
                    basic_creds=util.CredentialProvider(),
                    name=repository,
                    transport=http_obj) as r:
                images = [{'name': _DisplayName(c)} for c in r.children()]
                return images
예제 #13
0
def GetApitoolsTransport(timeout='unset',
                         response_encoding=None,
                         ca_certs=None,
                         client_certificate=None,
                         client_key=None,
                         client_cert_domain=None):
  """Get an unauthenticated transport client for use with apitools.

  Args:
    timeout: double, The request timeout in seconds.  This is the
      socket level timeout.  If timeout is None, timeout is infinite.  If
      default argument 'unset' is given, a sensible default is selected.
    response_encoding: str, the encoding to use to decode the response.
    ca_certs: str, absolute filename of a ca_certs file that overrides the
      default
    client_certificate: str, absolute filename of a client_certificate file
    client_key: str, absolute filename of a client_key file
    client_cert_domain: str, domain we are connecting to (used only by httplib2)

  Returns:
    1. A httplib2.Http-like object backed by httplib2 or requests.
  """
  if base.UseRequests():
    # pylint: disable=g-import-not-at-top
    from googlecloudsdk.core import requests
    session = requests.GetSession(
        timeout=timeout,
        ca_certs=ca_certs,
        client_certificate=client_certificate,
        client_key=client_key)

    return requests.GetApitoolsRequests(
        session, response_encoding=response_encoding)
  else:
    from googlecloudsdk.core import http  # pylint: disable=g-import-not-at-top
    http_client = http.Http(
        timeout=timeout, response_encoding=response_encoding, ca_certs=ca_certs)
    # httplib2 always applies the first client certificate
    # in the chain for authentication
    http_client.certificates.credentials.insert(
        0, (client_cert_domain, client_key, client_certificate, ''))
    return http_client
  def refresh(self, request):
    """Refreshes the access token and handles reauth request when it is asked.

    Args:
      request: google.auth.transport.Request, a callable used to make HTTP
        requests.
    """
    try:
      return self._Refresh(request)
    except ReauthRequiredError:
      # reauth.GetRaptToken is implemented in oauth2client and it is built on
      # httplib2. GetRaptToken does not work with
      # google.auth.transport.Request.
      response_encoding = None if six.PY2 else 'utf-8'
      http_request = http.Http(response_encoding=response_encoding).request
      self._rapt_token = reauth.GetRaptToken(http_request, self._client_id,
                                             self._client_secret,
                                             self._refresh_token,
                                             self._token_uri,
                                             list(self.scopes or []))
    return self._Refresh(request)
예제 #15
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      InvalidImageNameError: If the user specified an invalid image name.
    Returns:
      Some value that we want to have printed later.
    """
        repository = util.ValidateRepositoryPath(args.image_name)
        http_obj = http.Http()
        with util.WrapExpectedDockerlessErrors(repository):
            with docker_image.FromRegistry(
                    basic_creds=util.CredentialProvider(),
                    name=repository,
                    transport=http_obj) as image:
                manifests = image.manifests()
                return util.TransformManifests(manifests, repository)
예제 #16
0
  def testUserAgent_SpacesInVersion(self):
    # This is similar to what the versions look like for some internal builds
    config.CLOUD_SDK_VERSION = 'Mon Sep 12 08:35:01 2016'
    request_mock = self.StartObjectPatch(httplib2.Http, 'request')
    uuid_mock = self.StartObjectPatch(uuid, 'uuid4')
    uuid_mock.return_value = uuid.UUID('12345678123456781234567812345678')
    is_interactive_mock = self.StartObjectPatch(console_io, 'IsInteractive')
    is_interactive_mock.return_value = False
    python_version = '2.7.6'
    self.StartPatch('platform.python_version').return_value = python_version

    http_client = http.Http()
    url = 'http://foo.com'
    request_mock.return_value = self.default_response
    http_client.request(url)
    expect_user_agent = self.UserAgent('Mon_Sep_12_08:35:01_2016', 'None',
                                       uuid_mock.return_value.hex,
                                       python_version, False)
    request_mock.assert_called_once_with(
        url, headers={b'user-agent': expect_user_agent})
    request_mock.reset_mock()
예제 #17
0
    def Run(self, args):
        # pylint: disable=missing-docstring
        def Push(image, dest_name, creds, http_obj, src_name,
                 session_push_type):
            with session_push_type(dest_name, creds, http_obj) as push:
                push.upload(image)
                log.CreatedResource(dest_name)
            log.UpdatedResource(src_name)

        http_obj = http.Http()

        src_name = util.GetDockerImageFromTagOrDigest(args.src_image)
        dest_name = docker_name.Tag(args.dest_image)

        console_io.PromptContinue('This will tag {0} with {1}'.format(
            src_name, dest_name),
                                  default=True,
                                  cancel_on_no=True)
        creds = util.CredentialProvider()
        try:
            with v2_2_image.FromRegistry(src_name, creds,
                                         http_obj) as v2_2_img:
                if v2_2_img.exists():
                    Push(v2_2_img, dest_name, creds, http_obj, src_name,
                         v2_2_session.Push)
                    return

            with v2_image.FromRegistry(src_name, creds, http_obj) as v2_img:
                Push(v2_img, dest_name, creds, http_obj, src_name,
                     v2_session.Push)

        except (v2_docker_http.V2DiagnosticException,
                v2_2_docker_http.V2DiagnosticException) as err:
            raise util.GcloudifyRecoverableV2Errors(
                err, {
                    httplib.FORBIDDEN:
                    'Add-tag failed, access denied.',
                    httplib.NOT_FOUND:
                    'Add-tag failed, not found: {0}'.format(src_name)
                })
예제 #18
0
def RunWebFlow(webflow, launch_browser=True):
  """Runs a preconfigured webflow to get an auth token.

  Args:
    webflow: client.OAuth2WebServerFlow, The configured flow to run.
    launch_browser: bool, Open a new web browser window for authorization.

  Returns:
    client.Credentials, Newly acquired credentials from the web flow.

  Raises:
    FlowError: If there is a problem with the web flow.
  """
  # pylint:disable=g-import-not-at-top, This is imported on demand for
  # performance reasons.
  from googlecloudsdk.core.credentials import flow

  try:
    cred = flow.Run(webflow, launch_browser=launch_browser, http=http.Http())
  except flow.Error as e:
    raise FlowError(e)
  return cred
예제 #19
0
    def testRequestReason(self):
        properties.VALUES.core.request_reason.Set('my request justification')
        request_mock = self.StartObjectPatch(httplib2.Http, 'request')
        request_mock.return_value = ({
            'header1': 'value1',
            'header2': 'value2'
        }, b'response content')
        http_client = http.Http()

        http_client.request('http://www.example.com/foo',
                            method='GET',
                            body='request content',
                            headers={})

        expected_headers = {
            b'user-agent': mock.ANY,
            b'X-Goog-Request-Reason': b'my request justification'
        }
        request_mock.assert_called_once_with('http://www.example.com/foo',
                                             method='GET',
                                             body='request content',
                                             headers=expected_headers)
예제 #20
0
def _UploadFileToGeneratedUrl(source, messages, service, function_ref):
  """Upload function source to URL generated by API."""
  url = _GetUploadUrl(messages, service, function_ref)
  upload = transfer.Upload.FromFile(source,
                                    mime_type='application/zip')
  upload_request = http_wrapper.Request(
      url, http_method='PUT', headers={
          'content-type': 'application/zip',
          # Magic header, request will fail without it.
          # Not documented at the moment this comment was being written.
          'x-goog-content-length-range': '0,104857600',
          'Content-Length': '{0:d}'.format(upload.total_size)})
  upload_request.body = upload.stream.read()
  response = http_wrapper.MakeRequest(
      http_utils.Http(), upload_request, retry_func=upload.retry_func,
      retries=upload.num_retries)
  if not _CheckUploadStatus(response.status_code):
    raise exceptions.FunctionsError(
        'Failed to upload the function source code to signed url: {url}. '
        'Status: [{code}:{detail}]'.format(url=url,
                                           code=response.status_code,
                                           detail=response.content))
  return url
예제 #21
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.
    """
        repository_arg = args.repository
        if not repository_arg:
            repository_arg = 'gcr.io/{0}'.format(
                properties.VALUES.core.project.Get(required=True))

        # Throws if invalid.
        repository = util.ValidateRepositoryPath(repository_arg)

        def _DisplayName(c):
            """Display the fully-qualified name."""
            return '{0}/{1}'.format(repository, c)

        http_obj = http.Http()
        with docker_image.FromRegistry(basic_creds=util.CredentialProvider(),
                                       name=repository,
                                       transport=http_obj) as r:
            try:
                images = [{'name': _DisplayName(c)} for c in r.children()]
                return images
            except docker_http.V2DiagnosticException as err:
                if err.http_status_code == 403:
                    raise exceptions.Error(
                        'Access denied: {0}'.format(repository))
                elif err.http_status_code == 404:
                    raise exceptions.Error('Not found: {0}'.format(repository))
                else:
                    raise
  def Run(self, args):
    """Run the helper command."""

    try:
      creds = client.GoogleCredentials.get_application_default()
    except client.ApplicationDefaultCredentialsError as e:
      log.debug(e, exc_info=True)
      raise c_exc.ToolException(str(e))

    if creds.create_scoped_required():
      creds_type = creds.serialization_data['type']
      token_uri_override = properties.VALUES.auth.token_host.Get()
      if creds_type == client.SERVICE_ACCOUNT and token_uri_override:
        creds = creds.create_scoped([auth_util.CLOUD_PLATFORM_SCOPE],
                                    token_uri=token_uri_override)
      else:
        creds = creds.create_scoped([auth_util.CLOUD_PLATFORM_SCOPE])

    access_token_info = creds.get_access_token(http.Http())
    if not access_token_info:
      raise c_exc.ToolException(
          'No access token could be obtained from the current credentials.')

    return access_token_info
예제 #23
0
def Http(auth=True, creds=None, timeout='unset'):
    """Get an httplib2.Http client for working with the Google API.

  Args:
    auth: bool, True if the http client returned should be authorized.
    creds: oauth2client.client.Credentials, If auth is True and creds is not
        None, use those credentials to authorize the httplib2.Http client.
    timeout: double, The timeout in seconds to pass to httplib2.  This is the
        socket level timeout.  If timeout is None, timeout is infinite.  If
        default argument 'unset' is given, a sensible default is selected.

  Returns:
    An authorized httplib2.Http client object, or a regular httplib2.Http object
    if no credentials are available.

  Raises:
    c_store.Error: If an error loading the credentials occurs.
  """
    http_client = http.Http(timeout=timeout)

    authority_selector = properties.VALUES.auth.authority_selector.Get()
    authorization_token_file = (
        properties.VALUES.auth.authorization_token_file.Get())
    if authority_selector or authorization_token_file:
        http_client = _WrapRequestForIAMAuth(http_client, authority_selector,
                                             authorization_token_file)

    if auth:
        if not creds:
            creds = store.Load()
        http_client = creds.authorize(http_client)
        # Wrap the request method to put in our own error handling.
        http_client = http.Modifiers.WrapRequest(
            http_client, [], _HandleAuthError, client.AccessTokenRefreshError)

    return http_client
예제 #24
0
def RevokeCredentials(credentials):
    credentials.revoke(http.Http())
예제 #25
0
    def Run(self, args):
        """See ssh_utils.BaseSSHCommand.Run."""
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        cua_holder = base_classes.ComputeUserAccountsApiHolder(
            self.ReleaseTrack())
        client = holder.client

        ssh_helper = ssh_utils.BaseSSHHelper()
        ssh_helper.Run(args)
        ssh_helper.keys.EnsureKeysExist(args.force_key_file_overwrite,
                                        allow_passphrase=True)

        remote = ssh.Remote.FromArg(args.user_host)
        if not remote:
            raise ssh_utils.ArgumentError(
                'Expected argument of the form [USER@]INSTANCE. Received [{0}].'
                .format(args.user_host))
        if not remote.user:
            remote.user = ssh.GetDefaultSshUsername()

        hostname = '[{0}]:{1}'.format(args.serial_port_gateway,
                                      CONNECTION_PORT)
        # Update google_compute_known_hosts file with published host key
        if args.serial_port_gateway == SERIAL_PORT_GATEWAY:
            http_client = http.Http()
            http_response = http_client.request(HOST_KEY_URL)
            known_hosts = ssh.KnownHosts.FromDefaultFile()
            if http_response[0]['status'] == '200':
                host_key = http_response[1].strip()
                known_hosts.Add(hostname, host_key, overwrite=True)
                known_hosts.Write()
            elif known_hosts.ContainsAlias(hostname):
                log.warn(
                    'Unable to download and update Host Key for [{0}] from [{1}]. '
                    'Attempting to connect using existing Host Key in [{2}]. If '
                    'the connection fails, please try again to update the Host '
                    'Key.'.format(SERIAL_PORT_GATEWAY, HOST_KEY_URL,
                                  known_hosts.file_path))
            else:
                known_hosts.Add(hostname, DEFAULT_HOST_KEY)
                known_hosts.Write()
                log.warn(
                    'Unable to download Host Key for [{0}] from [{1}]. To ensure '
                    'the security of the SSH connetion, gcloud will attempt to '
                    'connect using a hard-coded Host Key value. If the connection '
                    'fails, please try again. If the problem persists, try '
                    'updating gcloud and connecting again.'.format(
                        SERIAL_PORT_GATEWAY, HOST_KEY_URL))
        instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources(
            [remote.host],
            compute_scope.ScopeEnum.ZONE,
            args.zone,
            holder.resources,
            scope_lister=instance_flags.GetInstanceZoneScopeLister(client))[0]
        instance = ssh_helper.GetInstance(client, instance_ref)
        project = ssh_helper.GetProject(client, instance_ref.project)

        # Determine the serial user, host tuple (remote)
        port = 'port={0}'.format(args.port)
        constructed_username_list = [
            instance_ref.project, instance_ref.zone,
            instance_ref.Name(), remote.user, port
        ]
        if args.extra_args:
            for k, v in args.extra_args.items():
                constructed_username_list.append('{0}={1}'.format(k, v))
        serial_user = '******'.join(constructed_username_list)
        serial_remote = ssh.Remote(args.serial_port_gateway, user=serial_user)

        identity_file = ssh_helper.keys.key_file
        options = ssh_helper.GetConfig(hostname,
                                       strict_host_key_checking='yes')
        del options['HostKeyAlias']
        cmd = ssh.SSHCommand(serial_remote,
                             identity_file=identity_file,
                             port=CONNECTION_PORT,
                             options=options)
        if args.dry_run:
            log.out.Print(' '.join(cmd.Build(ssh_helper.env)))
            return
        ssh_helper.EnsureSSHKeyExists(client, cua_holder.client, remote.user,
                                      instance, project)

        # Don't wait for the instance to become SSHable. We are not connecting to
        # the instance itself through SSH, so the instance doesn't need to have
        # fully booted to connect to the serial port. Also, ignore exit code 255,
        # since the normal way to terminate the serial port connection is ~. and
        # that causes ssh to exit with 255.
        try:
            return_code = cmd.Run(ssh_helper.env, force_connect=True)
        except ssh.CommandError:
            return_code = 255
        if return_code:
            sys.exit(return_code)
예제 #26
0
def Http(timeout='unset',
         response_encoding=None,
         ca_certs=None,
         enable_resource_quota=True,
         force_resource_quota=False,
         allow_account_impersonation=True,
         use_google_auth=None):
  """Get an httplib2.Http client for working with the Google API.

  Args:
    timeout: double, The timeout in seconds to pass to httplib2.  This is the
        socket level timeout.  If timeout is None, timeout is infinite.  If
        default argument 'unset' is given, a sensible default is selected.
    response_encoding: str, the encoding to use to decode the response.
    ca_certs: str, absolute filename of a ca_certs file that overrides the
        default
    enable_resource_quota: bool, By default, we are going to tell APIs to use
        the quota of the project being operated on. For some APIs we want to use
        gcloud's quota, so you can explicitly disable that behavior by passing
        False here.
    force_resource_quota: bool, If true resource project quota will be used by
      this client regardless of the settings in gcloud. This should be used for
      newer APIs that cannot work with legacy project quota.
    allow_account_impersonation: bool, True to allow use of impersonated service
      account credentials for calls made with this client. If False, the active
      user credentials will always be used.
    use_google_auth: bool, True if the calling command indicates to use
      google-auth library for authentication. If False, authentication will
      fallback to using the oauth2client library. If None, set the value based
      on the configuration.

  Returns:
    1. A regular httplib2.Http object if no credentials are available;
    2. Or a httplib2.Http client object authorized by oauth2client
       credentials if use_google_auth==False;
    3. Or a google_auth_httplib2.AuthorizedHttp client object authorized by
       google-auth credentials.

  Raises:
    c_store.Error: If an error loading the credentials occurs.
  """
  http_client = http.Http(timeout=timeout, response_encoding=response_encoding,
                          ca_certs=ca_certs)

  if use_google_auth is None:
    use_google_auth = base.UseGoogleAuth()
  request_wrapper = RequestWrapper()
  http_client = request_wrapper.WrapQuota(
      http_client,
      enable_resource_quota,
      force_resource_quota,
      allow_account_impersonation,
      use_google_auth)
  http_client = request_wrapper.WrapCredentials(http_client,
                                                allow_account_impersonation,
                                                use_google_auth)

  if hasattr(http_client, '_googlecloudsdk_credentials'):
    creds = http_client._googlecloudsdk_credentials  # pylint: disable=protected-access
    if core_creds.IsGoogleAuthCredentials(creds):
      apitools_creds = _GoogleAuthApitoolsCredentials(creds)
    else:
      apitools_creds = creds
    # apitools needs this attribute to do credential refreshes during batch API
    # requests.
    setattr(http_client.request, 'credentials', apitools_creds)

  return http_client
예제 #27
0
def Refresh(credentials,
            http_client=None,
            is_impersonated_credential=False,
            include_email=False,
            gce_token_format='standard',
            gce_include_license=False):
    """Refresh credentials.

  Calls credentials.refresh(), unless they're SignedJwtAssertionCredentials.
  If the credentials correspond to a service account or impersonated credentials
  issue an additional request to generate a fresh id_token.

  Args:
    credentials: oauth2client.client.Credentials, The credentials to refresh.
    http_client: httplib2.Http, The http transport to refresh with.
    is_impersonated_credential: bool, True treat provided credential as an
      impersonated service account credential. If False, treat as service
      account or user credential. Needed to avoid circular dependency on
      IMPERSONATION_TOKEN_PROVIDER.
    include_email: bool, Specifies whether or not the service account email is
      included in the identity token. Only applicable to impersonated service
      account.
    gce_token_format: str, Specifies whether or not the project and instance
      details are included in the identity token. Choices are "standard",
      "full".
    gce_include_license: bool, Specifies whether or not license codes for images
      associated with GCE instance are included in their identity tokens.

  Raises:
    TokenRefreshError: If the credentials fail to refresh.
    TokenRefreshReauthError: If the credentials fail to refresh due to reauth.
  """
    response_encoding = None if six.PY2 else 'utf-8'
    request_client = http_client or http.Http(
        response_encoding=response_encoding)
    try:
        credentials.refresh(request_client)

        id_token = None
        # Service accounts require an additional request to receive a fresh id_token
        if is_impersonated_credential:
            if not IMPERSONATION_TOKEN_PROVIDER:
                raise AccountImpersonationError(
                    'gcloud is configured to impersonate a service account but '
                    'impersonation support is not available.')
            if not IMPERSONATION_TOKEN_PROVIDER.IsImpersonationCredential(
                    credentials):
                raise AccountImpersonationError(
                    'Invalid impersonation account for refresh {}'.format(
                        credentials))
            id_token = _RefreshImpersonatedAccountIdToken(
                credentials, include_email=include_email)
        # Service accounts require an additional request to receive a fresh id_token
        elif isinstance(credentials,
                        service_account.ServiceAccountCredentials):
            id_token = _RefreshServiceAccountIdToken(credentials,
                                                     request_client)
        elif isinstance(credentials, oauth2client_gce.AppAssertionCredentials):
            id_token = c_gce.Metadata().GetIdToken(
                config.CLOUDSDK_CLIENT_ID,
                token_format=gce_token_format,
                include_license=gce_include_license)

        if id_token:
            if credentials.token_response:
                credentials.token_response['id_token'] = id_token
            credentials.id_tokenb64 = id_token

    except (client.AccessTokenRefreshError, httplib2.ServerNotFoundError) as e:
        raise TokenRefreshError(six.text_type(e))
    except reauth_errors.ReauthError as e:
        raise TokenRefreshReauthError(str(e))
예제 #28
0
    def Run(self, args):
        super(ConnectToSerialPort, self).Run(args)

        parts = args.user_host.split('@')
        if len(parts) == 1:
            user = getpass.getuser()
            instance = parts[0]
        elif len(parts) == 2:
            user, instance = parts
        else:
            raise exceptions.ToolException(
                'Expected argument of the form [USER@]INSTANCE; received [{0}].'
                .format(args.user_host))

        # Update google_compute_known_hosts file with published host key
        if args.serial_port_gateway == SERIAL_PORT_GATEWAY:
            http_client = http.Http()
            http_response = http_client.request(HOST_KEY_URL)
            hostname = '[{0}]:{1}'.format(SERIAL_PORT_GATEWAY, CONNECTION_PORT)
            known_hosts = ssh.KnownHosts.FromDefaultFile()
            if http_response[0]['status'] == '200':
                host_key = http_response[1].strip()
                known_hosts.Add(hostname, host_key, overwrite=True)
                known_hosts.Write()
            elif known_hosts.ContainsAlias(hostname):
                log.warn(
                    'Unable to download and update Host Key for [{0}] from [{1}]. '
                    'Attempting to connect using existing Host Key in [{2}]. If '
                    'the connection fails, please try again to update the Host '
                    'Key.'.format(SERIAL_PORT_GATEWAY, HOST_KEY_URL,
                                  known_hosts.file_path))
            else:
                known_hosts.Add(hostname, DEFAULT_HOST_KEY)
                known_hosts.Write()
                log.warn(
                    'Unable to download Host Key for [{0}] from [{1}]. To ensure '
                    'the security of the SSH connetion, gcloud will attempt to '
                    'connect using a hard-coded Host Key value. If the connection '
                    'fails, please try again. If the problem persists, try '
                    'updating gcloud and connecting again.'.format(
                        SERIAL_PORT_GATEWAY, HOST_KEY_URL))

        instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources(
            [instance],
            compute_scope.ScopeEnum.ZONE,
            args.zone,
            self.resources,
            scope_lister=flags.GetDefaultScopeLister(self.compute_client,
                                                     self.project))[0]
        instance = self.GetInstance(instance_ref)

        ssh_args = [self.ssh_executable]

        ssh_args.extend(self.GetDefaultFlags())
        if args.serial_port_gateway == SERIAL_PORT_GATEWAY:
            ssh_args.extend(['-o', 'StrictHostKeyChecking=yes'])

        ssh_args.extend(['-p', CONNECTION_PORT])

        if args.port:
            port = 'port={0}'.format(args.port)
        else:
            port = 'port=1'

        constructed_username_list = [
            instance_ref.project, instance_ref.zone,
            instance_ref.Name(), user, port
        ]

        if args.extra_args:
            for k, v in args.extra_args.items():
                constructed_username_list.append('{0}={1}'.format(k, v))

        ssh_args.append(
            ssh.UserHost('.'.join(constructed_username_list),
                         args.serial_port_gateway))

        log.info('ssh command: {0}'.format(' '.join(ssh_args)))

        # Don't wait for the instance to become SSHable. We are not connecting to
        # the instance itself through SSH, so the instance doesn't need to have
        # fully booted to connect to the serial port. Also, ignore exit code 255,
        # since the normal way to terminate the serial port connection is ~. and
        # that causes ssh to exit with 255.
        return_code = self.ActuallyRun(args,
                                       ssh_args,
                                       user,
                                       instance,
                                       instance_ref.project,
                                       strict_error_checking=False,
                                       use_account_service=False,
                                       wait_for_sshable=False,
                                       ignore_ssh_errors=True)
        if return_code:
            sys.exit(return_code)
예제 #29
0
def Http(timeout='unset',
         enable_resource_quota=True,
         force_resource_quota=False,
         response_encoding=None,
         ca_certs=None,
         allow_account_impersonation=True):
    """Get an httplib2.Http client for working with the Google API.

  Args:
    timeout: double, The timeout in seconds to pass to httplib2.  This is the
        socket level timeout.  If timeout is None, timeout is infinite.  If
        default argument 'unset' is given, a sensible default is selected.
    enable_resource_quota: bool, By default, we are going to tell APIs to use
        the quota of the project being operated on. For some APIs we want to use
        gcloud's quota, so you can explicitly disable that behavior by passing
        False here.
    force_resource_quota: bool, If true resource project quota will be used by
      this client regardless of the settings in gcloud. This should be used for
      newer APIs that cannot work with legacy project quota.
    response_encoding: str, the encoding to use to decode the response.
    ca_certs: str, absolute filename of a ca_certs file that overrides the
        default
    allow_account_impersonation: bool, True to allow use of impersonated service
      account credentials for calls made with this client. If False, the active
      user credentials will always be used.

  Returns:
    An authorized httplib2.Http client object, or a regular httplib2.Http object
    if no credentials are available.

  Raises:
    c_store.Error: If an error loading the credentials occurs.
  """
    http_client = http.Http(timeout=timeout,
                            response_encoding=response_encoding,
                            ca_certs=ca_certs)

    # Wrappers for IAM header injection.
    authority_selector = properties.VALUES.auth.authority_selector.Get()
    authorization_token_file = (
        properties.VALUES.auth.authorization_token_file.Get())
    handlers = _GetIAMAuthHandlers(authority_selector,
                                   authorization_token_file)

    creds = store.LoadIfEnabled(
        allow_account_impersonation=allow_account_impersonation)
    if creds:
        # Inject the resource project header for quota unless explicitly disabled.
        if enable_resource_quota or force_resource_quota:
            quota_project = core_creds.GetQuotaProject(creds,
                                                       force_resource_quota)
            if quota_project:
                handlers.append(
                    http.Modifiers.Handler(
                        http.Modifiers.SetHeader('X-Goog-User-Project',
                                                 quota_project)))

        http_client = creds.authorize(http_client)
        # Wrap the request method to put in our own error handling.
        http_client = http.Modifiers.WrapRequest(
            http_client, handlers, _HandleAuthError,
            client.AccessTokenRefreshError)

    return http_client
예제 #30
0
 def _Run(command):
     del command
     http.Http().request('https://example.com', method='GET')