7.14.2012

BPM y Workflow Foundation – Parte 1

Mucho se habla en estos días de la implementación de procesos de negocio utilizando BPM’s, y con este aparecen muchos “toolsets” para implementar BPMs en el negocio. ¿Pero qué es un BPM?¿Qué características tiene?¿Qué NO es un BPM?¿Puedo implementar un BPM en tecnologías Microsoft? Esta es una nueva serie de post orientadas a clarificar – o desenredar – un poco más el tema de los BPMs.

¿Qué es un BPM?

BPM – Business Process Management -  es la especialidad para el modelaje, automatización, administración, monitoreo y optimización de un proceso de negocios para aumentar su flexibilidad, su eficiencia, y su eficacia. En esta definición hay que destacar que BPM es una especialidad o disciplina y no una tecnología o herramienta. BPM no es solo software, si no que también la gente juega un rol muy importante; de hecho, la diferencia más importante entre un workflow y un BPM es que el BPM va más allá de la simple automatización de tareas para ayudar a la gente a llevar a cabo tareas de forma repetitiva.

Características de un BPM

Un BMP tiene cuatro características principales que vamos a discutir en esta sección:

  1. Un BPM tiene un designer: Todo BPM debe de tener un modelador de procesos visual que permita implementar el proceso de forma práctica y con rapidez.Hay que recordar que una de las ventajas de llevar a cabo BPMs es que son flexibles y permiten cambios de forma rápida, sin un diseñador esto sería una tarea prácticamente imposible.
  2. Un BPM tiene un motor de ejecución: Los BPMs corren sobre un motor de ejecución que se encarga de su ejecución de forma automática. Este motor se encarga entre otras cosas de persistir o cargar el proceso de acuerdo a las condiciones de su ejecución.
  3. Un BPM se puede monitorear: Todo BPM tiene que ser monitoreable, es decir debo saber que sucede con el mismo. Esto incluye saber si el proceso se completó, si está suspendido, o tuvo algún error, etc.
  4. Un BPM se puede optimizar: Todo BPM tiene la posibilidad de ser optimizado. Esto normalmente se logra con herramientas que permiten hacer simulación de procesos para verificar que sucedería si se le cambia, agrega o se le quita algo al proceso.

¿Qué no es un BPM?

Existen muchas herramientas en el mercado que se venden como herramientas BPM pero en realidad son flujos de trabajo básicos que dependen de la interfaz de usuario para poder ser utilizados. Un BPM no depende de ningún tipo de interfaz gráfica y puede ser activado desde una página Web, un servicio (Web o no), un servicio del sistema operativo, una aplicación de escritorio etc. Si un flujo de trabajo depende de una interfaz o de algún tipo de tecnología de presentación entonces no se considera un BPM, ya que ningún flujo de trabajo sin que haya tecnología de por medio depende intrínsecamente de la forma de activarse o de proseguir con una actividad determinada.

¿Existen BPMs en tecnologías Microsoft?

Esta pregunta es muy común cuando se habla de arquitectura de software y la empresa hace sus desarrollos en .NET. Considerando las cuatro características anteriores podemos decir que tenemos una solución BPM si utilizamos Workflow Foundation y el AppFabric. En este contexto, el workflow Foundation tiene un designer en Visual Studio –bastante completo por cierto – ,  puedo ejecutar los procesos en el motor de workflows de WF y por último con el AppFabric obtengo monitoreo, seguimiento y persistencia del Workflow. La única característica que no se cumple con el WF es la optimización del proceso, puesto que no existe una herramienta dentro del stack de Microsoft para llevar  a cabo esta tarea –> que basándome en mi experiencia es muy poco utilizada (He visto muy pocas empresas invertir en simulación de procesos para la optimización de los mismos, pese a que las herramientas que lo utilizan si lo permiten).

¿Y Biztalk Server?

Biztalk Server es un servidor de EAI –> Enterprise Application Integration –> y los wokflows que se construyen en él son workflows de integración. Biztalk Server al igual que WF tiene un diseñador, un motor de workflow y tiene monitoreo para los mismos. Sin embargo, la naturaleza de los workflows de Biztalk está dirigida hacia integrar aplicaciones a través de adaptadores permitiendo que los protocolos de comunicación y los formatos de los mensajes puedan ser dispares entre aplicaciones. Básicamente los workflows de WF son para dominios únicos de aplicación ( integración entre componentes del propio dominio ) y los workflows de Biztalk Server son para dominios externos en combinación con el dominio propio ( Integrar componentes de diversos dominios de aplicación).

