pythongssapi / httpx-gssapi

A GSSAPI authentication handler for Python's HTTPX
Other
12 stars 3 forks source link

Add support for Proxy-Authorization #3

Open alippai opened 3 years ago

alippai commented 3 years ago

Similar to HTTP error 401 + Authorization headers sometimes not the server, but a proxy needs authorization. It's using HTTP error 407 and Proxy-Authorization headers.

aiudirog commented 3 years ago

Is there any particular reason you can't use the standard proxy handling? Either through the HTTP[S]_PROXY environment variables or through the routing interface? It would be awkward and redundant to code the same functionality in every individual auth handler.

In theory, you should be able to do:

client = httpx.Client(
    ...
    proxies={
        "http://": "http://USERNAME:PASSWORD@HOST:PORT",
        "https://": "https://USERNAME:PASSWORD@HOST:SSL_PORT",
    },
)

or

export HTTP_PROXY=http://USERNAME:PASSWORD@HOST:PORT
export HTTPS_PROXY=https://USERNAME:PASSWORD@HOST:SSL_PORT

python my_code.py
alippai commented 3 years ago

I want to use password less kerberos interface (using keytab)

aiudirog commented 3 years ago

That doesn't have anything to do with proxy auth or much to do with this library really. GSSAPI authentication happens after you've acquired local Kerberos ticket through something like kinit. You can do that with a subprocess or some other Kerberos wrapper.

Some simple subprocess code could be:

subprocess.run(['kinit', 'USER@ADS', '-k', '-t', 'path/to/user.keytab'], check=True)

@frozencemetery Is there a way to kinit using a keytab with Python GSSAPI? I haven't explored that myself.

alippai commented 3 years ago

The Proxy-Authentication header can contain the kerberos ticket (to the proxy) similar to the Authentication header (to the service). Like you use gssapi to negotiate with the service instead of Basic auth upon HTTP error 401, it can be used to negotiate with the proxy instead of Basic auth upon HTTP error 407

aiudirog commented 3 years ago

Ohhh okay, sorry for the confusion, I understand now. You're trying to authenticate the proxy itself with GSSAPI. We can definitely do that, I'll just need to set up a test env for it.

alippai commented 3 years ago

Exactly, thanks for your patience and your responses. Next time I should start with a code snippet, sequence diag or some better illustration 🤔

frozencemetery commented 3 years ago

@frozencemetery Is there a way to kinit using a keytab with Python GSSAPI? I haven't explored that myself.

(I recognize that the discussion has moved on here, but going to answer this one in case anyone finds this later.)

Yes, but which way depends on what you're trying to do :)

GSSAPI prefers to sit above the level of kinit. But if you have a keytab, it can be specified using the KRB5_KEYTAB or KRB5_CLIENT_KEYTAB variables (see https://web.mit.edu/kerberos/krb5-latest/doc/basic/keytab_def.html) and then either calling acquire_cred or creating a security context as normal. Alternately, the path can be given to acquire_cred_from as either the keytab or client_keytab argument in the store.

alippai commented 3 years ago

This PR is somewhat relevant: https://github.com/requests/requests-kerberos/pull/149/files

aiudirog commented 3 years ago

Yeah I was looking over that earlier. I've been mocking up a test environment using proxy.py with a bare-bones GSSAPI auth plugin.

alippai commented 3 years ago

I didn't know this one, nice!

aiudirog commented 3 years ago

Just wanted to update that I am working on this, but I'm having a little trouble with the testing environment setup. I can get it to properly authenticate the proxy and connect to external websites, but connecting to the local webserver is causing the connection to be terminated. I'll figure it out, just wanted to provide an update.

aiudirog commented 3 years ago

Turns out, it was just a bug in proxy.py: https://github.com/abhinavsingh/proxy.py/issues/398. Setting the Content-Length header for our test cases solves the problem.

However, I've run into a new problem: I can't seem to determine the proxy host for generating the SecurityContext as it doesn't appear to be exposed as a part of the Request/Response class APIs. We may need to actually submit a PR to HTTPX to get this information in the response.

I've pushed my work so far to the proxy-support branch @ https://github.com/pythongssapi/httpx-gssapi/commit/82cca892dc85079a9d06a43bb3c379f15a2de1b1.