viernes, 28 de febrero de 2014

ORA-29273 HTTP request failed al consumir un Web Service desde un paquete de la base de datos



Hoy en día hay una gran cantidad de procesos que requieren como materia prima, datos que provienen de un servicio externo. Por ejemplo, una institución bancaria provee a través de un "WebServices" o "Servicio Web" el tipo de cambio de referencia para monedas extranjeras, que podría ser utilizado para calcular el monto en la moneda local de una compra en el extranjero ó para un registro contable multimoneda, etc.

Son muchas las fuentes de datos que pueden ser consumidos a lo interno de nuestro sistemas con origen externo.

Cuando estamos trabajando en la programación con un servicio web que va a traer un dato desde un sitio web, por lo general se trabaja en una infraestructura local, utilizando protocolo HTTP. Pero cuando se ejecuta contra el sitio oficial, es posible que el proveedor del servicio, utilice el protocolo seguro HTTPS para su página.

En caso de que sea así, es probable que obtengas el siguiente resultado.

SQL> connect pruebas/oracle
Connected.
SQL> select utl_http.request('https://www.sitioxxx.com') from dual;
select utl_http.request('https://www.sitioxxx.com') from dual
*
ERROR at line 1:
ORA-29273: HTTP request failed
ORA-06512: at "SYS.UTL_HTTP", line 1722
ORA-29024: Certificate validation failure
ORA-06512: at line 1

Este problema se debe a un problema con la validación del certificado de autentificación del sitio, como lo expresa la línea con el error ORA-29024.

Qué se debe hacer ?

Hay un documento claro de Tim Hall en oracle-base.com que explica como hacerlo, sin embargo, vamos a replicarlo acá.

1. Obtener el certificado del sitio

Este paso es realmente sencillo y si estas usando Chrome nada más debes seguir los siguientes pasos.

Utilizando tu navegador coloca el URL que se desea accesar desde el bloque PL/SQL de programación.

En este caso de ejemplo, la dirección es "https://gb.redhat.com/". Haga Click en el icono del URL en la barra de despliegue  y haga click en la opción de menu de "Conexión"



Click sobre el tab de "Certificate information" y nuevamente haga click en el "Certification Path"



Ahora en la pantalla que te aparece accesa el tab de  "Details" y presiona "Copy to File..." y proceda a guardar localmente en tu máquina el archivo con algún nombre como "certificado.cert".



Al dar click sobre el botón de "OK", te va a aparecer un asistente, sigue los siguientes pasos:
  • Click en la opción de "Next" en la pantalla de bienvenida.
  • Seleccione la opción de "Base-64 encoded X.509 (.CER)" y dale click al botón de "Next".
  • Ingresa el nombre del archivo y da click al botón de "Next".
  • Finalmente haz click sobre el botón de finalizar "Finish".
Para  Firefox debes hacer click en el "URL Icon > More Information > View Certificate > Details Tab".

2. Paso, configuración del contenedor de certificados del Wallet de Oracle

Primer punto, es necesario crear una carpeta dentro del alcance del usuario "Oracle". Para no hacer mucho desorden, vamos a utilizar como origen el directorio casa del software de la base de datos, que debería estar seteado a la variable $ORACLE_HOME.

login as: oracle
oracle@10.10.3.4's password:
Last login: Sun Feb 23 19:49:51 2014 from 100.100.100.1
[oracle@oracle ~]$ echo $ORACLE_HOME
/opt/oracle/111
[oracle@oracle ~]$ cd $ORACLE_BASE
[oracle@oracle oracle]$ pwd
/var/lib/oracle
[oracle@oracle oracle]$ ls -la
total 96
drwxr-xr-x 11 oracle dba  4096 Aug 24  2012 .
drwxr-xr-x 26 root   root 4096 Jun  7  2012 ..
drwxr-x---  6 oracle dba  4096 Jun  3  2013 admin
-rwxr-xr-x  1 oracle dba   699 Aug 24  2012 backup
drwxr-xr-x  5 oracle dba  4096 Jul  2  2012 cfgtoollogs
drwxr-xr-x  2 oracle dba  4096 Jun  7  2012 checkpoints
drwxrwxr-x  4 oracle dba  4096 Jun  7  2012 diag
drwxr-x---  4 oracle dba  4096 Dec  4  2012 flash_recovery_area
drwxr-x---  5 oracle dba  4096 Mar 29  2013 oradata
drwxr-xr-x  3 oracle dba  4096 Jun  7  2012 oradiag_oracle
drwxr-x---  5 oracle dba  4096 Aug 24  2012 recovery_area
drwxr-xr-x  2 oracle dba  4096 Oct 17 20:00 Respaldo

Vamos a crear un directorio con el nombre de "certificado" y dentro de él otro con el nombre de "wallet"

[oracle@oracle oracle]$ mkdir certificado
[oracle@oracle oracle]$ cd certificado

[oracle@oracle certificado]$ pwd
/var/lib/oracle/certificado

Esta ruta es importante que la tengas bien claro, ya que es requerida más adelante.

[oracle@oracle certificado]$ mkdir wallet
[oracle@oracle certificado]$ cd wallet

Ahora utilizando un utilitario sftp o ftp traslada el archivo que generamos con el certificado a esta ruta.
[oracle@oracle wallet]$ ls -la
total 12
drwxr-xr-x 2 oracle dba 4096 Feb 27 22:20 .
drwxr-xr-x 3 oracle dba 4096 Feb 27 22:20 ..
-rw-r--r-- 1 oracle dba 1760 Feb 27 22:09 certificado.cer

Ahora vamos a crear el nuevo wallet:

[oracle@oracle wallet]$ orapki wallet create -wallet /var/lib/oracle/certificado/wallet/ -pwd Pruebapasswd1234 -auto_login
Oracle PKI Tool : Version 11.2.0.1.0 - Production
Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.

[oracle@oracle wallet]$ pwd
/var/lib/oracle/certificado/wallet

Ahora puedes verificar la existencia de dos nuevos archivos, correspondientes al repositorio del wallet

[oracle@oracle wallet]$ ls -la
total 20
drwxr-xr-x 2 oracle dba 4096 Feb 27 22:21 .
drwxr-xr-x 3 oracle dba 4096 Feb 27 22:20 ..
-rw-r--r-- 1 oracle dba 1760 Feb 27 22:09 certificado.cer
-rw------- 1 oracle dba 3589 Feb 27 22:21 cwallet.sso
-rw------- 1 oracle dba 3512 Feb 27 22:21 ewallet.p12

Ahora vamos a agregar el certificado creado al nuevo repositorio.

[oracle@oracle wallet]$ orapki wallet add -wallet /var/lib/oracle/certificado/wallet -trusted_cert -cert "/var/lib/oracle/certificado/wallet/certificado.cer" -pwd Pruebapasswd1234
Oracle PKI Tool : Version 11.2.0.1.0 - Production
Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.


Con esto ya podríamos conectarnos a la base de datos y probar que podamos obtener alguna información de la dirección en donde se encuentra el servicio que deseamos consumir. Observen que es necesario antes de ejecutar el paquete utl_http, abrir el archivo de certificado del wallet. Si lo incluyes en un procedimiento almacenado en la base de datos, debes incluir la línea sin el "exec".

[oracle@oracle wallet]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.1.0 Production on Thu Feb 27 22:57:19 2014
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Release 11.2.0.1.0 - 64bit Production

SQL> set serveroutput on
SQL> exec utl_http.set_wallet('file:/var/lib/oracle/certificado/wallet', 'Pruebapasswd1234');

PL/SQL procedure successfully completed.


SQL> select utl_http.request('https://www.sitioxxx.com') from dual;

UTL_HTTP.REQUEST('HTTPS://WWW.DOCUMENTAGFACE.COM')
--------------------------------------------------------------------------------

g/TR/xhtml1/DTD/xhtml1-transitional.dtd">
...

Si vas a ejecutar el procedimiento con un usuario específico, debes brindar privilegios de ejecución sobre el paquete antes de ejecutar el procedimiento, sino podrías recibir el siguiente mensaje:

SQL> connect yrojas/2013tecno
Connected.
SQL> exec utl_http.set_wallet('file:/var/lib/oracle/certificado/wallet', 'Pruebapasswd1234');
BEGIN utl_http.set_wallet('file:/var/lib/oracle/certificado/wallet', 'Gynopasswd1234'); END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'UTL_HTTP' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

SQL> grant execute on utl_http to

Con este procedimiento, habrás logrado burlar el ORA-29273 explicado en esta nota.