[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:
parent
bf741cbc04
commit
260a9880ae
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue