j'essaye d'utiliser l'authentification Windows dans le conteneur de docker de linux sous kubernetes.
Je suis ces paramètres: https://docs.Microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio#kestrel
L'application est en .net core3, avec nuget Microsoft.AspNetCore.Authentication.Negotiate et s'exécute dans Kestrel
J'ai ajouté le
services.AddAuthentication(Microsoft.AspNetCore.Authentication.Negotiate.NegotiateDefaults.AuthenticationScheme).AddNegotiate();
aussi bien que
app.UseAuthentication();
et configurer mon image devbase comme
FROM mcr.Microsoft.com/dotnet/core/sdk:3.1-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y
ADD ca/ca.crt /usr/local/share/ca-certificates/ca.crt
RUN chmod 644 /usr/local/share/ca-certificates/*
RUN update-ca-certificates
RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user
COPY krb5.conf /etc/krb5.conf
RUN mkdir /app
RUN echo BQIAAA..== | base64 -d > /app/is.k01.HTTP.keytab
WORKDIR /app
#RUN docker version
RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --Shell /bin/bash -d /app app
RUN apt install -y mc Sudo syslog-ng realmd gss-ntlmssp
la construction dans le pipeline tfs crée une image docker d'application dérivée de ci-dessus et ajoute les variables d'environnement suivantes, copie également la construction dans/app
RUN chmod 0700 run.sh
ENV KRB5_KTNAME=/app/is.k01.HTTP.keytab
ENV KRB5_TRACE=/dev/stdout
ENV ASPNETCORE_URLS=http://*:80;https://+:443
RUN chown app:app /app -R
USER app
l'application est exécutée par run.sh
service syslog-ng start
kinit HTTP/[email protected] -k -t /app/is.k01.HTTP.keytab
klist
dotnet dev-certs https
dotnet /app/SampleApi.dll
klist répertorie le principal qui a attribué le SPN à la machine
dans ie et firefox, j'ai ajouté le network.negotiate-auth.trusted-uris à mon application
cependant j'obtiens la boîte de dialogue de connexion sans succès pour me connecter
donc la question est:
Comment activer le journal de débogage avec le package Microsoft.AspNetCore.Authentication.Negotiate?
Je suppose que ce paquet ne communique pas correctement avec Kerberos, peut-être qu'un paquet est manquant, ne fonctionne pas ou quelque chose.
Notez également que le conteneur et l'application .net sont connectés avec succès au domaine car j'utilise la sécurité intégrée pour la connexion à la base de données qui fonctionne.
**** Edit> Réponse à la première partie
Pour activer les journaux, il faut activer les journaux dans Kestrel: dans appsettings.json:
"Logging": {
"LogLevel": {
"Default": "Debug",
}
},
Dans program.cs:
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddFilter("Microsoft", LogLevel.Debug);
logging.AddFilter("System", LogLevel.Debug);
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
Dans Startup.cs, on peut suivre les événements de négociation:
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate(
options =>
{
options.PersistKerberosCredentials = true;
options.Events = new NegotiateEvents()
{
OnAuthenticated = challange =>
{
..
},
OnChallenge = challange =>
{
..
},
OnAuthenticationFailed = context =>
{
// context.SkipHandler();
Console.WriteLine($"{DateTimeOffset.Now.ToString(czechCulture)} OnAuthenticationFailed/Scheme: {context.Scheme.Str()}, Request: {context.Request.Str()}");
Console.WriteLine("context?.HttpContext?.Features?.Select(f=>f.Key.Name.ToString())");
var items = context?.HttpContext?.Features?.Select(f => "- " + f.Key?.Name?.ToString());
if (items != null)
{
Console.WriteLine(string.Join("\n", items));
}
Console.WriteLine("context.HttpContext.Features.Get<IConnectionItemsFeature>()?.Items " + context.HttpContext.Features.Get<IConnectionItemsFeature>()?.Items?.Count);
var items2 = context.HttpContext?.Features.Get<IConnectionItemsFeature>()?.Items?.Select(f => "- " + f.Key?.ToString() + "=" + f.Value?.ToString());
if (items2 != null) {
Console.WriteLine(string.Join("\n", items2));
}
return Task.CompletedTask;
}
};
}
);
**** Éditer
Pendant ce temps, selon mon objectif d'autoriser l'authentification Windows dans l'application Web Docker .net core, je parcourais le code source de .net core et corefx et je traduisais le code d'authentification vers cet exemple d'application console:
try
{
var token = "MyToken==";
var secAssembly = typeof(AuthenticationException).Assembly;
Console.WriteLine("var ntAuthType = secAssembly.GetType(System.Net.NTAuthentication, throwOnError: true);");
var ntAuthType = secAssembly.GetType("System.Net.NTAuthentication", throwOnError: true);
Console.WriteLine("var _constructor = ntAuthType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();");
var _constructor = ntAuthType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();
Console.WriteLine("var credential = CredentialCache.DefaultCredentials;");
var credential = CredentialCache.DefaultCredentials;
Console.WriteLine("var _instance = _constructor.Invoke(new object[] { true, Negotiate, credential, null, 0, null });");
var _instance = _constructor.Invoke(new object[] { true, "Negotiate", credential, null, 0, null });
var negoStreamPalType = secAssembly.GetType("System.Net.Security.NegotiateStreamPal", throwOnError: true);
var _getException = negoStreamPalType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(info => info.Name.Equals("CreateExceptionFromError")).Single();
Console.WriteLine("var _getOutgoingBlob = ntAuthType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(info => info.Name.Equals(GetOutgoingBlob) && info.GetParameters().Count() == 3).Single();");
var _getOutgoingBlob = ntAuthType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(info => info.Name.Equals("GetOutgoingBlob") && info.GetParameters().Count() == 3).Single();
Console.WriteLine("var decodedIncomingBlob = Convert.FromBase64String(token);;");
var decodedIncomingBlob = Convert.FromBase64String(token);
Console.WriteLine("var parameters = new object[] { decodedIncomingBlob, false, null };");
var parameters = new object[] { decodedIncomingBlob, false, null };
Console.WriteLine("var blob = (byte[])_getOutgoingBlob.Invoke(_instance, parameters);");
var blob = (byte[])_getOutgoingBlob.Invoke(_instance, parameters);
if (blob != null)
{
Console.WriteLine("var out1 = Convert.ToBase64String(blob);");
var out1 = Convert.ToBase64String(blob);
Console.WriteLine(out1);
}
else
{
Console.WriteLine("null blob value returned");
var securityStatusType = secAssembly.GetType("System.Net.SecurityStatusPal", throwOnError: true);
var _statusException = securityStatusType.GetField("Exception");
var securityStatus = parameters[2];
var error = (Exception)(_statusException.GetValue(securityStatus) ?? _getException.Invoke(null, new[] { securityStatus }));
Console.WriteLine("Error:");
Console.WriteLine(error);
Console.WriteLine("securityStatus:");
Console.WriteLine(securityStatus.ToString());
}
}
catch(Exception exc)
{
Console.WriteLine(exc.Message);
}
J'ai donc découvert que la bibliothèque communique avec System.Net.NTAuthentication qui communique avec System.Net.Security.NegotiateStreamPal qui communique avec la version unix de Interop.NetSecurityNative.InitSecContext
qui devrait en quelque sorte déclencher le GSSAPI dans os
Dans dotnet runtime git, ils nous disent que gss-ntlmssp est nécessaire pour que cela fonctionne même si cela n'est de toute façon pas mentionné dans la documentation de base d'aspnet.
https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=gss-ntlmssp
Néanmoins, j'ai compilé le gss-ntlmssp et découvert que sans cette bibliothèque, il génère une erreur " Un mécanisme non pris en charge a été demandé.". Avec ma bibliothèque, l'erreur " Aucune information d'identification n'a été fournie, ou les informations d'identification étaient indisponibles ou inaccessibles.", mais n'accédez jamais aux méthodes gss_ *.
J'ai testé l'utilisation des méthodes gss en ajoutant l'entrée de journal au fichier qui ne s'est jamais produite .. fe:
OM_uint32 gss_init_sec_context(OM_uint32 *minor_status,
gss_cred_id_t claimant_cred_handle,
gss_ctx_id_t *context_handle,
gss_name_t target_name,
gss_OID mech_type,
OM_uint32 req_flags,
OM_uint32 time_req,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token,
gss_OID *actual_mech_type,
gss_buffer_t output_token,
OM_uint32 *ret_flags,
OM_uint32 *time_rec)
{
FILE *fp;
fp = fopen("/tmp/gss-debug.log", "w+");
fprintf(fp, "gss_init_sec_context\n");
fclose(fp);
return gssntlm_init_sec_context(minor_status,
claimant_cred_handle,
context_handle,
target_name,
mech_type,
req_flags,
time_req,
input_chan_bindings,
input_token,
actual_mech_type,
output_token,
ret_flags,
time_rec);
}
Ainsi .net appelle gssapi, et gssapi n'appelle pas de mécanisme.
J'ai observé le même comportement dans centos7 vm, sous-système Windows ubuntu et image docker Debian (mcr.Microsoft.com/dotnet/core/sdk:3.1-buster personnalisé)
Alors la question est maintenant, comment puis-je déboguer gssapi?
Je suppose que mon gssapi actuel est géré par cette bibliothèque:
readelf -d /usr/lib64/libgssapi_krb5.so
Dynamic section at offset 0x4aa48 contains 34 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libkrb5.so.3]
0x0000000000000001 (NEEDED) Shared library: [libk5crypto.so.3]
0x0000000000000001 (NEEDED) Shared library: [libcom_err.so.2]
0x0000000000000001 (NEEDED) Shared library: [libkrb5support.so.0]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libkeyutils.so.1]
0x0000000000000001 (NEEDED) Shared library: [libresolv.so.2]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libgssapi_krb5.so.2]
0x000000000000000c (INIT) 0xb1d8
0x000000000000000d (FINI) 0x3ebcc
0x0000000000000019 (INIT_ARRAY) 0x24a120
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x24a128
0x000000000000001c (FINI_ARRAYSZ) 16 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x1f0
0x0000000000000005 (STRTAB) 0x3048
0x0000000000000006 (SYMTAB) 0x720
0x000000000000000a (STRSZ) 9167 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x24b000
0x0000000000000002 (PLTRELSZ) 8088 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x9240
0x0000000000000007 (RELA) 0x58b0
0x0000000000000008 (RELASZ) 14736 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffc (VERDEF) 0x5788
0x000000006ffffffd (VERDEFNUM) 3
0x000000006ffffffe (VERNEED) 0x57e0
0x000000006fffffff (VERNEEDNUM) 4
0x000000006ffffff0 (VERSYM) 0x5418
0x000000006ffffff9 (RELACOUNT) 504
0x0000000000000000 (NULL) 0x0
jusqu'à présent, j'ai compilé le nouveau dernier gssapi à partir de la source mit, et j'ai découvert qu'il me lance l'erreur "Un mécanisme non pris en charge a été demandé." car gssapi nécessite un interpréteur gss qui n'est pas fourni. Dans centos7, j'ai eu un autre problème que la bibliothèque openssl utilisait la bibliothèque kerberos partagée qui était incompatible, donc yum a cessé de fonctionner.
*** Éditer
J'ai découvert que le gss-ntlmssp a le drapeau GSS_C_MA_NOT_DFLT_MECH donc il échouait avec le message "Aucune information d'identification n'a été fournie, ou les informations d'identification étaient indisponibles ou inaccessibles.". La solution consiste à créer un gss-ntlmssp personnalisé sans cet attribut car je souhaite l'utiliser comme mécanisme d'authentification par défaut.
Mon exemple d'application de console pour vérifier les informations d'identification fonctionne maintenant, je vais essayer de le faire fonctionner dans le conteneur Docker maintenant.
*** Éditer
J'ai pu exécuter mon ConsoleApp avec succès dans kubernetes:
FROM mcr.Microsoft.com/dotnet/core/sdk:3.1-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y
ADD ca/ca.crt /usr/local/share/ca-certificates/ca.crt
RUN chmod 644 /usr/local/share/ca-certificates/*
RUN update-ca-certificates
RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user
RUN mkdir /app
RUN apt install -y mc Sudo syslog-ng python3-software-properties software-properties-common packagekit git gssproxy vim
RUN apt install -y autoconf automake libxslt-dev doxygen findutils libgettextpo-dev libtool m4 make libunistring-dev libssl-dev zlib1g-dev gettext xsltproc libxml2-utils libxml2-dev xml-core docbook-xml docbook-xsl bison libkrb5-dev
RUN systemctl enable syslog-ng
RUN mkdir /src
RUN cd /src && wget https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-1.18.tar.gz
RUN cd /src && tar -xf krb5-1.18.tar.gz
RUN cd /src/krb5-1.18/src && ./configure && make && make install
RUN cd /src && git clone https://github.com/scholtz/gss-ntlmssp.git
RUN cd /src/gss-ntlmssp/ && autoreconf -f -i && ./configure && make && make install
RUN cp /src/gss-ntlmssp/examples/mech.ntlmssp.conf /etc/gss/mech.d/mech.ntlmssp.conf
COPY testgss /testgss
RUN cd /testgss && dotnet ConsoleApp3.dll
RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --Shell /bin/bash -d /app app
RUN echo BQIA..AAAB | base64 -d > /app/user.keytab
RUN echo BQIA..oQ== | base64 -d > /etc/krb5.keytab
RUN echo BQIA..oQ== | base64 -d > /app/is.k01.HTTP.keytab
RUN echo BQIA..AAA= | base64 -d > /app/is.k01.kerb.keytab
COPY krb5.conf /etc/krb5.conf
COPY krb5.conf /usr/local/etc/krb5.conf
RUN ln -s /etc/gss /usr/local/etc/gss
RUN cd /app
WORKDIR /app
Cependant, j'obtiens cette erreur maintenant:
System.Exception: An authentication exception occured (0xD0000/0x4E540016).
---> Interop+NetSecurityNative+GssApiException: GSSAPI operation failed with error - Unspecified GSS failure. Minor code may provide more information (Feature not available).
at System.Net.Security.NegotiateStreamPal.GssAcceptSecurityContext(SafeGssContextHandle& context, Byte[] buffer, Byte[]& outputBuffer, UInt32& outFlags)
at System.Net.Security.NegotiateStreamPal.AcceptSecurityContext(SafeFreeCredentials credentialsHandle, SafeDeleteContext& securityContext, ContextFlagsPal requestedContextFlags, Byte[] incomingBlob, ChannelBinding channelBinding, Byte[]& resultBlob, ContextFlagsPal& contextFlags)
*** edit Maintenant, ça échoue ici: gssntlm_init_sec_context .. gssntlm_acquire_cred .. gssntlm_acquire_cred_from ..
if (cred_store != GSS_C_NO_CRED_STORE) {
retmin = get_creds_from_store(name, cred, cred_store);
} else {
retmin = get_user_file_creds(name, cred);
if (retmin) {
retmin = external_get_creds(name, cred);
}
}
get_user_file_creds () renvoie une erreur car je n'ai pas de configuration de fichier spécifique car je veux vérifier les utilisateurs à partir de l'annonce
external_get_creds () échoue ici:
wbc_status = wbcCredentialCache(¶ms, &result, NULL);
if(!WBC_ERROR_IS_OK(wbc_status)) goto done;
external_get_creds essaie de s'authentifier avec la bibliothèque winbind et, évidemment, dans le cache des informations d'identification, aucun utilisateur n'est présent
j'ai réussi à le compiler avec la bibliothèque winbind fournie par samba
donc la question est maintenant: Comment configurer la bibliothèque winbind pour communiquer avec AD?
*** Éditer
J'ai essayé d'utiliser .net 5 comme sur github, on m'a dit que NTLM fonctionne dans .net 5. Cependant, j'obtiens le même résultat qu'avec .net 3.1.
Image Docker avec laquelle j'ai essayé cela:
FROM mcr.Microsoft.com/dotnet/core-nightly/sdk:5.0-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y
RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user
RUN mkdir /app
RUN apt install -y mc Sudo syslog-ng python3-software-properties software-properties-common packagekit git gssproxy vim apt-utils
RUN apt install -y autoconf automake libxslt-dev doxygen findutils libgettextpo-dev libtool m4 make libunistring-dev libssl-dev zlib1g-dev gettext xsltproc libxml2-utils libxml2-dev xml-core docbook-xml docbook-xsl bison libkrb5-dev
RUN systemctl enable syslog-ng
RUN mkdir /src
#RUN cd /src && git clone https://github.com/scholtz/gss-ntlmssp.git
RUN DEBIAN_FRONTEND=noninteractive apt install -y libwbclient-dev samba samba-dev
#RUN cat /usr/include/samba-4.0/wbclient.h
COPY gss-ntlmssp /usr/local/src/gss-ntlmssp
RUN cd /usr/local/src/gss-ntlmssp/ && autoreconf -f -i && ./configure && make && make install
RUN cp /usr/local/src/gss-ntlmssp/examples/mech.ntlmssp.conf /etc/gss/mech.d/mech.ntlmssp.conf
RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --Shell /bin/bash -d /app app
RUN echo BQIAAABMA..ArHdoQ== | base64 -d > /etc/krb5.keytab
COPY krb5.conf /etc/krb5.conf
COPY smb.conf /etc/samba/smb.conf
COPY krb5.conf /usr/local/etc/krb5.conf
RUN DEBIAN_FRONTEND=noninteractive apt install -y winbind
ENV KRB5_TRACE=/dev/stdout
RUN mkdir /src2
WORKDIR /src2
RUN dotnet --list-runtimes
RUN dotnet new webapi --auth Windows
RUN dotnet add package Microsoft.AspNetCore.Authentication.Negotiate
RUN sed -i '/services.AddControllers/i services.AddAuthentication(Microsoft.AspNetCore.Authentication.Negotiate.NegotiateDefaults.AuthenticationScheme).AddNegotiate();' Startup.cs
RUN sed -i '/app.UseAuthorization/i app.UseAuthentication();' Startup.cs
run echo a
RUN cat Startup.cs
RUN dotnet restore
RUN dotnet build
ENV ASPNETCORE_URLS="http://*:5002;https://*:5003"
EXPOSE 5002
EXPOSE 5003
RUN cd /app
WORKDIR /app
docker run -it -p 5003:5003 -it registry.k01.mydomain.com/k01-devbase:latest
Dans le conteneur Docker:
kinit HTTP/[email protected] -k -t /etc/krb5.keytab
klist
dotnet run src2.dll
J'ai mis mes propres informations de débogage dans la bibliothèque gssntlmssp et je les ai mises dans un fichier
cat /tmp/gss-debug.log
C'est exactement la même fin où j'ai terminé avec .net core 3.1.
wbcCredentialCache (samba lib) échoue au point où il ne peut pas trouver les informations d'identification mises en cache
C'est mon krb5.conf:
[appdefaults]
default_lifetime = 25hrs
krb4_convert = false
krb4_convert_524 = false
ksu = {
forwardable = false
}
pam = {
minimum_uid = 100
forwardable = true
}
pam-afs-session = {
minimum_uid = 100
}
[libdefaults]
default_realm = MYDOMAIN.COM
[realms]
MYDOMAIN.COM = {
kdc = DC01.MYDOMAIN.COM
default_domain = MYDOMAIN.COM
}
[domain_realm]
mydomain.com. = MYDOMAIN.COM
.mydomain.com. = MYDOMAIN.COM
[logging]
default = CONSOLE
default = SYSLOG:INFO
default = FILE:/var/log/krb5-default.log
kdc = CONSOLE
kdc = SYSLOG:INFO:DAEMON
kdc = FILE:/var/log/krb5-kdc.log
admin_server = SYSLOG:INFO
admin_server = DEVICE=/dev/tty04
admin_server = FILE:/var/log/krb5-kadmin.log
et une partie du fichier samba:
[global]
security = domain
workgroup = mydomain.com
password server = *
idmap config * : range = 16777216-33554431
template Shell = /bin/bash
winbind use default domain = yes
winbind offline logon = false
wins server = 10.0.0.2
À mon avis, j'aimerais plus avoir NTLM que Negotiate car Negotiate n'est pas pris en charge par les navigateurs pour autant que je sache. Par exemple, dans Firefox, la personne doit configurer le about: config pour le serveur de négociation. Les caractères génériques ne sont pas pris en charge, ...
néanmoins, il semble que je ne pourrai pas exécuter l'application Web .net core 5 avec ntlm, donc je vais essayer de la configurer sans la bibliothèque gssntlmssp maintenant avec un mécanisme kerberos par défaut. Une idée de ce qui ne va pas avec mes paramètres krb5.conf?
**** Edit J'essaye donc maintenant deux approches différentes:
En ce qui concerne la négociation, j'ai réussi à faire des progrès.
Avec ce conteneur docker, j'ai pu contourner le mécanisme non pris en charge:
FROM mcr.Microsoft.com/dotnet/core/sdk:3.1-buster as final
USER root
RUN whoami
RUN apt update && apt dist-upgrade -y
RUN DEBIAN_FRONTEND=noninteractive apt install -y krb5-config krb5-user
RUN mkdir /app
RUN apt install -y mc Sudo syslog-ng python3-software-properties software-properties-common packagekit git gssproxy vim apt-utils
RUN apt install -y autoconf automake libxslt-dev doxygen findutils libgettextpo-dev libtool m4 make libunistring-dev libssl-dev zlib1g-dev gettext xsltproc libxml2-utils libxml2-dev xml-core docbook-xml docbook-xsl bison libkrb5-dev
RUN systemctl enable syslog-ng
RUN mkdir /src
RUN groupadd --gid 1000 app && useradd --uid 1000 --gid app --Shell /bin/bash -d /app app
RUN echo BQIAAAA8..vI | base64 -d > /etc/krb5.keytab
COPY krb5.conf /etc/krb5.conf
COPY krb5.conf /usr/local/etc/krb5.conf
ADD ca/is.k01.mydomain.com.p12 /etc/ssl/certs/is.k01.mydomain.com.pfx
RUN cd /app
WORKDIR /app
Cependant, j'ai maintenant un autre problème: Demander au serveur de tickets HTTP/[email protected] kvno 3 trouvé dans keytab mais pas avec enctype rc4-hmac
Cela me semble que le keytab n'est pas avec rc4-hmac ce qui est vrai, car le keytab a été généré avec
ktpass -princ HTTP/[email protected] -pass ***** -mapuser MYDOMAIN\is.k01.kerb -pType KRB5_NT_PRINCIPAL -out c:\temp\is.k01.HTTP.keytab -crypto AES256-SHA1
comme le dit la documentation .net.
Je n'ai pas été en mesure d'interdire l'utilisation de rc4-hmac et d'autoriser uniquement le codage plus récent, j'ai donc demandé à mon service infra de générer un nouveau keytab avec l'ancien codage rc4-hmac.
Cette étape m'a déplacé plus loin et j'obtiens cette erreur à la place: Demande du serveur de tickets HTTP/[email protected] kvno 4 introuvable dans keytab; keytab est probablement obsolète *
Ce qui est très étrange car les keytabs ne peuvent pas être obsolètes, le mot de passe n'a pas été changé et était valide à 100% il y a une heure lorsque le keytab a été généré, et il n'y a aucune information sur le Web - "kvno 4 not found in keytab" chercher seulement 4 résultats dans google.
**** ÉDITER
Donc, finalement, j'ai réussi à le faire fonctionner :)
Le problème avec "kvno 4 non trouvé dans keytab" était dans le fichier krb5.conf, où je suis en faveur de forcer le cryptage aes j'ai ajouté des lignes
# default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes256-cts-hmac-sha1-9
# default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes256-cts-hmac-sha1-9
# permitted_enctypes = aes256-cts-hmac-sha1-96 aes256-cts-hmac-sha1-9
Après les avoir commentés, l'authentification à l'aide de Negotiate a commencé à fonctionner. J'ai testé le NTLM avec .net 5 et cela ne fonctionne toujours pas.
Le fichier krb5.conf avec lequel négocier dans le conteneur docker comme build ci-dessus fonctionne:
[appdefaults]
default_lifetime = 25hrs
krb4_convert = false
krb4_convert_524 = false
ksu = {
forwardable = false
}
pam = {
minimum_uid = 100
forwardable = true
}
pam-afs-session = {
minimum_uid = 100
}
[libdefaults]
default_realm = MYDOMAIN.COM
[realms]
MYDOMAIN.COM = {
kdc = DC02.MYDOMAIN.COM
default_domain = MYDOMAIN.COM
}
[domain_realm]
mydomain.com. = MYDOMAIN.COM
.mydomain.com. = MYDOMAIN.COM
[logging]
default = CONSOLE
default = SYSLOG:INFO
default = FILE:/var/log/krb5-default.log
kdc = CONSOLE
kdc = SYSLOG:INFO:DAEMON
kdc = FILE:/var/log/krb5-kdc.log
admin_server = SYSLOG:INFO
admin_server = DEVICE=/dev/tty04
admin_server = FILE:/var/log/krb5-kadmin.log
Donc la question maintenant: Y a-t-il un moyen de permettre à de nombreux services d'exécuter le protocole de négociation sans ajouter chacun à spn par un, et de configurer manuellement les navigateurs?
Donc, pour le moment, chaque nouveau service Web doit avoir:
setspn -S HTTP/mywebservice.mydomain.com mymachine
setspn -S HTTP/[email protected] mymachine
et doit être autorisé dans Internet Explorer> paramètres> sécurité> sites Web> Détails> le domaine doit y figurer dans Firefox à propos de: config> network.negotiate-auth.trusted-uris chrome en ce qui concerne i know prend les paramètres d'Internet Explorer
je suppose que les paramètres d'Internet Explorer devraient être mis à jour d'une manière ou d'une autre par la stratégie de groupe de domaine .. quelqu'un a une idée de comment?
**** EDIT J'ai testé le caractère générique dans le domaine pour négocier les paramètres dans les navigateurs et voici les résultats:
**** EDIT J'ai commencé à utiliser l'authentification win avec negocier, mais j'obtiens maintenant des problèmes dans .net core
Ce code sous IIS express montre l'utilisateur sous la forme MYDOMAIN\myuser:
var userId = string.Join(',', User?.Identities?.Select(c => c.Name)) ?? "?";
Sous Linux, il s'affiche sous la forme [email protected]
User.Indentities.First () under IIS express est WindowsIdentity et je peux lister tous les groupes de l'utilisateur
User.Indentities.First () sous Linux est ClaimsIdentity sans informations de groupe
Quand j'essaye de le restreindre avec le groupe dans IIS Express j'obtiens:
//Access granted
[Authorize(Roles = "MYDOMAIN\\GROUP1")]
//403
[Authorize(Roles = "MYDOMAIN\\GROUP_NOT_EXISTS")]
Kestrel Linux avec negocier:
//403
[Authorize(Roles = "MYDOMAIN\\GROUP1")]
Il semble donc que la négociation dans Kestrel ne répertorie pas correctement les groupes. Je vais donc étudier maintenant, comment obtenir WindowsIdentity dans Kestrel.
Dans dotnet runtime git, ils nous disent que gss-ntlmssp est nécessaire pour que cela fonctionne même si cela n'est de toute façon pas mentionné dans la documentation de base d'aspnet.
Le paquet 'gss-ntlmssp' est un plug-in pour prendre en charge le protocole NTLM pour l'API GSS. Il prend en charge le protocole NTLM brut ainsi que NTLM utilisé comme solution de secours de Kerberos vers NTLM lorsque "Negotiate" (protocole SPNEGO) est utilisé. Réf: https://docs.Microsoft.com/en-us/openspecs/windows_protocols/MS-SPNG/f377a379-c24f-4a0f-a3eb-0d835389e28a
À la lecture de la discussion ci-dessus et de l'image que vous avez publiée, il semble que l'application essaie réellement d'utiliser NTLM au lieu de Kerberos. Vous pouvez le dire car le jeton encodé based64 commence par "T" au lieu de "Y".
Le serveur ASP.NET Core (Kestrel) ne prend PAS du tout en charge NTLM côté serveur sous Linux. Il prévoit uniquement le renvoi de "Www-Authenticate: Negotiate" aux clients. Et cela signifie généralement que Kerberos serait utilisé. Negotiate peut revenir à l'utilisation de NTLM. Cependant, cela ne fonctionne pas dans ASP.NET Core, sauf dans .NET 5 qui n'a pas encore été livré.
Vous attendez-vous à ce que votre application revienne à NTLM? Sinon, l'environnement Kerberos n'est peut-être pas complètement configuré. Cela peut être dû à divers problèmes, notamment les SPN et les fichiers keytab Linux qui ne sont pas corrects. Cela peut également être dû au fait que le client essaie d'utiliser un nom d'utilisateur/mot de passe qui ne fait pas partie du domaine Kerberos.
Ce problème est discuté ici: https://github.com/dotnet/aspnetcore/issues/19397
Je recommande que la conversation se poursuive dans la discussion sur la question du repo core aspnet.