Skip to content

Commit cdcc45b

Browse files
Allow passing in creds explicitly (deprecates principal)
Signed-off-by: Robbie Harwood <[email protected]>
1 parent b2de746 commit cdcc45b

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

requests_gssapi/compat.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
"""
44
import sys
55

6-
from .gssapi_ import REQUIRED, HTTPSPNEGOAuth # noqa
6+
import gssapi
7+
8+
from .gssapi_ import REQUIRED, HTTPSPNEGOAuth, SPNEGOExchangeError, log
79

810
# python 2.7 introduced a NullHandler which we want to use, but to support
911
# older versions, we implement our own if needed.
@@ -22,18 +24,34 @@ class HTTPKerberosAuth(HTTPSPNEGOAuth):
2224
def __init__(self, mutual_authentication=REQUIRED, service="HTTP",
2325
delegate=False, force_preemptive=False, principal=None,
2426
hostname_override=None, sanitize_mutual_error_response=True):
27+
# put this here for later
28+
self.principal = principal
29+
2530
HTTPSPNEGOAuth.__init__(
2631
self,
2732
mutual_authentication=mutual_authentication,
2833
service=service,
2934
delegate=delegate,
3035
opportunistic_auth=force_preemptive,
31-
principal=principal,
36+
creds=None,
3237
hostname_override=hostname_override,
3338
sanitize_mutual_error_response=sanitize_mutual_error_response)
3439

3540
def generate_request_header(self, response, host, is_preemptive=False):
3641
# This method needs to be shimmed because `host` isn't exposed to
37-
# __init__() and we need to derive things from it
38-
return HTTPSPNEGOAuth.generate_request_header(self, response, host,
39-
is_preemptive)
42+
# __init__() and we need to derive things from it. Also, __init__()
43+
# can't fail, in the strictest compatability sense.
44+
try:
45+
if self.principal is not None:
46+
gss_stage = "acquiring credentials"
47+
name = gssapi.Name(self.principal)
48+
self.creds = gssapi.Credentials(name=name, usage="initiate")
49+
50+
return HTTPSPNEGOAuth.generate_request_header(self, response,
51+
host, is_preemptive)
52+
except gssapi.exceptions.GSSError as error:
53+
msg = error.gen_message()
54+
log.exception(
55+
"generate_request_header(): {0} failed:".format(gss_stage))
56+
log.exception(msg)
57+
raise SPNEGOExchangeError("%s failed: %s" % (gss_stage, msg))

requests_gssapi/gssapi_.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,15 @@ def _negotiate_value(response):
8181
class HTTPSPNEGOAuth(AuthBase):
8282
"""Attaches HTTP GSSAPI Authentication to the given Request object."""
8383
def __init__(self, mutual_authentication=REQUIRED, service="HTTP",
84-
delegate=False, opportunistic_auth=False, principal=None,
84+
delegate=False, opportunistic_auth=False, creds=None,
8585
hostname_override=None, sanitize_mutual_error_response=True):
8686
self.context = {}
8787
self.mutual_authentication = mutual_authentication
8888
self.delegate = delegate
8989
self.pos = None
9090
self.service = service
9191
self.opportunistic_auth = opportunistic_auth
92-
self.principal = principal
92+
self.creds = creds
9393
self.hostname_override = hostname_override
9494
self.sanitize_mutual_error_response = sanitize_mutual_error_response
9595

@@ -118,16 +118,10 @@ def generate_request_header(self, response, host, is_preemptive=False):
118118

119119
kerb_spn = "{0}@{1}".format(self.service, kerb_host)
120120

121-
creds = None
122-
if self.principal:
123-
gss_stage = "acquiring credentials"
124-
creds = gssapi.Credentials(name=gssapi.Name(self.principal),
125-
usage="initiate")
126-
127121
gss_stage = "initiating context"
128122
self.context[host] = gssapi.SecurityContext(
129123
usage="initiate", flags=gssflags, name=gssapi.Name(kerb_spn),
130-
creds=creds)
124+
creds=self.creds)
131125

132126
gss_stage = "stepping context"
133127
if is_preemptive:

test_requests_gssapi.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,22 @@ def test_opportunistic_auth(self):
573573
self.assertEqual(request.headers.get('Authorization'),
574574
'Negotiate GSSRESPONSE')
575575

576+
def test_explicit_creds(self):
577+
with patch.multiple("gssapi.Credentials", __new__=fake_creds), \
578+
patch.multiple("gssapi.SecurityContext", __init__=fake_init,
579+
step=fake_resp):
580+
response = requests.Response()
581+
response.url = "http://www.example.org/"
582+
response.headers = {'www-authenticate': 'negotiate token'}
583+
host = urlparse(response.url).hostname
584+
creds = gssapi.Credentials()
585+
auth = requests_gssapi.HTTPSPNEGOAuth(creds=creds)
586+
auth.generate_request_header(response, host)
587+
fake_init.assert_called_with(
588+
name=gssapi.Name("[email protected]"),
589+
usage="initiate", flags=gssflags, creds="fake creds")
590+
fake_resp.assert_called_with("token")
591+
576592

577593
if __name__ == '__main__':
578594
unittest.main()

0 commit comments

Comments
 (0)