Seguridad integrada con SQL Server en un sitio web ASP.NET

miércoles, 20 de junio de 2007

Una consulta muy frecuente que recibimos es “como configurar un sitio web para acceder a SQL Server mediante seguridad integrada”, bajo la situación más habitual (y recomendada) que es aquella en la cual los usuarios que acceden al sitio no utilizan seguridad integrada de Windows o, aún en caso de hacerlo, no tienen asignados permisos individuales de acceso a la base de datos de la aplicación.

La implementación de este escenario, en la plataforma actual de servidores Web de Windows (Windows Server 2003), consta de los siguientes pasos:

1. Definir un usuario del dominio para ejecutar la aplicación web y acceder al SQL Server

Crear una cuenta de usuario en Active Directory, designada para ejecutar las aplicaciones web y acceder al SQL Server. Es recomendable que esta cuenta no sea administrador del dominio, ni del equipo en que ejecuta el website o el SQL Server.

2. Asignar permisos a ese usuario en Microsoft SQL Server

Mediante el SQL Server Management Studio (SQL Server 2005) o el SQL Server Enterprise Manager (SQL Server 2000) definir, dentro de la seccion Security, una cuenta (login) de seguridad integrada correspondiente a la cuenta designada del dominio; asignarle permisos sobre las bases que corresponda, solamente con los privilegios que requiera para ejeutarse.

3. Preparar la cuenta para ejecutar aplicaciones ASP.NET

Este es un paso comunmente omitido, que resulta en la imposibildad de ejecutar correctamente el sitio.
En el equipo en que se ejecuta el sitio Web (Internet Information Server) configurar lo siguiente:

  1. Asignar a la cuenta designada permisos de control total sobre la carpeta temporaria de Windows (habitualmente C:\Windows\Temp).
  2. Desde la línea de comandos posicionarse en la carpeta correspondiente al framework .NET en uso (por ejemplo C:\Windows\Microsoft.NET\Framework\ v2.0.50727) y allí ejecutar el siguiente comando:
    aspnet_regiis –ga {dominio\cuenta}
    reemplazando {dominio\cuenta} por la cuenta designada en el paso 1

4. Asignar la cuenta designada como identidad del proceso ASP.NET

En Windows Server 2003, eso se realiza en la consola de Administración de Servicios Internet (IIS) asignando la identidad del Application Pool que se utiliza para ejecutar la aplicación Web.
IMPORTANTE: si la aplicación está configurada para ejecutar en el “Default App Pool”, u otro compartido con múltiples aplicaciones, puede ser conveniente definir un application pool separado para los sitios que deban ejecutarse bajo esta cuenta de usuario, y asignar los sitios al App Pool creado.

5. En la aplicación ASP.NET, asegurarse que no esté activa la “impersonación”

Si se utiliza Authentication mode=”Windows”, asegurarse que en el archivo Web.config no exista un elemento <identity> o, si existe, asegurarse de que tenga asignado el atributo impersonate=”false”.
De ese modo, el proceso se ejecutará con la cuenta designada.
NOTA: sin necesidad de impersonar, desde el código de la aplicación Web puede conocerse el nombre de la cuenta autenticada mediante la propiedad User.Identity



Con estos pasos, se lograrán los objetivos buscados:

  • Evitar incluir nombres de usuario y password en la configuración de la aplicación (o en cualquier otro componente de la misma)
  • Ejecutar el sitio web con una cuenta que no tenga más privilegios de los requeridos
  • Evitar otorgar permisos sobre la base de datos a los usuarios del sitio.
Leer más...

SQL Server 2005 sobre Windows Vista

martes, 12 de junio de 2007

Dos recomendaciones muy importantes para utilizar SQL Server 2005 sobre el sistema operativo Windows Vista

1) En todos los casos (se trate de las herramientas cliente, o el motor de base de datos) instalar el Service Pack 2 de SQL Server 2005
http://www.microsoft.com/downloads/browse.aspx?displaylang=es&productID=9F07F9CC-C308-4EBF-A4E9-2B8530AB1EA8

2) Adicionalmente, si se ha instalado el server (motor de base de datos) sobre uno de estos sistemas operativos, tener en cuenta que cambia el manejo por defecto de la seguridad:

Al instalar un SQL 2005, automáticamente se agrega un login para el grupo BUILTIN\Administrators, con permisos de sysadmin.
Sin embargo, el manejo de seguridad de Windows Vista hace que un usuario, aunque sea administrador del equipo, no ejecute las aplicaciones como tal salvo cuando lo hace con "privilegios elevados" (Run as administrator)

Por lo tanto hay dos opciones para que un usuario administrador del equipo tenga privilegios completos de administracion del SQL Server 2005 en ese equipo:

a) [No recomendado] Ejecutar el SQL Server Management Studio mediante la opción "Run as Administrator"

b) [Recomendado] Empleando el "SQL Server Surface Area Configuration", agregar la cuenta del usuario para que actúe como administrador (opcion Add New Administrator)

Para más información sobre las buenas prácticas de administración y operación SQL Server 2005, puede descargarse este documento de Microsoft (en inglés):

SQL Server 2005 Security Best Practices - Operational and Administrative Tasks
Leer más...

Exception Handling y Logging con Enterprise Library 3.0

lunes, 11 de junio de 2007

En este artículo voy a mostrar como agregar un manejo simple de excepciones, y luego logging de éstas y otros eventos usando Enterprise Library 3.0, sin profundizar en todas las posibilidades que éstas librerías ofrecen.

Usaremos en este ejemplo los siguientes bloques de Enterprise Library 3.0:

  • Exception Handling Application Block
  • Logging Application Block (que registrará Excepciones recibidas por el bloque anterior, y otros mensajes de bitácora)
  • Data Application Block (para permitir al bloque anterior, Logging sobre una base de datos SQL)

(Es condición previa en el ejemplo siguiente, agregar referencias en nuestro proyecto a los assemblies correspondientes)

De la aplicación de ejemplo realizada en C#, nos interesa el siguiente bloque de código:


Vamos a trabajar sobre este método, que resulta crítico para nuestro sistema, por lo cual queremos una bitácora de su ejecución y resultado.



Exception Handling Application Block


Este bloque nos permite delegar el manejo de una excepción a una policy definida en archivos de configuración. En particular nos permitirá encapsular, reemplazar, absorber excepciones, o enviar éstas al Logging Application Block para registrarlas en una bitácora.

Para esto basta con modificar nuestro código de la siguiente manera:



Interceptamos cualquier tipo de Exception, y la manejamos con el método estático:

ExceptionPolicy.HandleException()

Éste recibe la excepción a ser manejada, el nombre de la policy a aplicar (a continuación vamos a definir esta política), y opcionalmente un parámetro out en el que se devuelve la excepción que reemplaza a la original (esto sucede cuando la policy utilizada decide que la excepción debe ser reemplazada o contenida dentro de una nueva), si la excepción no debe ser reemplaza este parámetro toma el valor null.

Este método devuelve true si la excepción (o la excepción que la reemplaza) debe ser relanzada.


Ahora sólo resta definir nuestra "TareasPolicy", para eso alcanza con editar el archivo de configuración (app.config, web.config, *.config) con la herramienta gráfica que incluye Enterprise Library (Enterprise Library Configuration Tool), con la cual resulta trivial lo siguiente:

  1. Agregar un bloque de configuración para Exception Handling, y dentro de éste crear una nueva policy con el nombre "TareasPolicy".
  2. Definir en esta policy para el tipo de excepción Exception (es decir para todas), un Logging Handler, y definimos para este Handler, que las excepciones produzcan entradas de Log de nivel "Error" (lógicamente), y con la categoría "Errores", vamos a ver que implica esto a continuación.

Dentro de una policy podemos definir también los siguientes Exception Handlers, que pueden utilizarse según el tipo de Exception lanzada:

Wrap Handler: Envuelve la excepción lanzada dentro de una nueva.
Replace Handler: Reemplaza la excepción con una nueva.
Logging Handler: Transfiere la excepción al Logging Application Block para poder registrarla en una bitácora.
Custom Handler: Permite manejar una excepción utilizando una clase definida en nuestra aplicación.
Fault Contract Exception Handler: Facilita el manejo de excepciones en aplicaciones SOA.



Logging and Instrumentation Application Block


Necesitamos ahora indicar como serán tratadas en este bloque las excepciones recibidas, pero antes es preciso definir las entidades más importantes en este bloque:

Trace Listener: Manejan los eventos registrándolos o emitiéndolos en distintos medios, son los siguientes:
  • Formatted EventLog: registra los eventos en el EventLog del sistema.
  • Flat File: simplemente almacena los eventos en un archivo de texto plano.
  • Rolling Flat File: utiliza un archivo de texto, que al alcanzar una antigüedad o támaño máximo se cierra y comienza uno nuevo.
  • Xml: en este caso el log generado es un documento xml, asimismo las entradas pueden contener un campo xml.
  • Email: envía notificaciones de eventos a traves de un servidor SMTP.
  • Msmq: utiliza Microsoft Message Query como destino de los eventos.
  • WMI: los eventos se manejan con Windows Management Instrumentation.
  • Database: Cuando recibe un evento, invoca un stored procedure con sus datos como parámetro. (Requiere el Data Access Block, para definir la base de datos a utilizar).
  • Custom: Si los anteriores no son suficientes, puede manejarse los eventos mediente una clase definida nuestra aplicación. Esto nos permitiría por ejemplo, mostrar un MessageBox, enviar el error con un POST HTTP, etc.
Formatter: Se encarga de serializar eventos, para facilitar su almacenamiento, son los siguientes:

  • Text Formatter
  • Binary Formatter
  • Xml Formatter
  • Custom Formatter
Event Sources: Representan fuentes de eventos, se les puede asociar uno o más Trace Listeners.
Pueden definirse segun categoría de los eventos, y están predifinidas adicionalmente las siguientes sources especiales:

  • All Events: Como su nombre lo indica, recibe todos los eventos de la aplicación.
  • Unprocessed category: Eventos de categorías no procesadas.
  • Logging Errors & Warnings: Recibe errores y advertencias producidos al registrar otros eventos (por ejemplo, caída del servidor del SQL, al intentar almacenar un evento en éste), permite una especie de "manotazo de ahogado", lo que hace apropiado asociar a esta fuente el Event Handler más "infalible", por ejemplo, Formatted EventLog.
Filters: Permiten filtrar eventos, según categoría, prioridad, o mediante clases personalizadas.


Ahora utilizamos una vez más la herramienta de edición de archivos de configuración para lo siguiente:

  1. Definir el bloque de configuración para el Logging Application Block.
  2. Definir el Category Source "Errores" como fue definido en el Exception Handling Block, este recibirá las Exceptions interceptadas por éste, y asociaremos a este un Database Handler, para crear nuestra bitácora en una base de datos.
  3. Crearemos (si no existe aún) la configuración para el Data Access Application Block, donde definiremos el connection string.
  4. Referenciar esta base de datos en nuestro Database Trace Listener, e indicar en éste el nombre del stored procedure que debe invocarse para agregar una entrada al log, y el stored procedure que se invoca inmediatemente después para indicar la categoría de ese evento (es por esto que el primer stored procedure, debe devolver el id de la entrada creada).
  5. Dado que nuestra conexión con la base de datos puede fallar (y queremos saber cuando!), agregamos un Formatted Event Log Trace Listener, y asociamos este al "Logging Errors & Warning" Special Source, para registrar en el EventLog los errores que ocurran al intentar usar la base de datos.

Por último aprovecharemos el Logging Application Block, para registrar también información adicional sobre la ejecución de nuestra tarea, para eso asociaremos nuestro Database Trace Listener al Special Source "All Events" (es posible definir un Trace Listener, o una categoría especial de eventos para este caso)

Ahora podemos modificar nuestro código C# de esta manera:


El método estático Logger.Write(), puede recibir también varios parametros adicionales como categoría, prioridad, severidad, etc.



Conclusiones

  • Las políticas de manejo de errores y logging, son totalmente independientes del código fuente: pueden ser establecidas de forma gráfica, en archivos de configuración, sin necesidad de recompilar la aplicación. Es decir, la modificación de estas políticas pueden ser delegada a un usuario administrador.
  • Por la misma razón que el punto anterior, al agregar estos bloques a una aplicación existente, el impacto sobre el código fuente es mínimo.
  • El manejo de Excepciones y Eventos de Log, es extensible definiendo "custom handlers", clases personalizadas que son invocadas para estas tareas.



Links


UPDATE 2009-06-12

Fe de erratas!, Como comenta Ariel (ver comentario en esta entrada), la forma correcta de relanzar una excepción es mediante throw; (de forma de mantener el stack trace), asi que en todos los bloques de codigo donde dice:

throw outEx ?? ex;

debería leerse:

if(outEx!=null)
throw outEx;
else
throw;
Leer más...