diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..41bdc666 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,28 @@ +sudo: true +language: c +services: docker +addons: + hosts: + - mariadb.example.com + +before_install: + - chmod +x .travis/script.sh + - chmod +x .travis/gen-ssl.sh + - export PROJ_PATH=`pwd` + - export ENTRYPOINT=$PROJ_PATH/.travis/sql + - mkdir tmp + - .travis/gen-ssl.sh mariadb.example.com tmp + - export SSLCERT=$PROJ_PATH/tmp + - export CONNECTOR_C_VERSION=v_2.3.3 + +env: + # - DB=mysql:5.5 + #- DB=mysql:5.6 + #- DB=mysql:5.7 + #- DB=mariadb:5.5 + #- DB=mariadb:10.0 + #- DB=mariadb:10.1 + - DB=mariadb:10.2 + #- DB=mariadb:10.3 + +script: .travis/script.sh diff --git a/.travis/docker-compose.yml b/.travis/docker-compose.yml new file mode 100644 index 00000000..3ec7365a --- /dev/null +++ b/.travis/docker-compose.yml @@ -0,0 +1,13 @@ +version: '2' +services: + db: + image: $DB + command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --ssl-ca=/etc/sslcert/ca.crt --ssl-cert=/etc/sslcert/server.crt --ssl-key=/etc/sslcert/server.key --bind-address=0.0.0.0 + ports: + - 3305:3306 + volumes: + - $SSLCERT:/etc/sslcert + - $ENTRYPOINT:/docker-entrypoint-initdb.d + environment: + MYSQL_DATABASE: odbc_test + MYSQL_ALLOW_EMPTY_PASSWORD: 1 diff --git a/.travis/gen-ssl.sh b/.travis/gen-ssl.sh new file mode 100644 index 00000000..4403a6ad --- /dev/null +++ b/.travis/gen-ssl.sh @@ -0,0 +1,134 @@ +#!/bin/bash +set -e + +log () { + echo "$@" 1>&2 +} + +print_error () { + echo "$@" 1>&2 + exit 1 +} + +print_usage () { + print_error "Usage: gen-ssl-cert-key " +} + +gen_cert_subject () { + local fqdn="$1" + [[ "${fqdn}" != "" ]] || print_error "FQDN cannot be blank" + echo "/C=/ST=/O=/localityName=/CN=${fqdn}/organizationalUnitName=/emailAddress=/" +} + +main () { + local fqdn="$1" + local sslDir="$2" + [[ "${fqdn}" != "" ]] || print_usage + [[ -d "${sslDir}" ]] || print_error "Directory does not exist: ${sslDir}" + + local caCertFile="${sslDir}/ca.crt" + local caKeyFile="${sslDir}/ca.key" + local certFile="${sslDir}/server.crt" + local keyFile="${sslDir}/server.key" + local csrFile=$(mktemp) + local clientCertFile="${sslDir}/client.crt" + local clientKeyFile="${sslDir}/client.key" + local clientKeystoreFile="${sslDir}/client-keystore.jks" + local fullClientKeystoreFile="${sslDir}/fullclient-keystore.jks" + local tmpKeystoreFile=$(mktemp) + local pcks12FullKeystoreFile="${sslDir}/fullclient-keystore.p12" + local clientReqFile=$(mktemp) + + log "Generating CA key" + openssl genrsa -out "${caKeyFile}" 2048 + + log "Generating CA certificate" + openssl req \ + -sha1 \ + -new \ + -x509 \ + -nodes \ + -days 3650 \ + -subj "$(gen_cert_subject ca.example.com)" \ + -key "${caKeyFile}" \ + -out "${caCertFile}" + + log "Generating private key" + openssl genrsa -out "${keyFile}" 2048 + + log "Generating certificate signing request" + openssl req \ + -new \ + -batch \ + -sha1 \ + -subj "$(gen_cert_subject "$fqdn")" \ + -set_serial 01 \ + -key "${keyFile}" \ + -out "${csrFile}" \ + -nodes + + log "Generating X509 certificate" + openssl x509 \ + -req \ + -sha1 \ + -set_serial 01 \ + -CA "${caCertFile}" \ + -CAkey "${caKeyFile}" \ + -days 3650 \ + -in "${csrFile}" \ + -signkey "${keyFile}" \ + -out "${certFile}" + + log "Generating client certificate" + openssl req \ + -batch \ + -newkey rsa:2048 \ + -days 3600 \ + -subj "$(gen_cert_subject "$fqdn")" \ + -nodes \ + -keyout "${clientKeyFile}" \ + -out "${clientReqFile}" + + openssl x509 \ + -req \ + -in "${clientReqFile}" \ + -days 3600 \ + -CA "${caCertFile}" \ + -CAkey "${caKeyFile}" \ + -set_serial 01 \ + -out "${clientCertFile}" + + # Now generate a keystore with the client cert & key + log "Generating client keystore" + openssl pkcs12 \ + -export \ + -in "${clientCertFile}" \ + -inkey "${clientKeyFile}" \ + -out "${tmpKeystoreFile}" \ + -name "mysqlAlias" \ + -passout pass:kspass + + + # Now generate a full keystore with the client cert & key + trust certificates + log "Generating full client keystore" + openssl pkcs12 \ + -export \ + -in "${clientCertFile}" \ + -inkey "${clientKeyFile}" \ + -out "${pcks12FullKeystoreFile}" \ + -name "mysqlAlias" \ + -passout pass:kspass + + + + # Clean up CSR file: + rm "$csrFile" + rm "$clientReqFile" + rm "$tmpKeystoreFile" + + log "Generated key file and certificate in: ${sslDir}" + ls -l "${sslDir}" +} + +main "$@" + diff --git a/.travis/maxscale-compose.yml b/.travis/maxscale-compose.yml new file mode 100644 index 00000000..84a001e1 --- /dev/null +++ b/.travis/maxscale-compose.yml @@ -0,0 +1,25 @@ +version: '2' +services: + maxscale: + depends_on: + - db + ports: + - 4006:4006 + - 4007:4007 + - 4008:4008 + build: + context: . + dockerfile: maxscale/Dockerfile + args: + MAXSCALE_VERSION: $MAXSCALE_VERSION + db: + image: $DB + command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --ssl-ca=/etc/sslcert/ca.crt --ssl-cert=/etc/sslcert/server.crt --ssl-key=/etc/sslcert/server.key --bind-address=0.0.0.0 + ports: + - 3305:3306 + volumes: + - $SSLCERT:/etc/sslcert + - $ENTRYPOINT:/docker-entrypoint-initdb.d + environment: + MYSQL_DATABASE: odbc_test + MYSQL_ALLOW_EMPTY_PASSWORD: 1 diff --git a/.travis/maxscale/Dockerfile b/.travis/maxscale/Dockerfile new file mode 100644 index 00000000..0ae214d9 --- /dev/null +++ b/.travis/maxscale/Dockerfile @@ -0,0 +1,24 @@ +FROM centos:7 + +ARG MAXSCALE_VERSION +ENV MAXSCALE_VERSION ${MAXSCALE_VERSION:-2.1.4} + +COPY maxscale/mariadb.repo /etc/yum.repos.d/ + +RUN rpm --import https://yum.mariadb.org/RPM-GPG-KEY-MariaDB \ + && yum -y install https://downloads.mariadb.com/MaxScale/${MAXSCALE_VERSION}/centos/7/x86_64/maxscale-${MAXSCALE_VERSION}-1.centos.7.x86_64.rpm \ + && yum -y update + +RUN yum -y install maxscale-${MAXSCALE_VERSION} MariaDB-client \ + && yum clean all \ + && rm -rf /tmp/* + +COPY maxscale/docker-entrypoint.sh / +RUN chmod 777 /etc/maxscale.cnf +COPY maxscale/maxscale.cnf /etc/ +RUN chmod 777 /docker-entrypoint.sh + + +EXPOSE 4006 4007 4008 + +ENTRYPOINT ["/docker-entrypoint.sh"] \ No newline at end of file diff --git a/.travis/maxscale/docker-entrypoint.sh b/.travis/maxscale/docker-entrypoint.sh new file mode 100644 index 00000000..601915fb --- /dev/null +++ b/.travis/maxscale/docker-entrypoint.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -e + +echo 'creating configuration done' + +sleep 15 + +################################################################################################# +# wait for db availability for 60s +################################################################################################# +mysql=( mysql --protocol=tcp -ubob -hdb --port=3306 ) +for i in {60..0}; do + if echo 'use test2' | "${mysql[@]}" &> /dev/null; then + break + fi + echo 'DB init process in progress...' + sleep 1 +done + +echo 'use test2' | "${mysql[@]}" +if [ "$i" = 0 ]; then + echo 'DB init process failed.' + exit 1 +fi + +echo 'maxscale launching ...' + +tail -n 500 /etc/maxscale.cnf + +/usr/bin/maxscale --nodaemon + +cd /var/log/maxscale +ls -lrt +tail -n 500 /var/log/maxscale/maxscale.log diff --git a/.travis/maxscale/mariadb.repo b/.travis/maxscale/mariadb.repo new file mode 100644 index 00000000..055f3b5c --- /dev/null +++ b/.travis/maxscale/mariadb.repo @@ -0,0 +1,7 @@ +# MariaDB 10.2 CentOS repository list - created 2017-06-05 08:06 UTC +# http://downloads.mariadb.org/mariadb/repositories/ +[mariadb] +name = MariaDB +baseurl = http://yum.mariadb.org/10.2/centos7-amd64 +gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB +gpgcheck=1 \ No newline at end of file diff --git a/.travis/maxscale/maxscale.cnf b/.travis/maxscale/maxscale.cnf new file mode 100644 index 00000000..2a723ba5 --- /dev/null +++ b/.travis/maxscale/maxscale.cnf @@ -0,0 +1,125 @@ +# MaxScale documentation on GitHub: +# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Documentation-Contents.md + +# Global parameters +# +# Complete list of configuration options: +# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Getting-Started/Configuration-Guide.md + + +[maxscale] +threads=2 +log_messages=1 +log_trace=1 +log_debug=1 + +# Server definitions +# +# Set the address of the server to the network +# address of a MySQL server. +# + +[server1] +type=server +address=db +port=3306 +protocol=MySQLBackend +authenticator_options=skip_authentication=true +router_options=master + +# Monitor for the servers +# +# This will keep MaxScale aware of the state of the servers. +# MySQL Monitor documentation: +# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Monitors/MySQL-Monitor.md + +[MySQL Monitor] +type=monitor +module=mysqlmon +servers=server1 +user=boby +passwd=hey +monitor_interval=10000 + +# Service definitions +# +# Service Definition for a read-only service and +# a read/write splitting service. +# + +# ReadConnRoute documentation: +# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Routers/ReadConnRoute.md + +[Read-Only Service] +enable_root_user=1 +version_string=10.2.99-MariaDB-maxScale +type=service +router=readconnroute +servers=server1 +user=boby +passwd=hey +router_options=slave +localhost_match_wildcard_host=1 + +[Read-Write Service] +enable_root_user=1 +version_string=10.2.99-MariaDB-maxScale +type=service +router=readwritesplit +servers=server1 +user=boby +passwd=hey +localhost_match_wildcard_host=1 + +[Write Service] +type=service +router=readconnroute +servers=server1 +user=boby +passwd=hey +router_options=master +localhost_match_wildcard_host=1 +version_string=10.2.99-MariaDB-maxscale + + +# This service enables the use of the MaxAdmin interface +# MaxScale administration guide: +# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Reference/MaxAdmin.mda + +[MaxAdmin Service] +enable_root_user=1 +version_string=10.2.99-MariaDB-maxScale +type=service +router=cli + +# Listener definitions for the services +# +# These listeners represent the ports the +# services will listen on. +# +[Write Listener] +type=listener +service=Write Service +protocol=MySQLClient +port=4007 +socket=/var/lib/maxscale/writeconn.sock + +[Read-Only Listener] +type=listener +service=Read-Only Service +protocol=MySQLClient +port=4008 +socket=/var/lib/maxscale/readconn.sock + +[Read-Write Listener] +type=listener +service=Read-Write Service +protocol=MySQLClient +port=4006 +socket=/var/lib/maxscale/rwsplit.sock + +[MaxAdmin Listener] +type=listener +service=MaxAdmin Service +protocol=maxscaled +socket=/tmp/maxadmin.sock diff --git a/.travis/script.sh b/.travis/script.sh new file mode 100644 index 00000000..3d83312c --- /dev/null +++ b/.travis/script.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +set -x +set -e + +################################################################################################################### +# test different type of configuration +################################################################################################################### +mysql=( mysql --protocol=tcp -ubob -h127.0.0.1 --port=3305 ) +export COMPOSE_FILE=.travis/docker-compose.yml + + + +################################################################################################################### +# launch docker server and maxscale +################################################################################################################### +export INNODB_LOG_FILE_SIZE=$(echo ${PACKET}| cut -d'M' -f 1)0M +docker-compose -f ${COMPOSE_FILE} build +docker-compose -f ${COMPOSE_FILE} up -d + + +################################################################################################################### +# wait for docker initialisation +################################################################################################################### + +for i in {60..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi + echo 'data server still not active' + sleep 1 +done + +docker-compose -f ${COMPOSE_FILE} logs + +if [ "$i" = 0 ]; then + echo 'SELECT 1' | "${mysql[@]}" + echo >&2 'data server init process failed.' + exit 1 +fi + +#list ssl certificates +ls -lrt ${SSLCERT} + + +#build C connector +DEBIAN_FRONTEND=noninteractive sudo apt-get install --allow-unauthenticated -y --force-yes -m unixodbc-dev +#mkdir ./connector_c +time git clone -b master --depth 1 "https://github.com/MariaDB/mariadb-connector-c.git" build +cd build +#git fetch --all --tags --prune +#git checkout tags/${CONNECTOR_C_VERSION} -b branch_odbc + +cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_OPENSSL=ON +#-DCMAKE_INSTALL_PREFIX= ../connector_c . +make +sudo make install +cd .. +rm build -rf + +#build odbc connector +export TEST_DRIVER=maodbc_test +export TEST_DSN=maodbc_test +export TEST_PORT=3305 +export TEST_SERVER=mariadb.example.com +export TEST_SOCKET= +export TEST_SCHEMA=odbc_test +export TEST_UID=bob +export TEST_PASSWORD= + +cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_OPENSSL=ON -DMARIADB_DIR=./connector_c . +cmake --build . --config RelWithDebInfo + +################################################################################################################### +# run test suite +################################################################################################################### +echo "Running tests" + +cd test +export ODBCINI=./odbc.ini +export ODBCSYSINI=./ + +ctest -V diff --git a/.travis/sql/dbinit.sql b/.travis/sql/dbinit.sql new file mode 100644 index 00000000..3ebdb26f --- /dev/null +++ b/.travis/sql/dbinit.sql @@ -0,0 +1,9 @@ +CREATE USER 'bob'@'%'; +GRANT ALL ON *.* TO 'bob'@'%' with grant option; + +CREATE USER 'boby'@'%' identified by 'hey'; +GRANT ALL ON *.* TO 'boby'@'%' with grant option; + +FLUSH PRIVILEGES; + +CREATE DATABASE test2;