1

For a web-application I am writing a middleware using the WSGI-Kerberos to handle the authentication. In general these efforts intend to implement the Single Sign-On technology. So, users that are logged/active in the Active Directory would get an access to the app.

I am deploying my web app on:

Linux TestServer 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64

This is a piece of code that I am executing:

from wsgiref.simple_server import make_server
from wsgi_kerberos import KerberosAuthMiddleware

def example(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello, %s' % environ['REMOTE_USER']]

if __name__ == '__main__':
    app = KerberosAuthMiddleware(example)
    http = make_server('0.0.0.0', 5000,  app)
    http.serve_forever()

However, in a Browser I am getting the 'Forbidden' response after opening the http://TestServer.l.s.d:5000/ link. What can be a problem?

In the cmd I can see this:

a.b.c.d - - [08/Jun/2021 07:44:43] "GET / HTTP/1.1" 401 12
a.b.c.d - - [08/Jun/2021 07:44:43] "GET / HTTP/1.1" 403 9

I have integrated the 'KRB5_KTNAME' to the location of the keytab file into the os.environ['KRB5_KTNAME'], as export os.environ['KRB5_KTNAME']='/path/to/keytab/file.keytab'.

The content of the keytab file looks as following:

ktutil:  list
slot KVNO Principal
---- ---- ---------------------------
   1    4 HTTP/TestServer.l.s.d@L.S.D
Taras
  • 266
  • 6
  • 23
  • 1
    Does your keytab have the correct service principal name? Does your client system have Kerberos tickets for the user? (Does it have the initial 'krbtgt' ticket, and did it also obtain a ticket for your web app's SPN?) – user1686 Jun 09 '21 at 12:11
  • 1
    Why are you wasting your time with this module? Use https://github.com/gssapi/mod_auth_gssapi – Michael-O Jun 15 '21 at 09:38
  • thank you so much @user1686, you comment was really helpful! – Taras Jun 16 '21 at 13:09
  • @Michael-O: That is a good alternative for sites using Apache as the frontend, but that's not always the case - e.g. it won't work for sites proxied via Nginx or hosted on "raw" gunicorn. The python module _could_ be better (e.g. it could be written using python-gssapi instead of the obsolete pykerberos), but there is nothing inherently wrong with implementing HTTP Negotiate at WSGI or even higher level. – user1686 Jun 16 '21 at 13:16
  • @user1686 While not necessary, you will lose the features of the server like expect continue support, etc. and not using python-gssapi module is just plain wrong. – Michael-O Jun 16 '21 at 13:19
  • Dear @user1686, how seriously would you pay attention to [*It's all because of WSGI is made for python 2, so you can face some troubles using it in python3.*](https://stackoverflow.com/a/57542682/5791355) when using WSGI Kerberos even though the [WSGI Kerberos](https://wsgi-kerberos.readthedocs.io/en/latest/) should work with Python 3... what are pros/cons? Maybe another option like Apache 2 WSGI, e.g. [mod wsgi](https://wiki.ubuntuusers.de/Apache/mod_wsgi/) – Taras Jun 16 '21 at 13:22
  • I personally use mod_wsgi and it works like a charm. – Michael-O Jun 16 '21 at 13:48
  • Dear @user1686 it would be a pleasure for me if you can provide an answer to my question, so I can grant you with a bounty, because you was the one that pointed me into the right direction. Thank you so much – Taras Jun 17 '21 at 08:28
  • 1
    @Taras: I don't buy the "made for python 2" argument. The poster assumes this from having to manually encode text to bytes, calling it "a workaround" while it's a completely normal thing. (If WSGI worked with text, it would be impossible to serve binary data with it.) – user1686 Jun 18 '21 at 19:52

1 Answers1

2

After going through all the questions left as comment by @user1686:

Does your keytab have the correct service principal name? Does your client system have Kerberos tickets for the user? (Does it have the initial 'krbtgt' ticket, and did it also obtain a ticket for your web app's SPN?)

it was observed that the keytab file had a wrong (arcfour-hmac is deprecated) encryption type.

A new keytab file using the aes256-cts-hmac-sha1-96 enctype was generated again and now it looks like:

KVNO Timestamp Principal
---- ------------------- --------------------------------------------------
5 01/01/1970 01:00:00 HTTP/TestServer.l.s.d@L.S.D (aes256-cts-hmac-sha1-96)

Thereafter it was again tested and on this stage I got the following error:

a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 401 12
a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 200 0
Traceback (most recent call last):
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 266, in write
    "write() argument must be a bytes instance"
AssertionError: write() argument must be a bytes instance
a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('10.169.43.210', 58080)
Traceback (most recent call last):
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 266, in write
    "write() argument must be a bytes instance"

AssertionError: write() argument must be a bytes instance

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 141, in run
    self.handle_error()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 368, in handle_error
    self.finish_response()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 274, in write
    self.send_headers()
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 331, in send_headers
    if not self.origin_server or self.client_is_modern():
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 344, in client_is_modern
    return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/socketserver.py", line 316, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python3.7/socketserver.py", line 347, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.7/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.7/socketserver.py", line 720, in __init__
    self.handle()
  File "/usr/lib/python3.7/wsgiref/simple_server.py", line 133, in handle
    handler.run(self.server.get_app())
  File "/usr/lib/python3.7/wsgiref/handlers.py", line 144, in run
    self.close()
  File "/usr/lib/python3.7/wsgiref/simple_server.py", line 35, in close
    self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
----------------------------------------
a.b.c.d - - [16/Jun/2021 14:11:30] "GET / HTTP/1.1" 403 9

In the error I found out, that:

AssertionError: write() argument must be a bytes instance

thereafter it led me to this thread argument must be a bytes instance WSGI Python3.

And then the content of the code was appropriately edited:

from wsgiref.simple_server import make_server
from wsgi_kerberos import KerberosAuthMiddleware

def example(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    response_body = 'Hello, %s!' % environ['REMOTE_USER']
    return [response_body.encode()]

if __name__ == '__main__':
    app = KerberosAuthMiddleware(example)
    http = make_server('0.0.0.0', 5000,  app)
    http.serve_forever()

And now I can this in my Browser:

Hello, username@L.S.D!

where username is my username in the Windows System.


References:

Taras
  • 266
  • 6
  • 23