python-ibmdb: Protocol specific error code(s): "414", "*", "*". SQLSTATE=08001 SQLCODE=-30081
- Operating System Name: MacOS M1 Chip System (host) (but running the package
ibm_db
in the podman) - DB2
- Instance Type: Db2 Standalone
- Machine Type: power
- Database Version: 11.5.8
- Python Version: 3.9.18 (container)
- ibm_db version:
ibm-db==3.2.1
(container) - For non-Windows, output of below commands: uname (container: Linux, host: Darwin) uname -m (contaner: x86_64, host: arm64)
- Test script to reproduce the problem.
ibmdb2_connect.py
import os
import ibm_db
database = os.getenv("DB2_DB")
hostname = os.getenv("DB2_HOST")
username = os.getenv("DB2_USER")
password = os.getenv("DB2_PASSWORD")
conn = ibm_db.connect(
f"DATABASE={database};"
+ f"HOSTNAME={hostname};"
+ "PORT=50001;"
+ "PROTOCOL=TCPIP;"
+ "SECURITY=SSL;"
+ f"UID={username};"
+ f"PWD={password};"
+ "sslConnection=true;"
+ "sslTrustStoreLocation=trustore.jks",
"",
"",
)
connState = ibm_db.active(conn)
print(f"connState: {connState}")
Dockerfile
FROM python:3.9-bullseye
RUN apt update && apt install -y neovim tmux
COPY requirements.txt .
COPY trustore.jks .
COPY load_archive_ticket.py .
COPY .bashrc /root
COPY .tmux.conf /root
RUN pip install virtualenv
RUN virtualenv venv
RUN /bin/bash -c "source venv/bin/activate && pip install -r requirements.txt"
Steps to Reproduce:
podman build --platform linux/amd64 -t ibmdb2 .
podman run --platform linux/amd64 --env-file .env -it ibmdb2 /bin/bash
- In the container
source venv/bin/activate
- In the container
python ibmdb2_connect.py
- Output
Traceback (most recent call last):
File "//load_archive_ticket.py", line 9, in <module>
conn = ibm_db.connect(
Exception: [IBM][CLI Driver] SQL30081N A communication error has been detected. Communication protocol being used: "SSL". Communication API being used: "SOCKETS". Location where the error was detected: "". Communication function detecting the error: "sqlccSSLSocketSetup". Protocol specific error code(s): "414", "*", "*". SQLSTATE=08001 SQLCODE=-30081
PS: with R
language and DBeaver
I was able to connect in the same DB:
drv <- RJDBC::JDBC(
"com.ibm.db2.jcc.DB2Driver",
"jars/db2jcc4.jar"
)
host <- Sys.getenv("DB2_HOST")
db <- Sys.getenv("DB2_DB")
user <- Sys.getenv("DB2_USER")
password <- Sys.getenv("DB2_PASSWORD")
uri <- sprintf(
paste0(
"jdbc:db2://%s:50001/%s:user=%s;password=%s;",
"sslConnection=true;sslTrustStoreLocation=trustore.jks"
),
host,
db,
user,
password
)
db2 <- DBI::dbConnect(drv, uri)
About this issue
- Original URL
- State: closed
- Created 4 months ago
- Comments: 17 (9 by maintainers)
@th1460 You need to use
SSLClientKeyStoreDB
keyword too pointing to full path of *.kdb file along withSSLClientKeystash
keyword in connection string. If you do not provide *.kdb file in connection string, how driver will know which kdb it has to look for certificate file using the *.sth file? Note that *.sth file stores the encrypted password for the *.kdb file. Driver need password to read from the kdb file. Basically, your connection string should be as below:Note that this *.kdb and *.sth file should be generated using GSKit on db2server system. Otherwise, get *.arm or *.cert file from trustore.jks using KeyTool and use below connection string. If your
trustore.sth
file is fortrustore.jks
, it will not work in connection string of ibm_db.connstr = "DATABASE=BLUDB;HOSTNAME=db2host.ibm.com;PORT=50001;PROTOCOL=TCPIP;SECURITY=SSL;SSLServerCertificate=/home/user/certs/servercert.arm;UID=dbuser;PWD=dbpass"
Only above two types of connection string will work for SSL connection. Either usingSSLServerCertificate
in connection string or using (SSLClientKeyStoreDB
&&SSLClientKeystash
in connection string ORSSLClientKeyStoreDB
&&SSLClientKeyStoreDBPassword
in connection string). Thanks.@th1460 Below two keywords used in your connection string is JDBC connection keywords which are not supported for
ibm_db
. ibm_db uses ODBC connection keywords.Please remove it. You have already used
"SECURITY=SSL;"
which is equivalent keyword for JDBC keywordsslConnection=true;
. You need to generated*.arm
certificate using GSKit and use it asSSLServerCertificate=<full path of *.arm file>
. The corresponding ODBC keyword forsslTrustStoreLocation
isSSLKeystoreDB
which should point to *.kdb file created by GSKit. Please check this doc link for three formats of SSL connection string supported by ibm_db: https://github.com/ibmdb/python-ibmdb?tab=readme-ov-file#example-of-ssl-connection-stringLet us know if it resolves your problem. Thanks.
Your question states sslTrustStoreLocation=trustore.jks ( the .jks extension suggests that the file contains a java key store, as used by java/jdbc applications).
python ibm_db is not a java application and it cannot use a java-keystore (.jks file).
Your options include: use a .kdb file created with gsk8capicmd_64, or use a PKCS12 format file, or use no keystore.
If you only have a single certificate file , then you do not need a keystore, and instead you can specify the absolute (fully qualified) pathname to the certificate file in your connection-string via the SSLServerCertificate=/path/to/your_certificate_file method. This is documented in the Db2-LUW knowledge centre.