Etiquetas de Technorati: ,,

7.01.2012

Biztalk: Error WCF-SqlAdapter–> The requested operation could not be performed because OLE DB provider does not support the required transaction interface

Trabajando en un proyecto con Biztalk server 2010 y los adaptadores WCF para sql server me encontré con un error muy interesante y algo complejo de comprender –> no de arreglar como sucede con la mayoría de los errores.

El problema

Resulta que estaba integrando equipos mainframe a través de un linked server con Biztalk Server. Cuando hacia consultas a los equipos mainframe la transacción funcionaba perfectamente, pero cuando la transacción tenía que modificar alguna entidad del mainframe entonces obtenía el siguiente error:

The requested operation could not be performed because OLE DB provider  does not support the required transaction interface

Haciendo un esfuerzo de memoria Lengua fuera en domingo, recordé que cuando uno utiliza linked servers contra equipos contra los que no se puede realizar transacciones distribuidas de forma automática, se debe configurar el proveedor –> en este caso OleDB –> para que no intente la operación con una interface para obtener la transacción. Esto se logra de manera simple a través de la pantalla de configuración del proveedor y marcando la opción “non transactions updates”.

image

Sin embargo seguía dando el mismo error en el servidor. Luego de un par de pruebas supuse que el error de configuración podría estar en el endpoint del servicio que se conectaba al linked server del lado de Biztalk, especificamente en el binding. Abriendo la configuración del adaptador pude ver que la configuración para la transacción de ambiente estaba en verdadero, lo cual por supuesto en una transacción distribuida eleva la transacción para que sea manejada por el  DTC y este obliga a todos los involucrados en la transacción a votar en la operación. Siendo que el mainframe contra el que estábamos interactuando no soporta el tipo de interface que solicitaba el DTC, se debió establecer esta propiedad en false y listo …problema solucionado Sonrisa 

image 

Etiquetas de Technorati: ,,

6.28.2012

Implementando un Foreach con expresión Lambda

En días pasados dando una capacitación, le solicité al grupo de desarrolladores que hicieran un método que recibiera una lista de clientes y un parámetro tipo string –> en este caso el país –> para filtrar la lista con este parámetro y retornar otra lista con los clientes que pertenecen al país solicitado. Como era de esperarse, la mayoría de los estudiantes solucionó el problema con un foreach y haciendo una comparación en cada iteración. Sin embargo, creo que es mucho más simple implementar esta solución a través de una expresión lambda y es lo que me llevó a escribir este post.

En primera instancia vamos a escribir la clase cliente sobre la cual vamos a llevar a cabo el procedimiento.

public class Cliente
{
public int Id { get; set; }
public string Nombre { get; set; }
public string Apellido1 { get; set; }
public string Apellido2 { get; set; }
public string Pais { get; set; }
}

Ahora procedemos a escribir el método que recibirá la lista de clientes y procederá a retornar otra lista filtrada con el parámetro número 2 –> el país de donde quiero los clientes.

public List<Cliente> ObtenerPorPais(List<Cliente> pLista, string pPais)
{
return pLista.Where(p => p.Pais == pPais).ToList();
}

En este código se va a comprara cada uno de los elementos de la lista, y los que cumplan con la condición ( p.Pais == pPais) serán retornados en una lista cuyo tipo se infiere a partir del tipo de la lista original y de la invocación del método ToList().


Como podemos ver en el método anterior, es mucho más simple implementar la solución con una expresión lambda y un método de extensión de linq que utilizar un foreach y una comparación por cada elemento de forma manual.



Etiquetas de Technorati: ,,,,

6.24.2012

Autenticando Servicios WCF – Certificados Digitales y Usuario/Password –Parte 3

Continuando con la serie de posts acerca de la autenticación de servicios, en este post vamos a proceder a realizar la autenticación de un servicio WCF vía usuario y password. En estos casos siempre es recomendable utilizar un certificado para asegurar el canal ya que de lo contrario, estaríamos enviando las credenciales en “clear text” y esto conlleva a que nos podamos ver en problemas si nos interceptan el mensaje.

Esquema usuario y password

Para este post vamos a utilizar una base de datos de usuarios muy conocida por los desarrolladores .NET y en especial los que utilizan mucho ASP.NET: ASPNETDB. Esta base de datos es generada a partir de un esquema que ya se encuentra incluido en los directorios de .NET y normalmente se accede utilizando el Sql Membership Provider –> Para más información acerca del ASPNETDB y el SQL Membership Provider visitar el siguiente sitio web. El esquema básico de esta base de datos con las características de usuarios y roles se ve en la siguiente figura:

