Created
September 10, 2024 12:33
Revisions
-
rajanadar created this gist
Sep 10, 2024 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,115 @@ using System; using System.Threading.Tasks; using Kerberos.NET.Client; using Kerberos.NET.Configuration; using Kerberos.NET.Credentials; using Kerberos.NET.Crypto; // Written by Raja Nadar for users of VaultSharp dealing with Kerberos based AuthMethod namespace VaultSharp.V1.AuthMethods.Kerberos { /// <summary> /// Helper class for Kerberos based Vault Auth Method /// Include the Nuget package Kerberos.NET before using this helper class. /// </summary> public static class KerberosAuthMethodHelper { /// <summary> /// Creates the Kerberos Service Principal Negotiation Token header from the keytab and conf files. /// </summary> /// <param name="serviceAccountUsername"> /// The username for the entry within the keytab to use for logging into Kerberos. /// This username must match a service account in LDAP. /// </param> /// <param name="servicePrincipalName"> /// The service principal name to use in obtaining a service ticket for gaining a SPNEGO token. /// This service must exist in LDAP. /// </param> /// <param name="realmName"> /// The name of the Kerberos realm. /// This realm must match the UPNDomain configured on the LDAP connection. /// This check is case-sensitive. /// </param> /// <param name="keyTabFilePath"> /// The path to the keytab in which the entry lives for the entity authenticating to Vault. /// Keytab files should be protected from other users on a shared server using appropriate file permissions. /// </param> /// <param name="krb5ConfigurationFilePath"> /// The path to a valid krb5.conf file describing how to communicate with the Kerberos environment. /// </param> /// <param name="disableFastNegotiation"> /// For disabling the Kerberos auth method's default of using FAST negotiation. /// FAST is a pre-authentication framework for Kerberos. /// It includes a mechanism for tunneling pre-authentication exchanges using armoured KDC messages. /// FAST provides increased resistance to passive password guessing attacks. /// Some common Kerberos implementations do not support FAST negotiation. /// </param> /// <returns>The "Negotiate " + ServicePrincipalNegotiationToken value.</returns> public static async Task<string> GetServicePrincipalNegotiationTokenAsync( string serviceAccountUsername, string servicePrincipalName, string realmName, string keyTabFilePath, string krb5ConfigurationFilePath, bool disableFastNegotiation) { if (string.IsNullOrEmpty(serviceAccountUsername)) { throw new ArgumentNullException(nameof(serviceAccountUsername)); } if (string.IsNullOrEmpty(servicePrincipalName)) { throw new ArgumentNullException(nameof(servicePrincipalName)); } if (string.IsNullOrEmpty(realmName)) { throw new ArgumentNullException(nameof(realmName)); } if (!System.IO.File.Exists(krb5ConfigurationFilePath)) { throw new System.IO.FileNotFoundException("Krb5Configuration file could not be found: " + krb5ConfigurationFilePath); } if (!System.IO.File.Exists(keyTabFilePath)) { throw new System.IO.FileNotFoundException("KeyTabFile file could not be found: " + keyTabFilePath); } try { var krb5Config = Krb5Config.Parse(krb5ConfigurationFilePath); var kerberosClient = new KerberosClient(krb5Config); // Assume pre-auth kerberosClient.AuthenticationOptions &= AuthenticationOptions.PreAuthenticate; if (disableFastNegotiation) { kerberosClient.AuthenticationOptions &= ~AuthenticationOptions.PreAuthenticate; } var keyTable = new KeyTable(System.IO.File.ReadAllBytes(keyTabFilePath)); KerberosCredential keytabCredential = new KeytabCredential(serviceAccountUsername, keyTable, realmName); await kerberosClient.Authenticate(keytabCredential); var ticket = await kerberosClient.GetServiceTicket(servicePrincipalName); var servicePrincipalNegotiationToken = Convert.ToBase64String(ticket.EncodeGssApi().ToArray()); var kerberosAuthHeader = "Negotiate " + servicePrincipalNegotiationToken; return kerberosAuthHeader; } catch (Exception ex) { throw new Exception("Failed to generate Kerberos service principal negotiation token.", ex); } } } }