Configuración de SSSD: nested groups

En el post anterior se describía la sustitución natural de libnss_ldap en RHEL6 que conocíamos hasta RHEL5. El inconveniente que presenta es que ahora ya no incluye soporte para nested_groups (grupos dentro de grupos) tal y como se recoge en el README del paquete: /usr/share/doc/nss-pam-ldapd-0.7.5/README

Para conseguir que nuestro sistema soporte los grupos dentro de grupos que hay en el directorio OpenLDAP, tendremos que configurar la segunda alternativa que incluye nuestro sistema RHEL6. Se trata de SSSD: System Security Services Daemon (SSSD). Este es un nuevo servicio que aparece en Fedora 11, y pretende ofrecer una interfaz para NSS y PAM, única desde la que administrar el acceso remoto a directorios LDAP y múltiples mecanismos de autenticación desde un único punto. Este servicio es un elemento fundamental en FreeIPA (el proyecto de identity-manager de RedHat, basado en su LDAP, no en OpenLDAP).

La idea es la misma que la anterior: Disponer un servicio independiente de nss que se encargue de las búsquedas en LDAP, Kerberos, etc, y que si se detiene el sistema no se ralentice. Para configurar este nuevo servicio de forma que busque los usuarios y grupos en nuestro OpenLDAP editaremos el fichero /etc/sssd/sssd.conf y configuraremos la sección [domain/LDAP] para que tenga el siguiente contenido:

[domain/LDAP]

id_provider = ldap
auth_provider = ldap
ldap_schema = rfc2307bis
ldap_uri = ldap://LDAPSERVER.tecnoquia.com

ldap_user_search_base = o=tecnoquia,c=es
ldap_group_search_base = ou=grupos,o=tecnoquia,c=es
ldap_default_bind_dn = cn=nss,o=tecnoquia,c=es
ldap_default_authtok_type = password
ldap_default_authtok = super-secreto

ldap_group_member = uniqueMember
cache_credentials = true
enumerate = true
Lo importante para el soporte de nested_groups es la declaración de ldap_schema=rfc2307bis. Además, debemos descomentar la línea:
domains = LOCAL,LDAP
y también la definición del dominio [domain/LOCAL], para quede como:
[domain/LOCAL]
description = LOCAL Users domain
id_provider = local

enumerate = true
min_id = 500
max_id = 999
Luego editar el fichero /etc/nsswitch.conf para cambiar la configuración de donde debemos buscar los usuarios y grupos:
passwd:  files [NOTFOUND=continue] sss
shadow: files
group: files [NOTFOUND=continue] sss
Para aplicar estos cambios, tendremos que iniciar el demonio sssd:
/etc/init.d/sssd start
chkconfig sssd on
y luego si, podremos ejecutar los comandos:
  • getent passwd, que nos mostrará un listado de todos los usuarios locales y en LDAP
  • getent group, nos mostrará un listado de las cuentas de grupo locales y en el directorio, expandiendo correctamente los usuarios de grupos que contenidos en otros grupos.
  • id <LOGIN> nos mostrará información del usuario, que puede estar almacenada en LDAP

La foto la he sacado del album de challiyan en flickr

Configuración de NSS para la integración con LDAP en RHLE6

NSS (Name Service Switch) es el componente de nuestro sistema Linux encargado de listar todos los usuarios, grupos, hosts, etc de nuestro sistema. Cómo consultar esta información se configura en el fichero /etc/nsswitch.conf y en él, normalmente encontramos las líneas:

passwd:         files
group: files
shadow: files
Estas líneas configuran que busque los grupos (groups), cuentas de usuario (passwd) y contraseñas del sistema (shadow) en ficheros, los archi conocidos/etc/group, /etc/passwd y /etc/shadow. Cuando queremos configurar que nuestro sistema Linux busque las cuentas de usuario en un directorio LDAP, instalaremos las librerías ldapnss, y configuraremos apropiadamente los ficheros /etc/ldap.conf y /etc/nsswitch.conf.

En RHEL6 esta configuración ha cambiado con respecto a como la conocíamos en los sistemas RedHat hasta ahora. En esta versión, se usa un demonio independiente llamado nslcd. La configuración de este servicio se almacena en /etc/nslcd.conf y sustituye al antiguo /etc/ldap.conf. La configuración del servicio está documentada en las notas de RedHat: La mayor ventaja que podemos obtener de ello, es que si se para este servicio, el sistema no tratará de buscar usuarios en LDAP, y esto es una ventaja ante situaciones de parada o error, ya que el sistema no tiene que esperar a que expiren los timeouts de conexión al directorio, ni tener que editar el fichero /etc/nsswitch.conf para salvar este comportamiento.

Para configurar la búsqueda de usuarios y grupos en LDAP en nuestro sistema RHEL6 editaremos el fichero /etc/nslcd.conf y aplicaremos los siguientes cambios:
  1. Configurar la URI del servidor LDAP al que se conectará:
    uri ldap://LDAPSERVER.tecnoquia.com/
  2. Configurar la versión del protocolo que usaremos,
    ldap_version 3
  3. Configurar las credenciales del usuario LDAP que se usará para conectar al directorio, en las búsquedas de usuarios y grupos
    binddn cn=nss,o=tecnoquia,c=es
    bindpw super-secreto
  4. Definir que las búsquedas sean en profundidad
    scope sub
  5. Especificar que siempre deben recorrerse los alias
    deref always
  6. Indicar las ramas y filtros para localizar las cuentas de usuario y grupo en el directorio,
    base    group   ou=grupos,o=tecnoquia,c=es
    base passwd o=tecnoquia,c=es
    filter passwd (objectClass=posixAccount)

    scope passwd sub
    scope group sub
  7. Establecer los parámetros de timeout para la conexión/desconexión del servicio de directorio,
    bind_timelimit 2
    timelimit 4
    idle_timelimit 10
    reconnect_retrytime 2
  8. Indicar que no se usará SSL para conectar al directorio,
    ssl no
    tls_cacertdir /etc/openldap/cacerts
  9. y que NSS no busque los usuarios locales (que hay en /etc/passwd)
    nss_initgroups_ignoreusers  ALLLOCAL
Como se puede comprobar existe una diferencia con respecto a versiones anteriores: Tenemos que configurar como rama base para la búsqueda de cuentas de usuario la raíz del árbol, para que la búsqueda en profundidad incluya la rama de usuarios y cuentas de máquina y luego añadir un filtro. Esto anteriormente no era necesario porque se podían especificar varias ramas, pero en esta nueva versión ya no es posible y si las especificamos, sólo tomará la última que aparezca en el fichero. La verdad es que es un paso atrás.

Luego editar el fichero /etc/nsswitch.conf para cambiar la configuración de donde debemos buscar los usuarios y grupos:
passwd: files [NOTFOUND=continue] ldap
shadow: files
group: files [NOTFOUND=continue] ldap
Para aplicar estos cambios, tendremos que iniciar el demonio nslcd:
/etc/init.d/nslcd start
...y luego sí podremos ejecutar los comandos:
  • getent passwd, que nos mostrará un listado de todos los usuarios y máquinas locales y en LDAP
  • getent group, nos mostrará un listado de las cuentas de grupo locales y en el directorio,
  • id <LOGIN> nos mostrará información del usuario, que puede estar almacenada en LDAP

DBLinks desde MySQL hacia Oracle

En el anterior post veíamos cómo conectar Oracle hacia MySQL, aunque el procedimiento nos puede servir para conectar Oracle a cualquier base de datos (sqllite, Postgres, SQLServer, etc) a través de su correspondiente driver ODBC usando hg4odbc.

No siempre puede que Oracle sea el centro del universo del origen de la información de nuestra organización, y es posible que nuestra organización se encuentre usando Oracle de forma residual, sólo por tranquilizar y sosegar algunos de nuestros desarrolladores y administradores que añoran tiempos pasados creidos que fueron mejores, pero en realidad tengamos toda la lógica de nuestro negocio en MySQL: Puestos a suponer, echémosle imaginación.

En este escenario nos surgirá la pregunta: ¿cómo podemos vincular MySQL hacia otras bases de datos? ¿Existen DBLinks o algo parecido en MySQL?. La respuesta hasta el momento, es corta: MySQL sólo permite vincular tablas entre diferentes base de datos mediante el uso de Tablas Federadas, y esta funcionalidad sólo está disponible a partir de la versión 5.1 y para conectar a otras bases de datos MySQL exclusivamente. Para saber si nuestro servidor soporta tablas federadas, tendremos que conectarnos y ejecutar show plugin:

mysql> show plugin;
+------------+--------+----------------+---------+---------+
| Name | Status | Type | Library | License |
+------------+--------+----------------+---------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| FEDERATED | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
+------------+--------+----------------+---------+---------+

Si no está activo este almacenamiento, tendremos que editar el fichero de configuración de nuestro servidor /etc/mysql/my.cnf y habilitar el soporte para tablas federadas en la sección [mysqld]. Cuando hayamos guardado los cambios, tendremos que reiniciar el servidor MySQL y volver a comprobar con show plugin.
[mysqld]
federated = ON

Como he escrito, el inconveniente a mi jucio de este soporte para tablas federadas es que sólo permite URLs que apuntan a bases de datos en MySQL, con formato:
CONNECTION='mysql://username:password@hostname:port/database/tablename'
CONNECTION='mysql://username@hostname/database/tablename'
CONNECTION='mysql://username:password@hostname/database/tablename'


Patrick Galbraith allá por el año 2008 desarrolló un plugin para MySQL que soportaba tablas federadas vía ODBC, pero parece que el desarrollo se quedó en su primera versión ALPHA, y ha quedado desmantenido. Yo no lo he probado, pero el propio Patrick demuestra que puede conectar a PostGres vía ODBC.
Cambiando de estrategia, Giuseppe Maxia escribió un interesante artículo titulado MySQL as universal server, donde se basaba en el módulo PERL DBIx::MyServer. Este módulo implementa un servidor y cliente MySQL, a modo de proxy, que usa la interfaz de clases DBI (DataBase Interface) de PERL para conectar a bases de datos remotas MYSQL. En el artículo Giuseppe Maxia, nos cuenta cómo aprovechar este módulo para conectar de forma remota a PostGres y SqlLite vía DBI. La idea es sencilla: Se implementa un pequeño demonio en PERL que use DBIx::MyServer y ofrezca un puerto de escucha para el protocolo MySQL, al que vincularemos nuestras tablas federadas, y luego internamente, este demonio reenviará las consultas y comandos a una base de datos remota usando su interfaz DBI.


El artículo es muy esclarecedor, pero tiene el problema que los scripts en los que se apoya no están accesibles y no podremos examinar cómo construía ese demonio que usaba DBIx::MyServer, para saber cuánto de bien funcionaba, así que... dependeremos de nuestras habilidades en PERL :P para conectarnos a Oracle.
Si retocar PERL no nos supone un problema, podemos atrevernos: El primer paso será, desde nuestro servidor MySQL en Ubuntu (por ejemplo) instalar el soporte DBI para PERL, ejecutando:
apt-get -y install libdbd-mysql libdbi-dev libdbi-perl libdbi1 \
libclass-dbi-perl libdbd-anydata-perl \
libdbix-simple-perl cpan

Además, debemos haber instalado correctamente los paquetes basic, sqlplus y sdk(devel) de Oracle Instant Client en nuestro servidor MySQL, para poder conectar a Oracle, y haber definido las siguientes variables de entorno en el fichero /etc/profile:
export ORACLE_HOME=/usr/lib/oracle/11.2/client32
export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
export TNS_ADMIN=$ORACLE_HOME/network/admin

Obviamente, adaptaremos las rutas según nuestra instalación, y tendremos correctamente configurado nuestro fichero $TNS_ADMIN/tnsnames.ora, para conectar a los servidores Oracle que nos interese. Para ilustrar el ejemplo, conectaremos a la base de datos CASA, con el mallogrado usuario scott: Comprobar que podemos conectar desde el servidor MySQL...
sqlplus scott/tiger@CASA

Una vez que la conectividad hacia Oracle no es un problema desde nuestro servidor MySQL, procederemos a instalar DBIx::MyServer desde el repositorio CPAN:
cpan install DBIx::MyServer

...y después el soporte DBD para Oracle, también vía CPAN:
cpan install DBD::Oracle

Una vez instalado, extraeremos el servidor de prueba que viene con DBIx::MyServer ejecutando:
mkdir test
cd test
find ~/.cpan -name "myserver.*" -exec cp {} . \;

Esto nos copiará al menos dos ficheros:
  • myserver.pl, que implementa el servidor/cliente MySQL vía DBI y permite la traducción de sentencias SQL a través de un pequeño fichero de configuración. Esto es necesario porque el protocolo MySQL permite sentencias como SHOW TABLES o SHOW DATABASES, que en otros servidores de base de datos no tienen traducción, y de esta forma, podemos traducirlos en otras sentencias que no provoquen fallos internos.
  • myserver.conf, es el fichero de configuración que contiene expresiones PERL para realizar la traducción de sentencias SQL ON-THE-FLY, antes de enviarlas al servidor remoto vía DBI.

Podemos lanzar una primera prueba, para comprobar que tenemos todo bien. Para ello, lanzaremos la ejecución del demonio mediante:
cd test
perl myserver.pl --port=1234 \
--dsn="dbi:Oracle:CASA" \
--dsn_user="scott" --dsn_password="tiger" \
--conf=myserver.conf --debug

Este comando lanza el demonio Perl para que escuche conexiones MySQL por el puerto 1234, y las redirija hacia la conexión Oracle scott/tiger@CASA, además de indicarle que debe usar para traducir SQL el fichero myserver.conf y queremos debug. El que el demonio arranque con el sistema lo dejo al lector. Ahora, para probar la conexión usaremos nuestro cliente MySQL de toda la vida:
mysql -h 127.0.0.1 -P1234 -umyuser --password=myuser

Con este comando lanzamos una conexión MySQL al servidor local por el puerto 1234, con el usuario myuser y contraseña myuser: Este servidor MySQL, es el demonio en PERL que acabamos de lanzar. Una vez en la consola del cliente MySQL, podemos ejecutar el comando ORACLE para consultar las tablas:
mysql> select * from cat;
+------------+------------+
| TABLE_NAME | TABLE_TYPE |
+------------+------------+
| BONUS | TABLE |
| DEPT | TABLE |
| EMP | TABLE |
| SALGRADE | TABLE |
+------------+------------+
4 rows in set (0.13 sec)

Este comando (select * from cat) es propio de Oracle y no de MySQL, pero sin embargo estamos usando un cliente MySQL conectado a un servidor MySQL, aunque internamente este redirija las peticiones hacia un servidor Oracle. Ya tenemos casi configurado nuestro servidor DBIx::MyServer, sólo nos falta configurar alguna tabla federada en nuestro servidor MySQL, para que use los datos de Oracle. Para ello, crearemos una pequeña base de datos en MySQL con una tabla federada:
  1. Conectarnos a nuestra base de datos MySQL local, (la de nuestro servidor MySQL, no la del proxy este en PERL) y crear una nueva base de datos llamada oratest:
    # mysql -u root

    sql> create database oratest;
  2. Crear la tabla federeda en esta nueva base de datos...
    mysql> use oratest;

    mysql> drop table dept_scott;

    mysql> create table dept_scott(
    deptno integer(2) not null,
    dname varchar(14),
    loc varchar(14)
    ) engine = federated
    connection = 'mysql://myuser:myuser@127.0.0.1:1234/scott/dept'
    ;
    lo importante es definir los mismos campos que tenemos en Oracle y de la URL, el último token, que nos indica la tabla o vista hacia la que apuntamos, (en nuestro ejemplo DEPT).

Si ahora ejecutamos desde nuestro cliente MySQL, la consulta...
mysql> select * from dept_scott;

Comprobaremos cómo no nos devuelve ningún valor, pero sí que nos funcionarán los inserts en la tabla:
insert into dept_scott values(49,'PRUEBAS','MADRID');

Para saber porqué no nos funcionan los SELECT sobre la tabla federada, tenemos que examinar la salida del demonio PERL y ver qué consultas se le envían a Oracle. El primer problema es que la clase DBIx::MyServer se empeña en entrecomillar los nombres de los campos y tablas con el símbolo ` , y ello provoca fallo en Oracle. Editar el fichero de la clase /usr/local/share/perl/5.12.4/DBIx/MyServer/DBI.pm, y aplicar el siguiente parche/chapuza:
24a25,26
> $query_text=~s/`//eg;
> print "----SE ENVIA A ORACLE --->[$query_text]\n";

Luego, podemos comprobar cómo MySQL se empeña en añadir WHERE 1=0 a las consultas que envía a Oracle. Esto no devolverá ningún resultado en Oracle. Para quitarlo, editaremos el fichero myserver.conf con el que lanzamos el demonio, y añadiremos el siguiente bloque entre las expresiones de traducción:
{
match => qr{^(SELECT.+)WHERE 1=0}io,
rewrite => sub { "$_[1]" },
}

Esta expresión en PERL permite eliminar el WHERE 1=0 de los SELECT. Si seguimos depurando, comprobaremos que MySQL se empeña en consultar las estadisticas de la tabla remota, cuando se hace un SELECT, ejecutando el comando SHOW TABLE STATUS LIKE DEPT. Este comando no existe en Oracle y provocará un fallo. Para evitarlo, añadiremos una nueva expresión a nuestro fichero myserver.conf :
{
match => qr{^show table status like\s+'([^']+)'}io,
rewrite => sub { "select table_name as Name, 'BDB' as Type, 'Fixed' as Row_Format, num_rows as \"ROWS\", AVG_ROW_LEN as Avg_row_length, BLOCKS as Data_length , MAX_EXTENTS as Max_data_length, INITIAL_EXTENT as Index_length, INITIAL_EXTENT as Data_free, 100 as Auto_increment, (sysdate-10) as Create_time, sysdate as Update_time, (sysdate+10) as Check_time, '' as Create_options, '' as \"Comment\" from user_tables where table_name='". uc($_[1]) ."'"
}

Lo que hacemos es capturar los SHOW TABLE STATUS que envía MySQL y traducirlos por lo análogo en Oracle (consulta a la vista USER_TABLES). Si reiniciamos nuestro demonio PERL (matando el proceso con kill -9) y volvemos a iniciarlo para que tome los cambios que hemos realizado en myserver.conf, podremos hacer la prueba definitiva:
# mysql

mysql> use oratest;

mysql>

mysql> select * from dept_scott;
+--------+------------+----------+
| deptno | dname | loc |
+--------+------------+----------+
| 49 | PRUEBAS | MADRID |
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
5 rows in set (0.10 sec)

La gran ventaja de usar DBLinks de este modo o como relatamos en el anterior post, no es otra que la de integrar datos de nuestra organización almacenados en servidores independientes, pero de forma cómoda en SQL (SELECT, INNER JOINs, etc) sin apoyarnos en otros mecanismos externos como WebServices, CSVs, SQL-Loaders, etc, etc, que siempre pueden fallar y cuando lo hacen, nos cuesta mucho tiempo averiguar la causa del problema. Suerte!

DBLinks desde Oracle hacia MySQL

A menudo nos encontramos con organizaciones que tienen ya implantados diferentes entornos para el almacenamiento de la información. Es habitual encontrar una base de datos Oracle para las aplicaciones más importantes con la lógica del negocio, escritas en Oracle Forms y Java, y luego, otras bases de datos (MySQL, Postgres) asociadas a proyectos OpenSource que han decidido usar, porque cubren con total garantía nuevas necesidades que en otro caso serían muy costosas de desarrollar en tiempo y dinero.

En este escenario, suele aparecer la necesidad de vincular información desde el servidor Oracle hacia otras bases de datos como MySQL. Un ejemplo habitual es encontrar la base de datos de nuestros clientes en Oracle, mantenidos desde una aplicación Oracle Forms, y en un momento dado se quiere sincronizar los datos de contacto de estos clientes, con nuestra centralita Asterisk (que usa MySQL) de forma que, cuando la aplicación actualice los datos de algún cliente automáticamente estén disponibles para Asterisk.

Si las dos bases de datos fueran Oracle, podríamos resolverlo mediante un DBLink desde la base de datos de clientes hacia la de Asterisk y desarrollar un pequeño trigger PL/SQL para que cuando se actualicen ciertos datos, automáticamente se actualicen las tablas que lee Asterisk. Al estar este sobre MySQL, no podemos crear un DBLink. Afortunadamente Oracle contempla este escenario a través de Heterogeneus Service (HS) junto a Oracle Database Gateway for ODBC (hs4odbc).



Para configurar este servicio, tendremos que:

  1. Lo primero será comprobar que instalamos en nuestro servidor Oracle el servicio, chequeando que existe el ejecutable $ORACLE_HOME/bin/dg4odbc
  2. Lo siguiente será instalar el driver ODBC para MySQL, en nuestro servidor Oracle:
    yum install  unixODBC.x86_64 mysql-connector-odbc.x86_64 
  3. Ahora, en nuestro servidor MySQL, crearemos un base de datos de prueba, a la que conectar desde Oracle, (cualquiera sabe lo que podría hacernos en MySQL un administrador/desarrollador de Oracle)
    mysql> create database oracletest character set latin1;

    mysql> grant all privileges on oracletest.* to 'oracleconn'@'%'
    identified by 'demo' with grant option;

    mysql> flush privileges;

    mysql> exit;
    Es importante usar latin1 para la Base de datos, porque en caso de usar UTF8, tendremos problemas al acceder desde Oracle.
  4. Ahora, desde el servidor Oracle, probar a conectar al servidor MySQL, usando el cliente MySQL:
    mysql -h SERVIDOR_MYSQL  --user=oracleconn --password=demo oracletest 
    ... y una vez nos hayamos conectado, crearemos una pequeña tabla:
    create table demo (
    col1 integer,
    col2 date,
    col3 varchar(10),
    col4 varchar(10) character set utf8,
    col5 varbinary(10)) engine innodb;
    ... y aprovecharemos para insertar algún registro...
    insert into demo(col1, col2, col3, col4, col5)
    values(1, cast(now() as date), '0123456789', '0123456789', '0123456789');
  5. Ahora desde el servidor Oracle, editar el fichero ~oracle/.odbc.ini y configurar el acceso a MySQL vía ODBC, escribiendo el siguiente contenido:
    [ODBC Data Sources]
    test_mysql = MySQL ODBC Driver 5.1

    [test_mysql]
    Driver = /usr/lib64/libmyodbc3.so
    DATABASE = oracletest
    DESCRIPTION = Conexion a MySQL ODBC
    PORT = 3306
    SERVER = SERVIDOR_MYSQL# UID = oracleconn
    # PWD = demo

    CHARSET = latin1
    TRACEFILE = /tmp/myodbc-demodsn.trc
    TRACE = ON
  6. Crear el fichero $ORACLE_HOME/hs/admin/initMysql.ora. El nombre Mysql será el SID, y es un nombre arbitrario: Cualquiera que se cree, debe ser $ORACLE_HOME/hs/admin/init$SID.ora
    #
    # HS init parameters
    #

    HS_FDS_CONNECT_INFO=test_mysql
    HS_FDS_TRACE_LEVEL=0
    HS_FDS_SHAREABLE_NAME=/usr/lib64/libmyodbc3.so
    HS_LANGUAGE=AMERICAN_AMERICA.WE8ISO8859P15
    # HS_NLS_NCHAR=AL32UTF8
    #
    # ODBC specific environment variables
    #

    set ODBCINI=/home/oracle/.odbc.ini
    set LD_LIBRARY_PATH=/usr/lib64:/lib64:/usr/local/lib64:/u01/oracle/soft/product/11.1.0/db_1/lib:/u01/oracle/soft/product/11.1.0/db_1/oracm/lib:/lib:/usr/lib:/usr/local/lib

    #
    # Environment variables required for the non-Oracle system
    #

    set HOME=/home/oracle
  7. Añadir a $ORACLE_HOME/network/admin/listener.ora dentro del SID_LIST, el siguiente bloque SID_DESC:
        (SID_DESC =
    (ORACLE_HOME = /u01/oracle/soft/product/11.1.0/db_1)
    (SID_NAME = Mysql)
    (PROGRAM = dg4odbc)
    (ENVS ="LD_LIBRARY_PATH=/usr/lib64:/lib64:/usr/local/lib64:/u01/oracle/soft/product/11.1.0/db_1/lib:/u01/oracle/soft/product/11.1.0/db_1/oracm/lib:/lib:/usr/lib:/usr/local/lib")
    )
  8. Reiniciar el listener de Oracle...
    su - oracle
    lsnrctl stop
    lsnrctl start
  9. Ahora editar el fichero $ORACLE_HOME/network/admin/tnsnames.ora y añadir el siguiente bloque:
    DEMOMYSQL =
    (DESCRIPTION =
    (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)
    (HOST = localhost)
    (PORT = 1521)
    )
    )
    (CONNECT_DATA =
    (SID = Mysql)
    )
    (HS = OK)
    )
  10. Comprobar que está accesible...
    tnsping demoMYSQL
  11. Crear un DBLINK para acceder a MySQL desde nuestro servidor Oracle...
    su - oracle

    $ sqlplus / as sysdba;

    SQL> CREATE PUBLIC DATABASE LINK dbtestmysql
    CONNECT TO oracleconn
    IDENTIFIED BY demo
    USING 'DEMOMYSQL';
  12. .. y probar que funciona...
    su - oracle

    $ sqlplus / as sysdba;

    SQL> select * from demo@dbtestmysql ;
    Si estás usando Oracle 11.1.0.6 no te funcionará: Necesitas actualizar tu servidor a 11.1.0.7, porque una de los fallos que arregla tiene que ver con hs4odbc.