def login_kerberos(self): """ Login to FreeIPA server using existing Kerberos credentials. In order to use this method, the package ```requests_kerberos`` <https://pypi.org/project/requests-kerberos/>`_ must be installed. There must already be a Kerberos Ticket-Granting Ticket (TGT) cached in a Kerberos credential cache. Whether a TGT is available can be easily determined by running the klist command. If no TGT is available, then it first must be obtained by running the kinit command, or pointing the ``$KRB5CCNAME`` environment variable to a credential cache with a valid TGT. :raises Unauthorized: raised if credentials are invalid. :raises ImportError: raised if the ``requests_kerberos`` module is unavailable. """ if isinstance(requests_kerberos, ImportError): raise requests_kerberos login_url = '{0}/session/login_kerberos'.format(self._base_url) headers = {'Referer': self._base_url} response = self._session.post( login_url, headers=headers, verify=self._verify_ssl, auth=requests_kerberos.HTTPKerberosAuth()) if not response.ok: raise Unauthorized(response.text) self.log.info('Successfully logged using Kerberos credentials.') return AuthenticatedSession(self, logged_in=True)
def create_kerberos_auth(config): global requests_kerberos if requests_kerberos is None: import requests_kerberos KERBEROS_STRATEGIES['required'] = requests_kerberos.REQUIRED KERBEROS_STRATEGIES['optional'] = requests_kerberos.OPTIONAL KERBEROS_STRATEGIES['disabled'] = requests_kerberos.DISABLED # For convenience if config['kerberos_auth'] is None or is_affirmative( config['kerberos_auth']): config['kerberos_auth'] = 'required' if config['kerberos_auth'] not in KERBEROS_STRATEGIES: raise ConfigurationError( 'Invalid Kerberos strategy `{}`, must be one of: {}'.format( config['kerberos_auth'], ' | '.join(KERBEROS_STRATEGIES))) return requests_kerberos.HTTPKerberosAuth( mutual_authentication=KERBEROS_STRATEGIES[config['kerberos_auth']], delegate=is_affirmative(config['kerberos_delegate']), force_preemptive=is_affirmative(config['kerberos_force_initiate']), hostname_override=config['kerberos_hostname'], principal=config['kerberos_principal'], )
def __init__( self, server_url: str, use_tls: bool = False, headers: dict = None, auth=None, verify: bool = True, ): """ Parameters ---------- server_url: The URL of the livy server. Should include protocol (http/https) and port headers, optional: A dictionary for the API request to Livy. auth, optional: An object for `requests` to use in its `auth` keyword. verify, optional: (True) Use TLS / SSL. (False) Ignore TLS / SSL errors """ self._verify = verify if auth is None: auth = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.REQUIRED, force_preemptive=True) self._auth = auth self._base_url = "%s/batches" % server_url if headers is None: headers = {"Content-Type": "application/json"} self._headers = headers
def get_raz_client(raz_url, username, auth='kerberos', service='s3', service_name='cm_s3', cluster_name='myCluster'): if not username: from crequest.middleware import CrequestMiddleware request = CrequestMiddleware.get_request() username = request.user.username if request and hasattr( request, 'user') and request.user.is_authenticated else None if not username: raise PopupException('No username set.') if auth == 'kerberos' or True: # True until JWT option auth_handler = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.OPTIONAL) raz = RazToken(raz_url, auth_handler) raz_token = raz.get_delegation_token(user=username) return RazClient(raz_url, raz_token, username, service=service, service_name=service_name, cluster_name=cluster_name)
def __init__(self, url, mode='r', buffer_size=DEFAULT_BUFFER_SIZE, kerberos=False, user=None, password=None): if kerberos: import requests_kerberos auth = requests_kerberos.HTTPKerberosAuth() elif user is not None and password is not None: auth = (user, password) else: auth = None self.buffer_size = buffer_size self.mode = mode self.response = requests.get(url, auth=auth, stream=True, headers=_HEADERS) if not self.response.ok: self.response.raise_for_status() self._read_iter = self.response.iter_content(self.buffer_size) self._read_buffer = b'' self._current_pos = 0 # # This member is part of the io.BufferedIOBase interface. # self.raw = None
def __init__(self, user, timeout=100, kerberized=False, principal=None, keytab=None, krb_conf=None, host = "localhost", protocol = "http", proxy_port = 50070, data_port = 50075, hdfs_ip = None, kdc_ip = None): self.host = host self.protocol = protocol self.proxy_port = proxy_port self.data_port = data_port self.user = user self.kerberized = kerberized self.principal = principal self.keytab = keytab self.timeout = timeout self.hdfs_ip = hdfs_ip self.kdc_ip = kdc_ip self.krb_conf = krb_conf # logging.basicConfig(level=logging.DEBUG) # logging.getLogger().setLevel(logging.DEBUG) # requests_log = logging.getLogger("requests.packages.urllib3") # requests_log.setLevel(logging.DEBUG) # requests_log.propagate = True if kerberized: self._run_kinit() self.kerberos_auth = reqkerb.HTTPKerberosAuth(mutual_authentication=reqkerb.DISABLED, hostname_override=self.host, principal=self.principal) if self.kerberos_auth is None: print("failed to obtain kerberos_auth") else: self.kerberos_auth = None
def get_requests_session(auth=False): """ Create a requests session with authentication (when enabled). :param bool auth: configure authentication on the session :return: the configured requests session :rtype: requests.Session """ config = get_worker_config() session = requests.Session() if auth: if config.cachito_auth_type == "kerberos": session.auth = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.OPTIONAL) elif config.cachito_auth_type == "cert": session.cert = config.cachito_auth_cert retry = Retry(total=5, read=5, connect=5, backoff_factor=1.3, status_forcelist=(500, 502, 503, 504)) adapter = requests.adapters.HTTPAdapter(max_retries=retry) session.mount("http://", adapter) session.mount("https://", adapter) return session
def pdc_client(url, token, insecure, develop): """ Because pdc_client is in upstream version and maybe change according to its own requirement, use some code here """ session = requests.Session() if not develop: # For local environment, we don't need to require a token, # just access API directly. # REQUIRED, OPTIONAL, DISABLED session.auth = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.DISABLED) if insecure: # turn off for servers with insecure certificates session.verify = False # turn off warnings about making insecure calls if requests.__version__ < '2.4.0': print("Requests version is too old, please upgrade to 2.4.0 or latest.") # disable all warnings, it had better to upgrade requests. warnings.filterwarnings("ignore") else: requests.packages.urllib3.disable_warnings() pdc = beanbag.BeanBag(url, session=session) if not develop: # For develop environment, we don't need to require a token if not token: token = obtain_token(pdc) session.headers["Authorization"] = "Token %s" % token return pdc, session
def test_generate_request_header_step_error(mock_client): response = requests.Response() response.url = "http://www.example.org/" response.headers = {'www-authenticate': 'negotiate dG9rZW4='} host = urlparse(response.url).hostname auth = requests_kerberos.HTTPKerberosAuth() mock_client.return_value.step.side_effect = spnego.exceptions.InvalidTokenError( ) with pytest.raises(requests_kerberos.exceptions.KerberosExchangeError, match="ctx step failed"): auth.generate_request_header(response, host) assert mock_client.call_count == 1 assert mock_client.call_args[1] == { "username": None, "hostname": "www.example.org", "service": "HTTP", "channel_bindings": None, "context_req": spnego.ContextReq.sequence_detect | spnego.ContextReq.mutual_auth, "protocol": "kerberos", } assert mock_client.return_value.step.call_count == 1 assert mock_client.return_value.step.call_args[1] == { "in_token": b"token", }
def _get_requests_config(cls, instance): auth = None # Authenticate our connection to JMX endpoint if required kerberos = instance.get('kerberos') username = instance.get('username') password = instance.get('password') if username is not None and password is not None: auth = (username, password) elif kerberos is not None: if kerberos not in KERBEROS_STRATEGIES: raise Exception( 'Invalid Kerberos strategy `{}`'.format(kerberos)) auth = requests_kerberos.HTTPKerberosAuth( mutual_authentication=KERBEROS_STRATEGIES[kerberos], delegate=is_affirmative( instance.get('kerberos_delegate', False)), force_preemptive=is_affirmative( instance.get('kerberos_force_initiate', False)), hostname_override=instance.get('kerberos_hostname'), principal=instance.get('kerberos_principal'), ) return RequestsConfig( auth=auth, ssl_verify=instance.get('ssl_verify'), ssl_cert=instance.get('ssl_cert'), ssl_key=instance.get('ssl_key'), kerberos_keytab=instance.get('kerberos_keytab'), )
def test_handle_response_500_mutual_auth_required_failure(self): with patch('kerberos.authGSSClientStep', clientStep_error): response_500 = requests.Response() response_500.url = "http://www.example.org/" response_500.status_code = 500 response_500.headers = {} response_500.request = "REQUEST" response_500.connection = "CONNECTION" response_500._content = "CONTENT" response_500.encoding = "ENCODING" response_500.raw = "RAW" response_500.cookies = "COOKIES" auth = requests_kerberos.HTTPKerberosAuth() auth.context = {"www.example.org": "CTX"} r = auth.handle_response(response_500) self.assertNotEqual(r, response_500) self.assertNotEqual(r.headers, response_500.headers) self.assertEqual(r.status_code, response_500.status_code) self.assertEqual(r.encoding, response_500.encoding) self.assertEqual(r.raw, response_500.raw) self.assertEqual(r.url, response_500.url) self.assertEqual(r.reason, response_500.reason) self.assertEqual(r.connection, response_500.connection) self.assertEqual(r.content, b'') self.assertNotEqual(r.cookies, response_500.cookies) self.assertFalse(clientStep_error.called)
def __init__(self, url, mode='r', kerberos=False, user=None, password=None): """ If Kerberos is True, will attempt to use the local Kerberos credentials. Otherwise, will try to use "basic" HTTP authentication via username/password. If none of those are set, will connect unauthenticated. """ if kerberos: import requests_kerberos auth = requests_kerberos.HTTPKerberosAuth() elif user is not None and password is not None: auth = (user, password) else: auth = None self.response = requests.get(url, auth=auth, stream=True) if not self.response.ok: self.response.raise_for_status() self.mode = mode self._read_buffer = None self._read_iter = None self._readline_iter = None
def __init__(self, url, mode='r', buffer_size=DEFAULT_BUFFER_SIZE, kerberos=False, user=None, password=None, headers=None, timeout=None): """ If Kerberos is True, will attempt to use the local Kerberos credentials. Otherwise, will try to use "basic" HTTP authentication via username/password. If none of those are set, will connect unauthenticated. """ self.url = url if kerberos: import requests_kerberos self.auth = requests_kerberos.HTTPKerberosAuth() elif user is not None and password is not None: self.auth = (user, password) else: self.auth = None if headers is None: self.headers = _HEADERS.copy() else: self.headers = headers self.timeout = timeout self.buffer_size = buffer_size self.mode = mode self.response = self._partial_request() if not self.response.ok: self.response.raise_for_status() logger.debug('self.response: %r, raw: %r', self.response, self.response.raw) self._seekable = True self.content_length = int( self.response.headers.get("Content-Length", -1)) if self.content_length < 0: self._seekable = False if self.response.headers.get("Accept-Ranges", "none").lower() != "bytes": self._seekable = False self._read_iter = self.response.iter_content(self.buffer_size) self._read_buffer = bytebuffer.ByteBuffer(buffer_size) self._current_pos = 0 # # This member is part of the io.BufferedIOBase interface. # self.raw = None
def test_no_force_preemptive(): auth = requests_kerberos.HTTPKerberosAuth() request = requests.Request(url="http://www.example.org") auth.__call__(request) assert 'Authorization' not in request.headers
def get_raz_client(raz_url, username, auth='kerberos', service='s3', service_name='cm_s3', cluster_name='myCluster'): if auth == 'kerberos' or True: # True until ABFS option auth_handler = requests_kerberos.HTTPKerberosAuth(mutual_authentication=requests_kerberos.OPTIONAL) raz = RazToken(raz_url, auth_handler) raz_token = raz.get_delegation_token(user=username) return RazClient(raz_url, raz_token, username, service=service, service_name=service_name, cluster_name=cluster_name)
def login(args): kerb = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.DISABLED) s = requests.session() s.get('{base}{authpath}'.format(base=args.server, authpath=args.auth_path), auth=kerb, verify=args.cacert) return s
def _download(url, temp): """Downloads the image.""" _LOGGER.debug('Downloading tar file from %r to %r.', url, temp) krb_auth = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.DISABLED) request = requests.get(url, stream=True, auth=krb_auth) shutil.copyfileobj(request.raw, temp)
def test_force_preemptive(mock_client): auth = requests_kerberos.HTTPKerberosAuth(force_preemptive=True) request = requests.Request(url="http://www.example.org") auth.__call__(request) assert 'Authorization' in request.headers assert request.headers.get('Authorization') == 'Negotiate R1NTUkVTUE9OU0U='
def _krb_auth(): """Returns kerberos auth object.""" auth_principle = None if os.name == 'posix': # kerberos 1.2.5 doesn't accept None principal. Remove this once fixed. auth_principle = '' return requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.DISABLED, principal=auth_principle, service=restclientopts.AUTH_PRINCIPAL)
def _download(url, temp): """Downloads the image.""" _LOGGER.debug('Downloading tar file from %r to %r.', url, temp) krb_auth = requests_kerberos.HTTPKerberosAuth( mutual_authentication=requests_kerberos.DISABLED, # kerberos 1.2.5 doesn't accept None principal. Remove this once fixed. principal='') request = requests.get(url, stream=True, auth=krb_auth) shutil.copyfileobj(request.raw, temp)
def test_generate_request_header_custom_service(self): with patch.multiple('kerberos', authGSSClientInit=clientInit_error, authGSSClientResponse=clientResponse, authGSSClientStep=clientStep_continue): response = requests.Response() response.url = "http://www.example.org/" response.headers = {'www-authenticate': 'negotiate token'} auth = requests_kerberos.HTTPKerberosAuth(service="barfoo") auth.generate_request_header(response), clientInit_error.assert_called_with("*****@*****.**")
def test_kerberos_sspi_reject_principal(self): with patch.multiple(kerberos_module_name, authGSSClientInit=clientInit_complete, authGSSClientResponse=clientResponse, authGSSClientStep=clientStep_continue): response = requests.Response() response.url = "http://www.example.org/" host = urlparse(response.url).hostname auth = requests_kerberos.HTTPKerberosAuth(principal="user@REALM") auth._using_kerberos_sspi = True self.assertRaises(NotImplementedError, auth.generate_request_header, response, host) auth = requests_kerberos.HTTPKerberosAuth(principal=None) auth._using_kerberos_sspi = True auth.generate_request_header(response, host) clientInit_complete.assert_called_with( "*****@*****.**", gssflags=(kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG))
def test_no_force_preemptive(self): with patch.multiple(kerberos_module_name, authGSSClientInit=clientInit_complete, authGSSClientResponse=clientResponse, authGSSClientStep=clientStep_continue): auth = requests_kerberos.HTTPKerberosAuth() request = requests.Request(url="http://www.example.org") auth.__call__(request) self.assertTrue('Authorization' not in request.headers)
def test_handle_response_200_mutual_auth_optional_soft_failure(mock_client): response_ok = requests.Response() response_ok.url = "http://www.example.org/" response_ok.status_code = 200 auth = requests_kerberos.HTTPKerberosAuth(requests_kerberos.OPTIONAL) auth._context = {"www.example.org": mock_client.return_value} r = auth.handle_response(response_ok) assert r == response_ok assert mock_client.return_value.step.call_count == 0
def _setup_tunnel(self, host_port): """Use HTTPConnection to HTTP CONNECT to our proxy, connect to the backend and return socket for this tunnel. host_port: tuple (host, port) from thrift.transport.TSocket._resolveAddr. """ conn = httplib.HTTPConnection(self.proxy_host, self.proxy_port) auth_header = requests_kerberos.HTTPKerberosAuth( ).generate_request_header(None, self.proxy_host, is_preemptive=True) conn.set_tunnel(*host_port, headers={'Proxy-Authorization': auth_header}) conn.connect() return conn.sock
def test_generate_request_header_step_error(self): with patch.multiple('kerberos', authGSSClientInit=clientInit_complete, authGSSClientResponse=clientResponse, authGSSClientStep=clientStep_error): response = requests.Response() response.url = "http://www.example.org/" response.headers = {'www-authenticate': 'negotiate token'} auth = requests_kerberos.HTTPKerberosAuth() self.assertEqual(auth.generate_request_header(response), None) clientInit_complete.assert_called_with("*****@*****.**") clientStep_error.assert_called_with("CTX", "token") self.assertFalse(clientResponse.called)
def test_handle_response_200_mutual_auth_required_failure(mock_client): response_ok = requests.Response() response_ok.url = "http://www.example.org/" response_ok.status_code = 200 response_ok.headers = {} auth = requests_kerberos.HTTPKerberosAuth() auth._context = {"www.example.org": mock_client.return_value} with pytest.raises(requests_kerberos.MutualAuthenticationError): auth.handle_response(response_ok) assert mock_client.return_value.step.call_count == 0
def test_handle_response_500_mutual_auth_required_failure(mock_client): response_500 = requests.Response() response_500.url = "http://www.example.org/" response_500.status_code = 500 response_500.headers = {} response_500.request = "REQUEST" response_500.connection = "CONNECTION" response_500._content = "CONTENT" response_500.encoding = "ENCODING" response_500.raw = "RAW" response_500.cookies = "COOKIES" auth = requests_kerberos.HTTPKerberosAuth() auth._context = {"www.example.org": mock_client.return_value} r = auth.handle_response(response_500) assert isinstance(r, requests_kerberos.kerberos_.SanitizedResponse) assert r != response_500 assert r.headers != response_500.headers assert r.status_code == response_500.status_code assert r.encoding == response_500.encoding assert r.raw == response_500.raw assert r.url == response_500.url assert r.reason == response_500.reason assert r.connection == response_500.connection assert r.content == '' assert r.cookies != response_500.cookies assert mock_client.return_value.step.call_count == 0 # re-test with error response sanitizing disabled auth = requests_kerberos.HTTPKerberosAuth( sanitize_mutual_error_response=False) auth._context = {"www.example.org": mock_client.return_value} r = auth.handle_response(response_500) assert not isinstance(r, requests_kerberos.kerberos_.SanitizedResponse)
def test_handle_response_401_rejected(mock_client, mocker): # Get a 401 from server, authenticate, and get another 401 back. # Ensure there is no infinite recursion. connection = mocker.MagicMock() def connection_send(self, *args, **kwargs): reject = requests.Response() reject.url = "http://www.example.org/" reject.status_code = 401 reject.connection = connection return reject connection.send.side_effect = connection_send request = requests.Request() response = requests.Response() response.request = request response.url = "http://www.example.org/" response.headers = {'www-authenticate': 'negotiate dG9rZW4='} response.status_code = 401 response.connection = connection response._content = "" response.raw = mocker.MagicMock(return_value=None) auth = requests_kerberos.HTTPKerberosAuth() r = auth.handle_response(response) assert r.status_code == 401 assert request.headers["Authorization"] == "Negotiate R1NTUkVTUE9OU0U=" assert connection.send.call_count == 1 assert connection.send.call_args[0] == (request, ) assert response.raw.release_conn.call_count == 1 assert response.raw.release_conn.call_args[0] == () assert mock_client.call_count == 1 assert mock_client.call_args[1] == { "username": None, "hostname": "www.example.org", "service": "HTTP", "channel_bindings": None, "context_req": spnego.ContextReq.sequence_detect | spnego.ContextReq.mutual_auth, "protocol": "kerberos", } assert mock_client.return_value.step.call_count == 1 assert mock_client.return_value.step.call_args[1] == { "in_token": b"token", }
def test_delegation(mock_client, mocker): response_ok = requests.Response() response_ok.url = "http://www.example.org/" response_ok.status_code = 200 response_ok.headers = {'www-authenticate': 'negotiate c2VydmVydG9rZW4='} connection = mocker.MagicMock() connection.send.return_value = response_ok request = requests.Request() response = requests.Response() response.request = request response.url = "http://www.example.org/" response.headers = {'www-authenticate': 'negotiate dG9rZW4='} response.status_code = 401 response.connection = connection response._content = "" response.raw = mocker.MagicMock(return_value=None) auth = requests_kerberos.HTTPKerberosAuth(1, "HTTP", True) r = auth.authenticate_user(response) assert response in r.history assert r == response_ok assert request.headers["Authorization"] == "Negotiate R1NTUkVTUE9OU0U=" assert connection.send.call_count == 1 assert connection.send.call_args[0] == (request, ) assert mock_client.call_count == 1 assert mock_client.call_args[1] == { "username": None, "hostname": "www.example.org", "service": "HTTP", "channel_bindings": None, "context_req": spnego.ContextReq.sequence_detect | spnego.ContextReq.mutual_auth | spnego.ContextReq.delegate, "protocol": "kerberos", } assert mock_client.return_value.step.call_count == 1 assert mock_client.return_value.step.call_args[1] == { "in_token": b"token", }