def _get_request_header( credentials = None ): """Gets a request header. Args: credentials: The credentials to use for GCP services. Returns: A header dict for requests. """ # If credentials is not given, use the default credentials if credentials is None: credentials, _ = google.auth.default() # Refresh credentials in case it has been expired. auth_req = google.auth.transport.requests.Request() credentials.refresh(auth_req) headers = {} # Set user-agent for logging usages. headers['user-agent'] = constants.USER_AGENT_FOR_CAIP_TRACKING credentials.apply(headers) return headers
def _get_credentials_email(self) -> str: """ Returns the email address associated with the currently logged in account If a service account is used, it returns the service account. If user authentication (e.g. gcloud auth) is used, it returns the e-mail account of that user. """ credentials = self._get_credentials() if isinstance(credentials, compute_engine.Credentials): try: credentials.refresh(_http_client.Request()) except RefreshError as msg: """ If the Compute Engine metadata service can't be reached in this case the instance has not credentials. """ self.log.debug(msg) service_account_email = getattr(credentials, 'service_account_email', None) if service_account_email: return service_account_email http_authorized = self._authorize() oauth2_client = discovery.build('oauth2', "v1", http=http_authorized, cache_discovery=False) return oauth2_client.tokeninfo().execute()['email']
def _get_access_token(self) -> str: """Returns a valid access token from Google API Credentials""" credentials = self._get_credentials() auth_req = google.auth.transport.requests.Request() # credentials.token is None # Need to refresh credentials to populate the token credentials.refresh(auth_req) return credentials.token
def create_kubernetes_configuration( self, credentials: credentials.Credentials, project_id: str, cluster_name: str, zone: str = 'us-west1-a') -> kubernetes.client.Configuration: """Create a kubernetes config which has access to the given cluster. Args: credentials: The credentials object used to generate tokens to access kubernetes clusters. project_id: GCP project id. cluster_name: Name of the kubernetes cluster we want to access. zone: Where is the cluster hosted. Raises: ClusterGetInfoError: When unexpected cluster information is returned from GCP. Returns: A kubernetes configuration which has access to the provided cluster. """ # This function will create a temporary file for cluster ca certificate. # Those temporary files should be removed after the program exists. if not ContainerClient._temp_ca_files: atexit.register(self._cleanup_temp_files) # credentials.token is a bearer token that can be used in HTTP headers # to make authenticated requests. When the given credentials does not # have token, we need to force it to get a new token. if not credentials.token: credentials.refresh(requests.Request()) request = self._container_service.projects().zones().clusters().get( projectId=project_id, zone=zone, clusterId=cluster_name) response = request.execute() if ('masterAuth' not in response or 'clusterCaCertificate' not in response['masterAuth']): raise ClusterGetInfoError( ('Unexpected response getting information of cluster "{}" in ' 'project "{}": {}').format(cluster_name, project_id, response)) ca = response['masterAuth']['clusterCaCertificate'] _, ca_file_path = tempfile.mkstemp() # Save temporary file path so that it can be cleaned up after the # program exits. self._temp_ca_files.append(ca_file_path) with open(ca_file_path, 'wb') as ca_file: ca_file.write(base64.standard_b64decode(ca)) configuration = kubernetes.client.Configuration() configuration.api_key['authorization'] = credentials.token configuration.api_key_prefix['authorization'] = 'Bearer' configuration.host = 'https://' + response['endpoint'] configuration.ssl_ca_cert = ca_file_path return configuration
def refresh_credentials(credentials): # Refresh must use a new http instance, as the one associated with the # credentials could be a AuthorizedHttp or an oauth2client-decorated # Http instance which would cause a weird recursive loop of refreshing # and likely tear a hole in spacetime. refresh_http = httplib2.Http() if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials): request = google_auth_httplib2.Request(refresh_http) return credentials.refresh(request) else: return credentials.refresh(refresh_http)
def _create_docker_client(self, credentials: credentials.Credentials): # credentials.token is a bearer token that can be used in HTTP headers # to make authenticated requests. When the given credentials does not # have token, we need to force it to get a new token. if not credentials.token: credentials.refresh(requests.Request()) # See https://cloud.google.com/container-registry/docs/advanced-authentication self._docker_client = docker.DockerClient() self._docker_client.login(username='******', password=credentials.token, registry='https://gcr.io')
def refresh_credentials(credentials): # Refresh must use a new http instance, as the one associated with the # credentials could be a AuthorizedHttp or an oauth2client-decorated # Http instance which would cause a weird recursive loop of refreshing # and likely tear a hole in spacetime. refresh_http = httplib2.Http() if HAS_GOOGLE_AUTH and isinstance( credentials, google.auth.credentials.Credentials): request = google_auth_httplib2.Request(refresh_http) return credentials.refresh(request) else: return credentials.refresh(refresh_http)
def test_apply_without_quota_project_id(self): headers = {} request = self.make_mock_request(status=http_client.OK, data=SUCCESS_RESPONSE) credentials = self.make_credentials() credentials.refresh(request) credentials.apply(headers) assert headers == { "authorization": "Bearer {}".format(SUCCESS_RESPONSE["access_token"]) }
def test_refresh_source_credentials_refresh_error(self): # Initialize downscoped credentials with source credentials that raise # an error on refresh. credentials = self.make_credentials( source_credentials=SourceCredentials(raise_error=True)) with pytest.raises(exceptions.RefreshError) as excinfo: credentials.refresh(mock.sentinel.request) assert excinfo.match( r"Failed to refresh access token in source credentials.") assert not credentials.expired assert credentials.token is None
def test_refresh_token_exchange_error(self): request = self.make_mock_request(status=http_client.BAD_REQUEST, data=ERROR_RESPONSE) credentials = self.make_credentials() with pytest.raises(exceptions.OAuthError) as excinfo: credentials.refresh(request) assert excinfo.match( r"Error code invalid_grant: Subject token is invalid. - https://tools.ietf.org/html/rfc6749" ) assert not credentials.expired assert credentials.token is None
def test_apply_with_quota_project_id(self): headers = {"other": "header-value"} request = self.make_mock_request(status=http_client.OK, data=SUCCESS_RESPONSE) credentials = self.make_credentials(quota_project_id=QUOTA_PROJECT_ID) credentials.refresh(request) credentials.apply(headers) assert headers == { "other": "header-value", "authorization": "Bearer {}".format(SUCCESS_RESPONSE["access_token"]), "x-goog-user-project": QUOTA_PROJECT_ID, }
def test_refresh_without_response_expires_in(self, unused_utcnow): response = SUCCESS_RESPONSE.copy() # Simulate the response is missing the expires_in field. # The downscoped token expiration should match the source credentials # expiration. del response["expires_in"] expected_expires_in = 1800 # Simulate the source credentials generates a token with 1800 second # expiration time. The generated downscoped token should have the same # expiration time. source_credentials = SourceCredentials(expires_in=expected_expires_in) expected_expiry = datetime.datetime.min + datetime.timedelta( seconds=expected_expires_in) headers = {"Content-Type": "application/x-www-form-urlencoded"} request_data = { "grant_type": GRANT_TYPE, "subject_token": "ACCESS_TOKEN_1", "subject_token_type": SUBJECT_TOKEN_TYPE, "requested_token_type": REQUESTED_TOKEN_TYPE, "options": urllib.parse.quote(json.dumps(CREDENTIAL_ACCESS_BOUNDARY_JSON)), } request = self.make_mock_request(status=http_client.OK, data=response) credentials = self.make_credentials( source_credentials=source_credentials) # Spy on calls to source credentials refresh to confirm the expected request # instance is used. with mock.patch.object(source_credentials, "refresh", wraps=source_credentials.refresh ) as wrapped_souce_cred_refresh: credentials.refresh(request) self.assert_request_kwargs(request.call_args[1], headers, request_data) assert credentials.valid assert credentials.expiry == expected_expiry assert not credentials.expired assert credentials.token == response["access_token"] # Confirm source credentials called with the same request instance. wrapped_souce_cred_refresh.assert_called_with(request)
def test_refresh(self, unused_utcnow): response = SUCCESS_RESPONSE.copy() # Test custom expiration to confirm expiry is set correctly. response["expires_in"] = 2800 expected_expiry = datetime.datetime.min + datetime.timedelta( seconds=response["expires_in"]) headers = {"Content-Type": "application/x-www-form-urlencoded"} request_data = { "grant_type": GRANT_TYPE, "subject_token": "ACCESS_TOKEN_1", "subject_token_type": SUBJECT_TOKEN_TYPE, "requested_token_type": REQUESTED_TOKEN_TYPE, "options": urllib.parse.quote(json.dumps(CREDENTIAL_ACCESS_BOUNDARY_JSON)), } request = self.make_mock_request(status=http_client.OK, data=response) source_credentials = SourceCredentials() credentials = self.make_credentials( source_credentials=source_credentials) # Spy on calls to source credentials refresh to confirm the expected request # instance is used. with mock.patch.object(source_credentials, "refresh", wraps=source_credentials.refresh ) as wrapped_souce_cred_refresh: credentials.refresh(request) self.assert_request_kwargs(request.call_args[1], headers, request_data) assert credentials.valid assert credentials.expiry == expected_expiry assert not credentials.expired assert credentials.token == response["access_token"] # Confirm source credentials called with the same request instance. wrapped_souce_cred_refresh.assert_called_with(request)