Docker Liquibase image Certificates issue with SQL Server

I’m trying to use the latest liquibase docker image to connect to a base sql server image but get the following when trying to connect. I know this error is related to the certificate chain and could install the certs into the keystore myself but I would expect the liquibase image to have this by default.
Also if you google the stacktrace it says as a workaround to put trustServerCertificate=true into the url but this doesn’t work.

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
2023-04-18 17:08:45     at java.base/sun.security.validator.PKIXValidator.doBuild(Unknown Source)
2023-04-18 17:08:45     at java.base/sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
2023-04-18 17:08:45     at java.base/sun.security.validator.Validator.validate(Unknown Source)
2023-04-18 17:08:45     at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
2023-04-18 17:08:45     at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
2023-04-18 17:08:45     at com.microsoft.sqlserver.jdbc.HostNameOverrideX509TrustManager.checkServerTrusted(SQLServerTrustManager.java:86)
2023-04-18 17:08:45     at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown Source)

Here’s my docker compose file. As an aside I’ve tried the liquibase image with a base postgres image and all works fine with a practically identical docker compose file.

services:

  mssql-db:
    container_name: mssql-base-image
    image: mcr.microsoft.com/mssql/server:latest
    networks:
     - dbnet
    ports:
      - "1433:1433"
    environment:
      - ACCEPT_EULA=Y
      - MSSQL_SA_PASSWORD=Password!

  db-update-mssql:
    container_name: update-mssql
    image: liquibase/liquibase:latest
    networks:
     - dbnet
    depends_on:
      mssql-db:
        condition: service_started
    volumes:
      - C:\[some path]\liquibase\changelog:/liquibase/changelog
    command: --log-level=FINE --changelog-file=master-changelog.xml update --url=jdbc:sqlserver://mssql-db:1433;trustServerCertificate=true;user=sa;password=Password!;

networks: 
  dbnet:
    ipam:
      driver: default

As in this works fine to postgres

services:

  postgres-db:
    container_name: postgres-base-image
    image: postgres
    restart: always
    networks:
     - dbnet
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: example
      
  db-update-postgres:
    container_name: update-postgres
    image: liquibase/liquibase:latest
    networks:
     - dbnet
    depends_on:
      postgres-db:
        condition: service_started
    volumes:
      - C:\[some path]\liquibase\changelog:/liquibase/changelog
    command: --log-level=FINE --changelog-file=master-changelog.xml update --url=jdbc:postgresql://postgres-db:5432/postgres --username=postgres --password=example;
 
networks: 
  dbnet:
    ipam:
      driver: default

Hi @markmann

Please check to make sure that you have the most recent JDBC driver, just in case the version you have isn’t respecting that trustServerCertificate flag.

You could also try adding

encrypt=false

into the JDBC URL for SqlServer.

- PJ

1 Like

I would expect the latest liquibase docker image to have the latest sql server jdbc driver by default. Looking at it has 12.2.0 which is the latest.

I’ve also tried encrypt=false and various other suggested combinations and it doesn’t work.

Whether this is just the way it logs but it only shows the base url never the full url with trustServerCertificate etc. So whether liquibase is ignoring those parameters I don’t know?

FINE [liquibase.database] Connecting to the URL:'jdbc:sqlserver://mssql-db:1433' using driver:'com.microsoft.sqlserver.jdbc.SQLServerDriver'

I’ve tried older versions of the docker image and get the same error. So either it’s something wrong with my set up (try it using the docker compose file above) or the image just doesn’t work with sql server.

So I found that to get it to respect the trustServerCerticate param in the url you have to set it as an environment variable. Note that this isn’t a solution for other environments where I need it to respect the certificate chain but at least this gets me working locally. I think this is definitely a bug btw.

services:

  mssql-db:
    container_name: mssql-base-image
    image: mcr.microsoft.com/mssql/server:latest
    networks:
     - dbnet
    ports:
      - "1433:1433"
    environment:
      - ACCEPT_EULA=Y
      - MSSQL_SA_PASSWORD=Password!

  db-update-mssql:
    container_name: update-mssql
    image: liquibase/liquibase:latest
    networks:
     - dbnet
    depends_on:
      mssql-db:
        condition: service_started
    environment:
      # have to put the url here as an env variable otherwise trustServerCertificate isn't read if --url used directly in command below
      - LIQUIBASE_COMMAND_URL=jdbc:sqlserver://mssql-db:1433;encrypt=true;trustServerCertificate=true;user=sa;password=Password!;
      - LIQUIBASE_COMMAND_CHANGELOG_FILE=master-changelog.xml
      - LIQUIBASE_LOG_LEVEL=FINE
    volumes:
      - C:\[some path]liquibase\changelog:/liquibase/changelog
    command: update

networks: 
  dbnet:
    ipam:
      driver: default