image

Luego volveremos para poder agregar usuarios en la base de datos seleccionada. Por ahora proseguiremos con la implementación del servicio.

Crear el Servicio

En este caso vamos a crear un servicio muy simple que tiene una operación que recibe un string y retorna un decimal. El contrato del servicio es el siguiente:

using System.ServiceModel;

namespace AutenticacionUP
{
[ServiceContract(Namespace="http://icomparable.blogspot.com")]
public interface IServicioCuentasBancarias
{
[OperationContract]
decimal ObtenerSaldo(string pNumeroCuenta);
}
}

Seguidamente procedemos con la implementación del servicio.

namespace AutenticacionUP
{
public class ServicioCuentasBancarias : IServicioCuentasBancarias
{
public decimal ObtenerSaldo(string pNumeroCuenta)
{
return 394232;
}
}
}

Ahora procedemos a configurar el servicio. El primer paso es configurar el endpoint y probar el servicio en el test client.

      <service name="AutenticacionUP.ServicioCuentasBancarias">
<
host>
<
baseAddresses>
<
add baseAddress = "http://localhost:8732/Design_Time_Addresses/AutenticacionUP/Service1/" />
</
baseAddresses>
</
host>
<
endpoint address ="" binding="wsHttpBinding" contract="AutenticacionUP.IServicioCuentasBancarias">
</endpoint>
<
endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</
service>

El servicio corriendo es el siguiente:


image


Ahora procedemos a configurar la seguridad del servicio. El primer paso es crear un binding en donde se especifica el tipo de seguridad que vamos a manejar para autenticar el servicio.

    <bindings>
<
wsHttpBinding>
<
binding name="wsHttpEndpointBinding">
<
security>
<
message clientCredentialType="UserName" />
</
security>
</
binding>
</
wsHttpBinding>
</
bindings>

Como podemos ver en el binding, vamos a especificar que la seguridad a nivel de mensaje se llevará a cabo usando el nombre usuario y password como tipo de credencial del cliente. Ahora procedemos a asociar la credencial al servicio.

<endpoint address ="" binding="wsHttpBinding" 
bindingConfiguration="wsHttpEndpointBinding" contract="AutenticacionUP.IServicioCuentasBancarias">

Ahora procedemos a modificar el comportamiento estándar del servicio para que utilice el certificado que vamos a especificar para que asegure el canal. Este certificado estará disponible en la máquina local y en el almacén My. Nótese además que le estamos indicando que la autenticación a utilizar es userNameAuthentication y que vamos a utilizar un membershipProvider llamar MySqlMembershipProvider.

        <behavior>
<
serviceMetadata httpGetEnabled="true" />
<
serviceDebug includeExceptionDetailInFaults="false" />
<
serviceCredentials>
<
serviceCertificate findValue="CN=DRMCert" storeLocation="LocalMachine" storeName="My" />
<
userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
membershipProviderName="MySqlMembershipProvider"
/>
</
serviceCredentials
>
</
behavior>

WCF soporta por defecto el uso del SQL Membership provider. Para poder utilizar tenemos que configurarlo en el app.config del servicio.

<configuration>
<
connectionStrings>
<
add name="MyLocalSQLServer"
connectionString="Initial Catalog=aspnetdb; data source=.\sqlexpress;Integrated Security=SSPI;" />
</
connectionStrings>
<
system.web>
<
compilation debug="true" />
<
membership defaultProvider="MySqlMembershipProvider" >
<
providers>
<
clear/>
<
add name="MySqlMembershipProvider"
connectionStringName="MyLocalSQLServer"
applicationName="MyAppName"
type="System.Web.Security.SqlMembershipProvider" />
</
providers>
</
membership>
</
system.web>

En este le vamos a indicar en que instancia de base de datos está la base de datos y además vamos a configurar el membership provider. En este vamos a definir el connection string que debe de utilizar para conectarse y además el nombre del provider, el cual será utilizado por el behavior configurado anteriormente para realizar la autenticación.


Ahora procedemos a instalar el servicio. Probamos que el mismos esté disponible navegando hasta la ubicación del servicio svc.


image


Ahora procedemos con el cliente. Para esto procedemos con una aplicación de consola, desde la cual agregamos una referencia al servicio que estamos elaborando:


