Merge pull request #5772 from hashicorp/f-disable-nomad-exec

client config flag to disable remote exec
This commit is contained in:
Mahmood Ali 2019-06-04 14:38:59 -04:00 committed by GitHub
commit 3d9967fc5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 101 additions and 13 deletions

View file

@ -144,6 +144,10 @@ func (a *Allocations) execImpl(encoder *codec.Encoder, decoder *codec.Decoder, e
return helper.Int64ToPtr(500), err
}
if a.c.GetConfig().DisableRemoteExec {
return nil, structs.ErrPermissionDenied
}
aclObj, token, err := a.c.resolveTokenAndACL(req.QueryOptions.AuthToken)
{
// log access

View file

@ -619,6 +619,62 @@ func TestAlloc_ExecStreaming_NoAllocation(t *testing.T) {
}
}
func TestAlloc_ExecStreaming_DisableRemoteExec(t *testing.T) {
t.Parallel()
require := require.New(t)
// Start a server and client
s := nomad.TestServer(t, nil)
defer s.Shutdown()
testutil.WaitForLeader(t, s.RPC)
c, cleanup := TestClient(t, func(c *config.Config) {
c.Servers = []string{s.GetConfig().RPCAddr.String()}
c.DisableRemoteExec = true
})
defer cleanup()
// Make the request
req := &cstructs.AllocExecRequest{
AllocID: uuid.Generate(),
Task: "testtask",
Tty: true,
Cmd: []string{"placeholder command"},
QueryOptions: nstructs.QueryOptions{Region: "global"},
}
// Get the handler
handler, err := c.StreamingRpcHandler("Allocations.Exec")
require.Nil(err)
// Create a pipe
p1, p2 := net.Pipe()
defer p1.Close()
defer p2.Close()
errCh := make(chan error)
frames := make(chan *drivers.ExecTaskStreamingResponseMsg)
// Start the handler
go handler(p2)
go decodeFrames(t, p1, frames, errCh)
// Send the request
encoder := codec.NewEncoder(p1, nstructs.MsgpackHandle)
require.Nil(encoder.Encode(req))
timeout := time.After(3 * time.Second)
select {
case <-timeout:
require.FailNow("timed out")
case err := <-errCh:
require.True(nstructs.IsErrPermissionDenied(err), "expected permission denied error but found: %v", err)
case f := <-frames:
require.Fail("received unexpected frame", "frame: %#v", f)
}
}
func TestAlloc_ExecStreaming_ACL_Basic(t *testing.T) {
t.Parallel()
require := require.New(t)

View file

@ -198,6 +198,9 @@ type Config struct {
// key/value/tag format, or simply a key/value format
DisableTaggedMetrics bool
// DisableRemoteExec disables remote exec targeting tasks on this client
DisableRemoteExec bool
// BackwardsCompatibleMetrics determines whether to show methods of
// displaying metrics for older versions, or to only show the new format
BackwardsCompatibleMetrics bool
@ -249,6 +252,7 @@ func DefaultConfig() *Config {
GCMaxAllocs: 50,
NoHostUUID: true,
DisableTaggedMetrics: false,
DisableRemoteExec: false,
BackwardsCompatibleMetrics: false,
RPCHoldTimeout: 5 * time.Second,
}

View file

@ -460,6 +460,7 @@ func convertClientConfig(agentConfig *Config) (*clientconfig.Config, error) {
}
conf.ClientMaxPort = uint(agentConfig.Client.ClientMaxPort)
conf.ClientMinPort = uint(agentConfig.Client.ClientMinPort)
conf.DisableRemoteExec = agentConfig.Client.DisableRemoteExec
// Setup the node
conf.Node = new(structs.Node)

View file

@ -239,6 +239,9 @@ type ClientConfig struct {
// random UUID.
NoHostUUID *bool `hcl:"no_host_uuid"`
// DisableRemoteExec disables remote exec targeting tasks on this client
DisableRemoteExec bool `hcl:"disable_remote_exec"`
// ServerJoin contains information that is used to attempt to join servers
ServerJoin *ServerJoin `hcl:"server_join"`
@ -686,6 +689,7 @@ func DefaultConfig() *Config {
GCInodeUsageThreshold: 70,
GCMaxAllocs: 50,
NoHostUUID: helper.BoolToPtr(true),
DisableRemoteExec: false,
ServerJoin: &ServerJoin{
RetryJoin: []string{},
RetryInterval: 30 * time.Second,
@ -1245,6 +1249,10 @@ func (a *ClientConfig) Merge(b *ClientConfig) *ClientConfig {
result.NoHostUUID = b.NoHostUUID
}
if b.DisableRemoteExec {
result.DisableRemoteExec = b.DisableRemoteExec
}
// Add the servers
result.Servers = append(result.Servers, b.Servers...)

View file

@ -78,6 +78,7 @@ var basicConfig = &Config{
GCInodeUsageThreshold: 91,
GCMaxAllocs: 50,
NoHostUUID: helper.BoolToPtr(false),
DisableRemoteExec: true,
},
Server: &ServerConfig{
Enabled: true,

View file

@ -88,11 +88,12 @@ func TestConfig_Merge(t *testing.T) {
Options: map[string]string{
"foo": "bar",
},
NetworkSpeed: 100,
CpuCompute: 100,
MemoryMB: 100,
MaxKillTimeout: "20s",
ClientMaxPort: 19996,
NetworkSpeed: 100,
CpuCompute: 100,
MemoryMB: 100,
MaxKillTimeout: "20s",
ClientMaxPort: 19996,
DisableRemoteExec: false,
Reserved: &Resources{
CPU: 10,
MemoryMB: 10,
@ -244,13 +245,14 @@ func TestConfig_Merge(t *testing.T) {
"foo": "bar",
"baz": "zip",
},
ChrootEnv: map[string]string{},
ClientMaxPort: 20000,
ClientMinPort: 22000,
NetworkSpeed: 105,
CpuCompute: 105,
MemoryMB: 105,
MaxKillTimeout: "50s",
ChrootEnv: map[string]string{},
ClientMaxPort: 20000,
ClientMinPort: 22000,
NetworkSpeed: 105,
CpuCompute: 105,
MemoryMB: 105,
MaxKillTimeout: "50s",
DisableRemoteExec: false,
Reserved: &Resources{
CPU: 15,
MemoryMB: 15,

View file

@ -68,6 +68,7 @@ client {
gc_inode_usage_threshold = 91
gc_max_allocs = 50
no_host_uuid = false
disable_remote_exec = true
}
server {
enabled = true

View file

@ -60,6 +60,7 @@
"network_interface": "eth0",
"network_speed": 100,
"no_host_uuid": false,
"disable_remote_exec": true,
"node_class": "linux-medium-64bit",
"options": [
{
@ -285,4 +286,4 @@
"token": "12345"
}
]
}
}

View file

@ -179,6 +179,7 @@ $ curl \
"ChrootEnv": {},
"ClientMaxPort": 14512,
"ClientMinPort": 14000,
"DisableRemoteExec": false,
"Enabled": true,
"GCDiskUsageThreshold": 99,
"GCInodeUsageThreshold": 99,

View file

@ -117,3 +117,9 @@ nomad alloc exec -job <job-id> <command> [<args>...]
Choosing a specific allocation is useful for debugging issues with a specific
instance of a service. For other operations using the `-job` flag may be more
convenient than looking up an allocation ID to use.
## Disabling remote execution
`alloc exec` is enabled by default to aid with debugging. Operators can disable the feature by setting [`disable_remote_exec` client config option][disable_remote_exec_flag] on all clients, or a subset of clients that run sensitive workloads.
[disable_remote_exec_flag]: /docs/configuration/client.html#disable_remote_exec

View file

@ -55,6 +55,9 @@ driver) but will be removed in a future release.
job is allowed to wait to exit. Individual jobs may customize their own kill
timeout, but it may not exceed this value.
- `disable_remote_exec` `(bool: false)` - Specifies if the client should disable
remote task execution to tasks running on this client.
- `meta` `(map[string]string: nil)` - Specifies a key-value map that annotates
with user-defined metadata.