Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go/oasis-node/cmd/node: Do not allow running oasis-node as root #4559

Merged
merged 1 commit into from
Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changelog/4464.cfg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
go/oasis-node/cmd/node: Do not allow running oasis-node as root

Nothing in oasis-node will ever require elevated privileges. Attempting
to run a node as the root user will now terminate the node immediately
on startup. While there may be specific circumstances where it is safe
to run network services with the effective user ID set to 0, the
overwelming majority of cases where this is done is misconfiguration.

If the previous behavior is required, the binary must be run in
unsafe/debug mode (via the intentionally undocumented flag), and
`debug.allow_root` must also be set.
6 changes: 6 additions & 0 deletions .changelog/4464.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
go/oasis-node/cmd/node: Do not allow running oasis-node as root

Running network accessible services as the root user is extremely
bad for system security as a general rule. While it would be "ok"
if we can drop privileges, `syscall.AllThreadsSyscall` does not
work if the binary uses cgo at all.
8 changes: 8 additions & 0 deletions go/oasis-node/cmd/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,11 @@ func SetBasicVersionTemplate(cmd *cobra.Command) {
Go toolchain version: {{ toolchain }}
`)
}

// IsNotRootOrAllowed returns if the current user is allowed to run a node,
// and if the effective user id is elevated or not.
func IsNotRootOrAllowed() (canRun bool, isRoot bool) {
isRoot = os.Geteuid() == 0
canRun = !isRoot || flags.DebugAllowRoot()
return
}
16 changes: 15 additions & 1 deletion go/oasis-node/cmd/common/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const (
// CfgDebugTestEntity is the command line flag to enable the debug test
// entity.
CfgDebugTestEntity = "debug.test_entity"
// CfgDebugAllowRoot is the command line flag to enable running the node
// as root.
CfgDebugAllowRoot = "debug.allow_root"
// CfgGenesisFile is the flag used to specify a genesis file.
CfgGenesisFile = "genesis.file"
// CfgConsensusValidator is the flag used to opt-in to being a validator.
Expand All @@ -38,6 +41,8 @@ var (
ForceFlags = flag.NewFlagSet("", flag.ContinueOnError)
// DebugTestEntityFlags has the test entity enable flag.
DebugTestEntityFlags = flag.NewFlagSet("", flag.ContinueOnError)
// DebugAllowRootFlag has the root enable flag.
DebugAllowRootFlag = flag.NewFlagSet("", flag.ContinueOnError)

// GenesisFileFlags has the genesis file flag.
GenesisFileFlags = flag.NewFlagSet("", flag.ContinueOnError)
Expand Down Expand Up @@ -75,6 +80,11 @@ func DebugTestEntity() bool {
return DebugDontBlameOasis() && viper.GetBool(CfgDebugTestEntity)
}

// DebugAllowRoot returns true iff the root account enable flag is set.
func DebugAllowRoot() bool {
return DebugDontBlameOasis() && viper.GetBool(CfgDebugAllowRoot)
}

// GenesisFile returns the set genesis file.
func GenesisFile() string {
return viper.GetString(CfgGenesisFile)
Expand Down Expand Up @@ -107,9 +117,12 @@ func init() {

GenesisFileFlags.StringP(CfgGenesisFile, "g", "genesis.json", "path to genesis file")

DebugDontBlameOasisFlag.Bool(CfgDebugDontBlameOasis, false, "Enable debug/unsafe/insecure options")
DebugDontBlameOasisFlag.Bool(CfgDebugDontBlameOasis, false, "enable debug/unsafe/insecure options")
_ = DebugDontBlameOasisFlag.MarkHidden(CfgDebugDontBlameOasis)

DebugAllowRootFlag.Bool(CfgDebugAllowRoot, false, "allow running as root account")
_ = DebugAllowRootFlag.MarkHidden(CfgDebugAllowRoot)

DryRunFlag.BoolP(CfgDryRun, "n", false, "don't actually do anything, just show what will be done")

AssumeYesFlag.BoolP(CfgAssumeYes, cfgAssumeYesShort, false, "automatically assume yes for all questions")
Expand All @@ -118,6 +131,7 @@ func init() {
VerboseFlags,
ForceFlags,
DebugTestEntityFlags,
DebugAllowRootFlag,
GenesisFileFlags,
ConsensusValidatorFlag,
DebugDontBlameOasisFlag,
Expand Down
1 change: 1 addition & 0 deletions go/oasis-node/cmd/debug/byzantine/byzantine.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ func init() {
byzantineCmd.PersistentFlags().AddFlagSet(flags.GenesisFileFlags)
byzantineCmd.PersistentFlags().AddFlagSet(flags.DebugDontBlameOasisFlag)
byzantineCmd.PersistentFlags().AddFlagSet(flags.DebugTestEntityFlags)
byzantineCmd.PersistentFlags().AddFlagSet(flags.DebugAllowRootFlag)
byzantineCmd.PersistentFlags().AddFlagSet(grpc.ServerLocalFlags)
byzantineCmd.PersistentFlags().AddFlagSet(grpc.ServerTCPFlags)
byzantineCmd.PersistentFlags().AddFlagSet(p2p.Flags)
Expand Down
1 change: 1 addition & 0 deletions go/oasis-node/cmd/ias/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,5 +269,6 @@ func init() {
proxyFlags.AddFlagSet(cmdGrpc.ClientFlags)
proxyFlags.AddFlagSet(flags.GenesisFileFlags)
proxyFlags.AddFlagSet(flags.DebugDontBlameOasisFlag)
proxyFlags.AddFlagSet(flags.DebugAllowRootFlag)
proxyFlags.AddFlagSet(pprof.Flags)
}
13 changes: 13 additions & 0 deletions go/oasis-node/cmd/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,18 @@ func NewNode() (node *Node, err error) { // nolint: gocyclo
return nil, errors.New("data directory not configured")
}

// Check to see if the user has elevated privs or not.
canRun, isRoot := cmdCommon.IsNotRootOrAllowed()
if !canRun {
logger.Error("running with elevated privileges not allowed")
return nil, errors.New("running with elevated privileges not allowed")
}
if isRoot {
// The flags for allowing running as root must be set, warn.
// If something bad happens, Don't Blame Oasis.
logger.Warn("running with elevated privileges is NOT RECOMMENDED")
}

// Load configured values for all registered crash points.
crash.LoadViperArgValues()

Expand Down Expand Up @@ -733,6 +745,7 @@ func Register(parentCmd *cobra.Command) {

func init() {
Flags.AddFlagSet(flags.DebugTestEntityFlags)
Flags.AddFlagSet(flags.DebugAllowRootFlag)
Flags.AddFlagSet(flags.ConsensusValidatorFlag)
Flags.AddFlagSet(flags.GenesisFileFlags)

Expand Down
1 change: 1 addition & 0 deletions go/oasis-node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ var (
{"log.format", "JSON"},
{cmdCommonFlags.CfgConsensusValidator, true},
{cmdCommonFlags.CfgDebugDontBlameOasis, true},
{cmdCommonFlags.CfgDebugAllowRoot, true},
{storageWorker.CfgBackend, "badger"},
{runtimeRegistry.CfgRuntimeMode, string(runtimeRegistry.RuntimeModeCompute)},
{runtimeRegistry.CfgRuntimeProvisioner, runtimeRegistry.RuntimeProvisionerMock},
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ func init() {
}

viper.Set(nodeFlags.CfgDebugDontBlameOasis, true)
viper.Set(nodeFlags.CfgDebugAllowRoot, true)
viper.Set(nodeCommon.CfgDebugAllowTestKeys, true)
})
}
7 changes: 7 additions & 0 deletions go/oasis-test-runner/oasis/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ func (args *argBuilder) debugDontBlameOasis() *argBuilder {
return args
}

func (args *argBuilder) debugAllowRoot() *argBuilder {
args.vec = append(args.vec, Argument{
Name: flags.CfgDebugAllowRoot,
})
return args
}

func (args *argBuilder) debugAllowTestKeys() *argBuilder {
args.vec = append(args.vec, Argument{
Name: cmdCommon.CfgDebugAllowTestKeys,
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/byzantine.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type ByzantineCfg struct {

func (worker *Byzantine) AddArgs(args *argBuilder) error {
args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
debugEnableProfiling(worker.Node.pprofPort).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type ClientCfg struct {

func (client *Client) AddArgs(args *argBuilder) error {
args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
debugEnableProfiling(client.Node.pprofPort).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/compute.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func (worker *Compute) AddArgs(args *argBuilder) error {
defer worker.RUnlock()

args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
debugEnableProfiling(worker.Node.pprofPort).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/ias.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type iasProxy struct {

func (ias *iasProxy) AddArgs(args *argBuilder) error {
args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
grpcServerPort(ias.grpcPort).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/keymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ func (km *Keymanager) AddArgs(args *argBuilder) error {
}

args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
debugEnableProfiling(km.Node.pprofPort).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/seed.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func (seed *Seed) AddArgs(args *argBuilder) error {
}

args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
workerCertificateRotation(true).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/sentry.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func (sentry *Sentry) AddArgs(args *argBuilder) error {
}

args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
debugEnableProfiling(sentry.Node.pprofPort).
Expand Down
1 change: 1 addition & 0 deletions go/oasis-test-runner/oasis/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func (val *Validator) ExternalGRPCAddress() string {

func (val *Validator) AddArgs(args *argBuilder) error {
args.debugDontBlameOasis().
debugAllowRoot().
debugAllowTestKeys().
debugSetRlimit().
debugEnableProfiling(val.Node.pprofPort).
Expand Down