def Store(credentials, account=None, scopes=None): """Store credentials according for an account address. Args: credentials: oauth2client.client.Credentials, The credentials to be stored. account: str, The account address of the account they're being stored for. If None, the account stored in the core.account property is used. scopes: tuple, Custom auth scopes to request. By default CLOUDSDK_SCOPES are requested. Raises: NoActiveAccountException: If account is not provided and there is no active account. """ cred_type = creds.CredentialType.FromCredentials(credentials) if not cred_type.is_serializable: return if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() store = creds.GetCredentialStore() store.Store(account, credentials) _LegacyGenerator(account, credentials, scopes).WriteTemplate()
def testCredentialStoreChangesToPrivate(self): """Tests that reading credentials turns the credential files private.""" store_file = os.path.join(self.temp_path, 'credentials.db') access_token_file = os.path.join(self.temp_path, 'access_token.db') creds.GetCredentialStore(store_file, access_token_file) for path in (store_file, access_token_file): # Open up the permissions to verify that they get changed back os.chmod(path, 0o777) creds.GetCredentialStore(store_file, access_token_file) for path in (store_file, access_token_file): self.assertEqual( os.stat(store_file).st_mode & 0o777, 0o600, 'File [{}] should be changed back to 0o600 permissions'.format( os.path.basename(path)))
def Revoke(account=None): """Revoke credentials and clean up related files. Args: account: str, The account address for the credentials to be revoked. If None, the currently active account is used. Returns: 'True' if this call revoked the account; 'False' if the account was already revoked. Raises: NoActiveAccountException: If account is not provided and there is no active account. NoCredentialsForAccountException: If the provided account is not tied to any known credentials. RevokeError: If there was a more general problem revoking the account. """ if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() if account in c_gce.Metadata().Accounts(): raise RevokeError('Cannot revoke GCE-provided credentials.') credentials = Load(account, prevent_refresh=True) if not credentials: raise NoCredentialsForAccountException(account) if isinstance(credentials, c_devshell.DevshellCredentials): raise RevokeError( 'Cannot revoke the automatically provisioned Cloud Shell credential.' 'This comes from your browser session and will not persist outside' 'of your connected Cloud Shell session.') rv = False try: if not account.endswith('.gserviceaccount.com'): RevokeCredentials(credentials) rv = True except client.TokenRevokeError as e: if e.args[0] == 'invalid_token': # Malformed or already revoked pass elif e.args[0] == 'invalid_request': # Service account token pass else: raise store = creds.GetCredentialStore() store.Remove(account) _LegacyGenerator(account, credentials).Clean() files.RmTree(config.Paths().LegacyCredentialsDir(account)) return rv
def SetUp(self): store_file = os.path.join(self.temp_path, 'credentials.db') access_token_file = os.path.join(self.temp_path, 'access_token.db') self.store = creds.GetCredentialStore(store_file, access_token_file) self.fake_account = 'test_account' # Mocks the refresh of oauth2client credentials. self.StartObjectPatch( httplib2.Http, 'request', return_value=_MakeFakeOauth2clientCredsRefreshResponse())
def _Load(account, scopes, prevent_refresh): """Helper for Load().""" # If a credential file is set, just use that and ignore the active account # and whatever is in the credential store. cred_file_override = properties.VALUES.auth.credential_file_override.Get() if cred_file_override: log.info('Using alternate credentials from file: [%s]', cred_file_override) try: cred = client.GoogleCredentials.from_stream(cred_file_override) except client.Error as e: raise InvalidCredentialFileException(cred_file_override, e) if cred.create_scoped_required(): if scopes is None: scopes = config.CLOUDSDK_SCOPES cred = cred.create_scoped(scopes) # Set token_uri after scopes since token_uri needs to be explicitly # preserved when scopes are applied. token_uri_override = properties.VALUES.auth.token_host.Get() if token_uri_override: cred_type = creds.CredentialType.FromCredentials(cred) if cred_type in (creds.CredentialType.SERVICE_ACCOUNT, creds.CredentialType.P12_SERVICE_ACCOUNT): cred.token_uri = token_uri_override # The credential override is not stored in credential store, but we still # want to cache access tokens between invocations. return creds.MaybeAttachAccessTokenCacheStore(cred) if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException( named_configs.ActiveConfig(False).file_path) cred = STATIC_CREDENTIAL_PROVIDERS.GetCredentials(account) if cred is not None: return cred store = creds.GetCredentialStore() cred = store.Load(account) if not cred: raise NoCredentialsForAccountException(account) # cred.token_expiry is in UTC time. if (not prevent_refresh and (not cred.token_expiry or cred.token_expiry < cred.token_expiry.utcnow())): Refresh(cred) return cred
def AvailableAccounts(): """Get all accounts that have credentials stored for the CloudSDK. This function will also ping the GCE metadata server to see if GCE credentials are available. Returns: [str], List of the accounts. """ store = creds.GetCredentialStore() accounts = store.GetAccounts() | STATIC_CREDENTIAL_PROVIDERS.GetAccounts() return sorted(accounts)
def testCredentialStoreCreatedPrivate(self): """Tests that reading credentials creates the credential files private.""" store_file = os.path.join(self.temp_path, 'credentials.db') access_token_file = os.path.join(self.temp_path, 'access_token.db') for path in (store_file, access_token_file): self.assertFalse( os.path.exists(path), 'File [{}] should not exist already (test error)'.format( os.path.basename(path))) creds.GetCredentialStore(store_file, access_token_file) for path in (store_file, access_token_file): self.assertEqual( os.stat(store_file).st_mode & 0o777, 0o600, 'File [{}] file should be created with 0o600 permissions'.format( os.path.basename(path)))
def AvailableAccounts(): """Get all accounts that have credentials stored for the CloudSDK. This function will also ping the GCE metadata server to see if GCE credentials are available. Returns: [str], List of the accounts. """ store = creds.GetCredentialStore() accounts = store.GetAccounts() | set(c_gce.Metadata().Accounts()) devshell_creds = c_devshell.LoadDevshellCredentials() if devshell_creds: accounts.add(devshell_creds.devshell_response.user_email) return sorted(accounts)
def SetUp(self): store_file = os.path.join(self.temp_path, 'credentials.db') access_token_file = os.path.join(self.temp_path, 'access_token.db') self.store = creds.GetCredentialStore(store_file, access_token_file) self.fake_account = 'test_account' # Mocks the refresh of oauth2client credentials. self.StartObjectPatch( httplib2.Http, 'request', return_value=_MakeFakeOauth2clientCredsRefreshResponse()) # Mocks the signer of oauth2client credentials. signer = self.StartPatch('oauth2client.crypt.Signer', autospec=True) self.StartObjectPatch(crypt, 'OpenSSLSigner', new=signer) self.StartObjectPatch( crypt, 'make_signed_jwt', return_value=b'fake_assertion') # Mocks the signer of google-auth credentials. self.StartObjectPatch(google_auth_crypt.RSASigner, 'from_service_account_info') self.StartObjectPatch(jwt, 'encode', return_value=b'fake_assertion')
def Store(credentials, account=None, scopes=None): """Store credentials according for an account address. gcloud only stores user account credentials, service account credentials and p12 service account credentials. GCE, IAM impersonation, and Devshell credentials are generated in runtime. Args: credentials: oauth2client.client.Credentials or google.auth.credentials.Credentials, The credentials to be stored. account: str, The account address of the account they're being stored for. If None, the account stored in the core.account property is used. scopes: tuple, Custom auth scopes to request. By default CLOUDSDK_SCOPES are requested. Raises: NoActiveAccountException: If account is not provided and there is no active account. """ if c_creds.IsOauth2ClientCredentials(credentials): cred_type = c_creds.CredentialType.FromCredentials(credentials) else: cred_type = c_creds.CredentialTypeGoogleAuth.FromCredentials( credentials) if not cred_type.is_serializable: return if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() store = c_creds.GetCredentialStore() store.Store(account, credentials) _LegacyGenerator(account, credentials, scopes).WriteTemplate()
def Store(credentials, account=None, scopes=None): """Store credentials according for an account address. Args: credentials: oauth2client.client.Credentials or google.auth.credentials.Credentials, The credentials to be stored. account: str, The account address of the account they're being stored for. If None, the account stored in the core.account property is used. scopes: tuple, Custom auth scopes to request. By default CLOUDSDK_SCOPES are requested. Raises: NoActiveAccountException: If account is not provided and there is no active account. """ if isinstance(credentials, client.OAuth2Credentials): cred_type = creds.CredentialType.FromCredentials(credentials) else: cred_type = creds.CredentialTypeGoogleAuth.FromCredentials(credentials) if not cred_type.is_serializable: return if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() store = creds.GetCredentialStore() store.Store(account, credentials) # TODO(b/151574510): Removes this if check once _LegacyGenerator supports # google-auth credentials. if isinstance(credentials, client.OAuth2Credentials): _LegacyGenerator(account, credentials, scopes).WriteTemplate()
def RemoveServiceAccount(self): c_store = c_creds.GetCredentialStore() c_store.Remove(_SERVICE_ACCOUNT_EMAIL)
def Revoke(account=None, use_google_auth=False): """Revoke credentials and clean up related files. Args: account: str, The account address for the credentials to be revoked. If None, the currently active account is used. use_google_auth: bool, True to revoke the credentials as google auth credentials. False to revoke the credentials as oauth2client credentials. Returns: True if this call revoked the account; False if the account was already revoked. Raises: NoActiveAccountException: If account is not provided and there is no active account. NoCredentialsForAccountException: If the provided account is not tied to any known credentials. RevokeError: If there was a more general problem revoking the account. """ # Import only when necessary to decrease the startup time. Move it to # global once google-auth is ready to replace oauth2client. # pylint: disable=g-import-not-at-top from googlecloudsdk.core.credentials import google_auth_credentials as c_google_auth # pylint: enable=g-import-not-at-top if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() if account in c_gce.Metadata().Accounts(): raise RevokeError('Cannot revoke GCE-provided credentials.') credentials = Load(account, prevent_refresh=True, use_google_auth=use_google_auth) if not credentials: raise NoCredentialsForAccountException(account) if (isinstance(credentials, c_devshell.DevshellCredentials) or isinstance( credentials, c_devshell.DevShellCredentialsGoogleAuth)): raise RevokeError( 'Cannot revoke the automatically provisioned Cloud Shell credential.' 'This comes from your browser session and will not persist outside' 'of your connected Cloud Shell session.') rv = False try: if not account.endswith('.gserviceaccount.com'): RevokeCredentials(credentials) rv = True except (client.TokenRevokeError, c_google_auth.TokenRevokeError) as e: if e.args[0] == 'invalid_token': # Malformed or already revoked pass elif e.args[0] == 'invalid_request': # Service account token pass else: raise store = c_creds.GetCredentialStore() store.Remove(account) _LegacyGenerator(account, credentials).Clean() legacy_creds_dir = config.Paths().LegacyCredentialsDir(account) if os.path.isdir(legacy_creds_dir): files.RmTree(legacy_creds_dir) return rv
def Load(account=None, scopes=None, prevent_refresh=False): """Get the credentials associated with the provided account. This loads credentials regardless of whether credentials have been disabled via properties. Only use this when the functionality of the caller absolutely requires credentials (like printing out a token) vs logically requiring credentials (like for an http request). Args: account: str, The account address for the credentials being fetched. If None, the account stored in the core.account property is used. scopes: tuple, Custom auth scopes to request. By default CLOUDSDK_SCOPES are requested. prevent_refresh: bool, If True, do not refresh the access token even if it is out of date. (For use with operations that do not require a current access token, such as credential revocation.) Returns: oauth2client.client.Credentials, The specified credentials. Raises: NoActiveAccountException: If account is not provided and there is no active account. NoCredentialsForAccountException: If there are no valid credentials available for the provided or active account. c_gce.CannotConnectToMetadataServerException: If the metadata server cannot be reached. TokenRefreshError: If the credentials fail to refresh. TokenRefreshReauthError: If the credentials fail to refresh due to reauth. """ # If a credential file is set, just use that and ignore the active account # and whatever is in the credential store. cred_file_override = properties.VALUES.auth.credential_file_override.Get() if cred_file_override: log.info('Using alternate credentials from file: [%s]', cred_file_override) try: cred = client.GoogleCredentials.from_stream(cred_file_override) except client.Error as e: raise InvalidCredentialFileException(cred_file_override, e) if cred.create_scoped_required(): if scopes is None: scopes = config.CLOUDSDK_SCOPES cred = cred.create_scoped(scopes) # Set token_uri after scopes since token_uri needs to be explicitly # preserved when scopes are applied. token_uri_override = properties.VALUES.auth.token_host.Get() if token_uri_override: cred_type = creds.CredentialType.FromCredentials(cred) if cred_type in (creds.CredentialType.SERVICE_ACCOUNT, creds.CredentialType.P12_SERVICE_ACCOUNT): cred.token_uri = token_uri_override # The credential override is not stored in credential store, but we still # want to cache access tokens between invocations. return creds.MaybeAttachAccessTokenCacheStore(cred) if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() cred = STATIC_CREDENTIAL_PROVIDERS.GetCredentials(account) if cred is not None: return cred store = creds.GetCredentialStore() cred = store.Load(account) if not cred: raise NoCredentialsForAccountException(account) # cred.token_expiry is in UTC time. if (not prevent_refresh and (not cred.token_expiry or cred.token_expiry < cred.token_expiry.utcnow())): Refresh(cred) return cred
def testSqliteBusyTimeoutSetting(self): store = creds.GetCredentialStore() with store._access_token_cache._cursor as cur: time_out = cur.Execute('PRAGMA busy_timeout;').fetchone()[0] self.assertEqual(1000, time_out)
def testNoWarnMessage(self): creds.GetCredentialStore() self.AssertErrEquals('')
def Load(account=None, scopes=None, prevent_refresh=False): """Get the credentials associated with the provided account. Args: account: str, The account address for the credentials being fetched. If None, the account stored in the core.account property is used. scopes: tuple, Custom auth scopes to request. By default CLOUDSDK_SCOPES are requested. prevent_refresh: bool, If True, do not refresh the access token even if it is out of date. (For use with operations that do not require a current access token, such as credential revocation.) Returns: oauth2client.client.Credentials, The specified credentials. Raises: NoActiveAccountException: If account is not provided and there is no active account. NoCredentialsForAccountException: If there are no valid credentials available for the provided or active account. c_gce.CannotConnectToMetadataServerException: If the metadata server cannot be reached. TokenRefreshError: If the credentials fail to refresh. TokenRefreshReauthError: If the credentials fail to refresh due to reauth. """ # If a credential file is set, just use that and ignore the active account # and whatever is in the credential store. cred_file_override = properties.VALUES.auth.credential_file_override.Get() if cred_file_override: log.info('Using alternate credentials from file: [%s]', cred_file_override) try: cred = client.GoogleCredentials.from_stream(cred_file_override) except client.Error as e: raise InvalidCredentialFileException(cred_file_override, e) if cred.create_scoped_required(): if scopes is None: scopes = config.CLOUDSDK_SCOPES cred = cred.create_scoped(scopes) # Set token_uri after scopes since token_uri needs to be explicitly # preserved when scopes are applied. token_uri_override = properties.VALUES.auth.token_host.Get() if token_uri_override: cred_type = creds.CredentialType.FromCredentials(cred) if cred_type in (creds.CredentialType.SERVICE_ACCOUNT, creds.CredentialType.P12_SERVICE_ACCOUNT): cred.token_uri = token_uri_override return cred if not account: account = properties.VALUES.core.account.Get() if not account: raise NoActiveAccountException() devshell_creds = c_devshell.LoadDevshellCredentials() if devshell_creds and (devshell_creds.devshell_response.user_email == account): return devshell_creds if account in c_gce.Metadata().Accounts(): return AcquireFromGCE(account) store = creds.GetCredentialStore() cred = store.Load(account) if not cred: raise NoCredentialsForAccountException(account) # cred.token_expiry is in UTC time. if (not prevent_refresh and (not cred.token_expiry or cred.token_expiry < cred.token_expiry.utcnow())): Refresh(cred) return cred