Beispiel #1
0
  def SetUp(self):
    self.fake_project = 'fake-project'
    self.fake_account = 'fake-account'
    properties.VALUES.core.account.Set(self.fake_account)
    properties.VALUES.core.project.Set(self.fake_project)

    # Set up user credentials
    self.fake_cred = client.OAuth2Credentials(
        'access-token',
        'client_id',
        'client_secret',
        'fake-token',
        datetime.datetime(2021, 1, 8, 0, 0, 0),
        'token_uri',
        'user_agent',
        scopes=config.CLOUDSDK_SCOPES)
    store.Store(self.fake_cred)
    store.Load()

    self.api_version = artifacts.API_VERSION_FOR_TRACK[self.track]
    self.client = mock.Client(
        core_apis.GetClientClass(API_NAME, self.api_version),
        real_client=core_apis.GetClientInstance(API_NAME, self.api_version))
    self.client.Mock()
    self.messages = core_apis.GetMessagesModule(API_NAME, self.api_version)
    self.addCleanup(self.client.Unmock)
Beispiel #2
0
    def SetUp(self):
        properties.VALUES.core.account.Set('fakeuser')
        fake_creds = self.MakeUserAccountCredentialsGoogleAuth()
        fake_creds.token = 'access-token'
        store.Store(fake_creds)
        properties.VALUES.auth.impersonate_service_account.Set(
            '*****@*****.**')

        self.refresh_mock = self.StartObjectPatch(
            google_auth_credentials.UserCredWithReauth, 'refresh')
        self.StartObjectPatch(client.OAuth2Credentials, 'refresh')

        self.request_mock = self.StartObjectPatch(
            httplib2.Http,
            'request',
            autospec=True,
            return_value=(httplib2.Response({'status': 200}), b''))
        self.impersonation_token = 'impersonation-token'
        self.StartObjectPatch(impersonated_credentials,
                              '_make_iam_token_request',
                              return_value=(self.impersonation_token,
                                            datetime.datetime(
                                                9999, 2, 3, 14, 15, 16)))

        store.IMPERSONATION_TOKEN_PROVIDER = (
            util.ImpersonationAccessTokenProvider())
    def SetUp(self):
        properties.VALUES.core.account.Set('fakeuser')
        self.fake_cred = client.OAuth2Credentials(
            'access-token',
            'client_id',
            'client_secret',
            'fake-token',
            None,
            'token_uri',
            'user_agent',
            scopes=config.CLOUDSDK_SCOPES)
        store.Store(self.fake_cred)
        self.refresh_mock = self.StartObjectPatch(client.OAuth2Credentials,
                                                  'refresh')

        self.mock_client = mock.Client(
            apis.GetClientClass('iamcredentials', 'v1'))
        self.mock_client.Mock()
        self.addCleanup(self.mock_client.Unmock)
        self.messages = self.mock_client.MESSAGES_MODULE
        self.gen_request_msg = (
            self.messages.
            IamcredentialsProjectsServiceAccountsGenerateAccessTokenRequest)

        self.request_mock = self.StartObjectPatch(httplib2.Http,
                                                  'request',
                                                  autospec=True)
Beispiel #4
0
  def testServiceAccountImpersonation(self):
    # This is the logged in credential, but it will not be used to make the call
    # because of the impersonation.
    store.Store(self.fake_cred)
    properties.VALUES.auth.impersonate_service_account.Set('*****@*****.**')

    # Expect a call to get a temp access token for impersonation.
    fake_token = 'impersonation-token'
    self.mock_client.projects_serviceAccounts.GenerateAccessToken.Expect(
        self.gen_request_msg(
            name='projects/-/serviceAccounts/[email protected]',
            generateAccessTokenRequest=self.messages.GenerateAccessTokenRequest(
                scope=config.CLOUDSDK_SCOPES)),
        self.messages.GenerateAccessTokenResponse(
            accessToken=fake_token, expireTime='2016-01-08T00:00:00Z')
    )

    request_mock = self.StartObjectPatch(
        httplib2.Http, 'request',
        return_value=(httplib2.Response({'status': 200}), b''))
    try:
      store.IMPERSONATION_TOKEN_PROVIDER = (
          util.ImpersonationAccessTokenProvider())
      http.Http().request('http://foo.com', 'GET', None, {})
      access_token = request_mock.call_args[0][3][b'Authorization']
      self.assertEqual(access_token, b'Bearer ' + fake_token.encode('utf8'))
    finally:
      store.IMPERSONATION_TOKEN_PROVIDER = None
