简体   繁体   English

以编程方式将IIS应用程序池标识“用户”分配给组

[英]Programmatically assigning IIS Application Pool Identity “users” to Groups

The Problem: When new IIS Application Pools are created and set to use the Application Pool Identity for permissions, I am unsure how to add those identities to User Groups such as Administrator or Performance Counter Users. 问题:创建新的IIS应用程序池并将其设置为使用应用程序池标识获取权限时,我不确定如何将这些标识添加到用户组(如管理员或性能计数器用户)。

The Background: I'm currently writing a C#.NET library which uses Microsoft.Web.Administration in order to do the following: 背景:我目前正在编写一个使用Microsoft.Web.Administration的C#.NET库,以便执行以下操作:

  • Detect if IIS 7.x is installed, and if so, what components. 检测是否已安装IIS 7.x,如果已安装,则检测哪些组件。
  • Install or upgrade IIS 7.x to a provided list of required components. 将IIS 7.x安装或升级到所提供的所需组件列表。
  • Create/manage one or more web sites through IIS. 通过IIS创建/管理一个或多个网站。
  • Automatically create/manage one application pool per web site 每个网站自动创建/管理一个应用程序池

The context is that this library is to be used by executable installers to provide automated deployment of a web server and web sites/services on Windows Server OSes as part of a larger software deployment. 上下文是可执行安装程序将此库用于在Windows Server操作系统上自动部署Web服务器和Web站点/服务,作为更大的软件部署的一部分。 So far, all of the above has been implemented, tested, and is (mostly) functional except for the automation of some permissions that need to be performed on Application Pool / Website creation. 到目前为止,除了需要在应用程序池/网站创建上执行的某些权限的自动化之外,所有上述内容都已实现,测试并且(大部分)功能正常。

In my method for installing a new website, I create a new Application Pool and force it to use the Application Pool Identity: 在我安装新网站的方法中,我创建了一个新的应用程序池并强制它使用应用程序池标识:

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 ...
}

As I understand it, this would be the best security practice, and I would then add permissions to specific web sites for anything more than minimal system access. 据我所知,这将是最好的安全实践,然后我会为特定网站添加权限,而不仅仅是最小的系统访问。 Part of this process would be to add these Application Pool identities to User Groups, such as Administrator or Performance Monitor Users. 此过程的一部分是将这些应用程序池标识添加到用户组,例如管理员或性能监视器用户。 This is where complications arise. 这是出现复杂情况的地方。

Now, as documented elsewhere , each Application Pool Identity exists in the format of IIS AppPool\\\\<pool_name> but this faux-user is not listed through the normal GUI user management controls, and does not seem to be accessible through libraries such as System.DirectoryServices.AccountManagement when following this example on SO . 现在,正如其他地方所述 ,每个应用程序池标识都以IIS AppPool\\\\<pool_name>的格式存在,但是这个faux-user没有通过普通的GUI用户管理控件列出,并且似乎无法通过诸如System.DirectoryServices.AccountManagement库访问System.DirectoryServices.AccountManagement以下时上SO这个例子 Also, other questions about the Application Pool Identity seem to relate to referencing it from within a child website , not from within an installation context. 此外,有关应用程序池标识的其他问题似乎与在子网站内引用它有关,而不是在安装上下文中引用它

So, does anyone know what the proper methods are for 那么,有谁知道适当的方法是什么

  • a) Referencing and accessing Application Pool Identities programmatically. a)以编程方式引用和访问应用程序池标识。
  • b) Giving Application Pool Identities permissions by adding them User Groups. b)通过添加用户组来授予应用程序池标识权限。

Thanks for your well-written question. 谢谢你写得很好的问题。 It is exactly the problem that I was trying to solve last night and it gave me enough to go on that I was able finally cobble together an answer that uses only managed code. 这正是我昨晚试图解决的问题,它让我足够继续,我终于能够拼凑出一个只使用托管代码的答案。 There were three steps that I found to getting the framework to find and work with the virtual user: 我发现有三个步骤可以让框架找到并使用虚拟用户:

  • using new System.Security.Principal.NTAccount(@"IIS APPPOOL\\<appPoolName>") to get a handle on the account. 使用new System.Security.Principal.NTAccount(@"IIS APPPOOL\\<appPoolName>")来获取帐户的句柄。
  • using .Translate(typeof (System.Security.Principal.SecurityIdentifier)) to convert it to a SID 使用.Translate(typeof (System.Security.Principal.SecurityIdentifier))将其转换为SID
  • understanding that Principal.FindByIdentity() treats that SID like it is a group, rather than a user 了解Principal.FindByIdentity()将SID视为一个组,而不是用户

A final working program (Windows Server 2012 for my test) is as follows: 最终的工作程序(我的测试的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();
        }
    }
}

A solution presented itself sooner than I expected, though it's not the one I preferred. 一个解决方案比我预期的要早,但它不是我喜欢的解决方案。 For anyone interested, there are a couple of additional options on this pinvoke page . 对于任何感兴趣的人, 此pinvoke页面上还有一些其他选项。 The managed solution did not work for me, but the sample using DllImport worked. 托管解决方案对我不起作用,但使用DllImport的示例工作正常。 I ended up adjusting the sample to handle arbitrary groups based on mapping an enum to SID strings, and including another DllImport for: 我最后调整了样本来处理任意组,基于将枚举映射到SID字符串,并包括另一个DllImport:

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

The modified (working) function looks something like this: 修改后的(工作)函数看起来像这样:

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);
}

Hopefully this will be of interest to someone else, and I would still like to know if anyone comes across a working, fully managed solution. 希望这对其他人感兴趣,我仍然想知道是否有人遇到过工作的,完全托管的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在IIS 7中以编程方式为自定义身份应用程序池设置用户帐户 - Programmatically set up user account for custom identity application pool in IIS 7 以编程方式获取应用程序池标识 - Get the Application Pool Identity programmatically 如何在IIS 8上以编程方式设置应用程序池标识 - How to programmatically set App Pool Identity on IIS 8 以编程方式停止应用程序池问题IIS7 - STOP Application Pool Issue Programmatically IIS7 使用安装程序以编程方式在IIS中创建应用程序池时出错 - Error creating an Application Pool in IIS programmatically with an installer 为远程IIS应用程序池标识配置MSMQ专用队列权限 - Configuring MSMQ private queue permissions for a remote IIS Application Pool Identity 如何正确设置IIS 7应用程序池标识? - How to set up IIS 7 application pool identity correctly? 应用程序池标识更改 - application pool identity change IIS 应用程序池身份对隔离存储的权限,无需更改 iis 身份验证方法 - IIS application pool identity permission to isolated storage without changing iis auth method 当我更改 IIS 应用程序池身份用户使用自定义帐户时,它会停止应用程序池,即使我再次启动它也是如此 - When I Change the IIS Application Pool Identity User Use Custom Account it stops the Application pool even if I start it again
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM