Add ability to disable pushes through the remoteapi (on by default)

This commit is contained in:
Neil Macneale IV
2023-12-12 10:45:59 -08:00
parent 25416c9a1e
commit 29548e2797
5 changed files with 59 additions and 5 deletions
+2 -3
View File
@@ -379,9 +379,8 @@ func Serve(
port := *serverConfig.RemotesapiPort()
listenaddr := fmt.Sprintf(":%d", port)
args, err := sqle.RemoteSrvServerArgs(sqlEngine.NewDefaultContext, remotesrv.ServerArgs{
Logger: logrus.NewEntry(lgr),
// NM4 - make this configurable. false by default, but can be set to true by the paranoid.
ReadOnly: false,
Logger: logrus.NewEntry(lgr),
ReadOnly: serverConfig.RemotesapiReadOnly() || serverConfig.ReadOnly(),
HttpListenAddr: listenaddr,
GrpcListenAddr: listenaddr,
})
@@ -163,6 +163,8 @@ type ServerConfig interface {
// as a dolt remote for things like `clone`, `fetch` and read
// replication.
RemotesapiPort() *int
// RemotesapiReadOnly is true if the remotesapi interface should be read only.
RemotesapiReadOnly() bool
// ClusterConfig is the configuration for clustering in this sql-server.
ClusterConfig() cluster.Config
// EventSchedulerStatus is the configuration for enabling or disabling the event scheduler in this server.
@@ -201,6 +203,7 @@ type commandLineServerConfig struct {
allowCleartextPasswords bool
socket string
remotesapiPort *int
remotesapiReadOnly bool
goldenMysqlConn string
eventSchedulerStatus string
}
@@ -326,6 +329,10 @@ func (cfg *commandLineServerConfig) RemotesapiPort() *int {
return cfg.remotesapiPort
}
func (cfg *commandLineServerConfig) RemotesapiReadOnly() bool {
return cfg.remotesapiReadOnly
}
func (cfg *commandLineServerConfig) ClusterConfig() cluster.Config {
return nil
}
@@ -475,6 +482,11 @@ func (cfg *commandLineServerConfig) WithRemotesapiPort(port *int) *commandLineSe
return cfg
}
func (cfs *commandLineServerConfig) WithRemotesapiReadOnly(readonly bool) *commandLineServerConfig {
cfs.remotesapiReadOnly = readonly
return cfs
}
func (cfg *commandLineServerConfig) goldenMysqlConnectionString() string {
return cfg.goldenMysqlConn
}
@@ -48,6 +48,7 @@ const (
allowCleartextPasswordsFlag = "allow-cleartext-passwords"
socketFlag = "socket"
remotesapiPortFlag = "remotesapi-port"
remotesapiReadOnlyFlag = "remotesapi-readonly"
goldenMysqlConn = "golden"
eventSchedulerStatus = "event-scheduler"
)
@@ -109,6 +110,8 @@ SUPPORTED CONFIG FILE FIELDS:
{{.EmphasisLeft}}remotesapi.port{{.EmphasisRight}}: A port to listen for remote API operations on. If set to a positive integer, this server will accept connections from clients to clone, pull, etc. databases being served.
{{.EmphasisLeft}}remotesapi.read_only{{.EmphasisRight}}: Boolean flag which disables the ability to perform pushes against the server.
{{.EmphasisLeft}}user_session_vars{{.EmphasisRight}}: A map of user name to a map of session variables to set on connection for each session.
{{.EmphasisLeft}}cluster{{.EmphasisRight}}: Settings related to running this server in a replicated cluster. For information on setting these values, see https://docs.dolthub.com/sql-reference/server/replication
@@ -167,6 +170,7 @@ func (cmd SqlServerCmd) ArgParserWithName(name string) *argparser.ArgParser {
ap.SupportsString(allowCleartextPasswordsFlag, "", "allow-cleartext-passwords", "Allows use of cleartext passwords. Defaults to false.")
ap.SupportsOptionalString(socketFlag, "", "socket file", "Path for the unix socket file. Defaults to '/tmp/mysql.sock'.")
ap.SupportsUint(remotesapiPortFlag, "", "remotesapi port", "Sets the port for a server which can expose the databases in this sql-server over remotesapi, so that clients can clone or pull from this server.")
ap.SupportsFlag(remotesapiReadOnlyFlag, "", "Disable writes to the sql-server via the push operations. SQL writes are unaffected by this setting.")
ap.SupportsString(goldenMysqlConn, "", "mysql connection string", "Provides a connection string to a MySQL instance to be used to validate query results")
ap.SupportsString(eventSchedulerStatus, "", "status", "Determines whether the Event Scheduler is enabled and running on the server. It has one of the following values: 'ON', 'OFF' or 'DISABLED'.")
return ap
@@ -430,6 +434,9 @@ func getCommandLineConfig(creds *cli.UserPassword, apr *argparser.ArgParseResult
if port, ok := apr.GetInt(remotesapiPortFlag); ok {
config.WithRemotesapiPort(&port)
}
if _, ok := apr.GetValue(remotesapiReadOnlyFlag); ok {
config.WithRemotesapiReadOnly(true)
}
if persistenceBehavior, ok := apr.GetValue(persistenceBehaviorFlag); ok {
config.withPersistenceBehavior(persistenceBehavior)
@@ -456,6 +463,7 @@ func getCommandLineConfig(creds *cli.UserPassword, apr *argparser.ArgParseResult
if _, ok := apr.GetValue(readonlyFlag); ok {
config.withReadOnly(true)
config.WithRemotesapiReadOnly(true)
}
if logLevel, ok := apr.GetValue(logLevelFlag); ok {
+12 -2
View File
@@ -126,13 +126,18 @@ type MetricsYAMLConfig struct {
}
type RemotesapiYAMLConfig struct {
Port_ *int `yaml:"port"`
Port_ *int `yaml:"port"`
ReadOnly_ bool `yaml:"read_only"`
}
func (r RemotesapiYAMLConfig) Port() int {
return *r.Port_
}
func (r RemotesapiYAMLConfig) ReadOnly() bool {
return r.ReadOnly_
}
type UserSessionVars struct {
Name string `yaml:"name"`
Vars map[string]string `yaml:"vars"`
@@ -214,7 +219,8 @@ func serverConfigAsYAMLConfig(cfg ServerConfig) YAMLConfig {
Port: intPtr(cfg.MetricsPort()),
},
RemotesapiConfig: RemotesapiYAMLConfig{
Port_: cfg.RemotesapiPort(),
Port_: cfg.RemotesapiPort(),
ReadOnly_: cfg.RemotesapiReadOnly(),
},
ClusterCfg: clusterConfigAsYAMLConfig(cfg.ClusterConfig()),
PrivilegeFile: strPtr(cfg.PrivilegeFilePath()),
@@ -413,6 +419,10 @@ func (cfg YAMLConfig) RemotesapiPort() *int {
return cfg.RemotesapiConfig.Port_
}
func (cfg YAMLConfig) RemotesapiReadOnly() bool {
return cfg.RemotesapiConfig.ReadOnly_
}
// PrivilegeFilePath returns the path to the file which contains all needed privilege information in the form of a
// JSON string.
func (cfg YAMLConfig) PrivilegeFilePath() string {
@@ -510,3 +510,28 @@ GRANT CLONE_ADMIN ON *.* TO clone_admin_user@'localhost';
dolt push origin --user clone_admin_user main:main
}
@test "sql-server-remotesrv: push to remotesapi fails when server is read only" {
mkdir remote
cd remote
dolt init
dolt sql -q 'create table names (name varchar(10) primary key);'
dolt sql -q 'insert into names (name) values ("abe"), ("betsy"), ("calvin");'
dolt add names
dolt commit -m 'initial names.'
APIPORT=$( definePORT )
export DOLT_REMOTE_PASSWORD="rootpass"
export SQL_USER="root"
start_sql_server_with_args -u "$SQL_USER" -p "$DOLT_REMOTE_PASSWORD" --remotesapi-port $APIPORT --remotesapi-readonly
cd ../
dolt clone http://localhost:$APIPORT/remote cloned_db -u "$SQL_USER"
cd cloned_db
dolt sql -q 'insert into names values ("dave");'
dolt commit -am 'add dave'
run dolt push origin --user "$SQL_USER" main:main
[[ "$status" -ne 0 ]] || false
[[ "$output" =~ "this server only provides read-only access" ]] || false
}