Unable to connect to Db2 database instance through the Db2Rest add-on pod

When you try to connect to your Db2 database instance by using the Db2Rest add-on pod, you get an error message from the Db2 CLI driver and are unable to connect.

Symptoms

You notice the following behavior:

  • You cannot connect to your Db2 database instance (Db2 s11.5.9.0-cn1)
  • You get an error message from the Db2 CLI driver
  • The SSL keystore and keystash files weren't created

The GSKit does not create the keystore and keystash files correctly, which causes GSKit commands to fail. This problem happens because the Db2Rest entrypoint script references a file that does not exist in the rest pod (db2_encryption_functions.sh).

Resolving the problem
The workaround involves patching the problematic entrypoint script with a new one.
  1. Save the following script as db2u_rest_entrypoint.sh:
    db2u_rest_entrypoint.sh
    1. #!/bin/bash
      
      # *******************************************************************************
      #
      # COPYRIGHT: P#2 P#1
      # (C) COPYRIGHT IBM CORPORATION 2019
      #
      # The source code for this program is not published or otherwise divested of
      # its trade secrets, irrespective of what has been deposited with the U.S.
      # Copyright Office.
      #
      # *******************************************************************************
      source ${DB2REST_INSTALL_PATH}/.bashrc
      STARTTIME=$(date '+%Y%m%d%H%M%S')
      echo "STARTTIME=$STARTTIME"
      
      # Get the PID 1 environ into the container namespace
      xargs -L1 -0 echo < /proc/1/environ > /tmp/env
      export IBM_PRODUCT="IBM Db2 REST"
      source ${DB2U_SCRIPTS}/include/db2u_logger.sh
      
      DB2REST_AUTH_PATH=${DB2REST_INSTALL_PATH}/auth
      DB2REST_TLS_KEY=${DB2REST_AUTH_PATH}/dbrest.key
      DB2REST_TLS_CRT=${DB2REST_AUTH_PATH}/dbrest.pem
      
      [[ -d ${DB2REST_AUTH_PATH} || "$(ls -A ${DB2REST_AUTH_PATH})" ]] || mkdir -p ${DB2REST_AUTH_PATH}
      if [[ ! -f ${DB2REST_TLS_KEY} ]]; then
        #Add SAN to REST self signed cert
        REST_SANS="DNS:$(hostname -f),DNS:$(hostname -s)"
      
        openssl req -newkey rsa:2048 -nodes -keyout ${DB2REST_TLS_KEY} -x509 -days 365 -out ${DB2REST_TLS_CRT} -subj "/C=CA/ST=ON/L=TO/O=IBM=OU=Db2Rest/CN=ibm.com" -extensions SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=$REST_SANS"))
        chmod 600 ${DB2REST_AUTH_PATH}/dbrest.*
      fi
      
      #
      ### Write DB2REST properties file ###
      #
      cat <<EOF >> ${DB2REST_CONFIG_PATH}/server.env
      DB2REST_TLS_PORT=50050
      DB2REST_TLS_KEY=${DB2REST_TLS_KEY}
      DB2REST_TLS_CRT=${DB2REST_TLS_CRT}
      EOF
      
      #Create shared storage
      SHARED_DB2REST_DIR=/mnt/blumeta0/db2rest
      TEMP_CONFIG_LOG=${SHARED_DB2REST_DIR}/temp_config.log
      CONFIG_LOG=${DB2REST_INSTALL_PATH}/logs/config.log
      if [[ ! -d ${SHARED_DB2REST_DIR} || ! "$(ls -A ${SHARED_DB2REST_DIR})" ]]; then
          sudo mkdir -p ${SHARED_DB2REST_DIR}
          sudo chown -R ${REST_USER} ${SHARED_DB2REST_DIR}
          echo "Created shared directory" > ${TEMP_CONFIG_LOG} 2>&1
      else
          echo "Shared directory already exists" > ${TEMP_CONFIG_LOG} 2>&1
      fi
      
      #Create shared logs directory
      SHARED_DB2REST_LOG_DIR=${SHARED_DB2REST_DIR}/logs
      if [[ ! -d ${SHARED_DB2REST_LOG_DIR} || ! "$(ls -A ${SHARED_DB2REST_LOG_DIR})" ]]; then
          sudo mkdir -p ${SHARED_DB2REST_LOG_DIR} >> ${TEMP_CONFIG_LOG} 2>&1
          sudo chown -R ${REST_USER} ${SHARED_DB2REST_LOG_DIR} >> ${TEMP_CONFIG_LOG} 2>&1
          echo "Created shared logs directory" >> ${TEMP_CONFIG_LOG} 2>&1
      else
          echo "Shared logs directory already exists" >> ${TEMP_CONFIG_LOG} 2>&1
      fi
      if [[ ! -d ${DB2REST_INSTALL_PATH}/logs ]]; then
          sudo ln -s ${SHARED_DB2REST_LOG_DIR} ${DB2REST_INSTALL_PATH}/logs >> ${TEMP_CONFIG_LOG} 2>&1
          echo "Created shared logs symlink" >> ${TEMP_CONFIG_LOG} 2>&1
      else
          echo "Shared logs symlink already exists" >> ${TEMP_CONFIG_LOG} 2>&1
      fi
      if [[ -f ${CONFIG_LOG} ]]; then
          rm ${CONFIG_LOG} >> ${TEMP_CONFIG_LOG} 2>&1
      fi
      mv ${TEMP_CONFIG_LOG} ${CONFIG_LOG}
      
      #Create and symlink the app.yaml file 
      DB2REST_CFG_FILE=app.yaml
      DEFAULT_DB2REST_CFG_FILE=default.app.yaml
      SHARED_DB2REST_CFG_FILE=${SHARED_DB2REST_DIR}/${DB2REST_CFG_FILE}
      if [[ ! -f ${SHARED_DB2REST_CFG_FILE} ]]; then
          cp ${DB2REST_CONFIG_PATH}/${DEFAULT_DB2REST_CFG_FILE} ${SHARED_DB2REST_CFG_FILE} >> ${CONFIG_LOG} 2>&1
      else
          echo "Shared Db2 REST configuration file already exists" >> ${CONFIG_LOG} 2>&1
      fi
      if [[ ! -f ${DB2REST_CONFIG_PATH}/${DB2REST_CFG_FILE} ]]; then
          sudo ln -s ${SHARED_DB2REST_CFG_FILE} ${DB2REST_CONFIG_PATH}/${DB2REST_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          echo "Create Db2 REST configuration file symlink" >> ${CONFIG_LOG} 2>&1
      else
          echo "Shared Db2 REST configuration symlink already exists" >> ${CONFIG_LOG} 2>&1
      fi
       
      #Create Db2 REST keystore/keystash
      SSL_KEY_PREFIX=bludb_ssl
      SSL_KEYSTORE_FILE=${SHARED_DB2REST_DIR}/${SSL_KEY_PREFIX}.kdb
      SSL_KEYSTASH_FILE=${SHARED_DB2REST_DIR}/${SSL_KEY_PREFIX}.sth
      DB2_ROOT_CERTIFICATE=/secrets/db2ssl/ca.crt
      if [[ -f ${DB2_ROOT_CERTIFICATE} ]]; then
          echo "Root certificate found" >> ${CONFIG_LOG} 2>&1
          if [[ -f ${SSL_KEYSTORE_FILE} ]]; then
              echo "Remove existing key artifacts" >> ${CONFIG_LOG} 2>&1
              rm -rf ${SHARED_DB2REST_DIR}/${SSL_KEY_PREFIX}.*
          fi
          ssl_keystore_pw=`cat /dev/urandom | tr -dc '[:alnum:][=@=][=_=]' | fold -w ${1:-29} | head -n 1`
          gsk8capicmd_64 -keydb -create -pqc false -db ${SSL_KEYSTORE_FILE} -pw ${ssl_keystore_pw} -type cms -stash >> ${CONFIG_LOG} 2>&1
          gsk8capicmd_64 -cert -add -db ${SSL_KEYSTORE_FILE} -pw ${ssl_keystore_pw} -file ${DB2_ROOT_CERTIFICATE} -format ascii >> ${CONFIG_LOG} 2>&1
      else
          echo "Root certificate not found" >> ${CONFIG_LOG} 2>&1
      fi
      
      #Create and symlink the db2dsdriver.cfg file
      DRIVER_CFG_FILE=db2dsdriver.cfg
      DRIVER_HADR_CFG_FILE=db2dsdriver.sample.hadr.cfg
      SHARED_DRIVER_CFG_FILE=${SHARED_DB2REST_DIR}/${DRIVER_CFG_FILE}
      SHARED_DRIVER_HADR_CFG_FILE=${SHARED_DB2REST_DIR}/${DRIVER_HADR_CFG_FILE}
      if [[ ! -f ${SHARED_DRIVER_CFG_FILE} ]]; then
          cp ${DB2REST_CONFIG_PATH}/db2dsdriver.sample.cfg ${SHARED_DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          cp ${DB2REST_CONFIG_PATH}/db2dsdriver.sample.hadr.cfg ${SHARED_DB2REST_DIR}/db2dsdriver.sample.hadr.cfg >> ${CONFIG_LOG} 2>&1
          sed -i "s/DB2_HOSTNAME/${DB2REST_DBHOSTNAME}/" ${SHARED_DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s/DB2_PORT/${DB2REST_DBPORT}/" ${SHARED_DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s/DBNAME/${DB2REST_DBNAME}/" ${SHARED_DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s,PATH_TO_KEYSTORE,${SSL_KEYSTORE_FILE}," ${SHARED_DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s,PATH_TO_KEYSTASH,${SSL_KEYSTASH_FILE}," ${SHARED_DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s/DB2_HOSTNAME/${DB2REST_DBHOSTNAME}/" ${SHARED_DRIVER_HADR_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s/DB2_PORT/${DB2REST_DBPORT}/" ${SHARED_DRIVER_HADR_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s/DBNAME/${DB2REST_DBNAME}/" ${SHARED_DRIVER_HADR_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s,PATH_TO_KEYSTORE,${SSL_KEYSTORE_FILE}," ${SHARED_DRIVER_HADR_CFG_FILE} >> ${CONFIG_LOG} 2>&1
          sed -i "s,PATH_TO_KEYSTASH,${SSL_KEYSTASH_FILE}," ${SHARED_DRIVER_HADR_CFG_FILE} >> ${CONFIG_LOG} 2>&1
      else
          echo "Shared driver configuration already exists" >> ${CONFIG_LOG} 2>&1
      fi
      if [[ ! -f ${DB2REST_DB2HOME}/cfg/${DRIVER_CFG_FILE} ]]; then
          sudo ln -s ${SHARED_DRIVER_CFG_FILE} ${DB2REST_DB2HOME}/cfg/${DRIVER_CFG_FILE} >> ${CONFIG_LOG} 2>&1
      else
          echo "Driver configuration already exists" >> ${CONFIG_LOG} 2>&1
      fi
      
      logger_info "Starting up ${IBM_PRODUCT} container..."
      ${DB2REST_INSTALL_PATH}/scripts/db2rest-start.sh
      
      # Setup an init banner for the rest container
      cat <<EOF
      #############################################################${HASHES}
      ###  ${IBM_PRODUCT} container was started successfully   ###
      #############################################################${HASHES}
      * If you used docker/oc/kubectl logs to monitor progress, detach from the
      console by pressing Ctrl+C.
      * To get a command line prompt, issue the following command from the host:
          [ docker | oc | kubectl -n <NS> ] exec -it <rest container name> bash
      #############################################################${HASHES}
      EOF
      
      # End-marker to enable readiness probe when deployed via charts
      DB2U_MARKER_FILE=${DB2U_DIR}/.db2u_rest_initialized
      touch ${DB2U_MARKER_FILE}
      
      set +x
      
      # Keep the container up in detached(-d) mode, unless --exit arg is passed
      #/usr/bin/bash
      [[ "X${1}" != "X--exit" ]] && \
          tail -f /dev/null

  2. Save the following script as patch_script_cm.sh:
    patch_script_cm.sh
    1. #!/bin/bash
      
      # Example usage: ./patch_script_cm.sh db2oltp-crd-hadr-primary standalone-rc manage_hadr.sh /db2u/scripts 755 false
      DB2U_ID=$1
      NAMESPACE=$2
      FILE=$3
      MOUNT_PATH=$4
      PERM=$5
      READ_ONLY=$6
      
      FILENAME=$(basename -- "${FILE}")
      EXTENSION="${FILENAME##*.}"
      FILENAME="${FILENAME%.*}"
      CM=$(echo "${FILENAME}-${EXTENSION}" | tr '_' '-')
      
      echo "-------------------------------------------------"
      echo -e "(Re)creating configmap ${CM}...\n"
      kubectl create configmap ${CM} -n ${NAMESPACE} --from-file=${FILE}=${FILE} -o yaml --dry-run=client | kubectl apply -f -
      
      echo -e "\n-------------------------------------------------"
      echo -e "Mounting ${CM} CM to ${DB2U_ID}-rest deployment..."
      DB2U_STS=c-${DB2U_ID}-rest
      oc set volume deployment/${DB2U_STS} -n ${NAMESPACE} --add --name=${CM} --type=configmap --containers=rest --mount-path="${MOUNT_PATH}/${FILE}" --sub-path="${FILE}" --configmap-name=${CM} --default-mode="${PERM}" --read-only=${READ_ONLY} --overwrite

  3. In a separate terminal window, log into your cluster's infrastructure node and run the following command:
    mkdir /root/rest_patch
  4. From your local machine (not the infrastructure node terminal window), run the following command:
    scp db2u_rest_entrypoint.sh root@<CLUSTER
              HOSTNAME>:/root/rest_patch/
  5. And then run the following command:
    scp patch_script_cm.sh root@<CLUSTER HOSTNAME>:/root/rest_patch/
  6. Switch back to your infrastructure node terminal window and run the following command:
    cd /root/rest_patch && chmod 777 patch_script_cm.sh && ./patch_script_cm.sh <NAME OF YOUR
              DB2U DEPLOYMENT> <NAMESPACE OF DB2U DEPLOYMENT> db2u_rest_entrypoint.sh /db2u 755
              false

The rest pod re-creates and fixes the problem.