6

问题:当新的IIS应用程序池创建并设置为使用应用程序池标识进行权限时,我不确定如何将这些标识添加到用户组,例如管理员或绩效计数器用户。以编程方式将IIS应用程序池标识“用户”分配给组

背景:我目前正在写它使用Microsoft.Web.Administration为了做以下一个C#.NET库:

  • 如果安装了IIS 7.x的检测,如果那么,什么组件。
  • 将IIS 7.x安装或升级到所需组件的提供列表。
  • 通过IIS创建/管理一个或多个网站。
  • 自动创建/管理每个网站一个应用程序池

的背景是,这个库是由可执行安装程序来提供的一个Web服务器和网站/服务的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 ... 
} 

据我了解,这将是最佳的安全实践,然后,我会为特定网站添加权限,以获取最少的系统访问权限。这个过程的一部分是将这些应用程序池标识添加到用户组,例如管理员或性能监视器用户。这是复杂性出现的地方。

现在,documented elsewhere,每个应用程序池标识存在的IIS AppPool\\<pool_name>格式,但这种人造用户不通过正常的GUI用户管理控制上市,似乎并没有被通过库如System.DirectoryServices.AccountManagement访问以下this example on SO当。此外,有关应用程序池标识的其他问题似乎与referencing it from within a child website有关,而不是来自安装上下文中。

因此,没有人知道什么是正确的方法是

  • 一)引用和访问应用程序池标识编程。
  • b)通过将应用程序池标识添加到用户组来授予应用程序池标识权限。

回答

1

解决方案早于我的预期呈现,尽管它不是我喜欢的。对于任何感兴趣的人,this pinvoke page有几个附加选项。受管理的解决方案对我无效,但使用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); 
} 

希望这会对其他人感兴趣,并且我仍然想知道是否有人遇到了一个可操作的,完全托管的解决方案。

5

感谢您的写作问题。这正是昨天晚上我试图解决的问题,它足够让我继续努力,终于可以拼凑出只使用托管代码的答案。有三个步骤,我发现越来越框架查找并与虚拟用户的工作:使用new System.Security.Principal.NTAccount(@"IIS APPPOOL\<appPoolName>")以取得该帐户手柄

  • 使用.Translate(typeof (System.Security.Principal.SecurityIdentifier))将其转换为一个SID
  • 理解是Principal.FindByIdentity()对待该SID喜欢它是一组,而不是用户

最后一个工作程序(Windows为我的测试服务器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(); 
     } 
    } 
} 
+0

为了重现结果,我将尝试更换此解决方案。这看起来很有前途,谢谢分享! – jmsb

相关问题