Beispiel #5
0
 def SetUp(self):
   with mock.patch('googlecloudsdk.core.credentials.store.Refresh') as ref:
     ref.return_value = None
     self._ActivateRefreshToken()
     creds = c_store.Load(use_google_auth=True)
   creds.token = 'invalid_access_token'
   c_store.Store(creds)
Beispiel #6
0
  def Run(self, args):
    """Run the authentication command."""

    if c_devshell.IsDevshellEnvironment():
      message = """
          You are already authenticated with gcloud when running
          inside the Cloud Shell and so do not need to run this
          command.

          Do you wish to proceed anyway?
        """
      answer = console_io.PromptContinue(message=message)
      if not answer:
        return None
    elif c_gce.Metadata().connected:
      message = textwrap.dedent("""
          You are running on a Google Compute Engine virtual machine.
          It is recommended that you use service accounts for authentication.

          You can run:

            $ gcloud config set account ``ACCOUNT''

          to switch accounts if necessary.

          Your credentials may be visible to others with access to this
          virtual machine. Are you sure you want to authenticate with
          your personal account?
          """)
      answer = console_io.PromptContinue(message=message)
      if not answer:
        return None

    account = args.account

    if account and not args.force:
      creds = c_store.LoadIfValid(account=account)
      if creds:
        # Account already has valid creds, just switch to it.
        return self.LoginAs(account, creds, args.project, args.activate,
                            args.brief)

    # No valid creds, do the web flow.
    launch_browser = auth_util.ShouldLaunchBrowser(args.launch_browser)
    creds = self.DoInstalledAppBrowserFlow(launch_browser)
    web_flow_account = creds.id_token['email']
    if account and account.lower() != web_flow_account.lower():
      raise c_exc.ToolException(
          'You attempted to log in as account [{account}] but the received '
          'credentials were for account [{web_flow_account}].\n\n'
          'Please check that your browser is logged in as account [{account}] '
          'and that you are using the correct browser profile.'.format(
              account=account, web_flow_account=web_flow_account))

    account = web_flow_account
    # We got new creds, and they are for the correct user.
    c_store.Store(creds, account)
    return self.LoginAs(account, creds, args.project, args.activate,
                        args.brief)
Beispiel #7
0
 def SetUp(self):
   self.StartPatch('googlecloudsdk.core.credentials.store.Refresh')
   self._ActivateRefreshToken()
   creds = c_store.Load(use_google_auth=True)
   # Make sure an invalid token is sent to services.
   creds.token = 'invalid_access_token'
   creds.expiry = creds.expiry + datetime.timedelta(hours=1)
   c_store.Store(creds)
def _SetUpWithServiceAccount(self):
  properties.VALUES.core.account.Set('fakeuser')
  fake_creds = self.MakeServiceAccountCredentialsGoogleAuth()
  fake_creds.expiry = datetime.datetime.utcnow() + datetime.timedelta(
      seconds=3600)
  store.Store(fake_creds)
  self.request_mock = self.StartObjectPatch(
      httplib2.Http, 'request', autospec=True)
  self.request_mock.return_value = (httplib2.Response({'status': 200}),
                                    b'{"projects": []}')
Beispiel #9
0
  def testRefreshImpersonationAccountId(self):
    # Store test credential
    store.Store(self.fake_cred)
    properties.VALUES.auth.impersonate_service_account.Set('*****@*****.**')
    try:
      # Set Token Provider
      store.IMPERSONATION_TOKEN_PROVIDER = (
          util.ImpersonationAccessTokenProvider())
      # Mock response from util.GenerateAccessToken
      self.mock_client.projects_serviceAccounts.GenerateAccessToken.Expect(
          self.gen_request_msg(
              name='projects/-/serviceAccounts/[email protected]',
              generateAccessTokenRequest=(
                  self.messages.GenerateAccessTokenRequest(
                      scope=config.CLOUDSDK_SCOPES))),
          self.messages.GenerateAccessTokenResponse(
              accessToken='impersonation-token',
              expireTime='2016-01-08T00:00:00Z'))

      # Load test impersonation token
      loaded = store.Load(allow_account_impersonation=True)
      loaded.token_response = {'id_token': 'old-id-token'}
      audience = 'https://service-hash-uc.a.run.app'
      config.CLOUDSDK_CLIENT_ID = audience

      # Refresh the credential
      # Mock response from util.GenerateAccessToken (2nd call from Refresh)
      self.mock_client.projects_serviceAccounts.GenerateAccessToken.Expect(
          self.gen_request_msg(
              name='projects/-/serviceAccounts/[email protected]',
              generateAccessTokenRequest=(
                  self.messages.GenerateAccessTokenRequest(
                      scope=config.CLOUDSDK_SCOPES))),
          self.messages.GenerateAccessTokenResponse(
              accessToken='impersonation-token',
              expireTime='2016-01-08T00:00:00Z'))

      # Mock response from util.GenerateIdToken
      new_token_id = 'new-id-token'
      self.mock_client.projects_serviceAccounts.GenerateIdToken.Expect(
          self.gen_id_msg(
              name='projects/-/serviceAccounts/[email protected]',
              generateIdTokenRequest=self.messages.GenerateIdTokenRequest(
                  audience=audience, includeEmail=False)),
          self.messages.GenerateIdTokenResponse(token=new_token_id)
      )
      # Load test impersonation token
      loaded = store.Load(allow_account_impersonation=True)
      loaded.token_response = {'id_token': 'old-id-token'}
      audience = 'https://service-hash-uc.a.run.app'
      config.CLOUDSDK_CLIENT_ID = audience
      store.Refresh(loaded, is_impersonated_credential=True)
      self.assertEqual(loaded.token_response['id_token'], new_token_id)
    finally:  # Clean-Up
      store.IMPERSONATION_TOKEN_PROVIDER = None
Beispiel #10
0
 def SetUp(self):
     with mock.patch(
             'googlecloudsdk.core.credentials.store.Refresh') as ref:
         ref.return_value = None
         self.Run('auth activate-refresh-token {account} {token}'.format(
             account=self.Account(),
             token=_TEST_CONFIG['auth_data']['user_account']
             ['refresh_token']))
         creds = c_store.Load()
         creds.access_token = 'invalid_access_token'
         c_store.Store(creds)
def _SetUpWithUserAccount(self):
  properties.VALUES.core.account.Set('fakeuser')
  fake_creds = self.MakeUserAccountCredentialsGoogleAuth()
  fake_creds.token = 'access-token'
  store.Store(fake_creds)

  self.refresh_mock = self.StartObjectPatch(
      google_auth_credentials.UserCredWithReauth, 'refresh')
  self.request_mock = self.StartObjectPatch(
      httplib2.Http, 'request', autospec=True)
  self.request_mock.return_value = (httplib2.Response({'status': 200}),
                                    b'{"projects": []}')
  def Run(self, args):
    """Create service account credentials."""

    try:
      private_key = open(args.key_file).read()
    except IOError as e:
      raise c_exc.BadFileException(e)

    password = None
    if args.password_file:
      try:
        password = open(args.password_file).read().strip()
      except IOError as e:
        raise c_exc.UnknownArgumentException('--password-file', e)
    if args.prompt_for_password:
      password = getpass.getpass('Password: '******'CLOUDSDK_PYTHON_SITEPACKAGES'):
        raise c_exc.ToolException(
            ('PyOpenSSL is not available. If you have already installed '
             'PyOpenSSL, you will need to enable site packages by '
             'setting the environment variable CLOUDSDK_PYTHON_SITEPACKAGES to '
             '1. If that does not work, See '
             'https://developers.google.com/cloud/sdk/crypto for details.'))
      else:
        raise c_exc.ToolException(
            ('PyOpenSSL is not available. See '
             'https://developers.google.com/cloud/sdk/crypto for details.'))

    if password:
      cred = client.SignedJwtAssertionCredentials(
          service_account_name=args.account,
          private_key=private_key,
          scope=config.CLOUDSDK_SCOPES,
          private_key_password=password,
          user_agent=config.CLOUDSDK_USER_AGENT)
    else:
      cred = client.SignedJwtAssertionCredentials(
          service_account_name=args.account,
          private_key=private_key,
          scope=config.CLOUDSDK_SCOPES,
          user_agent=config.CLOUDSDK_USER_AGENT)

    c_store.Store(cred, args.account)

    properties.PersistProperty(properties.VALUES.core.account, args.account)

    project = args.project
    if project:
      properties.PersistProperty(properties.VALUES.core.project, project)

    return cred
Beispiel #13
0
 def testGenerateAccessToken(self):
   store.Store(self.fake_cred)
   self.mock_client.projects_serviceAccounts.GenerateAccessToken.Expect(
       self.gen_request_msg(
           name='projects/-/serviceAccounts/[email protected]',
           generateAccessTokenRequest=self.messages.GenerateAccessTokenRequest(
               scope=config.CLOUDSDK_SCOPES)),
       self.messages.GenerateAccessTokenResponse(
           accessToken='access-token', expireTime='2016-01-08T00:00:00Z')
   )
   result = util.GenerateAccessToken('*****@*****.**', config.CLOUDSDK_SCOPES)
   self.assertEqual(result.accessToken, 'access-token')
   self.assertEqual(result.expireTime, '2016-01-08T00:00:00Z')
Beispiel #14
0
  def testGenerateIdToken(self):
    audience = 'https://service-hash-uc.a.run.app'
    store.Store(self.fake_cred)
    self.mock_client.projects_serviceAccounts.GenerateIdToken.Expect(
        self.gen_id_msg(
            name='projects/-/serviceAccounts/[email protected]',
            generateIdTokenRequest=self.messages.GenerateIdTokenRequest(
                audience=audience, includeEmail=False)),
        self.messages.GenerateIdTokenResponse(token='id-token')
    )

    result = util.GenerateIdToken('*****@*****.**', audience)

    self.assertEqual(result, 'id-token')
Beispiel #15
0
    def Run(self, args):
        """Run the authentication command."""

        if c_gce.Metadata().connected:
            message = textwrap.dedent("""
          You are running on a GCE VM. It is recommended that you use
          service accounts for authentication.

          You can run:

            $ gcloud config set account ``ACCOUNT''

          to switch accounts if necessary.

          Your credentials may be visible to others with access to this
          virtual machine. Are you sure you want to authenticate with
          your personal account?
          """)
            answer = console_io.PromptContinue(message=message)
            if not answer:
                return None

        account = args.account

        if account and not args.force:
            creds = c_store.LoadIfValid(account=account)
            if creds:
                # Account already has valid creds, just switch to it.
                return self.LoginAs(account, creds, args.project,
                                    args.do_not_activate)

        # No valid creds, do the web flow.
        creds = self.DoWebFlow(args.launch_browser)
        web_flow_account = creds.token_response['id_token']['email']
        if account and account != web_flow_account:
            raise c_exc.ToolException(
                'You attempted to log in as account [{account}] but the received '
                'credentials were for account [{web_flow_account}].\n\n'
                'Please check that your browser is logged in as account [{account}] '
                'and that you are using the correct browser profile.'.format(
                    account=account, web_flow_account=web_flow_account))

        account = web_flow_account
        # We got new creds, and they are for the correct user.
        c_store.Store(creds, account)
        return self.LoginAs(account, creds, args.project, args.do_not_activate)
    def SetUp(self):
        properties.VALUES.core.account.Set('fakeuser')
        fake_creds = self.MakeUserAccountCredentialsGoogleAuth()
        fake_creds.token = 'access-token'
        store.Store(fake_creds)
        self.refresh_mock = self.StartObjectPatch(
            google_auth_credentials.UserCredWithReauth, 'refresh')
        self.StartObjectPatch(client.OAuth2Credentials, 'refresh')

        self.request_mock = self.StartObjectPatch(httplib2.Http,
                                                  'request',
                                                  autospec=True)
        self.StartObjectPatch(impersonated_credentials,
                              '_make_iam_token_request',
                              return_value=('impersonation-token',
                                            datetime.datetime(
                                                9999, 2, 3, 14, 15, 16)))
Beispiel #17
0
def _SetUp(self):
    properties.VALUES.core.account.Set('fakeuser')
    self.fake_cred = client.OAuth2Credentials('access-token',
                                              'client_id',
                                              'client_secret',
                                              'fake-token',
                                              None,
                                              'token_uri',
                                              'user_agent',
                                              scopes=config.CLOUDSDK_SCOPES)
    store.Store(self.fake_cred)

    self.refresh_mock = self.StartObjectPatch(client.OAuth2Credentials,
                                              'refresh')
    self.request_mock = self.StartObjectPatch(httplib2.Http,
                                              'request',
                                              autospec=True)
    self.request_mock.return_value = (httplib2.Response({'status': 200}),
                                      b'{"projects": []}')
Beispiel #18
0
    def Run(self, args):
        """Run the authentication command."""

        token = args.token or console_io.PromptResponse('Refresh token: ')
        if not token:
            raise c_exc.InvalidArgumentException('token', 'No value provided.')

        creds = c_store.AcquireFromToken(token)
        account = args.account

        c_store.Refresh(creds)

        c_store.Store(creds, account)

        properties.PersistProperty(properties.VALUES.core.account, account)

        project = args.project
        if project:
            properties.PersistProperty(properties.VALUES.core.project, project)

        return creds
    def Run(self, args):
        """Run the authentication command."""

        if args.cred_file:
            cred_config = auth_util.GetCredentialsConfigFromFile(
                args.cred_file)
        else:
            cred_config = None

        scopes = GetScopes(args)

        if not ShouldContinueLogin(cred_config):
            return None

        if args.cred_file:
            return LoginWithCredFileConfig(cred_config, scopes, args.project,
                                           args.activate, args.brief,
                                           args.update_adc,
                                           args.add_quota_project_to_adc,
                                           args.account)

        if ShouldUseCachedCredentials(args, scopes):
            creds = c_store.Load(account=args.account, scopes=scopes)
            return LoginAs(args.account, creds, args.project, args.activate,
                           args.brief, args.update_adc,
                           args.add_quota_project_to_adc)

        # No valid creds, do the web flow.
        creds = auth_util.DoInstalledAppBrowserFlowGoogleAuth(
            scopes,
            no_launch_browser=not args.launch_browser,
            no_browser=args.no_browser,
            remote_bootstrap=args.remote_bootstrap)
        if not creds:
            return
        account = ExtractAndValidateAccount(args.account, creds)
        # We got new creds, and they are for the correct user.
        c_store.Store(creds, account, scopes)
        return LoginAs(account, creds, args.project, args.activate, args.brief,
                       args.update_adc, args.add_quota_project_to_adc)
Beispiel #20
0
  def SetUpCreds(self):
    """Set up service account credentials."""
    sa_creds = self.MakeServiceAccountCredentials()
    sa_creds.token_expiry = (
        datetime.datetime.utcnow() + datetime.timedelta(hours=2))

    store.Store(sa_creds, self.fake_account)
    store.Load(self.fake_account)
    creds_type = creds.CredentialType.FromCredentials(sa_creds)
    paths = config.Paths()
    with open(paths.LegacyCredentialsAdcPath(self.fake_account)) as f:
      adc_file = json.load(f)
    # Compare file contents to make sure credentials are set up correctly.
    self.assertEqual(
        json.loads("""\
        {
          "client_email": "*****@*****.**",
          "client_id": "bar.apps.googleusercontent.com",
          "private_key": "-----BEGIN PRIVATE KEY-----\\nasdf\\n-----END PRIVATE KEY-----\\n",
          "private_key_id": "key-id",
          "type": "service_account"
        }"""), adc_file)
    self.assertEqual(creds.CredentialType.SERVICE_ACCOUNT, creds_type)
Beispiel #21
0
    def Run(self, args):
        """Run the authentication command."""

        scopes = config.CLOUDSDK_SCOPES
        # Add REAUTH scope in case the user has 2fact activated.
        # This scope is only used here and when refreshing the access token.
        scopes += (config.REAUTH_SCOPE, )

        if args.enable_gdrive_access:
            scopes += (auth_util.GOOGLE_DRIVE_SCOPE, )

        if c_devshell.IsDevshellEnvironment():
            if c_devshell.HasDevshellAuth():
                message = textwrap.dedent("""
            You are already authenticated with gcloud when running
            inside the Cloud Shell and so do not need to run this
            command. Do you wish to proceed anyway?
            """)
                answer = console_io.PromptContinue(message=message)
                if not answer:
                    return None
        elif c_gce.Metadata().connected:
            message = textwrap.dedent("""
          You are running on a Google Compute Engine virtual machine.
          It is recommended that you use service accounts for authentication.

          You can run:

            $ gcloud config set account `ACCOUNT`

          to switch accounts if necessary.

          Your credentials may be visible to others with access to this
          virtual machine. Are you sure you want to authenticate with
          your personal account?
          """)
            answer = console_io.PromptContinue(message=message)
            if not answer:
                return None

        account = args.account

        if account and not args.force:
            try:
                creds = c_store.Load(account=account, scopes=scopes)
            except c_store.Error:
                creds = None
            if creds:
                # Account already has valid creds, just switch to it.
                log.warning(
                    'Re-using locally stored credentials for [{}]. '
                    'To fetch new credentials, re-run the command with the '
                    '`--force` flag.'.format(account))
                return LoginAs(account, creds, args.project, args.activate,
                               args.brief, args.update_adc)

        # No valid creds, do the web flow.
        launch_browser = check_browser.ShouldLaunchBrowser(args.launch_browser)
        creds = auth_util.DoInstalledAppBrowserFlow(launch_browser, scopes)
        web_flow_account = creds.id_token['email']
        if account and account.lower() != web_flow_account.lower():
            raise auth_exceptions.WrongAccountError(
                'You attempted to log in as account [{account}] but the received '
                'credentials were for account [{web_flow_account}].\n\n'
                'Please check that your browser is logged in as account [{account}] '
                'and that you are using the correct browser profile.'.format(
                    account=account, web_flow_account=web_flow_account))

        account = web_flow_account
        # We got new creds, and they are for the correct user.
        c_store.Store(creds, account, scopes)
        return LoginAs(account, creds, args.project, args.activate, args.brief,
                       args.update_adc)
Beispiel #22
0
  def Run(self, args):
    """Create service account credentials."""

    try:
      private_key = open(args.key_file, 'rb').read()
    except IOError as e:
      raise c_exc.BadFileException(e)

    json_key = None
    try:
      json_key = json.loads(private_key)
    except ValueError:
      pass

    account = None
    if json_key:
      if args.password_file or args.prompt_for_password:
        raise c_exc.InvalidArgumentException(
            '--password-file',
            'A .json service account key does not require a password.')
      account = json_key.get('client_email', None)
      if not account:
        raise c_exc.ToolException(
            'The .json key file is not in a valid format.')
      if args.account and args.account != account:
        raise c_exc.InvalidArgumentException(
            'ACCOUNT',
            'The given account name does not match the account name in the key '
            'file.  This argument can be omitted when using .json keys.')
      cred = service_account.ServiceAccountCredentials(
          service_account_id=json_key['client_id'],
          service_account_email=json_key['client_email'],
          private_key_id=json_key['private_key_id'],
          private_key_pkcs8_text=json_key['private_key'],
          scopes=config.CLOUDSDK_SCOPES,
          user_agent=config.CLOUDSDK_USER_AGENT)
    else:
      account = args.account
      if not account:
        raise c_exc.RequiredArgumentException(
            'ACCOUNT', 'An account is required when using .p12 keys')
      password = None
      if args.password_file:
        try:
          password = open(args.password_file).read().strip()
        except IOError as e:
          raise c_exc.UnknownArgumentException('--password-file', e)
      if args.prompt_for_password:
        password = getpass.getpass('Password: '******'CLOUDSDK_PYTHON_SITEPACKAGES'):
          raise c_exc.ToolException(
              ('PyOpenSSL is not available. If you have already installed '
               'PyOpenSSL, you will need to enable site packages by '
               'setting the environment variable CLOUDSDK_PYTHON_SITEPACKAGES '
               'to 1. If that does not work, see '
               'https://developers.google.com/cloud/sdk/crypto for details.'))
        else:
          raise c_exc.ToolException(
              ('PyOpenSSL is not available. See '
               'https://developers.google.com/cloud/sdk/crypto for details.'))

      if password:
        cred = client.SignedJwtAssertionCredentials(
            service_account_name=account,
            private_key=private_key,
            scope=config.CLOUDSDK_SCOPES,
            private_key_password=password,
            user_agent=config.CLOUDSDK_USER_AGENT)
      else:
        cred = client.SignedJwtAssertionCredentials(
            service_account_name=account,
            private_key=private_key,
            scope=config.CLOUDSDK_SCOPES,
            user_agent=config.CLOUDSDK_USER_AGENT)
      try:
        c_store.Refresh(cred)
      except c_store.RefreshError:
        log.error(
            'Failed to activate the given service account.  Please ensure the '
            'key is valid and that you have provided the correct account name.')
        raise

    c_store.Store(cred, account)

    properties.PersistProperty(properties.VALUES.core.account, account)

    project = args.project
    if project:
      properties.PersistProperty(properties.VALUES.core.project, project)

    log.status.Print('Activated service account credentials for: [{0}]'
                     .format(account))
    return cred
