[Security] Add finer control over script checks (#4715)

* Add -enable-local-script-checks options

These options allow for a finer control over when script checks are enabled by
giving the option to only allow them when they are declared from the local
file system.

* Add documentation for the new option

* Nitpick doc wording
This commit is contained in:
Aestek 2018-10-11 14:22:11 +02:00 committed by Paul Banks
parent 298af6dca7
commit 25f04fbd21
16 changed files with 415 additions and 149 deletions

View File

@ -69,6 +69,13 @@ const (
"service, but no reason was provided. This is a default message."
)
type configSource int
const (
ConfigSourceLocal configSource = iota
ConfigSourceRemote
)
// delegate defines the interface shared by both
// consul.Client and consul.Server.
type delegate interface {
@ -1858,7 +1865,7 @@ func (a *Agent) purgeCheck(checkID types.CheckID) error {
// AddService is used to add a service entry.
// This entry is persistent and the agent will make a best effort to
// ensure it is registered
func (a *Agent) AddService(service *structs.NodeService, chkTypes []*structs.CheckType, persist bool, token string) error {
func (a *Agent) AddService(service *structs.NodeService, chkTypes []*structs.CheckType, persist bool, token string, source configSource) error {
if service.Service == "" {
return fmt.Errorf("Service name missing")
}
@ -1940,7 +1947,7 @@ func (a *Agent) AddService(service *structs.NodeService, chkTypes []*structs.Che
if chkType.Status != "" {
check.Status = chkType.Status
}
if err := a.AddCheck(check, chkType, persist, token); err != nil {
if err := a.AddCheck(check, chkType, persist, token, source); err != nil {
return err
}
}
@ -2010,7 +2017,7 @@ func (a *Agent) RemoveService(serviceID string, persist bool) error {
// This entry is persistent and the agent will make a best effort to
// ensure it is registered. The Check may include a CheckType which
// is used to automatically update the check status
func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *structs.CheckType, persist bool, token string) error {
func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *structs.CheckType, persist bool, token string, source configSource) error {
if check.CheckID == "" {
return fmt.Errorf("CheckID missing")
}
@ -2020,8 +2027,14 @@ func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *structs.CheckType,
return fmt.Errorf("Check is not valid: %v", err)
}
if chkType.IsScript() && !a.config.EnableScriptChecks {
return fmt.Errorf("Scripts are disabled on this agent; to enable, configure 'enable_script_checks' to true")
if chkType.IsScript() {
if source == ConfigSourceLocal && !a.config.EnableLocalScriptChecks {
return fmt.Errorf("Scripts are disabled on this agent; to enable, configure 'enable_script_checks' or 'enable_local_script_checks' to true")
}
if source == ConfigSourceRemote && !a.config.EnableRemoteScriptChecks {
return fmt.Errorf("Scripts are disabled on this agent from remote calls; to enable, configure 'enable_script_checks' to true")
}
}
}
@ -2330,7 +2343,7 @@ func (a *Agent) RemoveCheck(checkID types.CheckID, persist bool) error {
// assigned. We need to restore from disk to enable to continue authenticating
// running proxies that already had that credential injected.
func (a *Agent) addProxyLocked(proxy *structs.ConnectManagedProxy, persist, FromFile bool,
restoredProxyToken string) error {
restoredProxyToken string, source configSource) error {
// Lookup the target service token in state if there is one.
token := a.State.ServiceToken(proxy.TargetServiceID)
@ -2372,7 +2385,7 @@ func (a *Agent) addProxyLocked(proxy *structs.ConnectManagedProxy, persist, From
}
}
err = a.AddService(proxyService, chkTypes, persist, token)
err = a.AddService(proxyService, chkTypes, persist, token, source)
if err != nil {
// Remove the state too
a.State.RemoveProxy(proxyService.ID)
@ -2402,10 +2415,10 @@ func (a *Agent) addProxyLocked(proxy *structs.ConnectManagedProxy, persist, From
// assigned. We need to restore from disk to enable to continue authenticating
// running proxies that already had that credential injected.
func (a *Agent) AddProxy(proxy *structs.ConnectManagedProxy, persist, FromFile bool,
restoredProxyToken string) error {
restoredProxyToken string, source configSource) error {
a.proxyLock.Lock()
defer a.proxyLock.Unlock()
return a.addProxyLocked(proxy, persist, FromFile, restoredProxyToken)
return a.addProxyLocked(proxy, persist, FromFile, restoredProxyToken, source)
}
// resolveProxyCheckAddress returns the best address to use for a TCP check of
@ -2893,13 +2906,13 @@ func (a *Agent) loadServices(conf *config.RuntimeConfig) error {
// syntax sugar and shouldn't be persisted in local or server state.
ns.Connect.SidecarService = nil
if err := a.AddService(ns, chkTypes, false, service.Token); err != nil {
if err := a.AddService(ns, chkTypes, false, service.Token, ConfigSourceLocal); err != nil {
return fmt.Errorf("Failed to register service %q: %v", service.Name, err)
}
// If there is a sidecar service, register that too.
if sidecar != nil {
if err := a.AddService(sidecar, sidecarChecks, false, sidecarToken); err != nil {
if err := a.AddService(sidecar, sidecarChecks, false, sidecarToken, ConfigSourceLocal); err != nil {
return fmt.Errorf("Failed to register sidecar for service %q: %v", service.Name, err)
}
}
@ -2962,7 +2975,7 @@ func (a *Agent) loadServices(conf *config.RuntimeConfig) error {
} else {
a.logger.Printf("[DEBUG] agent: restored service definition %q from %q",
serviceID, file)
if err := a.AddService(p.Service, nil, false, p.Token); err != nil {
if err := a.AddService(p.Service, nil, false, p.Token, ConfigSourceLocal); err != nil {
return fmt.Errorf("failed adding service %q: %s", serviceID, err)
}
}
@ -2988,7 +3001,7 @@ func (a *Agent) loadChecks(conf *config.RuntimeConfig) error {
for _, check := range conf.Checks {
health := check.HealthCheck(conf.NodeName)
chkType := check.CheckType()
if err := a.AddCheck(health, chkType, false, check.Token); err != nil {
if err := a.AddCheck(health, chkType, false, check.Token, ConfigSourceLocal); err != nil {
return fmt.Errorf("Failed to register check '%s': %v %v", check.Name, err, check)
}
}
@ -3043,7 +3056,7 @@ func (a *Agent) loadChecks(conf *config.RuntimeConfig) error {
// services into the active pool
p.Check.Status = api.HealthCritical
if err := a.AddCheck(p.Check, p.ChkType, false, p.Token); err != nil {
if err := a.AddCheck(p.Check, p.ChkType, false, p.Token, ConfigSourceLocal); err != nil {
// Purge the check if it is unable to be restored.
a.logger.Printf("[WARN] agent: Failed to restore check %q: %s",
checkID, err)
@ -3144,7 +3157,7 @@ func (a *Agent) loadProxies(conf *config.RuntimeConfig) error {
restoredToken = persisted.ProxyToken
}
if err := a.addProxyLocked(proxy, true, true, restoredToken); err != nil {
if err := a.addProxyLocked(proxy, true, true, restoredToken, ConfigSourceLocal); err != nil {
return fmt.Errorf("failed adding proxy: %s", err)
}
}
@ -3161,7 +3174,7 @@ func (a *Agent) loadProxies(conf *config.RuntimeConfig) error {
} else if !persisted.FromFile {
if a.State.Proxy(proxyID) == nil {
a.logger.Printf("[DEBUG] agent: restored proxy definition %q", proxyID)
if err := a.addProxyLocked(persisted.Proxy, false, false, persisted.ProxyToken); err != nil {
if err := a.addProxyLocked(persisted.Proxy, false, false, persisted.ProxyToken, ConfigSourceLocal); err != nil {
return fmt.Errorf("failed adding proxy %q: %v", proxyID, err)
}
} else {
@ -3251,7 +3264,7 @@ func (a *Agent) EnableServiceMaintenance(serviceID, reason, token string) error
ServiceName: service.Service,
Status: api.HealthCritical,
}
a.AddCheck(check, nil, true, token)
a.AddCheck(check, nil, true, token, ConfigSourceLocal)
a.logger.Printf("[INFO] agent: Service %q entered maintenance mode", serviceID)
return nil
@ -3297,7 +3310,7 @@ func (a *Agent) EnableNodeMaintenance(reason, token string) {
Notes: reason,
Status: api.HealthCritical,
}
a.AddCheck(check, nil, true, token)
a.AddCheck(check, nil, true, token, ConfigSourceLocal)
a.logger.Printf("[INFO] agent: Node entered maintenance mode")
}

View File

@ -570,7 +570,7 @@ func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Requ
}
// Add the check.
if err := s.agent.AddCheck(health, chkType, true, token); err != nil {
if err := s.agent.AddCheck(health, chkType, true, token, ConfigSourceRemote); err != nil {
return nil, err
}
s.syncChanges()
@ -889,18 +889,18 @@ func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Re
}
// Add the service.
if err := s.agent.AddService(ns, chkTypes, true, token); err != nil {
if err := s.agent.AddService(ns, chkTypes, true, token, ConfigSourceRemote); err != nil {
return nil, err
}
// Add proxy (which will add proxy service so do it before we trigger sync)
if proxy != nil {
if err := s.agent.AddProxy(proxy, true, false, ""); err != nil {
if err := s.agent.AddProxy(proxy, true, false, "", ConfigSourceRemote); err != nil {
return nil, err
}
}
// Add sidecar.
if sidecar != nil {
if err := s.agent.AddService(sidecar, sidecarChecks, true, sidecarToken); err != nil {
if err := s.agent.AddService(sidecar, sidecarChecks, true, sidecarToken, ConfigSourceRemote); err != nil {
return nil, err
}
}

View File

@ -1329,6 +1329,60 @@ func TestAgent_RegisterCheck_Scripts(t *testing.T) {
}
}
func TestAgent_RegisterCheckScriptsExecDisable(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), "")
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
args := &structs.CheckDefinition{
Name: "test",
ScriptArgs: []string{"true"},
Interval: time.Second,
}
req, _ := http.NewRequest("PUT", "/v1/agent/check/register?token=abc123", jsonReader(args))
res := httptest.NewRecorder()
_, err := a.srv.AgentRegisterCheck(res, req)
if err == nil {
t.Fatalf("expected error but got nil")
}
if !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("expected script disabled error, got: %s", err)
}
checkID := types.CheckID("test")
if _, ok := a.State.Checks()[checkID]; ok {
t.Fatalf("check registered with exec disable")
}
}
func TestAgent_RegisterCheckScriptsExecRemoteDisable(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), `
enable_local_script_checks = true
`)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
args := &structs.CheckDefinition{
Name: "test",
ScriptArgs: []string{"true"},
Interval: time.Second,
}
req, _ := http.NewRequest("PUT", "/v1/agent/check/register?token=abc123", jsonReader(args))
res := httptest.NewRecorder()
_, err := a.srv.AgentRegisterCheck(res, req)
if err == nil {
t.Fatalf("expected error but got nil")
}
if !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("expected script disabled error, got: %s", err)
}
checkID := types.CheckID("test")
if _, ok := a.State.Checks()[checkID]; ok {
t.Fatalf("check registered with exec disable")
}
}
func TestAgent_RegisterCheck_Passing(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), "")
@ -1419,7 +1473,7 @@ func TestAgent_DeregisterCheck(t *testing.T) {
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
if err := a.AddCheck(chk, nil, false, ""); err != nil {
if err := a.AddCheck(chk, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1445,7 +1499,7 @@ func TestAgent_DeregisterCheckACLDeny(t *testing.T) {
testrpc.WaitForLeader(t, a.RPC, "dc1")
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
if err := a.AddCheck(chk, nil, false, ""); err != nil {
if err := a.AddCheck(chk, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1472,7 +1526,7 @@ func TestAgent_PassCheck(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1500,7 +1554,7 @@ func TestAgent_PassCheck_ACLDeny(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1527,7 +1581,7 @@ func TestAgent_WarnCheck(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1555,7 +1609,7 @@ func TestAgent_WarnCheck_ACLDeny(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1582,7 +1636,7 @@ func TestAgent_FailCheck(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1610,7 +1664,7 @@ func TestAgent_FailCheck_ACLDeny(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1637,7 +1691,7 @@ func TestAgent_UpdateCheck(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1721,7 +1775,7 @@ func TestAgent_UpdateCheck_ACLDeny(t *testing.T) {
chk := &structs.HealthCheck{Name: "test", CheckID: "test"}
chkType := &structs.CheckType{TTL: 15 * time.Second}
if err := a.AddCheck(chk, chkType, false, ""); err != nil {
if err := a.AddCheck(chk, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2751,10 +2805,10 @@ func TestAgent_RegisterServiceDeregisterService_Sidecar(t *testing.T) {
testrpc.WaitForLeader(t, a.RPC, "dc1")
if tt.preRegister != nil {
require.NoError(a.AddService(tt.preRegister, nil, false, ""))
require.NoError(a.AddService(tt.preRegister, nil, false, "", ConfigSourceLocal))
}
if tt.preRegister2 != nil {
require.NoError(a.AddService(tt.preRegister2, nil, false, ""))
require.NoError(a.AddService(tt.preRegister2, nil, false, "", ConfigSourceLocal))
}
// Create an ACL token with require policy
@ -2910,6 +2964,80 @@ func TestAgent_RegisterService_ConnectNative(t *testing.T) {
assert.True(svc.Connect.Native)
}
func TestAgent_RegisterService_ScriptCheck_ExecDisable(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), "")
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
args := &structs.ServiceDefinition{
Name: "test",
Meta: map[string]string{"hello": "world"},
Tags: []string{"master"},
Port: 8000,
Check: structs.CheckType{
Name: "test-check",
Interval: time.Second,
ScriptArgs: []string{"true"},
},
Weights: &structs.Weights{
Passing: 100,
Warning: 3,
},
}
req, _ := http.NewRequest("PUT", "/v1/agent/service/register?token=abc123", jsonReader(args))
_, err := a.srv.AgentRegisterService(nil, req)
if err == nil {
t.Fatalf("expected error but got nil")
}
if !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("expected script disabled error, got: %s", err)
}
checkID := types.CheckID("test-check")
if _, ok := a.State.Checks()[checkID]; ok {
t.Fatalf("check registered with exec disable")
}
}
func TestAgent_RegisterService_ScriptCheck_ExecRemoteDisable(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), `
enable_local_script_checks = true
`)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
args := &structs.ServiceDefinition{
Name: "test",
Meta: map[string]string{"hello": "world"},
Tags: []string{"master"},
Port: 8000,
Check: structs.CheckType{
Name: "test-check",
Interval: time.Second,
ScriptArgs: []string{"true"},
},
Weights: &structs.Weights{
Passing: 100,
Warning: 3,
},
}
req, _ := http.NewRequest("PUT", "/v1/agent/service/register?token=abc123", jsonReader(args))
_, err := a.srv.AgentRegisterService(nil, req)
if err == nil {
t.Fatalf("expected error but got nil")
}
if !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("expected script disabled error, got: %s", err)
}
checkID := types.CheckID("test-check")
if _, ok := a.State.Checks()[checkID]; ok {
t.Fatalf("check registered with exec disable")
}
}
func TestAgent_DeregisterService(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), "")
@ -2920,7 +3048,7 @@ func TestAgent_DeregisterService(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2953,7 +3081,7 @@ func TestAgent_DeregisterService_ACLDeny(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -3127,7 +3255,7 @@ func TestAgent_ServiceMaintenance_Enable(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -3170,7 +3298,7 @@ func TestAgent_ServiceMaintenance_Disable(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -3207,7 +3335,7 @@ func TestAgent_ServiceMaintenance_ACLDeny(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}

View File

@ -438,7 +438,7 @@ func TestAgent_AddService(t *testing.T) {
t.Run(tt.desc, func(t *testing.T) {
// check the service registration
t.Run(tt.srv.ID, func(t *testing.T) {
err := a.AddService(tt.srv, tt.chkTypes, false, "")
err := a.AddService(tt.srv, tt.chkTypes, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -474,6 +474,62 @@ func TestAgent_AddService(t *testing.T) {
}
}
func TestAgent_AddServiceNoExec(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), `
node_name = "node1"
`)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
srv := &structs.NodeService{
ID: "svcid1",
Service: "svcname1",
Tags: []string{"tag1"},
Port: 8100,
}
chk := &structs.CheckType{
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddService(srv, []*structs.CheckType{chk}, false, "", ConfigSourceLocal)
if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("err: %v", err)
}
err = a.AddService(srv, []*structs.CheckType{chk}, false, "", ConfigSourceRemote)
if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("err: %v", err)
}
}
func TestAgent_AddServiceNoRemoteExec(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), `
node_name = "node1"
enable_local_script_checks = true
`)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
srv := &structs.NodeService{
ID: "svcid1",
Service: "svcname1",
Tags: []string{"tag1"},
Port: 8100,
}
chk := &structs.CheckType{
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddService(srv, []*structs.CheckType{chk}, false, "", ConfigSourceRemote)
if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("err: %v", err)
}
}
func TestAgent_RemoveService(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), "")
@ -498,7 +554,7 @@ func TestAgent_RemoveService(t *testing.T) {
}
chkTypes := []*structs.CheckType{&structs.CheckType{TTL: time.Minute}}
if err := a.AddService(srv, chkTypes, false, ""); err != nil {
if err := a.AddService(srv, chkTypes, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -510,7 +566,7 @@ func TestAgent_RemoveService(t *testing.T) {
TTL: time.Minute,
}
hc := check.HealthCheck("node1")
if err := a.AddCheck(hc, check.CheckType(), false, ""); err != nil {
if err := a.AddCheck(hc, check.CheckType(), false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %s", err)
}
@ -536,7 +592,7 @@ func TestAgent_RemoveService(t *testing.T) {
&structs.CheckType{TTL: time.Minute},
&structs.CheckType{TTL: 30 * time.Second},
}
if err := a.AddService(srv, chkTypes, false, ""); err != nil {
if err := a.AddService(srv, chkTypes, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -582,7 +638,7 @@ func TestAgent_RemoveServiceRemovesAllChecks(t *testing.T) {
hchk2 := &structs.HealthCheck{Node: "node1", CheckID: "chk2", Name: "chk2", Status: "critical", ServiceID: "redis", ServiceName: "redis"}
// register service with chk1
if err := a.AddService(svc, []*structs.CheckType{chk1}, false, ""); err != nil {
if err := a.AddService(svc, []*structs.CheckType{chk1}, false, "", ConfigSourceLocal); err != nil {
t.Fatal("Failed to register service", err)
}
@ -592,7 +648,7 @@ func TestAgent_RemoveServiceRemovesAllChecks(t *testing.T) {
}
// update the service with chk2
if err := a.AddService(svc, []*structs.CheckType{chk2}, false, ""); err != nil {
if err := a.AddService(svc, []*structs.CheckType{chk2}, false, "", ConfigSourceLocal); err != nil {
t.Fatal("Failed to update service", err)
}
@ -655,7 +711,7 @@ func verifyIndexChurn(t *testing.T, tags []string) {
Tags: tags,
Weights: weights,
}
if err := a.AddService(svc, nil, true, ""); err != nil {
if err := a.AddService(svc, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -668,7 +724,7 @@ func verifyIndexChurn(t *testing.T, tags []string) {
chkt := &structs.CheckType{
TTL: time.Hour,
}
if err := a.AddCheck(chk, chkt, true, ""); err != nil {
if err := a.AddCheck(chk, chkt, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -680,7 +736,7 @@ func verifyIndexChurn(t *testing.T, tags []string) {
chkt = &structs.CheckType{
TTL: time.Hour,
}
if err := a.AddCheck(chk, chkt, true, ""); err != nil {
if err := a.AddCheck(chk, chkt, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -745,7 +801,7 @@ func TestAgent_AddCheck(t *testing.T) {
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -784,7 +840,7 @@ func TestAgent_AddCheck_StartPassing(t *testing.T) {
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -823,7 +879,7 @@ func TestAgent_AddCheck_MinInterval(t *testing.T) {
ScriptArgs: []string{"exit", "0"},
Interval: time.Microsecond,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -858,7 +914,7 @@ func TestAgent_AddCheck_MissingService(t *testing.T) {
ScriptArgs: []string{"exit", "0"},
Interval: time.Microsecond,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err == nil || err.Error() != `ServiceID "baz" does not exist` {
t.Fatalf("expected service id error, got: %v", err)
}
@ -888,7 +944,7 @@ func TestAgent_AddCheck_RestoreState(t *testing.T) {
chk := &structs.CheckType{
TTL: time.Minute,
}
err = a.AddCheck(health, chk, false, "")
err = a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %s", err)
}
@ -923,7 +979,7 @@ func TestAgent_AddCheck_ExecDisable(t *testing.T) {
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("err: %v", err)
}
@ -932,6 +988,46 @@ func TestAgent_AddCheck_ExecDisable(t *testing.T) {
if memChk := a.State.Checks()["mem"]; memChk != nil {
t.Fatalf("should be missing mem check")
}
err = a.AddCheck(health, chk, false, "", ConfigSourceRemote)
if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
t.Fatalf("err: %v", err)
}
// Ensure we don't have a check mapping
if memChk := a.State.Checks()["mem"]; memChk != nil {
t.Fatalf("should be missing mem check")
}
}
func TestAgent_AddCheck_ExecRemoteDisable(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), `
enable_local_script_checks = true
`)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
health := &structs.HealthCheck{
Node: "foo",
CheckID: "mem",
Name: "memory util",
Status: api.HealthCritical,
}
chk := &structs.CheckType{
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddCheck(health, chk, false, "", ConfigSourceRemote)
if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent from remote calls") {
t.Fatalf("err: %v", err)
}
// Ensure we don't have a check mapping
if memChk := a.State.Checks()["mem"]; memChk != nil {
t.Fatalf("should be missing mem check")
}
}
func TestAgent_AddCheck_GRPC(t *testing.T) {
@ -949,7 +1045,7 @@ func TestAgent_AddCheck_GRPC(t *testing.T) {
GRPC: "localhost:12345/package.Service",
Interval: 15 * time.Second,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -987,7 +1083,7 @@ func TestAgent_AddCheck_Alias(t *testing.T) {
chk := &structs.CheckType{
AliasService: "foo",
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
require.NoError(err)
// Ensure we have a check mapping
@ -1021,7 +1117,7 @@ func TestAgent_AddCheck_Alias_setToken(t *testing.T) {
chk := &structs.CheckType{
AliasService: "foo",
}
err := a.AddCheck(health, chk, false, "foo")
err := a.AddCheck(health, chk, false, "foo", ConfigSourceLocal)
require.NoError(err)
cs := a.State.CheckState("aliashealth")
@ -1051,7 +1147,7 @@ acl_token = "hello"
chk := &structs.CheckType{
AliasService: "foo",
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
require.NoError(err)
cs := a.State.CheckState("aliashealth")
@ -1081,7 +1177,7 @@ acl_token = "hello"
chk := &structs.CheckType{
AliasService: "foo",
}
err := a.AddCheck(health, chk, false, "goodbye")
err := a.AddCheck(health, chk, false, "goodbye", ConfigSourceLocal)
require.NoError(err)
cs := a.State.CheckState("aliashealth")
@ -1120,7 +1216,7 @@ func TestAgent_RemoveCheck(t *testing.T) {
ScriptArgs: []string{"exit", "0"},
Interval: 15 * time.Second,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -1165,7 +1261,7 @@ func TestAgent_HTTPCheck_TLSSkipVerify(t *testing.T) {
TLSSkipVerify: true,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -1214,7 +1310,7 @@ func TestAgent_HTTPCheck_EnableAgentTLSForChecks(t *testing.T) {
Interval: 20 * time.Millisecond,
}
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -1263,7 +1359,7 @@ func TestAgent_updateTTLCheck(t *testing.T) {
}
// Add check and update it.
err := a.AddCheck(health, chk, false, "")
err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -1304,7 +1400,7 @@ func TestAgent_PersistService(t *testing.T) {
file := filepath.Join(a.Config.DataDir, servicesDir, stringHash(svc.ID))
// Check is not persisted unless requested
if err := a.AddService(svc, nil, false, ""); err != nil {
if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
if _, err := os.Stat(file); err == nil {
@ -1312,7 +1408,7 @@ func TestAgent_PersistService(t *testing.T) {
}
// Persists to file if requested
if err := a.AddService(svc, nil, true, "mytoken"); err != nil {
if err := a.AddService(svc, nil, true, "mytoken", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
if _, err := os.Stat(file); err != nil {
@ -1335,7 +1431,7 @@ func TestAgent_PersistService(t *testing.T) {
// Updates service definition on disk
svc.Port = 8001
if err := a.AddService(svc, nil, true, "mytoken"); err != nil {
if err := a.AddService(svc, nil, true, "mytoken", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
expected, err = json.Marshal(persistedService{
@ -1429,7 +1525,7 @@ func TestAgent_PurgeService(t *testing.T) {
}
file := filepath.Join(a.Config.DataDir, servicesDir, stringHash(svc.ID))
if err := a.AddService(svc, nil, true, ""); err != nil {
if err := a.AddService(svc, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1442,7 +1538,7 @@ func TestAgent_PurgeService(t *testing.T) {
}
// Re-add the service
if err := a.AddService(svc, nil, true, ""); err != nil {
if err := a.AddService(svc, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1476,7 +1572,7 @@ func TestAgent_PurgeServiceOnDuplicate(t *testing.T) {
}
// First persist the service
if err := a.AddService(svc1, nil, true, ""); err != nil {
if err := a.AddService(svc1, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
a.Shutdown()
@ -1530,7 +1626,7 @@ func TestAgent_PersistProxy(t *testing.T) {
Tags: []string{"foo"},
Port: 8000,
}
require.NoError(a.AddService(svc1, nil, true, ""))
require.NoError(a.AddService(svc1, nil, true, "", ConfigSourceLocal))
// Add a proxy for it
proxy := &structs.ConnectManagedProxy{
@ -1541,12 +1637,12 @@ func TestAgent_PersistProxy(t *testing.T) {
file := filepath.Join(a.Config.DataDir, proxyDir, stringHash("redis-proxy"))
// Proxy is not persisted unless requested
require.NoError(a.AddProxy(proxy, false, false, ""))
require.NoError(a.AddProxy(proxy, false, false, "", ConfigSourceLocal))
_, err := os.Stat(file)
require.Error(err, "proxy should not be persisted")
// Proxy is persisted if requested
require.NoError(a.AddProxy(proxy, true, false, ""))
require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
_, err = os.Stat(file)
require.NoError(err, "proxy should be persisted")
@ -1562,7 +1658,7 @@ func TestAgent_PersistProxy(t *testing.T) {
proxy.Config = map[string]interface{}{
"foo": "bar",
}
require.NoError(a.AddProxy(proxy, true, false, ""))
require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
content, err = ioutil.ReadFile(file)
require.NoError(err)
@ -1601,7 +1697,7 @@ func TestAgent_PurgeProxy(t *testing.T) {
Tags: []string{"foo"},
Port: 8000,
}
require.NoError(a.AddService(svc1, nil, true, ""))
require.NoError(a.AddService(svc1, nil, true, "", ConfigSourceLocal))
// Add a proxy for it
proxy := &structs.ConnectManagedProxy{
@ -1609,7 +1705,7 @@ func TestAgent_PurgeProxy(t *testing.T) {
Command: []string{"/bin/sleep", "3600"},
}
proxyID := "redis-proxy"
require.NoError(a.AddProxy(proxy, true, false, ""))
require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
file := filepath.Join(a.Config.DataDir, proxyDir, stringHash("redis-proxy"))
@ -1619,7 +1715,7 @@ func TestAgent_PurgeProxy(t *testing.T) {
require.NoError(err, "should not be removed")
// Re-add the proxy
require.NoError(a.AddProxy(proxy, true, false, ""))
require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
// Removed
require.NoError(a.RemoveProxy(proxyID, true))
@ -1649,7 +1745,7 @@ func TestAgent_PurgeProxyOnDuplicate(t *testing.T) {
Tags: []string{"foo"},
Port: 8000,
}
require.NoError(a.AddService(svc1, nil, true, ""))
require.NoError(a.AddService(svc1, nil, true, "", ConfigSourceLocal))
// Add a proxy for it
proxy := &structs.ConnectManagedProxy{
@ -1657,7 +1753,7 @@ func TestAgent_PurgeProxyOnDuplicate(t *testing.T) {
Command: []string{"/bin/sleep", "3600"},
}
proxyID := "redis-proxy"
require.NoError(a.AddProxy(proxy, true, false, ""))
require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
a.Shutdown()
@ -1716,7 +1812,7 @@ func TestAgent_PersistCheck(t *testing.T) {
file := filepath.Join(a.Config.DataDir, checksDir, checkIDHash(check.CheckID))
// Not persisted if not requested
if err := a.AddCheck(check, chkType, false, ""); err != nil {
if err := a.AddCheck(check, chkType, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
if _, err := os.Stat(file); err == nil {
@ -1724,7 +1820,7 @@ func TestAgent_PersistCheck(t *testing.T) {
}
// Should persist if requested
if err := a.AddCheck(check, chkType, true, "mytoken"); err != nil {
if err := a.AddCheck(check, chkType, true, "mytoken", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
if _, err := os.Stat(file); err != nil {
@ -1748,7 +1844,7 @@ func TestAgent_PersistCheck(t *testing.T) {
// Updates the check definition on disk
check.Name = "mem1"
if err := a.AddCheck(check, chkType, true, "mytoken"); err != nil {
if err := a.AddCheck(check, chkType, true, "mytoken", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
expected, err = json.Marshal(persistedCheck{
@ -1806,7 +1902,7 @@ func TestAgent_PurgeCheck(t *testing.T) {
}
file := filepath.Join(a.Config.DataDir, checksDir, checkIDHash(check.CheckID))
if err := a.AddCheck(check, nil, true, ""); err != nil {
if err := a.AddCheck(check, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1850,7 +1946,7 @@ func TestAgent_PurgeCheckOnDuplicate(t *testing.T) {
}
// First persist the check
if err := a.AddCheck(check1, nil, true, ""); err != nil {
if err := a.AddCheck(check1, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
a.Shutdown()
@ -1926,7 +2022,7 @@ func TestAgent_unloadChecks(t *testing.T) {
Tags: []string{"foo"},
Port: 8000,
}
if err := a.AddService(svc, nil, false, ""); err != nil {
if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -1939,7 +2035,7 @@ func TestAgent_unloadChecks(t *testing.T) {
ServiceID: "redis",
ServiceName: "redis",
}
if err := a.AddCheck(check1, nil, false, ""); err != nil {
if err := a.AddCheck(check1, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %s", err)
}
found := false
@ -2066,7 +2162,7 @@ func TestAgent_unloadServices(t *testing.T) {
}
// Register the service
if err := a.AddService(svc, nil, false, ""); err != nil {
if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
found := false
@ -2192,7 +2288,7 @@ func TestAgent_Service_MaintenanceMode(t *testing.T) {
}
// Register the service
if err := a.AddService(svc, nil, false, ""); err != nil {
if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2267,7 +2363,7 @@ func TestAgent_Service_Reap(t *testing.T) {
}
// Register the service.
if err := a.AddService(svc, chkTypes, false, ""); err != nil {
if err := a.AddService(svc, chkTypes, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2340,7 +2436,7 @@ func TestAgent_Service_NoReap(t *testing.T) {
}
// Register the service.
if err := a.AddService(svc, chkTypes, false, ""); err != nil {
if err := a.AddService(svc, chkTypes, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2383,7 +2479,7 @@ func TestAgent_addCheck_restoresSnapshot(t *testing.T) {
Tags: []string{"foo"},
Port: 8000,
}
if err := a.AddService(svc, nil, false, ""); err != nil {
if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2396,13 +2492,13 @@ func TestAgent_addCheck_restoresSnapshot(t *testing.T) {
ServiceID: "redis",
ServiceName: "redis",
}
if err := a.AddCheck(check1, nil, false, ""); err != nil {
if err := a.AddCheck(check1, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %s", err)
}
// Re-registering the service preserves the state of the check
chkTypes := []*structs.CheckType{&structs.CheckType{TTL: 30 * time.Second}}
if err := a.AddService(svc, chkTypes, false, ""); err != nil {
if err := a.AddService(svc, chkTypes, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %s", err)
}
check, ok := a.State.Checks()["service:redis"]
@ -2471,7 +2567,7 @@ func TestAgent_checkStateSnapshot(t *testing.T) {
Tags: []string{"foo"},
Port: 8000,
}
if err := a.AddService(svc, nil, false, ""); err != nil {
if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -2484,7 +2580,7 @@ func TestAgent_checkStateSnapshot(t *testing.T) {
ServiceID: "redis",
ServiceName: "redis",
}
if err := a.AddCheck(check1, nil, true, ""); err != nil {
if err := a.AddCheck(check1, nil, true, "", ConfigSourceLocal); err != nil {
t.Fatalf("err: %s", err)
}
@ -2976,9 +3072,9 @@ func TestAgent_AddProxy(t *testing.T) {
Service: "web",
Port: 8080,
}
require.NoError(a.AddService(reg, nil, false, ""))
require.NoError(a.AddService(reg, nil, false, "", ConfigSourceLocal))
err := a.AddProxy(tt.proxy, false, false, "")
err := a.AddProxy(tt.proxy, false, false, "", ConfigSourceLocal)
if tt.wantErr {
require.Error(err)
return
@ -3030,7 +3126,7 @@ func TestAgent_RemoveProxy(t *testing.T) {
Service: "web",
Port: 8080,
}
require.NoError(a.AddService(reg, nil, false, ""))
require.NoError(a.AddService(reg, nil, false, "", ConfigSourceLocal))
// Add a proxy for web
pReg := &structs.ConnectManagedProxy{
@ -3038,7 +3134,7 @@ func TestAgent_RemoveProxy(t *testing.T) {
ExecMode: structs.ProxyExecModeDaemon,
Command: []string{"foo"},
}
require.NoError(a.AddProxy(pReg, false, false, ""))
require.NoError(a.AddProxy(pReg, false, false, "", ConfigSourceLocal))
// Test the ID was created as we expect.
gotProxy := a.State.Proxy("web-proxy")
@ -3069,7 +3165,7 @@ func TestAgent_ReLoadProxiesFromConfig(t *testing.T) {
Service: "web",
Port: 8080,
}
require.NoError(a.AddService(reg, nil, false, ""))
require.NoError(a.AddService(reg, nil, false, "", ConfigSourceLocal))
proxies := a.State.Proxies()
require.Len(proxies, 0)

View File

@ -588,6 +588,9 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
proxyDefaultScriptCommand := c.Connect.ProxyDefaults.ScriptCommand
proxyDefaultConfig := c.Connect.ProxyDefaults.Config
enableRemoteScriptChecks := b.boolVal(c.EnableScriptChecks)
enableLocalScriptChecks := b.boolValWithDefault(c.EnableLocalScriptChecks, enableRemoteScriptChecks)
// ----------------------------------------------------------------
// build runtime config
//
@ -743,7 +746,8 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
DiscoveryMaxStale: b.durationVal("discovery_max_stale", c.DiscoveryMaxStale),
EnableAgentTLSForChecks: b.boolVal(c.EnableAgentTLSForChecks),
EnableDebug: b.boolVal(c.EnableDebug),
EnableScriptChecks: b.boolVal(c.EnableScriptChecks),
EnableRemoteScriptChecks: enableRemoteScriptChecks,
EnableLocalScriptChecks: enableLocalScriptChecks,
EnableSyslog: b.boolVal(c.EnableSyslog),
EnableUI: b.boolVal(c.UI),
EncryptKey: b.stringVal(c.EncryptKey),

View File

@ -191,6 +191,7 @@ type Config struct {
EnableAgentTLSForChecks *bool `json:"enable_agent_tls_for_checks,omitempty" hcl:"enable_agent_tls_for_checks" mapstructure:"enable_agent_tls_for_checks"`
EnableDebug *bool `json:"enable_debug,omitempty" hcl:"enable_debug" mapstructure:"enable_debug"`
EnableScriptChecks *bool `json:"enable_script_checks,omitempty" hcl:"enable_script_checks" mapstructure:"enable_script_checks"`
EnableLocalScriptChecks *bool `json:"enable_local_script_checks,omitempty" hcl:"enable_local_script_checks" mapstructure:"enable_local_script_checks"`
EnableSyslog *bool `json:"enable_syslog,omitempty" hcl:"enable_syslog" mapstructure:"enable_syslog"`
EncryptKey *string `json:"encrypt,omitempty" hcl:"encrypt" mapstructure:"encrypt"`
EncryptVerifyIncoming *bool `json:"encrypt_verify_incoming,omitempty" hcl:"encrypt_verify_incoming" mapstructure:"encrypt_verify_incoming"`

View File

@ -71,6 +71,7 @@ func AddFlags(fs *flag.FlagSet, f *Flags) {
add(&f.Config.Ports.DNS, "dns-port", "DNS port to use.")
add(&f.Config.DNSDomain, "domain", "Domain to use for DNS interface.")
add(&f.Config.EnableScriptChecks, "enable-script-checks", "Enables health check scripts.")
add(&f.Config.EnableLocalScriptChecks, "enable-local-script-checks", "Enables health check scripts from configuration file.")
add(&f.Config.EncryptKey, "encrypt", "Provides the gossip encryption key.")
add(&f.Config.Ports.GRPC, "grpc-port", "Sets the gRPC API port to listen on (currently needed for Envoy xDS only).")
add(&f.Config.Ports.HTTP, "http-port", "Sets the HTTP API port to listen on.")

View File

@ -638,13 +638,21 @@ type RuntimeConfig struct {
// hcl: enable_debug = (true|false)
EnableDebug bool
// EnableScriptChecks controls whether health checks which execute
// scripts are enabled. This includes regular script checks and Docker
// EnableLocalScriptChecks controls whether health checks declared from the local
// config file which execute scripts are enabled. This includes regular script
// checks and Docker checks.
//
// hcl: (enable_script_checks|enable_local_script_checks) = (true|false)
// flag: -enable-script-checks, -enable-local-script-checks
EnableLocalScriptChecks bool
// EnableRemoeScriptChecks controls whether health checks declared from the http API
// which execute scripts are enabled. This includes regular script checks and Docker
// checks.
//
// hcl: enable_script_checks = (true|false)
// flag: -enable-script-checks
EnableScriptChecks bool
EnableRemoteScriptChecks bool
// EnableSyslog is used to also tee all the logs over to syslog. Only supported
// on linux and OSX. Other platforms will generate an error.

View File

@ -351,7 +351,8 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
`-data-dir=` + dataDir,
},
patch: func(rt *RuntimeConfig) {
rt.EnableScriptChecks = true
rt.EnableLocalScriptChecks = true
rt.EnableRemoteScriptChecks = true
rt.DataDir = dataDir
},
},
@ -2973,6 +2974,7 @@ func TestFullConfig(t *testing.T) {
"enable_agent_tls_for_checks": true,
"enable_debug": true,
"enable_script_checks": true,
"enable_local_script_checks": true,
"enable_syslog": true,
"encrypt": "A4wELWqH",
"encrypt_verify_incoming": true,
@ -3504,6 +3506,7 @@ func TestFullConfig(t *testing.T) {
enable_agent_tls_for_checks = true
enable_debug = true
enable_script_checks = true
enable_local_script_checks = true
enable_syslog = true
encrypt = "A4wELWqH"
encrypt_verify_incoming = true
@ -4129,7 +4132,8 @@ func TestFullConfig(t *testing.T) {
EnableACLReplication: true,
EnableAgentTLSForChecks: true,
EnableDebug: true,
EnableScriptChecks: true,
EnableRemoteScriptChecks: true,
EnableLocalScriptChecks: true,
EnableSyslog: true,
EnableUI: true,
EncryptKey: "A4wELWqH",
@ -4918,7 +4922,8 @@ func TestSanitize(t *testing.T) {
"EnableACLReplication": false,
"EnableAgentTLSForChecks": false,
"EnableDebug": false,
"EnableScriptChecks": false,
"EnableLocalScriptChecks": false,
"EnableRemoteScriptChecks": false,
"EnableSyslog": false,
"EnableUI": false,
"EncryptKey": "hidden",

View File

@ -623,9 +623,9 @@ func (c *ConsulProvider) generateCA(privateKey string, sn uint64) (string, error
serialNum := &big.Int{}
serialNum.SetUint64(sn)
template := x509.Certificate{
SerialNumber: serialNum,
Subject: pkix.Name{CommonName: name},
URIs: []*url.URL{id.URI()},
SerialNumber: serialNum,
Subject: pkix.Name{CommonName: name},
URIs: []*url.URL{id.URI()},
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign |
x509.KeyUsageCRLSign |

View File

@ -79,7 +79,7 @@ func (s *snapshot) persistNodes(sink raft.SnapshotSink,
Node: n.Node,
Address: n.Address,
TaggedAddresses: n.TaggedAddresses,
NodeMeta: n.Meta,
NodeMeta: n.Meta,
}
// Register the node itself

View File

@ -283,7 +283,7 @@ func TestAgent_sidecarServiceFromNodeService(t *testing.T) {
a := NewTestAgent("jones", hcl)
if tt.preRegister != nil {
err := a.AddService(tt.preRegister.NodeService(), nil, false, "")
err := a.AddService(tt.preRegister.NodeService(), nil, false, "", ConfigSourceLocal)
require.NoError(err)
}

View File

@ -49,7 +49,7 @@ func TestMaintCommand_NoArgs(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", agent.ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
if err := a.EnableServiceMaintenance("test", "broken 1", ""); err != nil {
@ -145,7 +145,7 @@ func TestMaintCommand_EnableServiceMaintenance(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", agent.ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}
@ -179,7 +179,7 @@ func TestMaintCommand_DisableServiceMaintenance(t *testing.T) {
ID: "test",
Service: "test",
}
if err := a.AddService(service, nil, false, ""); err != nil {
if err := a.AddService(service, nil, false, "", agent.ConfigSourceLocal); err != nil {
t.Fatalf("err: %v", err)
}

View File

@ -28,8 +28,13 @@ There are several different kinds of checks:
Consul will wait for any child processes spawned by the script to finish. For any
other system, Consul will attempt to force-kill the script and any child processes
it has spawned once the timeout has passed.
In Consul 0.9.0 and later, the agent must be configured with [`enable_script_checks`]
(/docs/agent/options.html#_enable_script_checks) set to `true` in order to enable script checks.
In Consul 0.9.0 and later, script checks are not enabled by default. To use them you
can either use :
* [`enable_local_script_checks`](/docs/agent/options.html#_enable_local_script_checks):
enable script checks defile in local config files. Script checks defined via the HTTP
API will not be allowed.
* [`enable_script_checks`](/docs/agent/options.html#_enable_script_checks): enable
script checks regardless of how they are defined.
* HTTP + Interval - These checks make an HTTP `GET` request every Interval (e.g.
every 30 seconds) to the specified URL. The status of the service depends on

View File

@ -200,9 +200,13 @@ will exit with an error at startup.
* <a name="_enable_script_checks"></a><a href="#_enable_script_checks">`-enable-script-checks`</a> This
controls whether [health checks that execute scripts](/docs/agent/checks.html) are enabled on
this agent, and defaults to `false` so operators must opt-in to allowing these. If enabled,
it is recommended to [enable ACLs](/docs/guides/acl.html) as well to control which users are
allowed to register new checks to execute scripts. This was added in Consul 0.9.0.
this agent, and defaults to `false` so operators must opt-in to allowing these. If enabled, it is recommended
to [enable ACLs](/docs/guides/acl.html) as well to control which users are allowed to register new checks to
execute scripts. This was added in Consul 0.9.0.
* <a name="_enable_local_script_checks"></a><a href="#_enable_local_script_checks">`-enable-local-script-checks`</a>
Like [`enable_script_checks`](#_enable_script_checks), but only enable them when they are defined in the local
config files. Script checks defined in HTTP API registratrions will still not be allowed.
* <a name="_encrypt"></a><a href="#_encrypt">`-encrypt`</a> - Specifies the secret key to
use for encryption of Consul

View File

@ -996,8 +996,9 @@ to use for registration events:
access.
In addition to ACLs, in Consul 0.9.0 and later, the agent must be configured with
[`enable_script_checks`](/docs/agent/options.html#_enable_script_checks) set to `true` in order to enable
script checks.
[`enable_script_checks`](/docs/agent/options.html#_enable_script_checks) or
[`enable_local_script_checks`](/docs/agent/options.html#_enable_local_script_checks)
set to `true` in order to enable script checks.
#### Session Rules