Invocando Servicios Web de Forma Segura con Certificados x.509

Este post tiene que ver con la forma como se invocan servicios Web usando certificados X.509.  En especial visto como una guía muy básica de resolución de problemas al momento de configurar los clientes.  (Que como ya debe saberse pueden ser aplicaciones de escritorio o Aplicaciones Web).

Antecedentes.


La seguridad es un elemento clave en la construcción de servicios web, especialmente cuando estos servicios web se exponen en internet.

Para poder construir servicios web seguros se pueden utilizar diversos métodos de autenticación y certificación de identidad, algunos de ellos incluyen:

· Tokens de Seguridad Personalizados

· Tokens de Seguridad del Contexto

· Tiquetes de Kerberos

· Usuario y Contraseña

· y Certificados X.509, que son los que nos interesan hoy.

Un certificado X.509 es básicamente una llave de encripción emitida y certificada por una entidad certificadora valida, sin entrar mucho en definiciones que se pueden encontrar mas en detalle en Internet, el certificado es un archivo que me emite una entidad reconocida, y que básicamente es un numero único que me han dado para yo entregar a mis clientes y saber que son ellos los que esta llamando mi servicio.

Escenario.


Un cliente me pide invocar un servicio web seguro desde mi propia aplicación web, (por ejemplo para mostrar los valores de un combobox), este cliente me provee un certificado X.509 y me informa la política de encripción, autenticación para este servicio. 

Solución.


1. Debo instalar el certificado Digital en la Maquina de desarrollo, en el ambiente de pruebas y en el servidor de Producción, es posible que el cliente me provea con dos direcciones web, una para prueba, otra para desarrollo, eso es independiente del certificado.

2. La instalación del certificado puede realizarse de diversas maneras, una muy fácil es copiar el certificado en una ruta de la maquina donde desea instalarse, luego hacer clic derecho del mouse e seguir el asistente

clip_image001

La siguiente pregunta del asistente es si desea ubicar el certificado en un almacén determinado o si desea que el asistente lo instale basado en la información del certificado, esta es una de esas típicas preguntas que no se sabe bien que contestar o que significa. El repositorio de certificados esta divido por niveles.

El primer nivel indica si se quiere almacenar el certificado en la maquina local, en el perfil del usuario o en la cuenta del servicio con la que corre el OS.

luego viene un segundo nivel que incluye personal, autoridades, entidades certificadoras, directorio activo, entre varias otras, así que lo primero es saber donde colocar el certificado, una buena guía es esta que muestra las ubicaciones por default que se utilizan para buscar los certificados digitales, así, si la aplicación es un web service o una aplicación de escritorio que intenta firmar o encriptar el mensaje va a buscar en el User Personal Store.

clip_image002

3. Ahora que tengo el servidor instalado debo configurar el webconfig y la política que quiero seguir para este certificado. (hay muchas formas de hacerlo, algunos no usan el web config, sino que crean la política en ejecución, etc. esta es solo una forma de abordar el problema).  En e web config va algo como esto:

<!– WSE 2.0 –>
    <section name=”microsoft.web.services2″ type=”Microsoft.Web.Services2.Configuration.WebServicesConfiguration, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />

En la parte de configuración – </configSections> (ojo, esto en  VS2003, en VS2005 puede variar)

y claro, la sección donde en realidad hago la configuración (en web config)

<microsoft.web.services2>
    <diagnostics>
      <detailedErrors enabled=”true” />
      <trace enabled=”true” />
      <policyTrace enabled=”true”
       input=”receivePolicy.webinfo”
       output=”sendPolicy.webinfo”/>
    </diagnostics>
    <tokenIssuer>
      <autoIssueSecurityContextToken enabled=”true” />
    </tokenIssuer>
    <policy>
      <cache name=”policyCache.config” />
    </policy>
    <security>
      <x509 storeLocation=”LocalMachine” verifyTrust=”false” allowTestRoot=”false” allowRevocationUrlRetrieval=”true” allowUrlRetrieval=”false” />
    </security>
  </microsoft.web.services2>

esta es la versión de desarrollo o de pruebas, como puede ver esta habilitado el trace de la política <policyTrace enabled=”true”… y se esta generando archivos con información de las peticiones y las respuestas (input=”receivePolicy.webinfo” output=”sendPolicy.webinfo”). Para que estos archivos se puedan crear, son súper útiles, debe habilitarse la cuenta con la que esta corriendo la aplicación (ASP.NET generalmente) para que escriba en el directorio donde se esta ejecutando.

Lo otro importante de este segmento es el nombre de la política, en este caso policyCache.config. lo que se esta diciendo aquí es que en ese archivo config estará la definición completa de la política, pueden haber tantas políticas como se quiera. y claro, la seguridad usando X.509 y diciendo en que almacén esta el certificado (storeLocation),

Ahora el archivo de la política es como esto:

<?xml version=”1.0″ encoding=”utf-8″?>
<policyDocument xmlns=”http://schemas.microsoft.com/wse/2003/06/Policy”>
  <mappings xmlns:wse=”http://schemas.microsoft.com/wse/2003/06/Policy”>
    <!–The following policy describes the policy requirements for the service: http://algo.asmx .–>
    <endpoint uri=”algo.asmx”>
      <defaultOperation>
        <request policy=”” />
        <response policy=”” />
        <fault policy=”” />
      </defaultOperation>
    </endpoint>
    <endpoint uri=http://algo.asmx>
      <defaultOperation>
        <request policy=”#Encrypt-X.509″ />
        <response policy=”” />
        <fault policy=”” />
      </defaultOperation>
    </endpoint>
    <endpoint uri=http://algo.asmx>
      <defaultOperation>
        <request policy=”#Encrypt-X.509″ />
        <fault policy=”” />
      </defaultOperation>
    </endpoint>
  </mappings>
  <policies xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd” xmlns:wsp=”http://schemas.xmlsoap.org/ws/2002/12/policy” xmlns:wssp=”http://schemas.xmlsoap.org/ws/2002/12/secext” xmlns:wse=”http://schemas.microsoft.com/wse/2003/06/Policy” xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd” xmlns:wsa=”http://schemas.xmlsoap.org/ws/2004/03/addressing”>
    <wsp:Policy wsu:Id=”Encrypt-X.509″>
        <!–The Confidentiality assertion is used to ensure that the SOAP Body is encrypted.–>
        <wssp:Confidentiality wsp:Usage=”wsp:Required”>
            <wssp:KeyInfo>
                <!–The SecurityToken element within the KeyInfo element describes which token type must be used for Encryption.–>
          <wssp:SecurityToken>
            <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wssp:TokenType>
            <wssp:TokenIssuer>C=US, O=”VeriSign, Inc.”, OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/rpa (c)05, CN=VeriSign Class 3 Secure Server CA</wssp:TokenIssuer>
            <wssp:Claims>
              <!–By specifying the SubjectName claim, the policy system can look for a certificate with this subject name in the certificate store indicated in the application’s configuration, such as LocalMachine or CurrentUser. The WSE X.509 Certificate Tool is useful for finding the correct values for this field.–>             <wssp:SubjectName MatchType=”wssp:Exact”>C=US, S=Wisconsin, L=Milwaukee, O=CLIENTE Company, OU=IS Technical Services, CN=www.cliente.com</wssp:SubjectName>
              <wssp:X509Extension OID=”2.7.34.87” MatchType=”wssp:Exact”>0GJdsds3UdP3fsdtretterERFE4=</wssp:X509Extension>
            </wssp:Claims>
          </wssp:SecurityToken>
            </wssp:KeyInfo>
            <wssp:MessageParts Dialect=”http://schemas.xmlsoap.org/2002/12/wsse#part”>wsp:Body()</wssp:MessageParts>
        </wssp:Confidentiality>
    </wsp:Policy>
  </policies>
