:database-id exposes SQL credentials

I have set up Datomic locally using:

  • MariaDB database as storage
  • default database setup using the bin/sql/mysql-*.sql scripts
  • one transactor, using the MariaDB Java Connector
  • one peer server

I created a “test” database using the bin/shell script and the peer library.

When I use the client library to access the peer server, I can connect:

(require '[datomic.client.api :as d])

(def cfg {:server-type :peer-server
          :access-key "access-key"
          :secret "secret"
          :endpoint "localhost:8998"
          :validate-hostnames false})
(def client (d/client cfg))
(def conn (d/connect client {:db-name "test"}))

However, when I inspect the conn object, I see the full database URI including MariaDB credentials as “database ID”:

user=> conn
{:db-name "test", :database-id "datomic:sql://test?jdbc:mariadb://mariadb:3306/datomic?user=datomic&password=datomic", :t 66, :next-t 1000, :type :datomic.client/conn}

In the docs, the “database ID” is usually represented using a UUID, and was surprised to see the credentials to access storage here. Not only is sensitive data exposed, the “ID” would also change when I rotate the credentials.

Am I missing something?

What do you get when you list-databases on the client?

(d/list-databses client {})

I get a vector of database names:

["test"]

Sorry for my inane question asking you to list-databses! I’ve had a long day and I misunderstood the initial post!

Yes, the connection object will show you your connection string with credentials to storage. This is similar to other connection pools in SQL. This is not what I would consider leaking credentials. You cannot share your connection object.

Yes I think you are missing something you are looking at the connection object. The DB is a value and I believe that is what you are after. For instance (d/db conn):

(def db (d/db conn))
=> #'example/db
db
=> {:t 7, :next-t 8, :db-name "test2", :database-id "1a3eb1a4-d05e-4353-83ac-23a217a7be8e", :type :datomic.client/db}

Also worth noting that most our documentation examples assume that you are using DDB and seeing a UUID for the value of :database-id is an implementation detail of DDB.

Hm, I’m not quite convinced yet :slight_smile:

When using the Peer Library instead of the Client Library to connect to the Storage and Transactor directly, I get a different Database ID:

user=> conn
#object[datomic.peer.Connection 0x8549c5f "{:unsent-updates-queue 0, :pending-txes 0, :next-t 1003, :basis-t 1002, :index-rev 0, :db-id \"test-a31677df-f54c-4add-b448-d65bb0c5c7c3\"}"]

This test-a31677df-f54c-4add-b448-d65bb0c5c7c3 looks more like what I had expected, apparently UUIDs are also used for SQL storage?

The db value of the Client Library exposes the full Database URI including credentials as well:

user=> (d/db conn)
{:t 1002, :next-t 1003, :db-name "test", :database-id "datomic:sql://test?jdbc:mariadb://mariadb:3306/datomic?user=datomic&password=datomic", :type :datomic.client/db}

Looks like this is a behavior of the Peer Server: Using the Datomic Database URI as “Database ID” (unlike the Peer Library)?

I think my concern goes even a bit deeper, as I see the full URI is also logged by datomic, including DB credentials. This just seems unnecessary and a potential security problem to me.

@Fbeyer Thanks for not being convinced! I am going to look more closely at this and get back to you.

1 Like