SeguridadCarpetasLa información que ofrece en ocasiones MSDN sobre la plataforma .NET se puede decir, eufemísticamente, que "no es todo lo buena que debiera ser". Un buen ejemplo de ello es la documentación de la clase FileSystemAccessRule y más en concreto lo que se refiere a los indicadores sobre propagación y herencia de permisos en el acceso al sistema de archivos.

Consideremos este ejemplo. Necesitas controlar desde tu aplicación el acceso a un carpeta llamada "docs" de forma que te asegures de que el usuario "DOMINIO\Usuario" tendrá acceso de lectura a la carpeta y todas sus subcarpetas (y las hijas de éstas), pero sin embargo no tendrá acceso a ninguno de los archivos contenidos en éstas. Dejemos de lado la utilidad exacta de esto. Lo que quiero es mostrar lo retorcidas que han puesto las opciones correspondientes en la plataforma .NET :-S

El código en C# que necesitaríamos incluir es este:

   1: DirectorySecurity dirSec = Directory.GetAccessControl(@"c:\docs");
   2:  
   3: FileSystemAccessRule fsaRule = 
   4:     new FileSystemAccessRule(new NTAccount(@"DOMINIO\Usuario"), 
   5:                     FileSystemRights.Read, 
   6:                     InheritanceFlags.ContainerInherit, 
   7:                     PropagationFlags.None, 
   8:                     AccessControlType.Allow);
   9:  
  10: dirSec.AddAccessRules(fsaRule);
  11: Directory.SetAccessControl(@"c:\docs", dirSec);

Lo interesante aquí es la segunda línea en la que se define la regla de acceso al recurso en disco, y en concreto lo que se refiere a los flags que controlan la herencia de permisos (InheritanceFlags) y la propagación de éstos (PropagationFlags).

Los flags de herencia indican a qué objetos queremos hacer que se hereden los permisos de la regla de acceso. Tienen el siguiente significado:

  • None: No quieres que se hereden a ningún objeto. Aquí se acaba, pues los ajustes de propagación no hacen nada si no hay herencia.
  • ContainerInherit: Quieres que se hereden pero sólo a los objetos contenedores de otros objetos (por ejemplo carpetas o claves de registro (si estuvieras trabajando con el registro), pero no archivos o valores de registro).
  • ObjectInherit: Quieres que se hereden pero sólo a los objetos que no sean contenedores de otros objetos, por ejemplo archivos o valores de registro, pero no carpetas o claves de registro).

Así, si por ejemplo estamos controlando acceso al sistema de archivos y le ponemos como valor None, no se heredarán los permisos. Pero si le ponemos ContainerInherit se heredarán los permisos a las carpetas hijas, pero no a los archivos. Si le pones ObjectInherit se heredarán a archivos pero no a carpetas. Y si  le ponemos ContainerInherit | ObjectInherit (es decir, hacemos un OR de ambos flags) entonces se heredarán tanto para carpetas como para archivos. Así que ojo ya que es necesario combinar ambos para poder heredar tanto a carpetas como a archivos.

Hasta aquí la cosa es enrevesada pero fácil de entender. Ahora viene lo complicado, no por que lo sea realmente sino porque lo han hecho (en mi humilde opinión) fatal y está muy mal documentado.

Los flags de propagación indican cómo queremos que se hereden los permisos. Con los siguientes valores (que como digo no son nada intuitivos sino más bien lo contrario) controlamos este aspecto:

  • None: Si usamos este valor indicaremos que queremos que se propaguen las listas de control de acceso (ACLs) a todos los objetos indicados con el flag anterior, es decir, a las carpetas, archivos o ambos según hayas indicado. La verdad es que en mi opinión debería haberse llamado "All" en lugar de "None" sería más adecuado, y además es  un poco enrevesado el hecho de que depende del flag anterior :-(
  • InheritOnly: Este flag indica que la ACL se debe heredar en los objetos hijo indicado (carpetas, archivos o ambos), pero no en el objeto primario al que le estás aplicando los permisos. Es decir, si tienes una carpeta se aplicaría a todas las subcarpetas y/o archivos (según lo que hayas indicado), pero no a la propia carpeta raíz sobre la que lo estás aplicando.
  • NoPropagateInherit: Este (es de alucinar) indica que se debe aplicar a los hijos apropiados según lo que hayas indicado anteriormente, pero no a los hijos de éstos. Es decir, se aplica sólo a los hijos de primer nivel de los contenedores/carpetas.

Por supuesto podemos combinar las dos últimas entre sí al igual que hicimos en el caso anterior.

La verdad es que es de lo más enrevesado, pero una vez que lo descifras es fácil de seguir.

Así, en el ejemplo de arriba, teníamos el siguiente código:

   1: FileSystemAccessRule fsaRule = new FileSystemAccessRule(
   2:                             new NTAccount(@"DOMINIO\Usuario"), 
   3:                             FileSystemRights.Read, 
   4:                             InheritanceFlags.ContainerInherit, 
   5:                             PropagationFlags.None,
   6:                             AccessControlType.Allow);

Lo que estamos indicando con los flags de herencia y propagación es lo siguiente:

  • InheritanceFlags.ContainerInherit: Le estamos indicando que sólo hereden los objetos hijos que sean contenedores, es decir las carpetas. Como no le combinamos con una operación OR el otro valor del flag y por lo tanto no se heredan los permisos en los objetos no contenedores, o sea, en los archivos.
  • PropagationFlags.None: le indicamos que la herencia se propague a todos los elementos hijos antes indicados, es decir a todas las carpetas hijas de la actual, pero no a los archivos. Como no indicamos el flag InheritOnly, se incluye también la carpeta actual (o sea, c:\docs).

Así que aunque esté poco claro en la documentación con mi explicación anterior todo cobra sentido, pero está muy liado.

Si por ejemplo le hubiésemos puesto esto:

   1: FileSystemAccessRule fsaRule = new FileSystemAccessRule(
   2:                                 new NTAccount(@"DOMINIO\Usuario"), FileSystemRights.Read, 
   3:                                 InheritanceFlags.ContainerInherit, 
   4:                                 PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit,
   5:                                 AccessControlType.Allow);

Lo que estaríamos consiguiendo es que los permisos se hereden sólo para las carpetas hijas de primer nivel (NoPropagateInherit) y además que no se apliquen a la carpeta raíz (InheritOnly).

Es decir, que es enrevesado pero flexible, y totalmente anti-intuitivo, por desgracia.

Espero que mi explicación ayude a otra gente a aclararse con esto :-)

¿Te ha gustado este post? - Aprende .NET con los cursos on-line tutelados de campusMVP:
   ·
Preparación del examen 70-515: Desarrollo Web con .NET 4.0 (Tutelado por mi)
   · Desarrollo Web con ASP.NET 4.0 Web Forms (Tutelado por mi)
   · ASP.NET 4.0 Web Forms desde cero (Tutelado por mi)
   · Desarrollo Web con ASP.NET MVC 3 
   · Silverlight 4.0 - Aplicaciones Ricas para Internet (RIA)
   · jQuery paso a paso para programadores ASP.NET
   · Visual Studio 2010 desde cero

💪🏻 ¿Este post te ha ayudado?, ¿has aprendido algo nuevo?
Pues NO te pido que me invites a un café... Te pido algo más fácil y mucho mejor

Escrito por un humano, no por una IA