Skip to content

Commit

Permalink
Allowing the root superuser host and password to be overridden via en…
Browse files Browse the repository at this point in the history
…v vars
  • Loading branch information
fulghum committed Jan 14, 2025
1 parent d4d17aa commit 9eab71d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 26 deletions.
37 changes: 19 additions & 18 deletions docker/serverREADME.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,45 +76,46 @@ Learn more about Dolt use cases, configuration and guides to use dolt on our [do

# How to use this image

This image is for Dolt SQL Server, which is similar to MySQL Docker Image. Running this image without any arguments
is equivalent to running `dolt sql-server --host 0.0.0.0 --port 3306` command locally. The reason for persisted host
and port is that it allows user to connect to the server inside the container from the local host system through
This image is for Dolt SQL Server, which is similar to the MySQL Docker image. Running this image without any arguments
is equivalent to running `dolt sql-server --host 0.0.0.0 --port 3306` command inside a Docker container. The reason for the persisted host
and port is that it allows users to connect to the server inside the container and from the local host system through
port-mapping.

To check out supported options for `dolt sql-server`, you can run the image with `--help` flag.
To see all supported options for `dolt sql-server`, you can run the image with `--help` flag.

```shell
$ docker run dolthub/dolt-sql-server:latest --help
```

### Connect to the server in the container from the host system

To be able to connect to the server running in the container, we need to set up a port to connect to locally that
maps to the port in the container. The host is set to `0.0.0.0` for accepting connections to any available network
interface.
From the host system, to connect to a server running in a container, we need to map a port on the host system to the port our sql-server is running on in the container.

```shell
$ docker run -p 3307:3306 dolthub/dolt-sql-server:latest
We also need a user account that has permission to connect to the server
from the host system's address. By default, as of Dolt version 1.46.0, the `root` superuser is configured to only allow connections from localhost. This is a security feature to prevent unauthorized access to the server. If you don't want to log in to the container and then connect to your sql-server, you can use the `DOLT_ROOT_HOST` and `DOLT_ROOT_PASSWORD` environment variables to control how the `root` superuser is initialized. Note that these environment variables are only used when the sql-server is started for the first time and the `root` superuser account is being initialized. If a privileges database already exists when you start your sql-server, the root user initialization will not occur.

In our example below, we're using `DOLT_ROOT_HOST` to override the host of the `root` superuser account to `%` in order to allow any host to connect to our server and log in as `root`. We're also using `DOLT_ROOT_PASSWORD` to override the default, empty password and specify a password for the `root` account. Setting a password is strongly advised for security when allowing the `root` account to connect from any host.

```bash
> docker run -e DOLT_ROOT_PASSWORD=secret2 -e DOLT_ROOT_HOST=% -p 3307:3306 dolthub/dolt-sql-server:latest
```

Now, you have a running server in the container, and we can connect to it by specifying our host, 3307 for the port, and root for the user,
since that's the default user and we didn't provide any configuration when running the server.
If we run the command above with -d or switch to a separate window we can connect with MySQL:

For example, you can run mysql client to connect to the server like this:
```shell
$ mysql --host 0.0.0.0 -P 3307 -u root
```bash
> mysql --host 0.0.0.0 -P 3307 -u root -p secret2
```

### Define configuration for the server

You can either define server configuration as commandline arguments, or you can use yaml configuration file.
For the commandline argument definition you can simply define arguments after whole docker command.
You can specify server configuration with commandline arguments, or you can use a YAML configuration file.
For commandline arguments, you can simply add arguments at the end of the docker command, as shown below.

```shell
$ docker run -p 3307:3306 dolthub/dolt-sql-server:latest -l debug --no-auto-commit
```

Or, we can mount a local directory to specific directories in the container.
To use a configuration file, you can map a local directory to location in the container.
The special directory for server configuration is `/etc/dolt/servercfg.d/`. You can only have one `.yaml` configuration
file in this directory. If there are multiple, the default configuration will be used. If the location of
configuration file was `/Users/jennifer/docker/server/config.yaml`, this is how to use `-v` flag which mounts
Expand All @@ -127,7 +128,7 @@ $ docker run -p 3307:3306 -v /Users/jennifer/docker/server/:/etc/dolt/servercfg.
The Dolt configuration and data directories can be configured similarly:

- The dolt configuration directory is `/etc/dolt/doltcfg.d/`
There should be one `.json` dolt configuration file. It will replace the global dolt configuration file in the
There should be one `.json` Dolt configuration file. It will replace the global Dolt configuration file in the
container.

- We set the location of where data to be stored to default location at `/var/lib/dolt/` in the container.
Expand Down
22 changes: 20 additions & 2 deletions go/cmd/dolt/commands/sqlserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
remotesapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/remotesapi/v1alpha1"
"github.com/dolthub/dolt/go/libraries/doltcore/dconfig"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/doltcore/remotesrv"
Expand Down Expand Up @@ -397,8 +398,25 @@ func ConfigureServices(
// If no ephemeral superuser has been configured and root user initialization wasn't skipped,
// then create a root@localhost superuser.
if !serverConfig.UserIsSpecified() && !config.SkipRootUserInitialization {
logrus.Info("Creating root@localhost superuser")
mysqlDb.AddSuperUser(ed, servercfg.DefaultUser, "localhost", servercfg.DefaultPass)
// Allow the user to override the default root host (localhost) and password ("").
// This is particularly useful in a Docker container, where you need to connect
// to the sql-server from outside the container and can't rely on localhost.
rootHost := "localhost"
doltRootHost := os.Getenv(dconfig.EnvDoltRootHost)
if doltRootHost != "" {
logrus.Infof("Overriding root user host with value from DOLT_ROOT_HOST: %s", doltRootHost)
rootHost = doltRootHost
}

rootPassword := servercfg.DefaultPass
doltRootPassword := os.Getenv(dconfig.EnvDoltRootPassword)
if doltRootPassword != "" {
logrus.Info("Overriding root user password with value from DOLT_ROOT_PASSWORD")
rootPassword = doltRootPassword
}

logrus.Infof("Creating root@%s superuser", rootHost)
mysqlDb.AddSuperUser(ed, servercfg.DefaultUser, rootHost, rootPassword)
}

// TODO: The in-memory filesystem doesn't work with the GMS API
Expand Down
2 changes: 2 additions & 0 deletions go/libraries/doltcore/dconfig/envvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ const (
EnvDoltAuthorDate = "DOLT_AUTHOR_DATE"
EnvDoltCommitterDate = "DOLT_COMMITTER_DATE"
EnvDbNameReplace = "DOLT_DBNAME_REPLACE"
EnvDoltRootHost = "DOLT_ROOT_HOST"
EnvDoltRootPassword = "DOLT_ROOT_PASSWORD"
)
46 changes: 40 additions & 6 deletions integration-tests/bats/sql-privs.bats
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ teardown() {
teardown_common
}

# Asserts that the root@% superuser is automatically created when a sql-server is started
# Asserts that the root@localhost superuser is automatically created when a sql-server is started
# for the first time and no users are defined yet. As additional users are created, the
# root@% superuser remains and can be manually removed without coming back.
# root@localhost superuser remains and can be manually removed without coming back.
@test "sql-privs: implicit root superuser doesn't disappear after adding users" {
PORT=$( definePORT )
dolt sql-server --port $PORT &
Expand Down Expand Up @@ -98,6 +98,40 @@ teardown() {
[[ $output =~ "| user1 | localhost |" ]] || false
}

# Asserts that the root superuser host and password can be overridden through the DOLT_ROOT_HOST
# and DOLT_ROOT_PASSWORD environment variables, analogues to MySQL's MYSQL_ROOT_HOST and
# MYSQL_ROOT_PASSWORD environment variables. This is primarily provided for use during
# development when running a Dolt sql-server in a Docker container.
@test "sql-privs: root superuser honors DOLT_ROOT_HOST and DOLT_ROOT_PASSWORD" {
PORT=$( definePORT )
export DOLT_ROOT_HOST='%'
export DOLT_ROOT_PASSWORD='Pass1'
dolt sql-server --port $PORT &
SERVER_PID=$!
sleep 1

# Assert that the root user can log in with the overridden password and run a query
run dolt -u root -p Pass1 sql -q "select user, host from mysql.user where user='root';"
[ $status -eq 0 ]
! [[ $output =~ "localhost" ]] || false
[[ $output =~ "| root | % " ]] || false

# Restart the SQL server. Changing DOLT_ROOT_HOST and DOLT_ROOT_PASSWORD here is a no-op,
# since the root superuser was already initialized the previous time sql-server was started.
stop_sql_server 1 && sleep 0.5
dolt sql-server --port $PORT &
SERVER_PID=$!
export DOLT_ROOT_HOST='localhost'
export DOLT_ROOT_PASSWORD='donotuse'
sleep 1

# Assert that root is still configured for any host
run dolt -u root -p Pass1 sql -q "select user, host from mysql.user where user = 'root';"
[ $status -eq 0 ]
! [[ $output =~ "localhost" ]] || false
[[ $output =~ "| root | % " ]] || false
}

# Asserts that creating users via 'dolt sql' before starting a sql-server causes the privileges.db to be
# initialized and prevents the root superuser from being created, since the customer has already started
# manually managing user accounts.
Expand All @@ -117,8 +151,8 @@ teardown() {
[[ $output =~ "| user1 | localhost |" ]] || false
}

# Asserts that the root@% superuser does not get created when a temporary superuser is specified the
# first time a sql-server is started and privileges.db is initialized.
# Asserts that the root@localhost superuser does not get created when a temporary superuser is
# specified the first time a sql-server is started and privileges.db is initialized.
@test "sql-privs: implicit root superuser doesn't get created when specifying a temporary superuser" {
PORT=$( definePORT )
dolt sql-server --port $PORT -u temp1 &
Expand All @@ -131,8 +165,8 @@ teardown() {
! [[ $output =~ "root" ]] || false
}

# Asserts that the root@% superuser is not created when the --skip-default-root-user flag is specified
# when first running sql-server and initializing privileges.db.
# Asserts that the root@localhost superuser is not created when the --skip-default-root-user flag
# is specified when first running sql-server and initializing privileges.db.
@test "sql-privs: implicit root superuser doesn't get created when skipped" {
PORT=$( definePORT )
dolt sql-server --port $PORT --skip-root-user-initialization &
Expand Down

0 comments on commit 9eab71d

Please sign in to comment.