Parte 2 del kit de herramientas de integración de notificaciones, Azure y SharePoint

Esta es la segunda parte de una serie de cinco partes sobre el kit CASI (del inglés Claims, Azure, and SharePoint Integration).  En la parte 1 se presentó la solución y el marco completos y se describieron los temas que se van a tratar en la serie.  En esta entrada de blog nos centraremos en el diseño del enfoque:

1.       Uso de una aplicación WCF personalizada como el front-end de los datos y el contenido

2.       Apta para notificaciones

3.       Cambios adicionales para poder subirla a la nube de Windows Azure

Uso de WCF

La premisa principal del marco del kit CASI es que todos los datos de la aplicación usan una aplicación WCF como front-end.  Al igual que todas las aplicaciones personalizadas, se trata de un elemento que deberá crear el programador.  Prácticamente no es necesario tener ningún conocimiento específico sobre SharePoint para esta parte del proyecto. Puede hacerlo cualquier programador de .NET que sepa usar Visual Studio para crear una aplicación WCF.  Si su objetivo principal es hospedar este servicio WCF en Windows Azure, le recomiendo encarecidamente que use el kit de desarrollo de Windows Azure para descargar las plantillas para crear aplicaciones de Azure. También le recomiendo que comience con la creación de una aplicación WCF de Azure desde cero.  Vale la pena señalar una limitación importante que debe tenerse en cuenta con la versión actual del kit CASI.  El kit CASI en realidad solo admite el envío de tipos de datos .NET principales como parámetros a los métodos de WCF.  Por ello, las cadenas, los valores booleanos, los enteros y las fechas funcionan bien, pero no existe un método que pueda pasarse en una clase personalizada como parámetro.  No obstante, si necesita hacerlo, le recomiendo crear el parámetro como una cadena, deserializarlo en XML antes de llamar al método de WCF y, a continuación, volver a serializarlo en una instancia de objeto en el código WCF.  Más allá de eso, no he visto ninguna limitación importante hasta el momento, pero estoy seguro de que muy pronto se va a ir formando una lista de sugerencias a medida que más personas adopten y usen esta versión.  A modo de aclaración breve, el kit que hoy le presento en realidad solo consiste en la primera versión de mis propias ideas sobre el modo en que se pueden desarrollar estos elementos, y se diseñó para ajustarse a los escenarios principales que pensé y decidí que eran importantes.  No tengo duda de que habrá mucho espacio para incluir mejoras a medida que las personas lo usen.

Apta para notificaciones

Una vez creada la aplicación WCF, el siguiente paso es configurarla para que esté preparada para las notificaciones.  En este paso no puedo atribuirme el mérito en absoluto, ya que lo redirigiré a la excelente entrada de blog de cuatro partes que escribió Eric White del equipo de Office para describir cómo integrar las notificaciones de SharePoint en una aplicación WCF.  Suponiendo que ya ha creado el servicio WCF, comenzaré con la parte 2 de la serie de Eric que se encuentra en http://blogs.msdn.com/b/ericwhite/archive/2010/05/13/determining-caller-identity-within-a-wcf-web-service.aspx.  Además, DEBE continuar y realizar los pasos que desarrolla en la parte 3 en http://blogs.msdn.com/b/ericwhite/archive/2010/06/18/establishing-trust-between-a-wcf-web-service-and-the-sharepoint-2010-security-token-service.aspx comenzando por la sección sobre el  procedimiento para establecer confianza entre el servicio web y SharePoint Server.  Debe llevar a cabo todos los pasos indicados desde ese punto en adelante, es decir, copiar la huella digital del certificado de firma de tokens STS de SharePoint junto con otra información en el archivo web.config de la aplicación WCF.  Personalmente, yo no seguiría los pasos de SSL de la parte 3 paso a paso, ya que realmente no resultará útil usar un certificado autofirmado cuando la aplicación esté hospedada en Windows Azure.  Si es lo único que encuentra disponible, entonces hágalo. Pero, en general, debería planear obtener un certificado SSL adecuado de una entidad de certificación apropiada para la aplicación WCF de Windows Azure.  NOTA:  NO es necesario realizar los pasos de la parte 4 del blog de Eric.  Una vez realizados los pasos descritos anteriormente, tendrá una aplicación apta para notificaciones WCF de SharePoint en funcionamiento.  En la fase final de esta entrada de blog, lo guiaré por los pasos adicionales necesarios para subir la aplicación a Windows Azure.

Puesta en funcionamiento para Windows Azure

Ahora que tiene la aplicación WCF de Azure en funcionamiento, debe realizar algunas tareas adicionales para lograr que esta admita la autenticación de notificaciones y los tokens mediante Windows Identity Framework (WIF) y para hospedarla en la nube de Windows Azure.  Echemos un vistazo a la lista de tareas:

1.       Configure el proyecto WebRole (es decir, el proyecto WCF) para que use un directorio virtual local para la depuración.  Personalmente, me resulta mucho más sencillo trabajar así que con el servidor de desarrollo de VS.NET para tareas que requieren el uso de certificados, que seguramente deseará llevar a cabo.  Para cambiar esta configuración, haga doble clic en las propiedades del proyecto WebRole y, a continuación, haga clic en la pestaña Web.  Seleccione el botón de radio "Usar servidor web de IIS local" y, a continuación, haga clic en el botón Crear directorio virtual.  Una vez creado el directorio virtual, puede cerrar las propiedades del proyecto.

2.       Agregue una referencia a Microsoft.Identity en el proyecto WebRole.  DEBE cambiar la referencia a Copia local = true y Versión específica = false.  Esto es necesario para copiar el ensamblado de WIF en la nube con el paquete de aplicación.

3.       Obtenga esta revisión de WCF:  http://code.msdn.microsoft.com/KB981002/Release/ProjectReleases.aspx?ReleaseId=4009 para Win2k8 R2, http://code.msdn.microsoft.com/KB971842/Release/ProjectReleases.aspx?ReleaseId=3228 para Win2k8.

4.       DEBE agregar este atributo a la clase WCF:  [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)].  Por ejemplo, la clase tendrá este aspecto:

namespace CustomersWCF_WebRole

{

    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

    public class Customers : ICustomers

    {

 

5.       DEBE incluir los datos de configuración siguientes en el elemento de comportamiento que usa el servicio.  De este modo, solucionará problemas que se producen con asignaciones de puertos aleatorias en el entorno de Azure.  Para probarlo localmente, debe obtener la revisión indicada en el punto 3:

          <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme="http" port="80" />

              <add scheme="https" port="443" />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

 

Este es un ejemplo en contexto del archivo web.config de mi servicio WCF:

    <behaviors>

      <serviceBehaviors>

        <behavior name="CustomersWCF_WebRole.CustomersBehavior">

          <federatedServiceHostConfiguration name="CustomersWCF_WebRole.Customers"/>

          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>

          <serviceDebug includeExceptionDetailInFaults="false"/>

          <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme="http" port="80" />

              <add scheme="https" port="443" />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

        </behavior>

      </serviceBehaviors>