image


Ahora consumimos el servicio de la forma que normalmente lo hacemos, sin embargo esta vez, vamos a tener que agregar el usuario y el password que para nuestro caso ya fueron agregados a la base de datos del membershipProvider –> para agregar usuarios a esta base de datos lo mejor es crear una aplicación web y desde ahi levantar el sitio web de configuración del sitio, desde donde es muy simple agregar los usuarios.

using System;
using ClienteUP.ServicioCuentasBancarias;

namespace ClienteUP
{
class Program
{
static void Main()
{
using (var _proxy = new ServicioCuentasBancariasClient())
{
_proxy.ClientCredentials.UserName.UserName = "prueba";
_proxy.ClientCredentials.UserName.Password = "Pa$$word1";

var _resultado = _proxy.ObtenerSaldo("22222");
Console.WriteLine(_resultado);
}
}
}
}

El último paso es configurar el servicio del lado del cliente para que utilice el certificado para poder comunicarse de forma segura con el servicio. Primero configuramos el comportamiento en donde le decimos al servicio donde obtener el certificado.

      <behaviors>
<
endpointBehaviors>
<
behavior name="BehaviorNuevo">
<
clientCredentials>
<
clientCertificate findValue="CN=DRMCert"
storeLocation="LocalMachine"
storeName="My" />
<
serviceCertificate>
<
authentication revocationMode="NoCheck"/>
</
serviceCertificate>
</
clientCredentials>
</
behavior>
</
endpointBehaviors>
</
behaviors>

 


Ahora procedemos a agregar el behavior al endpoint del servicio:

        <client>
<
endpoint address="http://diego-pc/WCFCertificados/AutenticacionUP.ServicioCuentasBancarias.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServicioCuentasBancarias"
behaviorConfiguration="BehaviorNuevo"
contract="ServicioCuentasBancarias.IServicioCuentasBancarias"
name="WSHttpBinding_IServicioCuentasBancarias">
<
identity>
<
certificate encodedValue="AwAAAAEAAAAUAAAALKVZNNCYWPMn+f6f4SfBghH+PcIgAAAAAQAAAOwBAAAwggHoMIIBVaADAgECAhBZhs7Ez8SQt0Ud2V9N1dnOMAkGBSsOAwIdBQAwEjEQMA4GA1UEAxMHUm9vdERSTTAeFw0xMjA1MTYxNzQyMjBaFw0zOTEyMzEyMzU5NTlaMBIxEDAOBgNVBAMTB0RSTUNlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALG6+TrqsTKkBSNpfbpKHQGzdV8poX7+0fMf5/3jdrkFz1FnfZ7VmmMPIxdNuYJv63B2ScofpZEyvOfw61DHvjShORUSk3kw5NUW40hpVx4KUSneJjcvXklIHdODUfsCy7Werx30Q0CsgfydtCzJkKYLCuT3WVFxHeIqjNRFzIuzAgMBAAGjRzBFMEMGA1UdAQQ8MDqAEEPdF141cN5jkiYGrl1aJRChFDASMRAwDgYDVQQDEwdSb290RFJNghBrRb3C05OyokfF03CEBc6QMAkGBSsOAwIdBQADgYEAl+fRGhfd/gxgmtDLUFJ2UnAPII6lslW5hMeSs/VPXpCafoOzJSfBV3NPXMslTHKgRrBfuRwcf3ruID5Ttas5n1JPfvzn7TYqVDQ+vU2rOt0A19FAMMGJBW9Q934NxRVwPSR6Yklpunozb3EFg/YdVTcBbrr658wKN/O8hrGl+IM=" />
</
identity>
</
endpoint>
</
client>

El resultado al ejecutar el servicio es el siguiente:


image


Etiquetas de Technorati: ,

6.17.2012

Autenticando Servicios WCF – Certificados Digitales–Parte 2

En el post anterior empezamos creando el certificado digital e instalándolo de forma tal que pueda ser utilizado para autenticar un cliente a la hora de consumir un servicio utilizando WCF. Ahora vamos a proceder a crear un servicio que utilice este certificado como medio de autenticación.

Creando el Servicio WCF que Utiliza el Certificado Digital

Para iniciar vamos a crear un servicio WCF con la plantilla de proyecto “WCF Service Library”.

image

Ahora vamos a crear un contrato de servicio con una simple operación que suma dos número –> la complejidad del servicio no es relevante, incluso pudimos utilizar el servicio pre generado.

