我正在尝试使用 Python 来获取 Kerberos 安全令牌。我有一些确实需要的 C# 清晰语法,但我不知道从哪里开始将其转换为 Python。这是 C# 代码:
{
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());
}
我尝试使用“microsoft.identitymodel.dll”并使用 ctype 和 clr 库,但是,我对 Python 还很陌生,所以我不确定这是否是正确的途径。我还有一些 Powershell 代码可以满足我的需要:
[System.IdentityModel.Selectors.KerberosSecurityTokenProvider]$tokenProvider = [System.IdentityModel.Selectors.KerberosSecurityTokenProvider]::new($ServicePrincipalName, [System.Security.Principal.TokenImpersonationLevel]::Identification, $PSBoundParameters.Credential)
我知道 $ServicePrincipalName 应该是什么,我知道我可以使用子进程库,只需使用 Powershell.exe 调用命令,但我想将所有内容保留在 Python 中。
如有任何帮助,我们将不胜感激!
Windows 身份验证的主要非 CLR 接口是 SSPI(类似于 Linux 上的 GSSAPI)。 CLR 库只是 SSPI 的精美包装,因此不要浪费时间尝试从 Python 使用它们 - 这比直接使用 SSPI 需要更多工作。
如果您只在 Windows 上工作,请尝试作为 pywin32
一部分的
sspi
模块,或新的 sspilib
模块。谷歌告诉我“sspi”模块的工作原理有点像这样:
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
SSPI/GSSAPI 的基本模型是“循环调用 step() 直到机制报告完成”,但对于 HTTP Negotiate 身份验证只有一步(并且输入令牌通常为空),因此您可以跳过循环:
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
或使用sspilib:
import sspilib
creds = sspilib.UserCredential(usage="initiate",
protocol="Negotiate",
protocol_list=["!ntlm"])
ctx = sspilib.ClientSecurityContext(target_name="HTTP/foo.example.com",
credential=creds)
out_token = ctx.step(in_token)
由于大多数 Windows 协议使用 SPNEGO 而不是原始 Kerberos,因此 python-pyspnego 将是跨平台操作的最佳选择 - 它通过 Windows SSPI 和 Unix GSSAPI 提供到 SPNEGO 的统一接口。 (它也可以在 Unix 上执行 NTLM。)
import spnego
ctx = spnego.client(hostname="foo.example.com",
service="HTTP",
protocol="negotiate")
in_token = None
out_token = ctx.step(in_token)
sspi
模块的Linux/Unix等价物是python-gssapi,它使用非常相似的概念。但是,默认情况下它处理原始 Kerberos 令牌,而不是 SPNEGO 令牌。
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)
要强制其使用 SPNEGO,请使用:
SPNEGO = gssapi.Mechanism.from_sasl_name("SPNEGO")
ctx = gssapi.SecurityContext(name=target,
mech=SPNEGO,
usage="initiate")
(注意:不要
在 Windows 上安装 gssapi
模块 – 如果这样做,那么
spnego
模块将停止使用 SSPI,并开始抱怨缺少 MIT GSSAPI 库。)还有另外两个模块:用于 GSSAPI (Unix) 的 pykerberos和用于 SSPI (Windows) 的 winkerberos。它们的工作原理类似,但它们提供的 API 有点丑陋且非 Python 风格(pykerberos 最初是 MacOS 中 Objective-C 接口的包装器)。 当然,如果您尝试将其用于 HTTP,那么已经有几个模块可以实现 – 例如
requests-kerberos 通过 pyspnego 添加 SSPI(和 GSSAPI)支持:
import requests
import requests_kerberos
resp = requests.get("https://foo.example.com",
auth=requests_kerberos.HTTPKerberosAuth())
类似地,requests-gssapi
和 httpx-gssapi 在 Unix 上通过 gssapi
执行相同的操作。