X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/37ab0eedec5eaf99c27b6b64fd04cc9248081713..58e6402a72e9ac1a210b2d318591f973a37e1e57:/lib/boot/postgresql.go diff --git a/lib/boot/postgresql.go b/lib/boot/postgresql.go index df98904151..d105b0b623 100644 --- a/lib/boot/postgresql.go +++ b/lib/boot/postgresql.go @@ -11,7 +11,9 @@ import ( "fmt" "os" "os/exec" + "os/user" "path/filepath" + "strconv" "strings" "time" @@ -34,39 +36,91 @@ func (runPostgreSQL) Run(ctx context.Context, fail func(error), super *Superviso return err } + if super.ClusterType == "production" { + return nil + } + + iamroot := false + if u, err := user.Current(); err != nil { + return fmt.Errorf("user.Current(): %w", err) + } else if u.Uid == "0" { + iamroot = true + } + buf := bytes.NewBuffer(nil) - err = super.RunProgram(ctx, super.tempdir, buf, nil, "pg_config", "--bindir") + err = super.RunProgram(ctx, super.tempdir, runOptions{output: buf}, "pg_config", "--bindir") if err != nil { return err } bindir := strings.TrimSpace(buf.String()) datadir := filepath.Join(super.tempdir, "pgdata") - err = os.Mkdir(datadir, 0755) + err = os.Mkdir(datadir, 0700) if err != nil { return err } - err = super.RunProgram(ctx, super.tempdir, nil, nil, filepath.Join(bindir, "initdb"), "-D", datadir) + prog, args := filepath.Join(bindir, "initdb"), []string{"-D", datadir, "-E", "utf8"} + opts := runOptions{} + if iamroot { + postgresUser, err := user.Lookup("postgres") + if err != nil { + return fmt.Errorf("user.Lookup(\"postgres\"): %s", err) + } + postgresUID, err := strconv.Atoi(postgresUser.Uid) + if err != nil { + return fmt.Errorf("user.Lookup(\"postgres\"): non-numeric uid?: %q", postgresUser.Uid) + } + postgresGid, err := strconv.Atoi(postgresUser.Gid) + if err != nil { + return fmt.Errorf("user.Lookup(\"postgres\"): non-numeric gid?: %q", postgresUser.Gid) + } + err = os.Chown(super.tempdir, 0, postgresGid) + if err != nil { + return err + } + err = os.Chmod(super.tempdir, 0710) + if err != nil { + return err + } + err = os.Chown(datadir, postgresUID, 0) + if err != nil { + return err + } + opts.user = "postgres" + } + err = super.RunProgram(ctx, super.tempdir, opts, prog, args...) if err != nil { return err } - err = super.RunProgram(ctx, super.tempdir, nil, nil, "cp", "server.crt", "server.key", datadir) + err = super.RunProgram(ctx, super.tempdir, runOptions{}, "cp", "server.crt", "server.key", datadir) if err != nil { return err } + if iamroot { + err = super.RunProgram(ctx, super.tempdir, runOptions{}, "chown", "postgres", datadir+"/server.crt", datadir+"/server.key") + if err != nil { + return err + } + } port := super.cluster.PostgreSQL.Connection["port"] super.waitShutdown.Add(1) go func() { defer super.waitShutdown.Done() - fail(super.RunProgram(ctx, super.tempdir, nil, nil, filepath.Join(bindir, "postgres"), + prog, args := filepath.Join(bindir, "postgres"), []string{ "-l", // enable ssl "-D", datadir, // data dir "-k", datadir, // socket dir + "-h", super.cluster.PostgreSQL.Connection["host"], "-p", super.cluster.PostgreSQL.Connection["port"], - )) + } + opts := runOptions{} + if iamroot { + opts.user = "postgres" + } + fail(super.RunProgram(ctx, super.tempdir, opts, prog, args...)) }() for { @@ -78,11 +132,15 @@ func (runPostgreSQL) Run(ctx context.Context, fail func(error), super *Superviso } time.Sleep(time.Second / 2) } - db, err := sql.Open("postgres", arvados.PostgreSQLConnection{ + pgconn := arvados.PostgreSQLConnection{ "host": datadir, "port": port, "dbname": "postgres", - }.String()) + } + if iamroot { + pgconn["user"] = "postgres" + } + db, err := sql.Open("postgres", pgconn.String()) if err != nil { return fmt.Errorf("db open failed: %s", err) } @@ -96,7 +154,7 @@ func (runPostgreSQL) Run(ctx context.Context, fail func(error), super *Superviso if err != nil { return fmt.Errorf("createuser failed: %s", err) } - _, err = conn.ExecContext(ctx, `CREATE DATABASE `+pq.QuoteIdentifier(super.cluster.PostgreSQL.Connection["dbname"])) + _, err = conn.ExecContext(ctx, `CREATE DATABASE `+pq.QuoteIdentifier(super.cluster.PostgreSQL.Connection["dbname"])+` WITH TEMPLATE template0 ENCODING 'utf8'`) if err != nil { return fmt.Errorf("createdb failed: %s", err) }