    </behaviors>

 

6.       Cargue el certificado SSL usado para la aplicación WCF en el portal del programador de Azure en primer lugar.  NOTA:  la clase base del kit CASI está programada para usar SSL, por lo que DEBE implementar compatibilidad con SSL en la aplicación WCF de Windows Azure.  Esperamos que este sea un requisito previsto para pasar posibles datos confidenciales entre un servicio de nube y un conjunto o una granja de servidores de SharePoint. A continuación, agregue el certificado a las propiedades del rol de Azure en Visual Studio; para ello, haga doble clic en el nombre del proyecto WebRole (en la carpeta Roles).  En mi caso, descubrí que un certificado comodín funcionaba bien.  Sin embargo, necesitará un certificado PFX y deberá asegurarse de exportar todos los certificados de la cadena al crear el archivo PFX.  Azure los expandirá al cargarlo en el portal del programador.

7.       El certificado SSL debe ser para algúnNombre.suNombreDNS.com, aunque todas las aplicaciones de Azure se hospeden en aplicaciónDeLaNube.net.  Por ejemplo, mi certificado SSL era un certificado comodín para *.vbtoys.com.  En DNS, creé un nuevo registro CNAME denominado azurewcf.vbtoys.com, el cual hacía referencia a miAplicaciónDeAzure.aplicaciónDeLaNube.net.  Por lo tanto, establecer una conexión con https://azurewcf.vbtoys.com mi certificado funciona porque la solicitud y el certificado SSL son para *.vbtoys.com, pero DNS redirige mi solicitud en función del registro CNAME, que es miAplicaciónDeAzure.aplicaciónDeLaNube.net.

8.       En el proyecto de Azure, haga doble clic en el nombre del proyecto WebRole (en la carpeta Roles) y establezca estas propiedades como se muestra a continuación:

a.       Ficha Configuración:  desactive Iniciar explorador para:  extremos HTTP y HTTPS

b.      Ficha Certificados:  agregue el certificado que va a usar para SSL con el servicio.  Por ejemplo, en mi laboratorio uso un certificado comodín emitido por mi dominio para todos mis servidores web, por lo que agregué mi certificado comodín aquí.

c.       Ficha Extremos:  active las casillas de verificación de HTTP y HTTPS (los nombres deben ser HttpIn y HttpsIn respectivamente).  En la sección HTTPS, la lista desplegable del nombre del certificado SSL ahora debería incluir el certificado SSL agregado en el paso b.

9.       Si tiene un método de WCF que devuelve un script, la etiqueta de script debe incluir el atributo DEFER para funcionar correctamente al usar el elemento web incluido con el kit CASI, o si su propia función de JavaScript lo asigna al innerHTML de una etiqueta.  Por ejemplo, la etiqueta de script debería tener este aspecto: <script defer language='javascript'>

10.   Si tiene un método de WCF que devuelve contenido que incluye otras etiquetas de formato, como <style>, debe incluirlas en una etiqueta <pre> o no se procesarán correctamente al usar el elemento web incluido con el kit CASI, o si su propia función de JavaScript lo asigna al innerHTML de una etiqueta.  Por ejemplo, el contenido devuelto con una etiqueta de estilo debería tener este aspecto: <pre><style>.foo {font-size:8pt;}</style></pre>

Esos son los pasos necesarios para configurar la aplicación WCF para que se hospede en Azure. Las siguientes son algunas sugerencias adicionales que pueden ser útiles y, en algunos casos, necesarias, en función de la implementación:

1.       Use el nombre completo al crear la dirección de extremo que consume el servicio, es decir, nombreDeMáquina.foo.com en lugar de simplemente nombreDeMáquina.  De este modo, la transición al formato final hospedado en Windows Azure será más limpia y es posible que también desaparezcan los errores que se producen cuando el certificado SSL está diseñado para usar un nombre de dominio completo.

2.       PUEDE resultar útil agregar este atributo: httpsGetEnabled="true" a este elemento: <serviceMetadata httpGetEnabled="true" />, si desea usar SSL para el WSDL.  No obstante, actualmente hay un error en SharePoint Designer que impide usar SSL para WSDL.

3.       Para obtener sugerencias sobre la depuración y la conexión de datos, consulte mi entrada de blog en http://blogs.technet.com/b/speschka/archive/2010/09/19/azure-development-tips-for-debugging-and-connection-strings.aspx.

4.       En la mayoría de los casos, debe asumir que el espacio de nombres del servicio WCF será http://tempuri.org.  Para obtener instrucciones sobre cómo cambiarlo, puede leer la entrada de blog en http://blogs.infosupport.com/blogs/edwinw/archive/2008/07/20/WCF_3A00_-namespaces-in-WSDL.aspx.

Servicio WCF completo

Si ha seguido todos los pasos de configuración anteriores y ha implementado la aplicación WCF en Windows Azure, cuando un usuario realice una llamada al servicio WCF desde un sitio de SharePoint, también obtendrá su token de usuario completo, con todas las notificaciones que tiene asociadas.  También vale la pena tener en cuenta que una vez realizados estos cambios, el servicio WCF también funcionará localmente, de modo que resulta sencillo probarlo si desea poner en práctica algunos cambios incrementales antes de insertar la aplicación en la nube.  Dado que dispone del token de usuario, puede realizar algunas tareas realmente interesantes en el servicio WCF.  Por ejemplo, dentro del servicio WCF puede enumerar todas las notificaciones de un usuario y tomar cualquier tipo de decisión sobre permisos específicos en función de ellas.  A continuación se muestra un ejemplo de cómo usar LINQ en el conjunto de notificaciones de usuario para determinar si el usuario actual es un administrador, ya que si lo es, en la solicitud se devolverá algún nivel adicional de detalles.

//look for the claims identity

IClaimsIdentity ci =

System.Threading.Thread.CurrentPrincipal.Identity as IClaimsIdentity;

 

if (ci != null)

{

//see if there are claims present before running through this

       if (ci.Claims.Count > 0)

       {                       

       //look for a group claim of domain admin

var eClaim = from Microsoft.IdentityModel.Claims.Claim c in ci.Claims

              where c.ClaimType ==

"http://schemas.microsoft.com/ws/2008/06/identity/claims/role" &&

                     c.Value == "Domain Admins"

                     select c;

 

              //see if we got a match

              if (eClaim.Count() > 0)

                     //there’s a match so this user has the Domain Admins claim

                     //do something here

}

}

 

Lo que es igualmente interesante es que pueden realizarse demandas de permisos directamente en los métodos de WCF.  Por ejemplo, suponga que tiene un método de WCF que consulta un almacén de datos y devuelve una lista de consejeros delegados del cliente.  No desea que la información esté disponible para todos los empleados, sino solo para los jefes de ventas.  Una forma muy fácil y sencilla de lograrlo es con una demanda PrincipalPermission en el método, como se muestra a continuación:

//the customer CEO list should not be shared with everyone,

//so only show it to people in the Sales Manager role

[PrincipalPermission(SecurityAction.Demand, Role = "Sales Managers")]

public string GetCustomerCEOs()

{

//your code goes here

}

 

Ahora, si alguien intenta llamar a este método y no dispone de una notificación de "Sales Managers" (jefe de ventas), obtendrá un acceso denegado cuando ejecute el código que intente llamar a este método.  ¡Fantástico!

También es importante comprender que esta identidad no puede suplantarse (spoofing).  Por ejemplo, no puede simplemente crear su propio dominio en un laboratorio, agregarle una cuenta y crear un rol de jefe de ventas al cual le agregará dicha cuenta.  La razón por la cual no funcionará se relaciona con los pasos realizados en el blog de Eric White (en la sección anterior titulada Apta para notificaciones).  Si lo recuerda, agregó la huella digital del certificado de firma de tokens usado por el STS de SharePoint.  Esto significa que cuando una notificación entra en la aplicación WCF, hará que la clave pública del STS de SharePoint firme el token.  Solo el STS de SharePoint puede firmarlo con esa clave pública, ya que es la única entidad que tiene la clave privada para ese certificado de firma de tokens.  Esto garantiza que solo las personas que se han autenticado en esa granja de servidores de SharePoint podrán usar el servicio WCF y que los usuarios solo tendrán las notificaciones que se les concedieron al iniciar sesión.  Otra cosa interesante es que esto no solo incluye las notificaciones concedidas al autenticarse en su directorio de usuario, sino TAMBIÉN todas las notificaciones adicionales concedidas mediante el aumento de notificaciones en SharePoint con cualquier proveedor de notificaciones personalizado.  Por este motivo, esta sí es realmente una solución de un extremo a otro verdaderamente integrada.

Próximos pasos

En la siguiente entrada de blog, comenzaré a describir la base clase y el elemento web personalizados incluidos con el kit CASI, lo que le permitirá conectarse a la nueva aplicación WCF de Azure rápida y fácilmente.  Además, desde este momento, usaré un servicio WCF que escribí para el kit CASI como medio para demostrar la funcionalidad.  Adjuntaré a esta entrada de blog el archivo .cs que usé para este servicio.  No podrá usarlo tal como está, pero lo incluyo solo para que pueda ver los distintos métodos que contiene, el tipo de datos que contiene y cómo se han implementado algunas características para este kit.  Principalmente durante las siguientes entradas de blog me verá usar los métodos a) GetAllCustomersHtml, b) GetCustomerCEOs y c) GetAllCustomers.  Son interesantes porque devuelven HTML (que será el tipo de devolución preferido de facto para mostrar datos de elementos web), usan una demanda PrincipalPermission y muestran cómo devolver un tipo de clase personalizada desde la aplicación WCF y usar ese mismo tipo de clase enriquecida después de volver a obtener los datos en SharePoint con el kit CASI.

Esta entrada de blog es una traducción. Puede consultar el artículo original en The Claims, Azure and SharePoint Integration Toolkit Part 2