Beispiel #23
0
    def Run(self, args):
        """Run the helper command."""

        if args.method not in GitHelper.METHODS:
            if args.ignore_unknown:
                return
            raise c_exc.ToolException(
                'Unexpected method [{meth}]. One of [{methods}] expected.'.
                format(meth=args.method, methods=', '.join(GitHelper.METHODS)))

        info = self._ParseInput()
        credentialed_domains = [
            'code.google.com', 'source.developers.google.com'
        ]
        extra = properties.VALUES.core.credentialed_hosted_repo_domains.Get()
        if extra:
            credentialed_domains.extend(extra.split(','))
        if info.get('host') not in credentialed_domains:
            if args.ignore_unknown:
                return
            raise c_exc.ToolException(
                'Unknown host [{host}].'.format(host=info.get('host')))

        if args.method == GitHelper.GET:
            account = properties.VALUES.core.account.Get()
            try:
                cred = c_store.Load(account)
                c_store.Refresh(cred)
                c_store.Store(cred, account)
            except c_store.Error as e:
                sys.stderr.write(
                    textwrap.dedent("""\
            ERROR: {error}
            Run 'gcloud auth login' to log in.
            """.format(error=str(e))))
                return

            self._CheckNetrc()

            sys.stdout.write(
                textwrap.dedent("""\
          username={username}
          password={password}
          """).format(username=account, password=cred.access_token))
        elif args.method == GitHelper.STORE:
            # On OSX, there is an additional credential helper that gets called before
            # ours does.  When we return a token, it gets cached there.  Git continues
            # to get it from there first until it expires.  That command then fails,
            # and the token is deleted, but it does not retry the operation.  The next
            # command gets a new token from us and it starts working again, for an
            # hour.  This erases our credential from the other cache whenever 'store'
            # is called on us.  Because they are called first, the token will already
            # be stored there, and so we can successfully erase it to prevent caching.
            if (platforms.OperatingSystem.Current() ==
                    platforms.OperatingSystem.MACOSX):
                log.debug('Clearing OSX credential cache.')
                try:
                    input_string = 'protocol={protocol}\nhost={host}\n\n'.format(
                        protocol=info.get('protocol'), host=info.get('host'))
                    log.debug('Calling erase with input:\n%s', input_string)
                    p = subprocess.Popen(
                        ['git-credential-osxkeychain', 'erase'],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
                    (out, err) = p.communicate(input_string)
                    if p.returncode:
                        log.debug(
                            'Failed to clear OSX keychain:\nstdout: {%s}\nstderr: {%s}',
                            out, err)
                # pylint:disable=broad-except, This can fail and should only be done as
                # best effort.
                except Exception as e:
                    log.debug('Failed to clear OSX keychain', exc_info=True)
 def testNoSerialize(self):
     creds = c_store.Load()
     # This should just do nothing. If the creds are actually serialized,
     # things blow up.
     c_store.Store(creds)
def LoginWithCredFileConfig(cred_config, scopes, project, activate, brief,
                            update_adc, add_quota_project_to_adc,
                            args_account):
    """Login with the provided configuration loaded from --cred-file.

  Args:
    cred_config (Mapping): The configuration dictionary representing the
      credentials. This is loaded from the --cred-file argument.
    scopes (Tuple[str]): The default OAuth scopes to use.
    project (Optional[str]): The optional project ID to activate / persist.
    activate (bool): Whether to set the new account associated with the
      credentials to active.
    brief (bool): Whether to use minimal user output.
    update_adc (bool): Whether to write the obtained credentials to the
      well-known location for Application Default Credentials (ADC).
    add_quota_project_to_adc (bool): Whether to add the quota project to the
      application default credentials file.
    args_account (Optional[str]): The optional ACCOUNT argument. When provided,
      this should match the account ID on the authenticated credentials.

  Returns:
    google.auth.credentials.Credentials: The authenticated stored credentials.

  Raises:
    calliope_exceptions.ConflictingArgumentsException: If conflicting arguments
      are provided.
    calliope_exceptions.InvalidArgumentException: If invalid arguments are
      provided.
  """
    # Remove reauth scope (only applicable to 1P user accounts).
    scopes = tuple(x for x in scopes if x != config.REAUTH_SCOPE)
    # Reject unsupported arguments.
    if add_quota_project_to_adc:
        raise calliope_exceptions.ConflictingArgumentsException(
            '[--add-quota-project-to-adc] cannot be specified with --cred-file'
        )
    if auth_external_account.IsExternalAccountConfig(cred_config):
        creds = auth_external_account.CredentialsFromAdcDictGoogleAuth(
            cred_config)
        account = auth_external_account.GetExternalAccountId(creds)
    elif auth_service_account.IsServiceAccountConfig(cred_config):
        creds = auth_service_account.CredentialsFromAdcDictGoogleAuth(
            cred_config)
        account = creds.service_account_email
    else:
        raise calliope_exceptions.InvalidArgumentException(
            '--cred-file',
            'Only external account or service account JSON credential file types '
            'are supported.')

    if args_account and args_account != account:
        raise calliope_exceptions.InvalidArgumentException(
            'ACCOUNT',
            'The given account name does not match the account name in the '
            'credential file. This argument can be omitted when using '
            'credential files.')
    # Check if account already exists in storage.
    try:
        exist_creds = c_store.Load(account=account, scopes=scopes)
    except creds_exceptions.Error:
        exist_creds = None
    if exist_creds:
        message = textwrap.dedent("""
      You are already authenticated with '%s'.
      Do you wish to proceed and overwrite existing credentials?
      """)
        answer = console_io.PromptContinue(message=message % account,
                                           default=True)
        if not answer:
            return None
    # Store credentials and activate if --activate is true.
    c_store.Store(creds, account, scopes=scopes)
    return LoginAs(account, creds, project, activate, brief, update_adc, False)
Beispiel #26
0
  def Run(self, args):
    """Create service account credentials."""

    try:
      private_key = open(args.key_file, 'rb').read()
    except IOError as e:
      raise c_exc.BadFileException(e)

    json_key = None
    try:
      json_key = json.loads(private_key)
    except ValueError:
      pass

    if json_key and (args.password_file or args.prompt_for_password):
      raise c_exc.InvalidArgumentException(
          '--password-file',
          'A .json service account key does not require a password.')

    password = None
    if args.password_file:
      try:
        password = open(args.password_file).read().strip()
      except IOError as e:
        raise c_exc.UnknownArgumentException('--password-file', e)
    if args.prompt_for_password:
      password = getpass.getpass('Password: '******'CLOUDSDK_PYTHON_SITEPACKAGES'):
        raise c_exc.ToolException(
            ('PyOpenSSL is not available. If you have already installed '
             'PyOpenSSL, you will need to enable site packages by '
             'setting the environment variable CLOUDSDK_PYTHON_SITEPACKAGES to '
             '1. If that does not work, see '
             'https://developers.google.com/cloud/sdk/crypto for details '
             'or consider using .json private key instead.'))
      else:
        raise c_exc.ToolException(
            ('PyOpenSSL is not available. See '
             'https://developers.google.com/cloud/sdk/crypto for details '
             'or consider using .json private key instead.'))

    if json_key:
      cred = service_account.ServiceAccountCredentials(
          service_account_id=json_key['client_id'],
          service_account_email=json_key['client_email'],
          private_key_id=json_key['private_key_id'],
          private_key_pkcs8_text=json_key['private_key'],
          scopes=config.CLOUDSDK_SCOPES,
          user_agent=config.CLOUDSDK_USER_AGENT)
    elif password:
      cred = client.SignedJwtAssertionCredentials(
          service_account_name=args.account,
          private_key=private_key,
          scope=config.CLOUDSDK_SCOPES,
          private_key_password=password,
          user_agent=config.CLOUDSDK_USER_AGENT)
    else:
      cred = client.SignedJwtAssertionCredentials(
          service_account_name=args.account,
          private_key=private_key,
          scope=config.CLOUDSDK_SCOPES,
          user_agent=config.CLOUDSDK_USER_AGENT)

    c_store.Store(cred, args.account)

    properties.PersistProperty(properties.VALUES.core.account, args.account)

    project = args.project
    if project:
      properties.PersistProperty(properties.VALUES.core.project, project)

    return cred