Hello community,
here is the log from the commit of package python-requests-kerberos for
openSUSE:Factory checked in at 2016-11-15 18:02:33
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-requests-kerberos (Old)
and /work/SRC/openSUSE:Factory/.python-requests-kerberos.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-requests-kerberos"
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-requests-kerberos/python-requests-kerberos.changes
2016-03-17 16:47:22.000000000 +0100
+++
/work/SRC/openSUSE:Factory/.python-requests-kerberos.new/python-requests-kerberos.changes
2016-11-15 18:02:34.000000000 +0100
@@ -1,0 +2,11 @@
+Tue Nov 15 09:32:18 UTC 2016 - [email protected]
+
+- update to 0.10.0:
+ - Make it possible to receive errors without having their contents and
headers
+ stripped.
+ - Resolve a bug caused by passing the ``principal`` keyword argument to
+ kerberos-sspi on Windows.
+ - Support for principal, hostname, and realm override.
+ - Added support for mutual auth.
+
+-------------------------------------------------------------------
Old:
----
requests-kerberos-0.8.0.tar.gz
New:
----
requests-kerberos-0.10.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-requests-kerberos.spec ++++++
--- /var/tmp/diff_new_pack.qXgnwd/_old 2016-11-15 18:02:35.000000000 +0100
+++ /var/tmp/diff_new_pack.qXgnwd/_new 2016-11-15 18:02:35.000000000 +0100
@@ -17,13 +17,13 @@
Name: python-requests-kerberos
-Version: 0.8.0
+Version: 0.10.0
Release: 0
Summary: A Kerberos authentication handler for python-requests
License: ISC
Group: Development/Languages/Python
Url: https://github.com/requests/requests-kerberos
-Source:
https://pypi.python.org/packages/source/r/requests-kerberos/requests-kerberos-%{version}.tar.gz
+Source:
https://pypi.io/packages/source/r/requests-kerberos/requests-kerberos-%{version}.tar.gz
BuildRequires: python-devel
BuildRequires: python-requests
BuildRequires: python-setuptools
++++++ requests-kerberos-0.8.0.tar.gz -> requests-kerberos-0.10.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-kerberos-0.8.0/HISTORY.rst
new/requests-kerberos-0.10.0/HISTORY.rst
--- old/requests-kerberos-0.8.0/HISTORY.rst 2016-01-07 19:15:26.000000000
+0100
+++ new/requests-kerberos-0.10.0/HISTORY.rst 2016-05-18 14:20:14.000000000
+0200
@@ -1,6 +1,21 @@
History
=======
+0.10.0: 2016-05-18
+------------------
+
+- Make it possible to receive errors without having their contents and headers
+ stripped.
+- Resolve a bug caused by passing the ``principal`` keyword argument to
+ kerberos-sspi on Windows.
+
+0.9.0: 2016-05-06
+-----------------
+
+- Support for principal, hostname, and realm override.
+
+- Added support for mutual auth.
+
0.8.0: 2016-01-07
-----------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-kerberos-0.8.0/PKG-INFO
new/requests-kerberos-0.10.0/PKG-INFO
--- old/requests-kerberos-0.8.0/PKG-INFO 2016-01-07 19:17:15.000000000
+0100
+++ new/requests-kerberos-0.10.0/PKG-INFO 2016-05-18 14:20:59.000000000
+0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: requests-kerberos
-Version: 0.8.0
+Version: 0.10.0
Summary: A Kerberos authentication handler for python-requests
Home-page: https://github.com/requests/requests-kerberos
Author: Ian Cordasco, Cory Benfield, Michael Komitee
@@ -14,7 +14,7 @@
authentication. Basic GET usage:
- .. code-block:: pycon
+ .. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth
@@ -32,11 +32,26 @@
Mutual Authentication
---------------------
+ REQUIRED
+ ^^^^^^^^
+
By default, ``HTTPKerberosAuth`` will require mutual authentication
from the
server, and if a server emits a non-error response which cannot be
- authenticated, a
``requests_kerberos.errors.MutualAuthenticationError`` will be
- raised. If a server emits an error which cannot be authenticated, it
will be
- returned to the user but with its contents and headers stripped.
+ authenticated, a
``requests_kerberos.errors.MutualAuthenticationError`` will
+ be raised. If a server emits an error which cannot be authenticated,
it will
+ be returned to the user but with its contents and headers stripped. If
the
+ response content is more important than the need for mutual auth on
errors,
+ (eg, for certain WinRM calls) the stripping behavior can be suppressed
by
+ setting ``sanitize_mutual_error_response=False``:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(mutual_authentication=REQUIRED,
sanitize_mutual_error_response=False)
+ >>> r = requests.get("https://windows.example.org/wsman",
auth=kerberos_auth)
+ ...
+
OPTIONAL
^^^^^^^^
@@ -44,7 +59,7 @@
If you'd prefer to not require mutual authentication, you can set your
preference when constructing your ``HTTPKerberosAuth`` object:
- .. code-block:: pycon
+ .. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth, OPTIONAL
@@ -62,7 +77,7 @@
While we don't recommend it, if you'd prefer to never attempt mutual
authentication, you can do that as well:
- .. code-block:: pycon
+ .. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth, DISABLED
@@ -70,6 +85,65 @@
>>> r = requests.get("http://example.org", auth=kerberos_auth)
...
+ Preemptive Authentication
+ -------------------------
+
+ ``HTTPKerberosAuth`` can be forced to preemptively initiate the
Kerberos
+ GSS exchange and present a Kerberos ticket on the initial request (and
all
+ subsequent). By default, authentication only occurs after a
+ ``401 Unauthorized`` response containing a Kerberos or Negotiate
challenge
+ is received from the origin server. This can cause mutual
authentication
+ failures for hosts that use a persistent connection (eg,
Windows/WinRM), as
+ no Kerberos challenges are sent after the initial auth handshake. This
+ behavior can be altered by setting ``force_preemptive=True``:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(mutual_authentication=REQUIRED, force_preemptive=True)
+ >>> r = requests.get("https://windows.example.org/wsman",
auth=kerberos_auth)
+ ...
+
+ Hostname Override
+ -----------------
+
+ If communicating with a host whose DNS name doesn't match its
+ kerberos hostname (eg, behind a content switch or load balancer),
+ the hostname used for the Kerberos GSS exchange can be overridden by
+ setting the ``hostname_override`` arg:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(hostname_override="internalhost.local")
+ >>> r = requests.get("https://externalhost.example.org/",
auth=kerberos_auth)
+ ...
+
+ Explicit Principal
+ ------------------
+
+ ``HTTPKerberosAuth`` normally uses the default principal (ie, the user
for
+ whom you last ran ``kinit`` or ``kswitch``, or an SSO credential if
+ applicable). However, an explicit principal can be specified, which
will
+ cause Kerberos to look for a matching credential cache for the named
user.
+ This feature depends on OS support for collection-type credential
caches,
+ as well as working principal support in pykerberos (it is broken in
many
+ builds). An explicit principal can be specified with the ``principal``
arg:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth = HTTPKerberosAuth(principal="user@REALM")
+ >>> r = requests.get("http://example.org", auth=kerberos_auth)
+ ...
+
+ **Windows users:** Explicit Principal is currently not supported when
using
+ ``kerberos-sspi``. Providing a value for ``principal`` in this
scenario will raise
+ ``NotImplementedError``.
+
Logging
-------
@@ -87,6 +161,21 @@
History
=======
+ 0.10.0: 2016-05-18
+ ------------------
+
+ - Make it possible to receive errors without having their contents and
headers
+ stripped.
+ - Resolve a bug caused by passing the ``principal`` keyword argument to
+ kerberos-sspi on Windows.
+
+ 0.9.0: 2016-05-06
+ -----------------
+
+ - Support for principal, hostname, and realm override.
+
+ - Added support for mutual auth.
+
0.8.0: 2016-01-07
-----------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-kerberos-0.8.0/README.rst
new/requests-kerberos-0.10.0/README.rst
--- old/requests-kerberos-0.8.0/README.rst 2014-02-15 20:37:58.000000000
+0100
+++ new/requests-kerberos-0.10.0/README.rst 2016-05-18 14:16:11.000000000
+0200
@@ -6,7 +6,7 @@
authentication. Basic GET usage:
-.. code-block:: pycon
+.. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth
@@ -24,11 +24,26 @@
Mutual Authentication
---------------------
+REQUIRED
+^^^^^^^^
+
By default, ``HTTPKerberosAuth`` will require mutual authentication from the
server, and if a server emits a non-error response which cannot be
-authenticated, a ``requests_kerberos.errors.MutualAuthenticationError`` will be
-raised. If a server emits an error which cannot be authenticated, it will be
-returned to the user but with its contents and headers stripped.
+authenticated, a ``requests_kerberos.errors.MutualAuthenticationError`` will
+be raised. If a server emits an error which cannot be authenticated, it will
+be returned to the user but with its contents and headers stripped. If the
+response content is more important than the need for mutual auth on errors,
+(eg, for certain WinRM calls) the stripping behavior can be suppressed by
+setting ``sanitize_mutual_error_response=False``:
+
+.. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth = HTTPKerberosAuth(mutual_authentication=REQUIRED,
sanitize_mutual_error_response=False)
+ >>> r = requests.get("https://windows.example.org/wsman",
auth=kerberos_auth)
+ ...
+
OPTIONAL
^^^^^^^^
@@ -36,7 +51,7 @@
If you'd prefer to not require mutual authentication, you can set your
preference when constructing your ``HTTPKerberosAuth`` object:
-.. code-block:: pycon
+.. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth, OPTIONAL
@@ -54,7 +69,7 @@
While we don't recommend it, if you'd prefer to never attempt mutual
authentication, you can do that as well:
-.. code-block:: pycon
+.. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth, DISABLED
@@ -62,6 +77,65 @@
>>> r = requests.get("http://example.org", auth=kerberos_auth)
...
+Preemptive Authentication
+-------------------------
+
+``HTTPKerberosAuth`` can be forced to preemptively initiate the Kerberos
+GSS exchange and present a Kerberos ticket on the initial request (and all
+subsequent). By default, authentication only occurs after a
+``401 Unauthorized`` response containing a Kerberos or Negotiate challenge
+is received from the origin server. This can cause mutual authentication
+failures for hosts that use a persistent connection (eg, Windows/WinRM), as
+no Kerberos challenges are sent after the initial auth handshake. This
+behavior can be altered by setting ``force_preemptive=True``:
+
+.. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth = HTTPKerberosAuth(mutual_authentication=REQUIRED,
force_preemptive=True)
+ >>> r = requests.get("https://windows.example.org/wsman",
auth=kerberos_auth)
+ ...
+
+Hostname Override
+-----------------
+
+If communicating with a host whose DNS name doesn't match its
+kerberos hostname (eg, behind a content switch or load balancer),
+the hostname used for the Kerberos GSS exchange can be overridden by
+setting the ``hostname_override`` arg:
+
+.. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(hostname_override="internalhost.local")
+ >>> r = requests.get("https://externalhost.example.org/",
auth=kerberos_auth)
+ ...
+
+Explicit Principal
+------------------
+
+``HTTPKerberosAuth`` normally uses the default principal (ie, the user for
+whom you last ran ``kinit`` or ``kswitch``, or an SSO credential if
+applicable). However, an explicit principal can be specified, which will
+cause Kerberos to look for a matching credential cache for the named user.
+This feature depends on OS support for collection-type credential caches,
+as well as working principal support in pykerberos (it is broken in many
+builds). An explicit principal can be specified with the ``principal`` arg:
+
+.. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth = HTTPKerberosAuth(principal="user@REALM")
+ >>> r = requests.get("http://example.org", auth=kerberos_auth)
+ ...
+
+**Windows users:** Explicit Principal is currently not supported when using
+``kerberos-sspi``. Providing a value for ``principal`` in this scenario will
raise
+``NotImplementedError``.
+
Logging
-------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-kerberos-0.8.0/requests_kerberos/__init__.py
new/requests-kerberos-0.10.0/requests_kerberos/__init__.py
--- old/requests-kerberos-0.8.0/requests_kerberos/__init__.py 2016-01-07
19:15:35.000000000 +0100
+++ new/requests-kerberos-0.10.0/requests_kerberos/__init__.py 2016-05-18
14:20:22.000000000 +0200
@@ -22,4 +22,4 @@
__all__ = ('HTTPKerberosAuth', 'MutualAuthenticationError', 'REQUIRED',
'OPTIONAL', 'DISABLED')
-__version__ = '0.8.0'
+__version__ = '0.10.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-kerberos-0.8.0/requests_kerberos/exceptions.py
new/requests-kerberos-0.10.0/requests_kerberos/exceptions.py
--- old/requests-kerberos-0.8.0/requests_kerberos/exceptions.py 2014-02-15
20:37:58.000000000 +0100
+++ new/requests-kerberos-0.10.0/requests_kerberos/exceptions.py
2016-05-06 10:10:09.000000000 +0200
@@ -10,3 +10,6 @@
class MutualAuthenticationError(RequestException):
"""Mutual Authentication Error"""
+
+class KerberosExchangeError(RequestException):
+ """Kerberos Exchange Failed Error"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-kerberos-0.8.0/requests_kerberos/kerberos_.py
new/requests-kerberos-0.10.0/requests_kerberos/kerberos_.py
--- old/requests-kerberos-0.8.0/requests_kerberos/kerberos_.py 2016-01-07
19:08:46.000000000 +0100
+++ new/requests-kerberos-0.10.0/requests_kerberos/kerberos_.py 2016-05-18
14:16:11.000000000 +0200
@@ -1,7 +1,9 @@
try:
import kerberos
+ using_kerberos_sspi = False
except ImportError:
import kerberos_sspi as kerberos
+ using_kerberos_sspi = True
import re
import logging
@@ -11,11 +13,10 @@
from requests.structures import CaseInsensitiveDict
from requests.cookies import cookiejar_from_dict
-from .exceptions import MutualAuthenticationError
+from .exceptions import MutualAuthenticationError, KerberosExchangeError
log = logging.getLogger(__name__)
-
# Different types of mutual authentication:
# with mutual_authentication set to REQUIRED, all responses will be
# authenticated with the exception of errors. Errors will have their contents
@@ -31,7 +32,6 @@
OPTIONAL = 2
DISABLED = 3
-
class SanitizedResponse(Response):
"""The :class:`Response <Response>` object, which contains a server's
response to an HTTP request.
@@ -86,21 +86,27 @@
object."""
def __init__(
self, mutual_authentication=REQUIRED,
- service="HTTP", delegate=False):
+ service="HTTP", delegate=False, force_preemptive=False,
+ principal=None, hostname_override=None,
sanitize_mutual_error_response=True):
self.context = {}
self.mutual_authentication = mutual_authentication
self.delegate = delegate
self.pos = None
self.service = service
+ self.force_preemptive = force_preemptive
+ self.principal = principal
+ self.hostname_override = hostname_override
+ self.sanitize_mutual_error_response = sanitize_mutual_error_response
+ self._using_kerberos_sspi = using_kerberos_sspi
- def generate_request_header(self, response):
+ def generate_request_header(self, response, host, is_preemptive=False):
"""
Generates the GSSAPI authentication token with kerberos.
- If any GSSAPI step fails, return None.
+ If any GSSAPI step fails, raise KerberosExchangeError
+ with failure detail.
"""
- host = urlparse(response.url).hostname
# Flags used by kerberos module.
gssflags = kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG
@@ -108,48 +114,66 @@
gssflags |= kerberos.GSS_C_DELEG_FLAG
try:
- result, self.context[host] = kerberos.authGSSClientInit(
- "{0}@{1}".format(self.service, host), gssflags=gssflags)
- except kerberos.GSSError as error:
- log.error("generate_request_header(): authGSSClientInit() failed:")
- log.exception(error)
- return None
-
- if result < 1:
- log.error("generate_request_header(): authGSSClientInit() failed: "
- "{0}".format(result))
- return None
+ kerb_stage = "authGSSClientInit()"
+ # contexts still need to be stored by host, but hostname_override
+ # allows use of an arbitrary hostname for the kerberos exchange
+ # (eg, in cases of aliased hosts, internal vs external, CNAMEs
+ # w/ name-based HTTP hosting)
+ kerb_host = self.hostname_override if self.hostname_override is
not None else host
+ kerb_spn = "{0}@{1}".format(self.service, kerb_host)
+
+ kwargs = {}
+ # kerberos-sspi: Never pass principal. Raise if user tries to
specify one.
+ if not self._using_kerberos_sspi:
+ kwargs['principal'] = self.principal
+ elif self.principal:
+ raise NotImplementedError("Can't use 'principal' argument with
kerberos-sspi.")
+
+ result, self.context[host] = kerberos.authGSSClientInit(kerb_spn,
+ gssflags=gssflags, **kwargs)
+
+ if result < 1:
+ raise EnvironmentError(result, kerb_stage)
+
+ # if we have a previous response from the server, use it to
continue
+ # the auth process, otherwise use an empty value
+ negotiate_resp_value = '' if is_preemptive else
_negotiate_value(response)
- try:
+ kerb_stage = "authGSSClientStep()"
result = kerberos.authGSSClientStep(self.context[host],
- _negotiate_value(response))
- except kerberos.GSSError as error:
- log.exception(
- "generate_request_header(): authGSSClientStep() failed:")
- log.exception(error)
- return None
+ negotiate_resp_value)
- if result < 0:
- log.error(
- "generate_request_header(): authGSSClientStep() failed: "
- "{0}".format(result))
- return None
+ if result < 0:
+ raise EnvironmentError(result, kerb_stage)
- try:
+ kerb_stage = "authGSSClientResponse()"
gss_response = kerberos.authGSSClientResponse(self.context[host])
+
+ return "Negotiate {0}".format(gss_response)
+
except kerberos.GSSError as error:
log.exception(
- "generate_request_header(): authGSSClientResponse() failed:")
+ "generate_request_header(): {0} failed:".format(kerb_stage))
log.exception(error)
- return None
+ raise KerberosExchangeError("%s failed: %s" % (kerb_stage,
str(error.args)))
- return "Negotiate {0}".format(gss_response)
+ except EnvironmentError as error:
+ # ensure we raised this for translation to KerberosExchangeError
+ # by comparing errno to result, re-raise if not
+ if error.errno != result:
+ raise
+ message = "{0} failed, result: {1}".format(kerb_stage, result)
+ log.error("generate_request_header(): {0}".format(message))
+ raise KerberosExchangeError(message)
def authenticate_user(self, response, **kwargs):
"""Handles user authentication with gssapi/kerberos"""
- auth_header = self.generate_request_header(response)
- if auth_header is None:
+ host = urlparse(response.url).hostname
+
+ try:
+ auth_header = self.generate_request_header(response, host)
+ except KerberosExchangeError:
# GSS Failure, return existing response
return response
@@ -211,7 +235,8 @@
log.error("handle_other(): Mutual authentication
unavailable "
"on {0} response".format(response.status_code))
- if self.mutual_authentication == REQUIRED:
+ if(self.mutual_authentication == REQUIRED and
+ self.sanitize_mutual_error_response):
return SanitizedResponse(response)
else:
return response
@@ -285,6 +310,17 @@
response.request.deregister_hook('response', self.handle_response)
def __call__(self, request):
+ if self.force_preemptive:
+ # add Authorization header before we receive a 401
+ # by the 401 handler
+ host = urlparse(request.url).hostname
+
+ auth_header = self.generate_request_header(None, host,
is_preemptive=True)
+
+ log.debug("HTTPKerberosAuth: Preemptive Authorization header:
{0}".format(auth_header))
+
+ request.headers['Authorization'] = auth_header
+
request.register_hook('response', self.handle_response)
try:
self.pos = request.body.tell()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-kerberos-0.8.0/requests_kerberos.egg-info/PKG-INFO
new/requests-kerberos-0.10.0/requests_kerberos.egg-info/PKG-INFO
--- old/requests-kerberos-0.8.0/requests_kerberos.egg-info/PKG-INFO
2016-01-07 19:17:15.000000000 +0100
+++ new/requests-kerberos-0.10.0/requests_kerberos.egg-info/PKG-INFO
2016-05-18 14:20:59.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: requests-kerberos
-Version: 0.8.0
+Version: 0.10.0
Summary: A Kerberos authentication handler for python-requests
Home-page: https://github.com/requests/requests-kerberos
Author: Ian Cordasco, Cory Benfield, Michael Komitee
@@ -14,7 +14,7 @@
authentication. Basic GET usage:
- .. code-block:: pycon
+ .. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth
@@ -32,11 +32,26 @@
Mutual Authentication
---------------------
+ REQUIRED
+ ^^^^^^^^
+
By default, ``HTTPKerberosAuth`` will require mutual authentication
from the
server, and if a server emits a non-error response which cannot be
- authenticated, a
``requests_kerberos.errors.MutualAuthenticationError`` will be
- raised. If a server emits an error which cannot be authenticated, it
will be
- returned to the user but with its contents and headers stripped.
+ authenticated, a
``requests_kerberos.errors.MutualAuthenticationError`` will
+ be raised. If a server emits an error which cannot be authenticated,
it will
+ be returned to the user but with its contents and headers stripped. If
the
+ response content is more important than the need for mutual auth on
errors,
+ (eg, for certain WinRM calls) the stripping behavior can be suppressed
by
+ setting ``sanitize_mutual_error_response=False``:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(mutual_authentication=REQUIRED,
sanitize_mutual_error_response=False)
+ >>> r = requests.get("https://windows.example.org/wsman",
auth=kerberos_auth)
+ ...
+
OPTIONAL
^^^^^^^^
@@ -44,7 +59,7 @@
If you'd prefer to not require mutual authentication, you can set your
preference when constructing your ``HTTPKerberosAuth`` object:
- .. code-block:: pycon
+ .. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth, OPTIONAL
@@ -62,7 +77,7 @@
While we don't recommend it, if you'd prefer to never attempt mutual
authentication, you can do that as well:
- .. code-block:: pycon
+ .. code-block:: python
>>> import requests
>>> from requests_kerberos import HTTPKerberosAuth, DISABLED
@@ -70,6 +85,65 @@
>>> r = requests.get("http://example.org", auth=kerberos_auth)
...
+ Preemptive Authentication
+ -------------------------
+
+ ``HTTPKerberosAuth`` can be forced to preemptively initiate the
Kerberos
+ GSS exchange and present a Kerberos ticket on the initial request (and
all
+ subsequent). By default, authentication only occurs after a
+ ``401 Unauthorized`` response containing a Kerberos or Negotiate
challenge
+ is received from the origin server. This can cause mutual
authentication
+ failures for hosts that use a persistent connection (eg,
Windows/WinRM), as
+ no Kerberos challenges are sent after the initial auth handshake. This
+ behavior can be altered by setting ``force_preemptive=True``:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(mutual_authentication=REQUIRED, force_preemptive=True)
+ >>> r = requests.get("https://windows.example.org/wsman",
auth=kerberos_auth)
+ ...
+
+ Hostname Override
+ -----------------
+
+ If communicating with a host whose DNS name doesn't match its
+ kerberos hostname (eg, behind a content switch or load balancer),
+ the hostname used for the Kerberos GSS exchange can be overridden by
+ setting the ``hostname_override`` arg:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth =
HTTPKerberosAuth(hostname_override="internalhost.local")
+ >>> r = requests.get("https://externalhost.example.org/",
auth=kerberos_auth)
+ ...
+
+ Explicit Principal
+ ------------------
+
+ ``HTTPKerberosAuth`` normally uses the default principal (ie, the user
for
+ whom you last ran ``kinit`` or ``kswitch``, or an SSO credential if
+ applicable). However, an explicit principal can be specified, which
will
+ cause Kerberos to look for a matching credential cache for the named
user.
+ This feature depends on OS support for collection-type credential
caches,
+ as well as working principal support in pykerberos (it is broken in
many
+ builds). An explicit principal can be specified with the ``principal``
arg:
+
+ .. code-block:: python
+
+ >>> import requests
+ >>> from requests_kerberos import HTTPKerberosAuth, REQUIRED
+ >>> kerberos_auth = HTTPKerberosAuth(principal="user@REALM")
+ >>> r = requests.get("http://example.org", auth=kerberos_auth)
+ ...
+
+ **Windows users:** Explicit Principal is currently not supported when
using
+ ``kerberos-sspi``. Providing a value for ``principal`` in this
scenario will raise
+ ``NotImplementedError``.
+
Logging
-------
@@ -87,6 +161,21 @@
History
=======
+ 0.10.0: 2016-05-18
+ ------------------
+
+ - Make it possible to receive errors without having their contents and
headers
+ stripped.
+ - Resolve a bug caused by passing the ``principal`` keyword argument to
+ kerberos-sspi on Windows.
+
+ 0.9.0: 2016-05-06
+ -----------------
+
+ - Support for principal, hostname, and realm override.
+
+ - Added support for mutual auth.
+
0.8.0: 2016-01-07
-----------------