mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-30 10:45:18 -06:00
Changing to persist a root superuser that gets created on first launch of sql-server when there are no existing privileges.
This commit is contained in:
@@ -63,22 +63,23 @@ type contextFactory func(ctx context.Context, session sql.Session) (*sql.Context
|
||||
type SystemVariables map[string]interface{}
|
||||
|
||||
type SqlEngineConfig struct {
|
||||
IsReadOnly bool
|
||||
IsServerLocked bool
|
||||
DoltCfgDirPath string
|
||||
PrivFilePath string
|
||||
BranchCtrlFilePath string
|
||||
ServerUser string
|
||||
ServerPass string
|
||||
ServerHost string
|
||||
Autocommit bool
|
||||
DoltTransactionCommit bool
|
||||
Bulk bool
|
||||
JwksConfig []servercfg.JwksConfig
|
||||
SystemVariables SystemVariables
|
||||
ClusterController *cluster.Controller
|
||||
BinlogReplicaController binlogreplication.BinlogReplicaController
|
||||
EventSchedulerStatus eventscheduler.SchedulerStatus
|
||||
IsReadOnly bool
|
||||
IsServerLocked bool
|
||||
DoltCfgDirPath string
|
||||
PrivFilePath string
|
||||
BranchCtrlFilePath string
|
||||
ServerUser string
|
||||
ServerPass string
|
||||
ServerHost string
|
||||
SkipRootUserInitialization bool
|
||||
Autocommit bool
|
||||
DoltTransactionCommit bool
|
||||
Bulk bool
|
||||
JwksConfig []servercfg.JwksConfig
|
||||
SystemVariables SystemVariables
|
||||
ClusterController *cluster.Controller
|
||||
BinlogReplicaController binlogreplication.BinlogReplicaController
|
||||
EventSchedulerStatus eventscheduler.SchedulerStatus
|
||||
}
|
||||
|
||||
// NewSqlEngine returns a SqlEngine
|
||||
|
||||
@@ -29,32 +29,33 @@ import (
|
||||
)
|
||||
|
||||
type commandLineServerConfig struct {
|
||||
host string
|
||||
port int
|
||||
user string
|
||||
password string
|
||||
timeout uint64
|
||||
readOnly bool
|
||||
logLevel servercfg.LogLevel
|
||||
dataDir string
|
||||
cfgDir string
|
||||
autoCommit bool
|
||||
doltTransactionCommit bool
|
||||
maxConnections uint64
|
||||
tlsKey string
|
||||
tlsCert string
|
||||
requireSecureTransport bool
|
||||
maxLoggedQueryLen int
|
||||
shouldEncodeLoggedQuery bool
|
||||
privilegeFilePath string
|
||||
branchControlFilePath string
|
||||
allowCleartextPasswords bool
|
||||
socket string
|
||||
remotesapiPort *int
|
||||
remotesapiReadOnly *bool
|
||||
goldenMysqlConn string
|
||||
eventSchedulerStatus string
|
||||
valuesSet map[string]struct{}
|
||||
host string
|
||||
port int
|
||||
user string
|
||||
password string
|
||||
skipRootUserInitialization bool
|
||||
timeout uint64
|
||||
readOnly bool
|
||||
logLevel servercfg.LogLevel
|
||||
dataDir string
|
||||
cfgDir string
|
||||
autoCommit bool
|
||||
doltTransactionCommit bool
|
||||
maxConnections uint64
|
||||
tlsKey string
|
||||
tlsCert string
|
||||
requireSecureTransport bool
|
||||
maxLoggedQueryLen int
|
||||
shouldEncodeLoggedQuery bool
|
||||
privilegeFilePath string
|
||||
branchControlFilePath string
|
||||
allowCleartextPasswords bool
|
||||
socket string
|
||||
remotesapiPort *int
|
||||
remotesapiReadOnly *bool
|
||||
goldenMysqlConn string
|
||||
eventSchedulerStatus string
|
||||
valuesSet map[string]struct{}
|
||||
}
|
||||
|
||||
var _ servercfg.ServerConfig = (*commandLineServerConfig)(nil)
|
||||
@@ -116,6 +117,10 @@ func NewCommandLineConfig(creds *cli.UserPassword, apr *argparser.ArgParseResult
|
||||
config.withPassword(creds.Password)
|
||||
}
|
||||
|
||||
if apr.Contains(skipRootUserInitialization) {
|
||||
config.skipRootUserInitialization = true
|
||||
}
|
||||
|
||||
if port, ok := apr.GetInt(remotesapiPortFlag); ok {
|
||||
config.WithRemotesapiPort(&port)
|
||||
}
|
||||
@@ -202,11 +207,22 @@ func (cfg *commandLineServerConfig) User() string {
|
||||
return cfg.user
|
||||
}
|
||||
|
||||
// UserIsSpecified returns true if the configuration explicitly specified a user.
|
||||
func (cfg *commandLineServerConfig) UserIsSpecified() bool {
|
||||
return cfg.user != ""
|
||||
}
|
||||
|
||||
// Password returns the password that connecting clients must use.
|
||||
func (cfg *commandLineServerConfig) Password() string {
|
||||
return cfg.password
|
||||
}
|
||||
|
||||
// SkipRootUserInitialization returns whether the server should skip creating the implicit root
|
||||
// superuser the first time a sql-server instance is launched.
|
||||
func (cfg *commandLineServerConfig) SkipRootUserInitialization() bool {
|
||||
return cfg.skipRootUserInitialization
|
||||
}
|
||||
|
||||
// ReadTimeout returns the read and write timeouts.
|
||||
func (cfg *commandLineServerConfig) ReadTimeout() uint64 {
|
||||
return cfg.timeout
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -56,6 +57,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqlserver"
|
||||
"github.com/dolthub/dolt/go/libraries/events"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/config"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/svcs"
|
||||
)
|
||||
|
||||
@@ -219,19 +221,20 @@ func ConfigureServices(
|
||||
InitSqlEngineConfig := &svcs.AnonService{
|
||||
InitF: func(context.Context) error {
|
||||
config = &engine.SqlEngineConfig{
|
||||
IsReadOnly: serverConfig.ReadOnly(),
|
||||
PrivFilePath: serverConfig.PrivilegeFilePath(),
|
||||
BranchCtrlFilePath: serverConfig.BranchControlFilePath(),
|
||||
DoltCfgDirPath: serverConfig.CfgDir(),
|
||||
ServerUser: serverConfig.User(),
|
||||
ServerPass: serverConfig.Password(),
|
||||
ServerHost: serverConfig.Host(),
|
||||
Autocommit: serverConfig.AutoCommit(),
|
||||
DoltTransactionCommit: serverConfig.DoltTransactionCommit(),
|
||||
JwksConfig: serverConfig.JwksConfig(),
|
||||
SystemVariables: serverConfig.SystemVars(),
|
||||
ClusterController: clusterController,
|
||||
BinlogReplicaController: binlogreplication.DoltBinlogReplicaController,
|
||||
IsReadOnly: serverConfig.ReadOnly(),
|
||||
PrivFilePath: serverConfig.PrivilegeFilePath(),
|
||||
BranchCtrlFilePath: serverConfig.BranchControlFilePath(),
|
||||
DoltCfgDirPath: serverConfig.CfgDir(),
|
||||
ServerUser: serverConfig.User(),
|
||||
ServerPass: serverConfig.Password(),
|
||||
ServerHost: serverConfig.Host(),
|
||||
Autocommit: serverConfig.AutoCommit(),
|
||||
DoltTransactionCommit: serverConfig.DoltTransactionCommit(),
|
||||
JwksConfig: serverConfig.JwksConfig(),
|
||||
SystemVariables: serverConfig.SystemVars(),
|
||||
ClusterController: clusterController,
|
||||
BinlogReplicaController: binlogreplication.DoltBinlogReplicaController,
|
||||
SkipRootUserInitialization: serverConfig.SkipRootUserInitialization(),
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -363,30 +366,75 @@ func ConfigureServices(
|
||||
}
|
||||
controller.Register(InitBinlogging)
|
||||
|
||||
// Add superuser if specified user exists; add root superuser if no user specified and no existing privileges
|
||||
InitSuperUser := &svcs.AnonService{
|
||||
InitF: func(context.Context) error {
|
||||
userSpecified := config.ServerUser != ""
|
||||
// MySQL creates a root superuser when the mysql install is first initialized. Depending on the options
|
||||
// specified, the root superuser is created without a password, or with a random password. This varies
|
||||
// slightly in some OS-specific installers. Dolt initializes the root superuser the first time a
|
||||
// sql-server is started and initializes its privileges database. We do this on sql-server initialization,
|
||||
// instead of dolt db initialization, because we only want to create the privileges database when it's
|
||||
// used for a server, and because we want the same root initialization logic when a sql-server is started
|
||||
// for a clone. More details: https://dev.mysql.com/doc/mysql-security-excerpt/8.0/en/default-privileges.html
|
||||
//
|
||||
// NOTE: The MySQL root user is created for host 'localhost', not any host ('%'). We could do the same here,
|
||||
// but it seems like it would cause problems for users who want to connect from outside of Docker.
|
||||
InitImplicitRootSuperUser := &svcs.AnonService{
|
||||
InitF: func(ctx context.Context) error {
|
||||
// If privileges.db has already been initialized, indicating that this is NOT the
|
||||
// first time sql-server has been launched, then don't initialize the root superuser.
|
||||
if permissionDbExists, err := doesPrivilegesDbExist(dEnv, serverConfig.PrivilegeFilePath()); err != nil {
|
||||
return err
|
||||
} else if permissionDbExists {
|
||||
logrus.Debug("privileges.db already exists, not creating root superuser")
|
||||
return nil
|
||||
}
|
||||
|
||||
// We always persist the privileges.db file, to signal that the privileges system has been initialized
|
||||
mysqlDb := sqlEngine.GetUnderlyingEngine().Analyzer.Catalog.MySQLDb
|
||||
ed := mysqlDb.Editor()
|
||||
var numUsers int
|
||||
ed.VisitUsers(func(*mysql_db.User) { numUsers += 1 })
|
||||
privsExist := numUsers != 0
|
||||
defer ed.Close()
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// TODO: The in-memory filesystem doesn't work with the GMS API
|
||||
// for persisting the privileges database. The filesys API
|
||||
// is in the Dolt layer, so when the file path is passed to
|
||||
// GMS, it expects it to be a path on disk, and errors out.
|
||||
if _, isInMemFs := dEnv.FS.(*filesys.InMemFS); isInMemFs {
|
||||
return nil
|
||||
} else {
|
||||
sqlCtx, err := sqlEngine.NewDefaultContext(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mysqlDb.Persist(sqlCtx, ed)
|
||||
}
|
||||
},
|
||||
}
|
||||
controller.Register(InitImplicitRootSuperUser)
|
||||
|
||||
// Add an ephemeral superuser if one was requested
|
||||
InitEphemeralSuperUser := &svcs.AnonService{
|
||||
InitF: func(context.Context) error {
|
||||
mysqlDb := sqlEngine.GetUnderlyingEngine().Analyzer.Catalog.MySQLDb
|
||||
ed := mysqlDb.Editor()
|
||||
|
||||
userSpecified := config.ServerUser != ""
|
||||
if userSpecified {
|
||||
superuser := mysqlDb.GetUser(ed, config.ServerUser, "%", false)
|
||||
if userSpecified && superuser == nil {
|
||||
mysqlDb.AddSuperUser(ed, config.ServerUser, "%", config.ServerPass)
|
||||
if superuser == nil {
|
||||
mysqlDb.AddEphemeralSuperUser(ed, config.ServerUser, "%", config.ServerPass)
|
||||
}
|
||||
} else if !privsExist {
|
||||
mysqlDb.AddSuperUser(ed, servercfg.DefaultUser, "%", servercfg.DefaultPass)
|
||||
}
|
||||
ed.Close()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
controller.Register(InitSuperUser)
|
||||
controller.Register(InitEphemeralSuperUser)
|
||||
|
||||
var metListener *metricsListener
|
||||
InitMetricsListener := &svcs.AnonService{
|
||||
@@ -406,7 +454,7 @@ func ConfigureServices(
|
||||
InitF: func(context.Context) error {
|
||||
mysqlDb := sqlEngine.GetUnderlyingEngine().Analyzer.Catalog.MySQLDb
|
||||
ed := mysqlDb.Editor()
|
||||
mysqlDb.AddSuperUser(ed, LocalConnectionUser, "localhost", localCreds.Secret)
|
||||
mysqlDb.AddEphemeralSuperUser(ed, LocalConnectionUser, "localhost", localCreds.Secret)
|
||||
ed.Close()
|
||||
return nil
|
||||
},
|
||||
@@ -859,6 +907,29 @@ func (r *remotesapiAuth) ApiAuthorize(ctx context.Context, superUserRequired boo
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// doesPrivilegesDbExist looks for an existing privileges database as the specified |privilegeFilePath|. If
|
||||
// |privilegeFilePath| is an absolute path, it is used directly. If it is a relative path, then it is resolved
|
||||
// relative to the root of the specified |dEnv|.
|
||||
func doesPrivilegesDbExist(dEnv *env.DoltEnv, privilegeFilePath string) (exists bool, err error) {
|
||||
if !filepath.IsAbs(privilegeFilePath) {
|
||||
privilegeFilePath, err = dEnv.FS.Abs(privilegeFilePath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = os.Stat(privilegeFilePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func LoadClusterTLSConfig(cfg servercfg.ClusterConfig) (*tls.Config, error) {
|
||||
rcfg := cfg.RemotesAPIConfig()
|
||||
if rcfg.TLSKey() == "" && rcfg.TLSCert() == "" {
|
||||
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
const (
|
||||
hostFlag = "host"
|
||||
portFlag = "port"
|
||||
skipRootUserInitialization = "skip-root-user-initialization"
|
||||
passwordFlag = "password"
|
||||
timeoutFlag = "timeout"
|
||||
readonlyFlag = "readonly"
|
||||
@@ -83,7 +84,7 @@ SUPPORTED CONFIG FILE FIELDS:
|
||||
|
||||
{{.EmphasisLeft}}log_level{{.EmphasisRight}}: Level of logging provided. Options are: {{.EmphasisLeft}}trace{{.EmphasisRight}}, {{.EmphasisLeft}}debug{{.EmphasisRight}}, {{.EmphasisLeft}}info{{.EmphasisRight}}, {{.EmphasisLeft}}warning{{.EmphasisRight}}, {{.EmphasisLeft}}error{{.EmphasisRight}}, and {{.EmphasisLeft}}fatal{{.EmphasisRight}}.
|
||||
|
||||
{{.EmphasisLeft}}privilege_file{{.EmphasisRight}}: "Path to a file to load and store users and grants. Defaults to {{.EmphasisLeft}}$doltcfg-dir/privileges.db{{.EmphasisRight}}. Will be created as needed.
|
||||
{{.EmphasisLeft}}privilege_file{{.EmphasisRight}}: "Path to a file to load and store users and grants. Defaults to {{.EmphasisLeft}}$doltcfg-dir/privileges.db{{.EmphasisRight}}. Will be created automatically if it doesn't exist.
|
||||
|
||||
{{.EmphasisLeft}}branch_control_file{{.EmphasisRight}}: Path to a file to load and store branch control permissions. Defaults to {{.EmphasisLeft}}$doltcfg-dir/branch_control.db{{.EmphasisRight}}. Will be created as needed.
|
||||
|
||||
@@ -95,9 +96,9 @@ SUPPORTED CONFIG FILE FIELDS:
|
||||
|
||||
{{.EmphasisLeft}}behavior.dolt_transaction_commit{{.EmphasisRight}}: If true all SQL transaction commits will automatically create a Dolt commit, with a generated commit message. This is useful when a system working with Dolt wants to create versioned data, but doesn't want to directly use Dolt features such as dolt_commit().
|
||||
|
||||
{{.EmphasisLeft}}user.name{{.EmphasisRight}}: The username that connections should use for authentication
|
||||
{{.EmphasisLeft}}user.name{{.EmphasisRight}}: The username for an ephemeral superuser that will exist for the lifetime of the sql-server process. This user will not be persisted to the privileges database.
|
||||
|
||||
{{.EmphasisLeft}}user.password{{.EmphasisRight}}: The password that connections should use for authentication.
|
||||
{{.EmphasisLeft}}user.password{{.EmphasisRight}}: The password for an ephemeral superuser that will exist for the lifetime of the sql-server process. This user will not be persisted to the privileges database.
|
||||
|
||||
{{.EmphasisLeft}}listener.host{{.EmphasisRight}}: The host address that the server will run on. This may be {{.EmphasisLeft}}localhost{{.EmphasisRight}} or an IPv4 or IPv6 address
|
||||
|
||||
@@ -163,6 +164,7 @@ func (cmd SqlServerCmd) ArgParserWithName(name string) *argparser.ArgParser {
|
||||
ap.SupportsString(hostFlag, "H", "host address", fmt.Sprintf("Defines the host address that the server will run on. Defaults to `%v`.", serverConfig.Host()))
|
||||
ap.SupportsUint(portFlag, "P", "port", fmt.Sprintf("Defines the port that the server will run on. Defaults to `%v`.", serverConfig.Port()))
|
||||
ap.SupportsString(commands.UserFlag, "u", "user", fmt.Sprintf("Defines the server user. Defaults to `%v`. This should be explicit if desired.", serverConfig.User()))
|
||||
ap.SupportsFlag(skipRootUserInitialization, "", "Skips the automatic creation of a default root super user on the first launch of a SQL server.")
|
||||
ap.SupportsString(passwordFlag, "p", "password", fmt.Sprintf("Defines the server password. Defaults to `%v`.", serverConfig.Password()))
|
||||
ap.SupportsInt(timeoutFlag, "t", "connection timeout", fmt.Sprintf("Defines the timeout, in seconds, used for connections\nA value of `0` represents an infinite timeout. Defaults to `%v`.", serverConfig.ReadTimeout()))
|
||||
ap.SupportsFlag(readonlyFlag, "r", "Disable modification of the database.")
|
||||
@@ -381,6 +383,12 @@ func getServerConfig(cwdFS filesys.Filesys, apr *argparser.ArgParseResults, data
|
||||
}
|
||||
}
|
||||
|
||||
if apr.Contains(skipRootUserInitialization) {
|
||||
if wcfg, ok := cfg.(servercfg.WritableServerConfig); ok {
|
||||
wcfg.SetSkipRootUserInitialization(true)
|
||||
}
|
||||
}
|
||||
|
||||
if connStr, ok := apr.GetValue(goldenMysqlConn); ok {
|
||||
if yamlCfg, ok := cfg.(servercfg.YAMLConfig); ok {
|
||||
cli.Println(connStr)
|
||||
|
||||
@@ -291,7 +291,7 @@ func newLateBindingEngine(
|
||||
dbUser = DefaultUser
|
||||
ed := rawDb.Editor()
|
||||
defer ed.Close()
|
||||
rawDb.AddSuperUser(ed, dbUser, config.ServerHost, "")
|
||||
rawDb.AddEphemeralSuperUser(ed, dbUser, config.ServerHost, "")
|
||||
}
|
||||
|
||||
// Set client to specified user
|
||||
|
||||
@@ -125,8 +125,13 @@ type ServerConfig interface {
|
||||
Port() int
|
||||
// User returns the username that connecting clients must use.
|
||||
User() string
|
||||
// UserIsSpecified returns true if a user was explicitly provided in the configuration.
|
||||
UserIsSpecified() bool
|
||||
// Password returns the password that connecting clients must use.
|
||||
Password() string
|
||||
// SkipRootUserInitialization returns whether the server should skip initializing the default root superuser.
|
||||
// This option is only valid the first time a sql-server is started, when the root user is being initialized.
|
||||
SkipRootUserInitialization() bool
|
||||
// ReadTimeout returns the read timeout in milliseconds
|
||||
ReadTimeout() uint64
|
||||
// WriteTimeout returns the write timeout in milliseconds
|
||||
@@ -239,6 +244,9 @@ type WritableServerConfig interface {
|
||||
SetUserName(string)
|
||||
// SetPassword sets the password for servers with no other auth established
|
||||
SetPassword(string)
|
||||
// SetSkipRootUserInitialization controls whether the default root superuser should be initialized,
|
||||
// or if it should be skipped and not created.
|
||||
SetSkipRootUserInitialization(bool)
|
||||
}
|
||||
|
||||
type ValidatingServerConfig interface {
|
||||
|
||||
@@ -14,6 +14,7 @@ BehaviorConfig servercfg.BehaviorYAMLConfig 0.0.0 behavior,omitempty
|
||||
UserConfig servercfg.UserYAMLConfig 0.0.0 user,omitempty
|
||||
-Name *string 0.0.0 name,omitempty
|
||||
-Password *string 0.0.0 password,omitempty
|
||||
SkipRootUserInit *bool 0.0.0 skip_root_user_initialization,omitempty
|
||||
ListenerConfig servercfg.ListenerYAMLConfig 0.0.0 listener,omitempty
|
||||
-HostStr *string 0.0.0 host,omitempty
|
||||
-PortNumber *int 0.0.0 port,omitempty
|
||||
|
||||
@@ -129,6 +129,7 @@ type YAMLConfig struct {
|
||||
EncodeLoggedQuery *bool `yaml:"encode_logged_query,omitempty"`
|
||||
BehaviorConfig BehaviorYAMLConfig `yaml:"behavior,omitempty"`
|
||||
UserConfig UserYAMLConfig `yaml:"user,omitempty"`
|
||||
SkipRootUserInit *bool `yaml:"skip_root_user_initialization,omitempty"`
|
||||
ListenerConfig ListenerYAMLConfig `yaml:"listener,omitempty"`
|
||||
PerformanceConfig *PerformanceYAMLConfig `yaml:"performance,omitempty"`
|
||||
DataDirStr *string `yaml:"data_dir,omitempty"`
|
||||
@@ -584,6 +585,27 @@ func (cfg YAMLConfig) User() string {
|
||||
return *cfg.UserConfig.Name
|
||||
}
|
||||
|
||||
// UserIsSpecified returns true if the configuration explicitly specified a user.
|
||||
func (cfg YAMLConfig) UserIsSpecified() bool {
|
||||
return cfg.UserConfig.Name != nil
|
||||
}
|
||||
|
||||
// SkipRootUserInitialization returns whether the server should skip initializing the default, root
|
||||
// superuser.
|
||||
func (cfg YAMLConfig) SkipRootUserInitialization() bool {
|
||||
if cfg.SkipRootUserInit == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return *cfg.SkipRootUserInit
|
||||
}
|
||||
|
||||
// SetSkipRootUserInitialization sets whether the server should skip initializing the default, root
|
||||
// superuser.
|
||||
func (cfg YAMLConfig) SetSkipRootUserInitialization(b bool) {
|
||||
cfg.SkipRootUserInit = &b
|
||||
}
|
||||
|
||||
func (cfg *YAMLConfig) SetUserName(s string) {
|
||||
cfg.UserConfig.Name = &s
|
||||
}
|
||||
|
||||
@@ -325,6 +325,7 @@ func TestYAMLConfigDefaults(t *testing.T) {
|
||||
assert.Equal(t, DefaultHost, cfg.Host())
|
||||
assert.Equal(t, DefaultPort, cfg.Port())
|
||||
assert.Equal(t, DefaultUser, cfg.User())
|
||||
assert.False(t, cfg.UserIsSpecified())
|
||||
assert.Equal(t, DefaultPass, cfg.Password())
|
||||
assert.Equal(t, uint64(DefaultTimeout), cfg.WriteTimeout())
|
||||
assert.Equal(t, uint64(DefaultTimeout), cfg.ReadTimeout())
|
||||
|
||||
@@ -263,7 +263,7 @@ SQL
|
||||
[ $status -eq 0 ]
|
||||
[[ $output =~ '| repo1 | eventTest1 | `__dolt_local_user__`@`localhost` | SYSTEM | RECURRING | NULL | 1 | SECOND | 2020-02-20 00:00:00 | NULL | ENABLED | 0 | utf8mb4 | utf8mb4_0900_bin | utf8mb4_0900_bin |' ]] || false
|
||||
|
||||
# Sleep for a few seconds to give the scheduler timer to run this event and verify that it executed
|
||||
# Sleep for a few seconds to give the scheduler time to run this event and verify that it executed
|
||||
sleep 2
|
||||
run dolt sql -q "SELECT (SELECT COUNT(*) FROM totals) > 0;"
|
||||
[ $status -eq 0 ]
|
||||
@@ -286,7 +286,7 @@ SQL
|
||||
run dolt sql -q "SHOW EVENTS;"
|
||||
[[ $output =~ '| repo1 | eventTest1 | `__dolt_local_user__`@`localhost` | SYSTEM | RECURRING | NULL | 1 | SECOND | 2020-02-20 00:00:00 | NULL | ENABLED | 0 | utf8mb4 | utf8mb4_0900_bin | utf8mb4_0900_bin |' ]] || false
|
||||
|
||||
# Sleep for a few seconds to give the scheduler timer to run this event and verify that it is still enabled
|
||||
# Sleep for a few seconds to give the scheduler time to run this event and verify that it is still enabled
|
||||
sleep 2
|
||||
run dolt sql -q "SHOW EVENTS"
|
||||
[ $status -eq 0 ]
|
||||
|
||||
@@ -145,17 +145,17 @@ get_commit_hash_at() {
|
||||
|
||||
stop_sql_server 1
|
||||
|
||||
run dolt --verbose-engine-setup --data-dir="$ROOT_DIR" --user dolt --password "" --use-db altDB sql -q "show tables"
|
||||
run dolt --verbose-engine-setup --data-dir="$ROOT_DIR" --use-db altDB sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "starting local mode" ]] || false
|
||||
[[ "$output" =~ "altDB_tbl" ]] || false
|
||||
|
||||
run dolt --verbose-engine-setup --data-dir="$ROOT_DIR" --user dolt --password "" --use-db defaultDB sql -q "show tables"
|
||||
run dolt --verbose-engine-setup --data-dir="$ROOT_DIR" --use-db defaultDB sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "starting local mode" ]] || false
|
||||
[[ "$output" =~ "defaultDB_tbl" ]] || false
|
||||
|
||||
run dolt --verbose-engine-setup --data-dir="$ROOT_DIR" --user dolt --password "" sql -q "show tables"
|
||||
run dolt --verbose-engine-setup --data-dir="$ROOT_DIR" sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "starting local mode" ]] || false
|
||||
[[ "$output" =~ "altDB_tbl" ]] || false
|
||||
@@ -310,7 +310,7 @@ get_commit_hash_at() {
|
||||
[ "$status" -eq 0 ] || false
|
||||
localOutput=$output
|
||||
|
||||
run dolt --user dolt --password "" status --ignored
|
||||
run dolt status --ignored
|
||||
[ "$status" -eq 0 ] || false
|
||||
localIgnoredOutput=$output
|
||||
|
||||
@@ -376,11 +376,11 @@ get_commit_hash_at() {
|
||||
|
||||
stop_sql_server 1
|
||||
|
||||
run dolt --verbose-engine-setup --user dolt --password "" branch b2
|
||||
run dolt --verbose-engine-setup branch b2
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "starting local mode" ]] || false
|
||||
|
||||
run dolt --verbose-engine-setup --user dolt --password "" branch
|
||||
run dolt --verbose-engine-setup branch
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "starting local mode" ]] || false
|
||||
[[ "$output" =~ "main" ]] || false
|
||||
|
||||
@@ -53,35 +53,106 @@ teardown() {
|
||||
teardown_common
|
||||
}
|
||||
|
||||
@test "sql-privs: default user is root. create new user destroys default user." {
|
||||
make_test_repo
|
||||
# Asserts that the root@% 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.
|
||||
@test "sql-privs: implicit root superuser doesn't disappear after adding users" {
|
||||
PORT=$( definePORT )
|
||||
dolt sql-server --host 0.0.0.0 --port=$PORT &
|
||||
SERVER_PID=$! # will get killed by teardown_common
|
||||
SQL_USER='root'
|
||||
wait_for_connection $PORT 8500
|
||||
dolt sql-server --port $PORT &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
run dolt sql -q "select user from mysql.user order by user"
|
||||
# Assert that the root user can log in and run a query
|
||||
run dolt -u root sql -q "select user, host from mysql.user where user='root';"
|
||||
[ $status -eq 0 ]
|
||||
[[ $output =~ "root" ]] || false
|
||||
[[ $output =~ "| root | localhost |" ]] || false
|
||||
|
||||
dolt sql -q "create user new_user"
|
||||
run dolt sql -q "select user from mysql.user order by user"
|
||||
# Create a new user
|
||||
dolt -u root sql -q "CREATE USER user1@localhost; GRANT ALL PRIVILEGES on *.* to user1@localhost;"
|
||||
|
||||
# Restart the SQL server
|
||||
stop_sql_server 1 && sleep 0.5
|
||||
dolt sql-server --port $PORT &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
# Assert that both users are still present
|
||||
run dolt -u root sql -q "select user, host from mysql.user where user in ('root', 'user1');"
|
||||
[ $status -eq 0 ]
|
||||
[[ $output =~ "root" ]] || false
|
||||
[[ $output =~ "new_user" ]] || false
|
||||
[[ $output =~ "| root | localhost |" ]] || false
|
||||
[[ $output =~ "| user1 | localhost |" ]] || false
|
||||
|
||||
stop_sql_server
|
||||
# Delete the root user
|
||||
dolt -u root sql -q "DROP USER root@localhost;"
|
||||
|
||||
# Restart the SQL server
|
||||
stop_sql_server 1 && sleep 0.5
|
||||
dolt sql-server --port $PORT &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
# Assert that the root user is gone
|
||||
run dolt -u user1 sql -q "select user, host from mysql.user where user in ('root', 'user1');"
|
||||
[ $status -eq 0 ]
|
||||
! [[ $output =~ "root" ]] || false
|
||||
[[ $output =~ "| user1 | localhost |" ]] || 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.
|
||||
@test "sql-privs: implicit root superuser doesn't get created when users are created before the server starts" {
|
||||
dolt sql -q "CREATE USER user1@localhost; GRANT ALL PRIVILEGES on *.* to user1@localhost;"
|
||||
|
||||
# restarting server
|
||||
PORT=$( definePORT )
|
||||
dolt sql-server --host 0.0.0.0 --port=$PORT &
|
||||
SERVER_PID=$! # will get killed by teardown_common
|
||||
SQL_USER='new_user'
|
||||
wait_for_connection $PORT 8500
|
||||
dolt sql-server --port $PORT &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
run dolt -u root sql -q "select user from mysql.user order by user"
|
||||
# Assert that the root superuser was not automatically created
|
||||
run dolt -u user1 sql -q "select user, host from mysql.user where user in ('root', 'user1');"
|
||||
echo "OUTPUT: $output"
|
||||
[ $status -eq 0 ]
|
||||
! [[ $output =~ "root" ]] || false
|
||||
[[ $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.
|
||||
@test "sql-privs: implicit root superuser doesn't get created when specifying a temporary superuser" {
|
||||
PORT=$( definePORT )
|
||||
dolt sql-server --port $PORT -u temp1 &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
# Assert that there is no root user
|
||||
run dolt -u temp1 sql -q "select user, host from mysql.user where user='root';"
|
||||
[ $status -eq 0 ]
|
||||
! [[ $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.
|
||||
@test "sql-privs: implicit root superuser doesn't get created when skipped" {
|
||||
PORT=$( definePORT )
|
||||
dolt sql-server --port $PORT --skip-root-user-initialization &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
# Assert that the root user cannot log in
|
||||
run dolt -u root sql -q "select user, host from mysql.user where user='root';"
|
||||
[ $status -ne 0 ]
|
||||
|
||||
# Restart the SQL server with a temporary superuser
|
||||
stop_sql_server 1 && sleep 0.5
|
||||
dolt sql-server --port $PORT --u user1 &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
# Assert that there is no root user
|
||||
run dolt -u user1 sql -q "select user, host from mysql.user where user='root';"
|
||||
[ $status -eq 0 ]
|
||||
! [[ $output =~ "root" ]] || false
|
||||
}
|
||||
|
||||
# Asserts that `dolt sql` can always be used to access the database as a superuser. For example, if the root
|
||||
@@ -258,6 +329,7 @@ behavior:
|
||||
[[ $output =~ dolt ]] || false
|
||||
[[ $output =~ new_user ]] || false
|
||||
[[ $output =~ privs_user ]] || false
|
||||
[[ $output =~ __dolt_local_user__ ]] || false
|
||||
}
|
||||
|
||||
@test "sql-privs: errors instead of panic when reading badly formatted privilege file" {
|
||||
@@ -276,7 +348,7 @@ behavior:
|
||||
start_sql_server test_db
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
[[ "$output" =~ ".doltcfg" ]] || false
|
||||
|
||||
run dolt sql -q "select user from mysql.user"
|
||||
[ $status -eq 0 ]
|
||||
@@ -334,7 +406,7 @@ behavior:
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
|
||||
run ls -a db_dir
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
[[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
|
||||
run dolt -u dolt --port $PORT --host 0.0.0.0 --no-tls --use-db db1 sql -q "show databases"
|
||||
@@ -375,7 +447,7 @@ behavior:
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "doltcfgdir" ]] || false
|
||||
[[ "$output" =~ "doltcfgdir" ]] || false
|
||||
|
||||
run dolt sql -q "select user from mysql.user"
|
||||
[ $status -eq 0 ]
|
||||
@@ -402,8 +474,12 @@ behavior:
|
||||
start_sql_server_with_args --host 0.0.0.0 --user=dolt --privilege-file=privs.db
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "privs.db" ]] || false
|
||||
[[ "$output" =~ ".doltcfg" ]] || false
|
||||
[[ "$output" =~ "privs.db" ]] || false
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
|
||||
run ls .doltcfg
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
|
||||
run dolt sql -q "select user from mysql.user"
|
||||
[ $status -eq 0 ]
|
||||
@@ -415,6 +491,7 @@ behavior:
|
||||
[ $status -eq 0 ]
|
||||
[[ $output =~ dolt ]] || false
|
||||
[[ $output =~ new_user ]] || false
|
||||
! [[ $output =~ root ]] || false
|
||||
|
||||
run ls -a
|
||||
[[ "$output" =~ ".doltcfg" ]] || false
|
||||
@@ -428,7 +505,7 @@ behavior:
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "doltcfgdir" ]] || false
|
||||
[[ "$output" =~ "doltcfgdir" ]] || false
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
|
||||
run ls -a db_dir
|
||||
@@ -474,10 +551,10 @@ behavior:
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "privs.db" ]] || false
|
||||
[[ "$output" =~ "privs.db" ]] || false
|
||||
|
||||
run ls -a db_dir
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
[[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "privs.db" ]] || false
|
||||
|
||||
run dolt -u dolt --port $PORT --host 0.0.0.0 --no-tls --use-db db1 sql -q "show databases"
|
||||
@@ -518,8 +595,9 @@ behavior:
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "doltcfgdir" ]] || false
|
||||
! [[ "$output" =~ "privs.db" ]] || false
|
||||
[[ "$output" =~ "doltcfgdir" ]] || false
|
||||
[[ "$output" =~ "privs.db" ]] || false
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
|
||||
run dolt sql -q "select user from mysql.user"
|
||||
[ $status -eq 0 ]
|
||||
@@ -549,9 +627,9 @@ behavior:
|
||||
|
||||
run ls -a
|
||||
! [[ "$output" =~ ".doltcfg" ]] || false
|
||||
! [[ "$output" =~ "doltcfgdir" ]] || false
|
||||
[[ "$output" =~ "doltcfgdir" ]] || false
|
||||
! [[ "$output" =~ "privileges.db" ]] || false
|
||||
! [[ "$output" =~ "privs.db" ]] || false
|
||||
[[ "$output" =~ "privs.db" ]] || false
|
||||
|
||||
run dolt -u dolt --port $PORT --host 0.0.0.0 --no-tls --use-db db1 sql -q "show databases"
|
||||
[ $status -eq 0 ]
|
||||
|
||||
@@ -711,7 +711,7 @@ SQL
|
||||
|
||||
# verify changes outside the session
|
||||
cd newdb
|
||||
run dolt --user=dolt sql -q "show tables"
|
||||
run dolt sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
}
|
||||
@@ -1095,7 +1095,7 @@ END""")
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "new table a" ]] || false
|
||||
|
||||
run dolt --user=dolt sql -q "show tables"
|
||||
run dolt sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "a" ]] || false
|
||||
|
||||
@@ -1104,7 +1104,7 @@ END""")
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "new table b" ]] || false
|
||||
|
||||
run dolt --user=dolt sql -q "show tables"
|
||||
run dolt sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "b" ]] || false
|
||||
|
||||
@@ -1337,7 +1337,7 @@ END""")
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "new table a" ]] || false
|
||||
|
||||
run dolt --user=dolt sql -q "show tables"
|
||||
run dolt sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "a" ]] || false
|
||||
|
||||
@@ -1346,7 +1346,7 @@ END""")
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "new table b" ]] || false
|
||||
|
||||
run dolt --user=dolt sql -q "show tables"
|
||||
run dolt sql -q "show tables"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "b" ]] || false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user