using System.ServiceModel;

namespace ServicioSeguroBlog
{
[ServiceContract(Namespace="http://www.formsevolution.com")]
public interface IServicioSeguro
{
[OperationContract]
int Sumar(int pX, int pY);
}
}


Y procedemos a implementar el servicio

namespace ServicioSeguroBlog
{
public class ServicioSeguro : IServicioSeguro
{
public int Sumar(int pX, int pY)
{
return pX + pY;
}
}
}

Ahora procedemos a configurar el servicio de forma tal que pueda utilizar el certificado para la autenticación. El primer paso es definir un “binding” para establecer como se va a manejar la seguridad en el endpoint, esta seguridad se define por tipo de protocolo a utilizar –> podemos tener múltiples configuraciones para cada binding ya que siempre los podemos identificar vía el nombre. Como se puede ver en el siguiente código, en este binding vamos a utilizar seguridad a nivel de mensaje y el tipo de credencial a utilizar será certificado.

<bindings>
<
wsHttpBinding>
<
binding name="wsHttpEndpointBinding">
<
security>
<
message clientCredentialType="Certificate" />
</
security>
</
binding>
</
wsHttpBinding>
</
bindings>

El siguiente paso es modificar el comportamiento estándar definido para el endpoint por parte de la plantilla de WCF para establecer como se van a manejar los certificados a la hora de autenticar. En primera instancia, al estar utilizando un certificado temporal tenemos que habilitar el revocationMode. Seguidamente configuramos el certificado a nivel de servicio para indicarle el nombre de mismo, su ubicación, y el nombre del almacén que lo contiene.

        <behavior>
<
serviceMetadata httpGetEnabled="True"/>
<
serviceDebug includeExceptionDetailInFaults="False" />
<
serviceCredentials>
<
clientCertificate
>
<
authentication revocationMode="NoCheck"
/>
</
clientCertificate
>
<
serviceCertificate findValue="CN=DRMCert" storeLocation="LocalMachine" storeName="My"
/>
</
serviceCredentials
>
</
behavior>

Por último procedemos a “ligar” el endpoint del servicio con los ítems configurados anteriormente.

      <service name="ServicioSeguroBlog.ServicioSeguro">
<
host>
<
baseAddresses>
<
add baseAddress = "http://localhost:8732/Design_Time_Addresses/ServicioSeguroBlog/Service1/" />
</
baseAddresses>
</
host>
<
endpoint address ="" bindingConfiguration="wsHttpEndpointBinding" binding="wsHttpBinding" contract="ServicioSeguroBlog.IServicioSeguro">
<
identity>
<
dns value="localhost"/>
</
identity>
</
endpoint>
<
endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</
service>

A nivel del comportamiento no es necesario agregarle nada ya que el servicio utiliza el que esta definido por defecto, por lo tanto solo tenemos que agregar el binding el cual hacemos a través de la etiqueta bindingConfiguration. Ahora procedemos a instalar el servicio en el IIS.


Antes de instalar el servicio podemos probar que este este funcionando correctamente con el host temporal de VS 2010 –> svcHost. Si el servicio carga esta bien configurado.


image


Sin embargo, si lo ejecutamos debe de fallar ya que el cliente de prueba auto configurado no tiene la información del certificado para autenticarse.


image


Para instalar el servicio, hacemos una aplicación web dentro del IIS


image


Seguidamente creamos un Application Pool que tenga un usuario que tenga permisos para acceder al certificado, en mi caso es usuario local –> Local System.


image


Luego procedemos a asignar ese pool a la nueva aplicación web.


image


El siguiente paso es instalar el servicio en la nueva aplicación creada en el IIS. Esto se hace seleccionado la opción de publicar el servicio.


image


El VS nos dirá si la instalación estuvo correcta o no.


image


Si habilitamos el directory browsing y vamos a la dirección del servicio vamos a ver el contenido del directorio.


image


si le damos click al archivo svc veremos la presentación del servicio y ahí podemos seleccionar ver el wsdl del servicio.


image




Configurar el Cliente


El último paso es configurar el cliente. Para esto vamos a crear una aplicación de consola que va a consumir el servicio. El primer paso es agregar la referencia al servicio con la dirección del WSDL.


image


Seguidamente procedemos a codificar la invocación a la operación.


 

using System;
using ClienteSeguro.ReferenciaServicio;

