6

Il problema: Quando vengono creati nuovi pool di applicazioni IIS e impostati per utilizzare l'identità del pool di applicazioni per le autorizzazioni, non sono sicuro come aggiungere tali identità a gruppi di utenti come Amministratore o contatore di prestazioni.Assegnazione programmatica di "utenti" di identità applicazione IIS ai gruppi

Sfondo: Attualmente sto scrivendo una libreria .NET C# che utilizza Microsoft.Web.Administration al fine di effettuare le seguenti operazioni:

  • Rileva se è installato IIS 7.x, e se quindi, quali componenti.
  • Installare o aggiornare IIS 7.x in un elenco fornito di componenti richiesti.
  • Creare/gestire uno o più siti Web tramite IIS.
  • automaticamente creare/gestire un pool di applicazioni per ogni sito web

Il contesto è che questa libreria è per essere utilizzato da installatori eseguibili per fornire distribuzione automatizzata di un server Web e siti web/servizi su sistemi operativi Windows Server come parte di una più ampia distribuzione del software. Finora, tutto quanto sopra è stato implementato, testato ed è (soprattutto) funzionale tranne che per l'automazione di alcune autorizzazioni che devono essere eseguite sul pool di applicazioni/creazione di siti web.

Nel mio metodo per l'installazione di un nuovo sito web, creo un nuovo pool di applicazioni e costringerlo a utilizzare il pool di applicazioni:

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

Da quanto ho capito, questa sarebbe la migliore pratica di sicurezza, e Aggiungerei quindi le autorizzazioni a siti Web specifici per qualcosa di più che un accesso minimo al sistema. Parte di questo processo consisterebbe nell'aggiungere queste identità del pool di applicazioni a gruppi di utenti, come ad esempio gli utenti di Amministratore o Performance Monitor. È qui che sorgono le complicazioni.

Ora, come documented elsewhere, ogni Identità pool di applicazioni esiste nel formato IIS AppPool\\<pool_name> ma questo finto-utente non è elencato attraverso i normali controlli di gestione GUI, e non sembra essere accessibile attraverso le biblioteche, come System.DirectoryServices.AccountManagement quando segue this example on SO . Inoltre, altre domande sull'identità del pool di applicazioni sembrano correlate a referencing it from within a child website, non da un contesto di installazione.

Così, qualcuno sa quali sono i metodi propri sono per

  • a) Riferimenti e l'accesso Application Pool Identities di programmazione.
  • b) Fornire le autorizzazioni di identità del pool di applicazioni aggiungendole Gruppi di utenti.

risposta

1

Una soluzione si presentava prima di quanto mi aspettassi, anche se non è quella che preferivo. Per chiunque sia interessato, ci sono un paio di opzioni aggiuntive su this pinvoke page. La soluzione gestita non ha funzionato per me, ma il campione che utilizzava DllImport ha funzionato.Ho finito per regolare il campione per gestire gruppi arbitraria basata sulla mappatura un enum in stringhe SID, e tra cui un altro DllImport per:

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

La funzione

modificato (di lavoro) simile a questa:

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

Spero che questo possa interessare a qualcun altro, e mi piacerebbe ancora sapere se qualcuno trova una soluzione funzionante e completamente gestita.

5

Grazie per la tua domanda ben scritta. È esattamente il problema che stavo cercando di risolvere la scorsa notte e mi ha dato abbastanza per andare avanti che finalmente sono riuscito a mettere insieme una risposta che usa solo il codice gestito. C'erano tre passi che ho trovato per ottenere il quadro per trovare e lavorare con l'utente virtuale:

  • utilizzando new System.Security.Principal.NTAccount(@"IIS APPPOOL\<appPoolName>") per ottenere un handle sul conto.
  • utilizzando .Translate(typeof (System.Security.Principal.SecurityIdentifier)) per convertirlo in un SID
  • intesa che Principal.FindByIdentity() tratta che SID come si tratta di un gruppo, piuttosto che un utente

Un programma di lavoro finale (Windows Server 2012 per la mia prova) è come segue:

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

Ho intenzione di provare a scambiare la mia soluzione per questo per riprodurre i risultati. Questo sembra promettente, grazie per la condivisione! – jmsb

Problemi correlati