'How to get a Kerberos token in Python? I have working C# and PS syntax but would like to convert it

I'm trying to use Python to get a Kerberos security token. I have some C# sharp syntax that does want I need but I have no clue where to begin to converting that to Python. Here is the C# code:

{
            AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
            var domain = Domain.GetCurrentDomain().ToString();
            using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
            {
                KerberosSecurityTokenProvider tokenProvider = new KerberosSecurityTokenProvider(serviceName, System.Security.Principal.TokenImpersonationLevel.Identification, CredentialCache.DefaultNetworkCredentials);
                KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(5)) as KerberosRequestorSecurityToken;
                string serviceToken = Convert.ToBase64String(securityToken.GetRequest());
}

I've tried to use the 'microsoft.identitymodel.dll' and using the ctype and clr library, but, I am pretty new to Python so I'm not sure if that's even the correct avenue. I also have some Powershell code that does what I need as such:

[System.IdentityModel.Selectors.KerberosSecurityTokenProvider]$tokenProvider = [System.IdentityModel.Selectors.KerberosSecurityTokenProvider]::new($ServicePrincipalName, [System.Security.Principal.TokenImpersonationLevel]::Identification, $PSBoundParameters.Credential)

I know what the $ServicePrincipalName should be and I know I could use the subprocess library and just call the command using Powershell.exe, but I wanted to keep everything in Python.

Any help would be appreciated!



Solution 1:[1]

The primary non-CLR interface to Windows authentication is SSPI (likewise GSSAPI on Linux). The CLR libraries are just fancy wrappers around SSPI, so don't waste time trying to use them from Python – it's going to be more work than using SSPI directly.

If you're working exclusively on Windows, try the sspi module which is part of pywin32. Google tells me it works somewhat like this:

import sspi
context = sspi.ClientAuth(pkg_name="Negotiate",
                          targetspn="HTTP/foo.example.com")
# [receive input_token from server]
while True:
    err, bufs = context.authorize(input_token)
    output_token = bufs[0].Buffer
    # [send output_token to server, receive input_token back]
    if err == 0:
        break

The basic model of SSPI/GSSAPI is "call step() in a loop until the mechanism reports it's complete", but for HTTP Negotiate authentication there is just one step (and the input token is usually empty), so you could skip the loop:

import sspi
ctx = sspi.ClientAuth("Negotiate",
                      targetspn="HTTP/foo.example.com")
in_token = None
err, bufs = ctx.authorize(in_token)
assert(err == 0)
out_token = bufs[0].Buffer

Since most Windows protocols use SPNEGO rather than raw Kerberos, python-pyspnego would be the best choice for cross-platform operation – it provides a unified interface to SPNEGO over both Windows SSPI and over Unix GSSAPI. (It can also do NTLM on Unix.)

import spnego
ctx = spnego.client(hostname="foo.example.com",
                    service="HTTP",
                    protocol="negotiate")
in_token = None
out_token = ctx.step(in_token)

The Linux/Unix equivalent of the sspi module would be python-gssapi, which uses very similar concepts. However, by default it deals with raw Kerberos tokens, not SPNEGO tokens.

import gssapi
target = gssapi.Name("[email protected]",
                     gssapi.NameType.hostbased_service)
ctx = gssapi.SecurityContext(name=target,
                             usage="initiate")
in_token = None
out_token = ctx.step(in_token)

To force it to use SPNEGO, use:

SPNEGO = gssapi.Mechanism.from_sasl_name("SPNEGO")
ctx = gssapi.SecurityContext(name=target,
                             mech=SPNEGO,
                             usage="initiate")

(Note: do not install the gssapi module on Windows – if you do, then the spnego module will stop using SSPI and will start complaining about missing MIT GSSAPI libraries.)

Two other modules exist: pykerberos for GSSAPI (Unix) and winkerberos for SSPI (Windows). They work similarly, but the API they provide is a bit ugly and non-Pythonic (pykerberos was originally a wrapper for Objective-C interfaces in MacOS).

And of course if you're trying to use this for HTTP, there already are several modules for that – e.g. requests-kerberos adds SSPI (and GSSAPI) support through pyspnego:

import requests
import requests_kerberos

resp = requests.get("https://foo.example.com",
                    auth=requests_kerberos.HTTPKerberosAuth())

Similarly, requests-gssapi and httpx-gssapi do the same via gssapi on Unix.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1