namespace ClienteSeguro
{
class Program
{
static void Main()
{
using (var _proxy = new ServicioSeguroClient())
{
var _resultado = _proxy.Sumar(3, 5);
Console.WriteLine(_resultado);
}
}
}
}

El siguiente paso es configurar el cliente para que pueda autenticarse con el certificado. Primeramente procedemos a agregar el comportamiento del lado del cliente para que el cliente sepa donde esta el certificado a utilizar. En este caso será igual del servicio porque estamos haciendo el ejercicio en la misma máquina, en situaciones reales hay que instalar el certificado en el cliente e indicar en la configuración en donde se encuentra este certificado.

  <system.serviceModel>
<
behaviors>
<
endpointBehaviors>
<
behavior name="BehaviorNuevo">
<
clientCredentials>
<
clientCertificate findValue="CN=DRMCert" storeLocation="LocalMachine" storeName="My" />
<
serviceCertificate>
<
authentication revocationMode="NoCheck"/>
</
serviceCertificate>
</
clientCredentials>
</
behavior>
</
endpointBehaviors>
</
behaviors>








Por último agregamos el comportamiento al endpoint del servicio.

      <endpoint address="http://diego-pc.cgccr.priv/WCFCertificados/ServicioSeguroBlog.ServicioSeguro.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServicioSeguro" behaviorConfiguration="BehaviorNuevo"
contract="ReferenciaServicio.IServicioSeguro" name="WSHttpBinding_IServicioSeguro">
<
identity>
<
certificate encodedValue="AwAAAAEAAAAUAAAALKVZNNCYWPMn+f6f4SfBghH+PcIgAAAAAQAAAOwBAAAwggHoMIIBVaADAgECAhBZhs7Ez8SQt0Ud2V9N1dnOMAkGBSsOAwIdBQAwEjEQMA4GA1UEAxMHUm9vdERSTTAeFw0xMjA1MTYxNzQyMjBaFw0zOTEyMzEyMzU5NTlaMBIxEDAOBgNVBAMTB0RSTUNlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALG6+TrqsTKkBSNpfbpKHQGzdV8poX7+0fMf5/3jdrkFz1FnfZ7VmmMPIxdNuYJv63B2ScofpZEyvOfw61DHvjShORUSk3kw5NUW40hpVx4KUSneJjcvXklIHdODUfsCy7Werx30Q0CsgfydtCzJkKYLCuT3WVFxHeIqjNRFzIuzAgMBAAGjRzBFMEMGA1UdAQQ8MDqAEEPdF141cN5jkiYGrl1aJRChFDASMRAwDgYDVQQDEwdSb290RFJNghBrRb3C05OyokfF03CEBc6QMAkGBSsOAwIdBQADgYEAl+fRGhfd/gxgmtDLUFJ2UnAPII6lslW5hMeSs/VPXpCafoOzJSfBV3NPXMslTHKgRrBfuRwcf3ruID5Ttas5n1JPfvzn7TYqVDQ+vU2rOt0A19FAMMGJBW9Q934NxRVwPSR6Yklpunozb3EFg/YdVTcBbrr658wKN/O8hrGl+IM=" />
</
identity>
</
endpoint>

Si ejecutamos el cliente anterior el resultado es el siguiente:


image


Etiquetas de Technorati: ,

5.25.2012

Autenticando Servicios WCF – Certificados Digitales–Parte 1

Crear e Instalar el Certificado

Cuando se crea un servicio que se debe autenticar utilizando certificados digitales para brindar seguridad a nivel de mensaje debemos crear un certificado temporal. Para esta tarea procederemos con la herramienta makecert.exe. Esta herramienta genera certificados del tipo x.509 para propósitos de prueba. En realidad esta herramienta crea una pareja de llaves –> una pública y otra privada – que servirán para las firmas digitales las cuales se van a almacenar en un archivo.

Para desarrollar un servicio que use certificados x.509 para brindar seguridad a nivel de mensaje –> la seguridad se puede aplicar a nivel de mensaje o a nivel de transporte dependiendo del protocolo utilizado –> los certificados tienen que tener un nivel de confianza los cuales tienen que tener un nivel de confianza especificado. Las opciones disponibles son:

  • Peer Trust: el certificado se valida de forma directa
  • Chain Trust: el certificado se valida contra el emisor del mensaje conocido como “root authority”.