</policyDocument>

Donde he puesto en negrilla los valores que son claves, vienen del certificado y se pueden ubicar usando alguna de las herramientas enumeradas mas adelante.

Ya podía verse desde aquí la introducción a los conceptos como endpoint que luego serian aun mas completos en WCF pero eso es otra historia.

Herramientas.


Utilidad para ver información de los certificados (con código fuente)

Configurar una consola para gestionar los certificados digitales.

La herramienta de gestión de información de los certificados incluida con WSE*

Referencia


Como Firmar un Mensage usando un certificado X.509

Espero que esto le ahorre un par de horas, en resumen, el certificado se instala en una de las ubicaciones de búsqueda por defecto o toca cambiar la configuración en los archivos de config.  Luego se modifica el archivo webconfig y los archivos de políticas con la información que se saca del certificado usando una de las herramientas enumeradas, para poder revisar errores, se habilitan los servicios de trace.

Juan Peláez

Arquitecto de Software

Visite: www.juanpelaez.com  

keywords:  Web Services, WSE, certificados X.509, encriptar, firmar, servicios web, herramientas para configurar certificados digitales, políticas de configuración, certificados digitales. seguridad en servicios web, servicios seguros, identificación de clientes, identidad de clientes.

Un comentario en “Invocando Servicios Web de Forma Segura con Certificados x.509”

  1. Hola como andas, te estoy escribiendo porque tengo una aplicacion .net que consume un web service y debo utilizar x.509.
    cuando lo instalo en el servidor web que es un w2003 standard edition sp2, con en .net 2.0 instalado, sobre IIS 6.0 y tengo instalado WSE 3.0
    Cuando invoco un procedimiento de test, me tira este mensaje que realmente no se como decifrar.
    gracias y saludos.
    aca va el mensaje que me tira.

    System.Security.Cryptography.CryptographicException: Object contains only the public half of a key pair. A private key must also be provided.
    at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, String str)
    at Microsoft.Web.Services3.Security.Cryptography.RSASHA1SignatureFormatter.SignHash(Byte[] rgbHash)
    at Microsoft.Web.Services3.Security.Cryptography.RSASHA1SignatureFormatter.Sign(Stream data)
    at Microsoft.Web.Services3.Security.MessageSignature.BuildSignedInfo(SignatureFormatter formatter)
    at Microsoft.Web.Services3.Security.MessageSignature.ComputeAsymmetricSignature(AsymmetricKeyAlgorithm key)
    at Microsoft.Web.Services3.Security.MessageSignature.ComputeSignature()
    at Microsoft.Web.Services3.Security.Security.SerializeXml(SoapEnvelope document)
    at Microsoft.Web.Services3.Security.Security.Execute(SoapEnvelope envelope)
    at Microsoft.Web.Services3.Security.SendSecurityFilter.ProcessMessage(SoapEnvelope envelope)
    at Microsoft.Web.Services3.Pipeline.ProcessOutputMessage(SoapEnvelope envelope)
    at Microsoft.Web.Services3.Xml.SoapEnvelopeWriter.Finish()
    at Microsoft.Web.Services3.Xml.XmlWrappingWriter.Flush()
    at System.Web.Services.Protocols.SoapHttpClientProtocol.Serialize(SoapClientMessage message)
    at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
    at DGR.SecureDgrWs.ETimbreBrokerWse.echo(echo echo1) in C:Documents and SettingsAdministratorMy DocumentsVisual Studio 2005ProjectsDGRDGRWeb ReferencesSecureDgrWsReference.cs:line 136
    at DGR.GxServices.testConnection(String message) in C:Documents and SettingsAdministratorMy DocumentsVisual Studio 2005ProjectsDGRDGRGxServices.asmx.cs:line 46

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *