Программное присвоение групп пользователей IIS Application Identity Identity

Проблема: Когда новые пулы приложений IIS создаются и настроены на использование идентификатора пула приложений для разрешений, я не уверен, как добавить эти идентификаторы в группы пользователей, такие как администратор или пользователи счетчика производительности.

Предыстория: в настоящее время я пишу библиотеку C#.NET, которая использует Microsoft.Web.Administration для того, чтобы сделать следующее:

  • Определите, установлен ли IIS 7.x, и, если да, какие компоненты.
  • Установите или обновите IIS 7.x до предоставленного списка необходимых компонентов.
  • Создание / управление одним или несколькими веб-сайтами через IIS.
  • Автоматически создавать / управлять одним пулом приложений для каждого веб-сайта

Контекст заключается в том, что эта библиотека должна использоваться исполняемыми установщиками для автоматического развертывания веб-сервера и веб-сайтов / служб в ОС Windows Server в рамках более широкого развертывания программного обеспечения. Пока что все вышеперечисленное было реализовано, протестировано и (в основном) функционально, за исключением автоматизации некоторых разрешений, которые необходимо выполнить при создании пула приложений / веб-сайта.

В моем методе установки нового веб-сайта я создаю новый пул приложений и заставляю его использовать идентификатор пула приложений:

static public void InstallSite(string name, string path, int port)
{
    Site site;
    var appPoolName = ApplicationPoolBaseName + name;

    using (var iisManager = new ServerManager())
    {
        // Set up a custom application pool for any site we run.
        if (!iisManager.ApplicationPools.Any(pool => pool.Name.Equals(appPoolName)))
        {
            iisManager.ApplicationPools.Add(appPoolName);
            iisManager.ApplicationPools[appPoolName].ManagedRuntimeVersion = "v4.0";
        }
        iisManager.CommitChanges();
    }

    // ... other code here ('site' gets initialized) ...

    using (var iisManager = new ServerManager())
    {
        // Set anonymous auth appropriately
        var config = iisManager.GetWebConfiguration(site.Name);
        var auth = config.GetSection("system.web/authentication");
        auth.SetMetadata("mode", "Windows");
        var authSection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication");
        authSection.SetAttributeValue("enabled", true);
        authSection.SetAttributeValue("userName", string.Empty); // Forces the use of the Pool's Identity.
        authSection = config.GetSection("system.webServer/security/authentication/basicAuthentication");
        authSection.SetAttributeValue("enabled", false);
        authSection = config.GetSection("system.webServer/security/authentication/digestAuthentication");
        authSection.SetAttributeValue("enabled", false);
        authSection = config.GetSection("system.webServer/security/authentication/windowsAuthentication");
        authSection.SetAttributeValue("enabled", false);

        iisManager.CommitChanges();
    }

    // ... other code here ...
}

Насколько я понимаю, это было бы наилучшей практикой безопасности, и тогда я бы добавил разрешения для определенных веб-сайтов для чего-то большего, чем минимальный доступ к системе. Частью этого процесса будет добавление этих идентификаторов пула приложений в группы пользователей, такие как администратор или пользователи системного монитора. Здесь возникают осложнения.

Теперь, как описано в другом месте, каждая идентификация пула приложений существует в формате IIS AppPool\\<pool_name> но этот фальшивый пользователь не перечислен через обычные элементы управления пользовательским интерфейсом GUI, и, кажется, не доступен через библиотеки, такие как System.DirectoryServices.AccountManagement при следовании этому примеру на SO. Кроме того, другие вопросы об идентификации пула приложений, по-видимому, относятся к ссылкам на него из дочернего веб-сайта, а не из контекста установки.

Итак, кто-нибудь знает, для чего нужны правильные методы

  • а) Ссылка и доступ к идентификаторам пула приложений программно.
  • b) Предоставление разрешений для удостоверений пула приложений путем добавления их в группы пользователей.

2 ответа

Решение

Решение появилось раньше, чем я ожидал, хотя это не то, что я предпочел. Для тех, кто заинтересован, есть несколько дополнительных опций на этой странице pinvoke. Управляемое решение у меня не сработало, но пример с использованием DllImport сработал. В итоге я настроил образец для обработки произвольных групп на основе сопоставления перечисления со строками SID и включения другого DllImport для:

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool ConvertStringSidToSid(
    string StringSid,
    out IntPtr ptrSid);

Модифицированная (рабочая) функция выглядит примерно так:

static public bool AddUserToGroup(string user, UserGroup group)
{
    var name = new StringBuilder(512);
    var nameSize = (uint)name.Capacity;
    var refDomainName = new StringBuilder(512);
    var refDomainNameSize = (uint)refDomainName.Capacity;
    var sid = new IntPtr();
    switch (group)
    {
        case UserGroup.PerformanceMonitorUsers:
            ConvertStringSidToSid("S-1-5-32-558", out sid);
            break;
        case UserGroup.Administrators:
            ConvertStringSidToSid("S-1-5-32-544", out sid);
            break;
        // Add additional Group/cases here.
    }

    // Find the user and populate our local variables.
    SID_NAME_USE sidType;
    if (!LookupAccountSid(null, sid, name, ref nameSize,
        refDomainName, ref refDomainNameSize, out sidType))
        return false;

    LOCALGROUP_MEMBERS_INFO_3 info;
    info.Domain = user;

    // Add the user to the group.
    var val = NetLocalGroupAddMembers(null, name.ToString(), 3, ref info, 1);

    // If the user is in the group, success!
    return val.Equals(SUCCESS) || val.Equals(ERROR_MEMBER_IN_ALIAS);
}

Надеюсь, это будет интересно кому-то еще, и я все еще хотел бы знать, сталкивался ли кто-нибудь с работающим, полностью управляемым решением.

Спасибо за ваш хорошо написанный вопрос. Это именно та проблема, которую я пытался решить прошлой ночью, и она дала мне достаточно, чтобы продолжить, и я смог наконец собрать ответ, который использует только управляемый код. Я нашел три шага, чтобы заставить фреймворк найти виртуального пользователя и работать с ним:

  • с помощью new System.Security.Principal.NTAccount(@"IIS APPPOOL\<appPoolName>") чтобы получить ручку на счет.
  • с помощью .Translate(typeof (System.Security.Principal.SecurityIdentifier)) преобразовать его в SID
  • понимая, что Principal.FindByIdentity() рассматривает этот SID как группу, а не как пользователя

Последняя рабочая программа (Windows Server 2012 для моего теста) выглядит следующим образом:

using System;
using System.DirectoryServices.AccountManagement;

namespace WebAdminTest
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var user = new System.Security.Principal.NTAccount(@"IIS APPPOOL\10e6c294-9836-44a9-af54-207385846ebf");
            var sid = user.Translate(typeof (System.Security.Principal.SecurityIdentifier));

            var ctx = new PrincipalContext(ContextType.Machine);

            // This is weird - the user SID resolves to a group prinicpal, but it works that way.
            var appPoolIdentityGroupPrincipal = GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, sid.Value);

            Console.WriteLine(appPoolIdentityGroupPrincipal.Name);
            Console.WriteLine(appPoolIdentityGroupPrincipal.DisplayName);

            GroupPrincipal targetGroupPrincipal = GroupPrincipal.FindByIdentity(ctx, "Performance Monitor Users");

            // Making appPoolIdentity "group" a member of the "Performance Monitor Users Group"
            targetGroupPrincipal.Members.Add(appPoolIdentityGroupPrincipal);
            targetGroupPrincipal.Save();

            Console.WriteLine("DONE!");
            Console.ReadKey();
        }
    }
}
Другие вопросы по тегам