En este tutorial vamos a utilizar Chain Trust. El primer paso es crear un certificado auto firmado que será la autoridad raíz; este certificado será almacenado en el almacén de autoridades raíz de certificación de confianza. En WCF se utilizará posteriormente para crear un certificado desde el certificado autofirmado raíz y que se instalará en el almacén de la máquina local.

Crear el Certificado Raíz

El primer paso para crear un certificado raíz que se va a utilizar para firmar los certificados que se van a intercambiar entre el servicio WCF y el cliente. Para esto utilizamos el “command prompt” de Visual Studio y procedemos con la siguiente instrucción:

image

En este caso el parámetro –n indica el nombre del CA, –r indica que el certificado va a ser autofirmado y por último –sv nos indica que el archivo contiene la llave privada del certificado.

Cuando ejecutamos este comando aparece la pantalla para crear el password de la llave privada.

image

Luego nos va a pedir el password de nuevo con el fin de poder acceder la llave privada del archivo pvk para generar el .cer que es el que contiene la llave pública.

image

Podemos verificar que los certificados están creados en el directorio donde nos ubicamos para crearlos utilizando el Windows Explorer

image

Instalar el certificado

Ahora procedemos a instalar el certificado en la locación “Trusted Root Certification Authorities” lo cual nos indica que todos los certificados firmados por esta autoridad serán de confianza tanto para el cliente como para el servidor. [ Este ejemplo corre en una sola máquina, si se desea tener un cliente en una máquina virtual o vía red, se debe instalar el certificado también en la máquina cliente.

Para levar a cabo esta tarea procedemos a correr la consola de administración utilizando el comando ejecutar – Windows + R – y procedemos a escribir mmc y le damos enter.

image

Tenemos que agregar el complemento – snap – para poder agregar el certificado, para esto seleccionamos archivo y agregar o quitar complemento…

image

Seguidamente agregamos el complemento de certificados tal y como se ve en la siguiente pantalla.

image

Cuando arranca el wizard, seleccionamos cuenta de equipo para que el certificado este disponible para todos los usuarios.

image

Seleccionamos el equipo local como administrador del complemento y luego finalizamos el wizard..

image

Y finalizamos el wizard. La pantalla del MMC debe verse ahora así:

image

Expandir el folder de Certificados y seleccionar el folder de Entidades de certificación raíz de confianza –> vaya traducción.

image

Ahí le damos botón derecho y procedemos a seleccionar la opción “todas las tareas/importar”.

image

El wizard inicia con la siguiente pantalla en la cual seleccionamos siguiente

image

Buscamos el archivo .cert que acabamos de generar y lo agregamos

image

En el siguiente paso aceptamos los valores por defecto.

image

En la última pantalla revisamos los valores del wizard y lo finalizamos

image

El certificado esta instalado en el almacén de certificados de confianza de la raíz. Para verlo procedemos a expandir el folder de certificados en la consola y los buscamos por el nombre.

image

Crear e instalar el certificado temporal para el uso del servicio WCF

Ahora procedemos a crear e instalar el certificado en la máquina del servidor. Para esto procedemos a movernos a la ubicación del  certificado raíz en la máquina del servidor.  Una vez en la ubicación procedemos con el siguiente comando desde el “prompt de Visual Studio”.

image

Este comando nos permite crear el certificado e instalarlo en el store My. El certificado se llama DRMCert.cer y esta creado a partir del certificado emitido en el paso anterior RootDRM. Al estar utilizando la misma máquina tanto para el servidor como para el cliente el mismo store y el mismo proceso nos sirve para interactuar con el certificado. Si estuviéramos trabajando con máquinas separadas, habría que copiar el certificado y aplicar el mismo comando del lado del cliente de prueba.

Si vamos a la consola consola de administración, el certificado recién creado deberá aparecer en el almacén de equipo local, dentro del folder certificados de los certificados personales.

image

En el siguiente post iniciaremos el trabajo con el servicio WCF y su respectivo cliente.

Etiquetas de Technorati: ,,

5.06.2012

Métricas en Visual Studio: Cobertura de las pruebas unitarias

En lo que respecta a las pruebas unitarias, siempre existirá el factor humano a la hora de garantizar la calidad estructural del software a partir de estas pruebas, y normalmente cuando se trata de enseñar el tema a los desarrolladores de software surgen las mismas preguntas:

  • ¿Cómo saber si las pruebas están bien hechas?
  • ¿Qué debo probar y que no debo probar?
  • ¿Cómo se cuanto código es verificado con nuestros unit test?

Esta y muchas otras preguntas pueden responderse de muchas formas; sin embargo, con la ayuda de las métricas de visual studio podemos obtener información para responder estas y muchas otras preguntas. En este post nos vamos a enfocar en como determinar la cantidad de código cubierto por nuestras pruebas unitarias utilizando Visual Studio 2010.

Proyecto Ejemplo

Nuestro proyecto será una simple aplicación de consola con dos clases con diferentes propósitos. Una que nos permitirá manipular colecciones de objetos y otra que nos permita manipular arreglos de enteros.

La clase que nos permite manipular colecciones de objetos es la siguiente:

public class AdministradorDeColecciones
{
public T PrimerElemento<T>(IEnumerable<T> pColeccion )
{
return pColeccion.FirstOrDefault();
}

public T UltimoElemento<T>(IEnumerable<T> pColeccion)
{
return pColeccion.LastOrDefault();
}

public IEnumerable<T> ObtenerDelTipo<T>( IEnumerable<T> pColeccion, Type pType)
{
return pColeccion.Where(p => p.GetType() == pType);
}

public IEnumerable<T> ObtenerTodosMenosDelTipo<T>( IEnumerable<T> pColeccion, Type pType )
{
return pColeccion.Where(p => p.GetType() != pType);
}
}

La clase que nos permite manipular arreglos de enteros es la siguiente:

public class AdministradorDeArreglosNumericos
{
public decimal ObtenerPromedio( int[] pArreglo)
{
return (pArreglo.Sum() / pArreglo.Count());
}

public int ObtenerElMayor( int[] pArreglo)
{
return
(from _i in pArreglo orderby _i descending select _i).FirstOrDefault();
}
}

Ahora procedemos a crear un proyecto para realizar nuestras pruebas unitarias a la clase anterior. Para esto creamos en la misma solución un proyecto de Test en WCF. La solución se ve ahora de la siguiente forma:


image


En la figura anterior se pueden ver dos cosas relevantes: 1. se agregó una referencia al proyecto donde están las clases a probar. 2. Se creó un archivo del tipo “unit test” básico. Ahora vamos a crear un test para probar el método ObtenerElMayor de la clase AdministradorDeArreglosNumericos.

[TestClass]
public class PruebasEjemploMetricas
{
[TestMethod]
public void ObtenerElMayorDeLaLista_RetornaTreinta()
{
int[] _lista = {11, 4, 8, 6, 30, 7};
var _administrador = new AdministradorDeArreglosNumericos();

int _resultado = _administrador.ObtenerElMayor(_lista);

Assert.AreEqual(30, _resultado, "Retorno del mayor de la lista incorrecto");
}
}

Esta prueba al ser ejecutada pasa sin ningún problema.


image


Ahora, queremos ver cuanto código esta cubierto por nuestras pruebas unitarias –> en este caso, un método con una prueba. Este dato es relevante sobre todo cuando la cantidad de código escrito es abundante y las pruebas unitarias aparentan tener todo cubierto.


Test Coverage en Visual Studio


En Visual Studio 2010 podemos calcular la cantidad de código que está cubierta por las pruebas unitarias cambiando la configuración en el archivo Local.testsettings.


image


Al darle doble click al archivo nos aparecerá un diálogo de configuración. En esta pantalla procedemos seleccionar “Data and Diagnostics” y marcamos la opción “Code Coverge” tal y como se muestra en la figura.


image


El siguiente paso es configurar el “Code Coverage” por lo que procedemos a dar click sobre el botón “configure” justo arriba de la lista de roles. Ahí nos aparecerá la siguiente pantalla.


image Aquí procedemos a seleccionar el assembly sobre el cual queremos aplicar la métrica. Ahora procedemos a ejecutar la prueba unitaria de nuevo y seleccionamos la opción de ver los resultados de la cobertura de las pruebas.


image


En esta pantalla si expandimos los resultados podemos ver el código cubierto por nuestra prueba unitaria. Como podemos ver en los resultados todos los métodos tienen 0% de cobertura excepto el método ObtenerElMayor.


image



Por último, en Visual Studio todos los métodos que no estén cubiertos por las pruebas unitarias estarán marcados por un fondo rojo, y los que si estén cubiertos por al menos una prueba unitaria estarán con el fondo celeste. Esto se puede ver en la siguiente figura.


image


Igualmente, la clase AdministradorDeColecciones al no tener una prueba unitaria tendrá todos sus métodos marcados con fondo rojo.


image



Etiquetas de Technorati: ,,