Yubikey и выполнение задач администратора в Active Directory на C#C#

Место общения программистов C#
Ответить
Anonymous
 Yubikey и выполнение задач администратора в Active Directory на C#

Сообщение Anonymous »

У меня есть приложение, которое я создал, которое помогает мне выполнять некоторые задачи, такие как добавление пользователей в группы, удаление, создание пользователей, удаление пользователей и разблокировка пользователей в Active Directory. Все это требует некоторых прав администратора.
В настоящее время аутентификация подключения учетной записи администратора к домену осуществляется на основе пароля.
Пользователь получает запрос на ввод имени пользователя и пароля и с помощью PrincipalContext я аутентифицирую сеанс. Во всем приложении я ссылаюсь на переменную context для выполнения этих задач.

Код: Выделить всё

using (PrincipalContext context = new PrincipalContext(ContextType.Domain, _myDomainName, adminUsername, adminPassword))
Я хочу проверить вход в приложение для использования смарт-карты. Мне удалось это использовать, но похоже, что PrincipalContext поддерживает только аутентификацию на основе пароля, насколько я могу судить, аутентификация на основе сертификации не поддерживается. Это привело к тому, что переменная context не могла ссылаться на мою учетную запись администратора в сеансе, что вызывало ошибки «Доступ запрещен».
В настоящее время я аутентифицирую пользователя следующим образом:
В настоящее время я аутентифицирую пользователя следующим образом:
р>

Код: Выделить всё

static X509Certificate2 GetAdminCertificate()
{
Console.Write("Enter admin username: ");
adminUsername = Console.ReadLine().Trim();
/*
Console.Write("Enter your smart card PIN: ");
string smartCardPin = PasswordManager.GetPassword().Trim();
*/

using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadOnly);

X509Certificate2Collection yubiKeyCerts = new X509Certificate2Collection();

foreach (var cert in store.Certificates)
{
// First, check if the subject name matches the admin username
string subjectName = cert.GetNameInfo(X509NameType.SimpleName, false);

if (!subjectName.Equals(adminUsername, StringComparison.OrdinalIgnoreCase))
{
// Skip this certificate if the subject does not match
continue;
}

try
{
if (cert.HasPrivateKey)
{
// Access the private key
var privateKey = cert.PrivateKey;

if (privateKey is RSACng rsaCng)
{
if (rsaCng.KeyExchangeAlgorithm.Equals("RSA", StringComparison.OrdinalIgnoreCase))
{
// Match the certificate with admin username
if (subjectName.Equals(adminUsername, StringComparison.OrdinalIgnoreCase))
{
// Attempt to sign data with the RSA key to validate access
byte[] dataToSign = new byte[] { 0x01 }; // Dummy data
byte[] signedData = rsaCng.SignData(dataToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
yubiKeyCerts.Add(cert);
}  // end of if-statement
}  // end of if-statement
}  // end of if-statement
}  // end of if-statement
}  // end of try
catch (Exception ex)
{
Console.WriteLine($"Error obtaining certification: {ex.Message}");
continue;
}  // end of catch
}  // end of foreach

if (yubiKeyCerts.Count == 0)
{
Console.WriteLine("No smart card detected or no valid certificates found on the connected smart card.");
return null;
}

// X509Certificate2 selectedCert = null;
if (yubiKeyCerts.Count >  0)
{
selectecdCert = X509Certificate2UI.SelectFromCollection(
yubiKeyCerts,
"Select a YubiKey certificate",
"Please select your admin certificate from the YubiKey",
X509SelectionFlag.SingleSelection
)[0];
}

adminUsername = selectecdCert.GetNameInfo(X509NameType.SimpleName, false);
// adminPassword = selectecdCert.Verify();

return selectecdCert;
}  // end of using x509Store
}  // end of GetAdminCertificate
(слишком много операторов if — я знаю)
Приложение подключается к домену следующим образом:

Код: Выделить всё

static void Main(string[] args)
{
ActiveDirectoryManager ADManager = new ActiveDirectoryManager();
AccountCreationManager ACManager;
AccountDeactivationManager ACCDeactivationManager = new AccountDeactivationManager();
PasswordManager PWDManager = null;
ADGroupActionManager ADGroupManager = null;
AuditLogManager auditLogManager = null;

configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("Appsettings.json", optional: false, reloadOnChange: true)
.Build();

EmailNotifcationManager emailManager = new EmailNotifcationManager(configuration);
string _myDomainName = configuration["AccountCreationSettings:myDomainName"];

do
{
X509Certificate2 certificate = GetAdminCertificate();

if (certificate == null)
{
Console.WriteLine("No valid smart card certificate found.");
return;
}

try
{
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, _myDomainName))
// Check if the the password/user are correct
{
// Throw error if the password/username is incorrect
if (context.ConnectedServer != null)
{
isAuthenticated = true;
Console.WriteLine($"Connected to Active Directory as: {adminUsername}.".Pastel(Color.GreenYellow));

auditLogManager = new AuditLogManager(adminUsername, configuration);
ADGroupManager = new ADGroupActionManager(auditLogManager);
PWDManager = new PasswordManager(auditLogManager);
ACManager = new AccountCreationManager(auditLogManager, configuration);

bool exit = false;

// Loop the menu
while (!exit)
{
DisplayMainMenu();
string choice = Console.ReadLine();
exit = HandleMainMenuChoice(choice, context, ADManager, ADGroupManager, PWDManager, ACManager, ACCDeactivationManager);
}   // end of while-loop
}    // end of if statement

context.Dispose();
}   // end of using
}   // end of try
catch (DirectoryServicesCOMException)
{
// Error out if password/username are incorrect
Console.WriteLine("Error: Unable to connect to the Active Directory server. Please check your credentials and try again.".Pastel(Color.IndianRed));
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}".Pastel(Color.IndianRed));
}    // end of Catch
} while (!isAuthenticated || string.IsNullOrEmpty(adminUsername));
// Repeat until a valid password is entered
}  // end of Main Method
Пример фрагмента кода, в котором я получаю отказ в доступе. Как видите, я ссылаюсь здесь на переменную context, чтобы использовать сеанс администратора для выполнения этих задач.

Код: Выделить всё

UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);

// Check for user in AD
if (user != null)
{
// Check for group in AD
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, groupName);

if (group != null)
{
// If the user is not in the group add him
if (!group.Members.Contains(user))
{
// Add the user to the group
group.Members.Add(user);
// Apply changes
group.Save();

group.Dispose();

Console.WriteLine($"User '{username}' added to group '{groupName}' successfully.".Pastel(Color.LimeGreen));

string logEntry = ($"\"{user.DisplayName}\" has been added to \"{groupName}\" group in Active Directory\n");
emailActionLog.Add(logEntry);
auditLogManager.Log(logEntry);
}   // end of inner-2 if-statement
else
{
Console.WriteLine($"User '{username}' is already a member of group '{groupName}'.".Pastel(Color.DarkGoldenrod));
}   // end of inner-2 else-statement
}   // end of inner if-statement
else
{
Console.WriteLine($"Group '{groupName}' not found in Active Directory.".Pastel(Color.IndianRed));
}   // end of outer else-statement
}
Мой главный вопрос: есть ли способ аутентифицировать свою учетную запись администратора с помощью входа на основе сертификации?

Подробнее здесь: https://stackoverflow.com/questions/792 ... in-c-sharp
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»