From 0c184042c52377d0c76ee5a12b4bbe9a774933e5 Mon Sep 17 00:00:00 2001 From: Ashesh Vidyut <134911583+absolutelightning@users.noreply.github.com> Date: Wed, 6 Sep 2023 01:09:06 +0530 Subject: [PATCH 1/6] change log for audit log (#18668) * change log for audit log * fix file name * breaking change --- .changelog/18668.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/18668.txt diff --git a/.changelog/18668.txt b/.changelog/18668.txt new file mode 100644 index 000000000000..fdd63e1c6d4b --- /dev/null +++ b/.changelog/18668.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +audit-logging: **(Enterprise only)** allowing timestamp based filename only on rotation. initially the filename will be just file.json +``` From 7ea986783d1bec75779225cd358bec042d6f020e Mon Sep 17 00:00:00 2001 From: Phil Porada Date: Tue, 5 Sep 2023 16:34:44 -0400 Subject: [PATCH 2/6] Add TCP+TLS Healthchecks (#18381) * Begin adding TCPUseTLS * More TCP with TLS plumbing * Making forward progress * Keep on adding TCP+TLS support for healthchecks * Removed too many lines * Unit tests for TCP+TLS * Update tlsutil/config.go Co-authored-by: Samantha * Working on the tcp+tls unit test * Updated the runtime integration tests * Progress * Revert this file back to HEAD * Remove debugging lines * Implement TLS enabled TCP socket server and make a successful TCP+TLS healthcheck on it * Update docs * Update agent/agent_test.go Co-authored-by: Samantha * Update website/content/docs/ecs/configuration-reference.mdx Co-authored-by: Samantha * Update website/content/docs/ecs/configuration-reference.mdx Co-authored-by: Samantha * Update agent/checks/check.go Co-authored-by: Samantha * Address comments * Remove extraneous bracket * Update agent/agent_test.go Co-authored-by: Samantha * Update agent/agent_test.go Co-authored-by: Samantha * Update website/content/docs/ecs/configuration-reference.mdx Co-authored-by: Samantha * Update the mockTLSServer * Remove trailing newline * Address comments * Fix merge problem * Add changelog entry --------- Co-authored-by: Samantha --- .changelog/18381.txt | 6 + agent/agent.go | 20 +- agent/agent_test.go | 90 +++++- agent/checks/check.go | 38 ++- agent/config/builder.go | 1 + agent/config/config.go | 1 + agent/config/runtime_test.go | 61 +++- .../TestRuntimeConfig_Sanitize.golden | 2 + agent/structs/check_definition.go | 6 + agent/structs/check_type.go | 5 + agent/structs/structs.go | 2 + agent/txn_endpoint.go | 1 + api/agent.go | 1 + api/health.go | 1 + proto/private/pbservice/healthcheck.gen.go | 4 + proto/private/pbservice/healthcheck.pb.go | 306 ++++++++++-------- proto/private/pbservice/healthcheck.proto | 2 + website/content/api-docs/agent/check.mdx | 4 + .../docs/dynamic-app-config/watches.mdx | 1 + .../docs/ecs/configuration-reference.mdx | 3 +- .../checks-configuration-reference.mdx | 4 +- 21 files changed, 385 insertions(+), 174 deletions(-) create mode 100644 .changelog/18381.txt diff --git a/.changelog/18381.txt b/.changelog/18381.txt new file mode 100644 index 000000000000..f6af62993f59 --- /dev/null +++ b/.changelog/18381.txt @@ -0,0 +1,6 @@ +```release-note:improvement +checks: It is now possible to configure agent TCP checks to use TLS with +optional server SNI and mutual authentication. To use TLS with a TCP check, the +check must enable the `tcp_use_tls` boolean. By default the agent will use the +TLS configuration in the `tls.default` stanza. +``` diff --git a/agent/agent.go b/agent/agent.go index dead6b38696b..a85fead58291 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -3066,14 +3066,20 @@ func (a *Agent) addCheck(check *structs.HealthCheck, chkType *structs.CheckType, chkType.Interval = checks.MinInterval } + var tlsClientConfig *tls.Config + if chkType.TCPUseTLS { + tlsClientConfig = a.tlsConfigurator.OutgoingTLSConfigForCheck(chkType.TLSSkipVerify, chkType.TLSServerName) + } + tcp := &checks.CheckTCP{ - CheckID: cid, - ServiceID: sid, - TCP: chkType.TCP, - Interval: chkType.Interval, - Timeout: chkType.Timeout, - Logger: a.logger, - StatusHandler: statusHandler, + CheckID: cid, + ServiceID: sid, + TCP: chkType.TCP, + Interval: chkType.Interval, + Timeout: chkType.Timeout, + Logger: a.logger, + TLSClientConfig: tlsClientConfig, + StatusHandler: statusHandler, } tcp.Start() a.checkTCPs[cid] = tcp diff --git a/agent/agent_test.go b/agent/agent_test.go index c597f1d5d575..f3932c792d40 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -14,11 +14,7 @@ import ( "encoding/json" "errors" "fmt" - "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/proxycfg-sources/local" - "github.com/hashicorp/consul/agent/xds" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" + "io" mathrand "math/rand" "net" "net/http" @@ -34,6 +30,12 @@ import ( "testing" "time" + "github.com/hashicorp/consul/agent/grpc-external/limiter" + "github.com/hashicorp/consul/agent/proxycfg" + "github.com/hashicorp/consul/agent/proxycfg-sources/local" + "github.com/hashicorp/consul/agent/xds" + proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tcpproxy" @@ -973,6 +975,80 @@ func TestAgent_AddServiceWithH2CPINGCheck(t *testing.T) { requireCheckExists(t, a, "test-h2cping-check") } +func startMockTLSServer(t *testing.T) (addr string, closeFunc func() error) { + // Load certificates + cert, err := tls.LoadX509KeyPair("../test/key/ourdomain_server.cer", "../test/key/ourdomain_server.key") + require.NoError(t, err) + // Create a certificate pool + rootCertPool := x509.NewCertPool() + caCert, err := os.ReadFile("../test/ca/root.cer") + require.NoError(t, err) + rootCertPool.AppendCertsFromPEM(caCert) + // Configure TLS + config := &tls.Config{ + Certificates: []tls.Certificate{cert}, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: rootCertPool, + } + // Start TLS server + ln, err := tls.Listen("tcp", "127.0.0.1:0", config) + require.NoError(t, err) + go func() { + for { + conn, err := ln.Accept() + if err != nil { + return + } + io.Copy(io.Discard, conn) + conn.Close() + } + }() + return ln.Addr().String(), ln.Close +} + +func TestAgent_AddServiceWithTCPTLSCheck(t *testing.T) { + t.Parallel() + dataDir := testutil.TempDir(t, "agent") + a := NewTestAgent(t, ` + data_dir = "`+dataDir+`" + enable_agent_tls_for_checks = true + datacenter = "dc1" + tls { + defaults { + ca_file = "../test/ca/root.cer" + cert_file = "../test/key/ourdomain_server.cer" + key_file = "../test/key/ourdomain_server.key" + } + } + `) + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + // Start mock TCP+TLS server + addr, closeServer := startMockTLSServer(t) + defer closeServer() + check := &structs.HealthCheck{ + Node: "foo", + CheckID: "arbitraryTCPServerTLSCheck", + Name: "arbitraryTCPServerTLSCheck", + Status: api.HealthCritical, + } + chkType := &structs.CheckType{ + TCP: addr, + TCPUseTLS: true, + TLSServerName: "server.dc1.consul", + Interval: 5 * time.Second, + } + err := a.AddCheck(check, chkType, false, "", ConfigSourceLocal) + require.NoError(t, err) + // Retry until the healthcheck is passing. + retry.Run(t, func(r *retry.R) { + status := getCheck(a, "arbitraryTCPServerTLSCheck") + if status.Status != api.HealthPassing { + r.Fatalf("bad: %v", status.Status) + } + }) +} + func TestAgent_AddServiceNoExec(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -4308,7 +4384,7 @@ func TestAgent_consulConfig_RequestLimits(t *testing.T) { t.Parallel() hcl := ` - limits { + limits { request_limits { mode = "enforcing" read_rate = 8888 @@ -6278,7 +6354,7 @@ func TestAgent_scadaProvider(t *testing.T) { }, Overrides: ` cloud { - resource_id = "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/project/0b9de9a3-8403-4ca6-aba8-fca752f42100/consul.cluster/0b9de9a3-8403-4ca6-aba8-fca752f42100" + resource_id = "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/project/0b9de9a3-8403-4ca6-aba8-fca752f42100/consul.cluster/0b9de9a3-8403-4ca6-aba8-fca752f42100" client_id = "test" client_secret = "test" }`, diff --git a/agent/checks/check.go b/agent/checks/check.go index 0c730b510942..cabecddcf5a2 100644 --- a/agent/checks/check.go +++ b/agent/checks/check.go @@ -625,19 +625,20 @@ func (c *CheckH2PING) Start() { go c.run() } -// CheckTCP is used to periodically make an TCP/UDP connection to -// determine the health of a given check. +// CheckTCP is used to periodically make a TCP connection to determine the +// health of a given check. // The check is passing if the connection succeeds // The check is critical if the connection returns an error // Supports failures_before_critical and success_before_passing. type CheckTCP struct { - CheckID structs.CheckID - ServiceID structs.ServiceID - TCP string - Interval time.Duration - Timeout time.Duration - Logger hclog.Logger - StatusHandler *StatusHandler + CheckID structs.CheckID + ServiceID structs.ServiceID + TCP string + Interval time.Duration + Timeout time.Duration + Logger hclog.Logger + TLSClientConfig *tls.Config + StatusHandler *StatusHandler dialer *net.Dialer stop bool @@ -694,17 +695,30 @@ func (c *CheckTCP) run() { // check is invoked periodically to perform the TCP check func (c *CheckTCP) check() { - conn, err := c.dialer.Dial(`tcp`, c.TCP) + var conn io.Closer + var err error + var checkType string + + if c.TLSClientConfig == nil { + conn, err = c.dialer.Dial(`tcp`, c.TCP) + checkType = "TCP" + } else { + conn, err = tls.DialWithDialer(c.dialer, `tcp`, c.TCP, c.TLSClientConfig) + checkType = "TCP+TLS" + } + if err != nil { - c.Logger.Warn("Check socket connection failed", + c.Logger.Warn(fmt.Sprintf("Check %s connection failed", checkType), "check", c.CheckID.String(), "error", err, ) c.StatusHandler.updateCheck(c.CheckID, api.HealthCritical, err.Error()) return } + conn.Close() - c.StatusHandler.updateCheck(c.CheckID, api.HealthPassing, fmt.Sprintf("TCP connect %s: Success", c.TCP)) + c.StatusHandler.updateCheck(c.CheckID, api.HealthPassing, fmt.Sprintf("%s connect %s: Success", checkType, c.TCP)) + } // CheckUDP is used to periodically send a UDP datagram to determine the health of a given check. diff --git a/agent/config/builder.go b/agent/config/builder.go index a3ca1abfd0c1..e67409635184 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -1618,6 +1618,7 @@ func (b *builder) checkVal(v *CheckDefinition) *structs.CheckDefinition { Body: stringVal(v.Body), DisableRedirects: boolVal(v.DisableRedirects), TCP: stringVal(v.TCP), + TCPUseTLS: boolVal(v.TCPUseTLS), UDP: stringVal(v.UDP), Interval: b.durationVal(fmt.Sprintf("check[%s].interval", id), v.Interval), DockerContainerID: stringVal(v.DockerContainerID), diff --git a/agent/config/config.go b/agent/config/config.go index baaa1805191a..91db8e42a1c3 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -423,6 +423,7 @@ type CheckDefinition struct { DisableRedirects *bool `mapstructure:"disable_redirects"` OutputMaxSize *int `mapstructure:"output_max_size"` TCP *string `mapstructure:"tcp"` + TCPUseTLS *bool `mapstructure:"tcp_use_tls"` UDP *string `mapstructure:"udp"` Interval *string `mapstructure:"interval"` DockerContainerID *string `mapstructure:"docker_container_id" alias:"dockercontainerid"` diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index e39557b3d41b..d71bb5088955 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2357,12 +2357,12 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, json: []string{`{ "cloud": { - "resource_id": "file-id" + "resource_id": "file-id" } }`}, hcl: []string{` cloud = { - resource_id = "file-id" + resource_id = "file-id" } `}, expected: func(rt *RuntimeConfig) { @@ -2529,6 +2529,60 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { rt.DataDir = dataDir }, }) + run(t, testCase{ + desc: "tcp check with tcp_use_tls set", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "tcp": "localhost:55555", "tcp_use_tls": true, "interval": "5s" } }`, + }, + hcl: []string{ + `check = { name = "a" tcp = "localhost:55555" tcp_use_tls = true interval = "5s" }`, + }, + expected: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + {Name: "a", TCP: "localhost:55555", TCPUseTLS: true, OutputMaxSize: checks.DefaultBufSize, Interval: 5 * time.Second}, + } + rt.DataDir = dataDir + }, + }) + run(t, testCase{ + desc: "tcp check with tcp_use_tls set to false", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "tcp": "localhost:55555", "tcp_use_tls": false, "interval": "5s" } }`, + }, + hcl: []string{ + `check = { name = "a" tcp = "localhost:55555" tcp_use_tls = false interval = "5s" }`, + }, + expected: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + {Name: "a", TCP: "localhost:55555", TCPUseTLS: false, OutputMaxSize: checks.DefaultBufSize, Interval: 5 * time.Second}, + } + rt.DataDir = dataDir + }, + }) + run(t, testCase{ + desc: "tcp check with tcp_use_tls not set", + args: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "tcp": "localhost:55555", "interval": "5s" } }`, + }, + hcl: []string{ + `check = { name = "a" tcp = "localhost:55555" interval = "5s" }`, + }, + expected: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + {Name: "a", TCP: "localhost:55555", TCPUseTLS: false, OutputMaxSize: checks.DefaultBufSize, Interval: 5 * time.Second}, + } + rt.DataDir = dataDir + }, + }) run(t, testCase{ desc: "h2ping check without h2ping_use_tls set", args: []string{ @@ -6287,6 +6341,7 @@ func TestLoad_FullConfig(t *testing.T) { Body: "wSjTy7dg", DisableRedirects: true, TCP: "RJQND605", + TCPUseTLS: false, H2PING: "9N1cSb5B", H2PingUseTLS: false, OSService: "aAjE6m9Z", @@ -6317,6 +6372,7 @@ func TestLoad_FullConfig(t *testing.T) { DisableRedirects: false, OutputMaxSize: checks.DefaultBufSize, TCP: "4jG5casb", + TCPUseTLS: false, H2PING: "HCHU7gEb", H2PingUseTLS: false, OSService: "aqq95BhP", @@ -6346,6 +6402,7 @@ func TestLoad_FullConfig(t *testing.T) { DisableRedirects: true, OutputMaxSize: checks.DefaultBufSize, TCP: "JY6fTTcw", + TCPUseTLS: false, H2PING: "rQ8eyCSF", H2PingUseTLS: false, OSService: "aZaCAXww", diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index 6bb08ff95fed..e339923dc95f 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -117,6 +117,7 @@ "Status": "", "SuccessBeforePassing": 0, "TCP": "", + "TCPUseTLS": false, "TLSServerName": "", "TLSSkipVerify": false, "TTL": "0s", @@ -368,6 +369,7 @@ "Status": "", "SuccessBeforePassing": 0, "TCP": "", + "TCPUseTLS": false, "TLSServerName": "", "TLSSkipVerify": false, "TTL": "0s", diff --git a/agent/structs/check_definition.go b/agent/structs/check_definition.go index ec760832609a..0b04290e707d 100644 --- a/agent/structs/check_definition.go +++ b/agent/structs/check_definition.go @@ -36,6 +36,7 @@ type CheckDefinition struct { Body string DisableRedirects bool TCP string + TCPUseTLS bool UDP string Interval time.Duration DockerContainerID string @@ -76,6 +77,7 @@ func (t *CheckDefinition) UnmarshalJSON(data []byte) (err error) { DockerContainerIDSnake string `json:"docker_container_id"` TLSServerNameSnake string `json:"tls_server_name"` TLSSkipVerifySnake bool `json:"tls_skip_verify"` + TCPUseTLSSnake bool `json:"tcp_use_tls"` GRPCUseTLSSnake bool `json:"grpc_use_tls"` ServiceIDSnake string `json:"service_id"` H2PingUseTLSSnake bool `json:"h2ping_use_tls"` @@ -119,6 +121,9 @@ func (t *CheckDefinition) UnmarshalJSON(data []byte) (err error) { if aux.TLSSkipVerifySnake { t.TLSSkipVerify = aux.TLSSkipVerifySnake } + if aux.TCPUseTLSSnake { + t.TCPUseTLS = aux.TCPUseTLSSnake + } if aux.GRPCUseTLSSnake { t.GRPCUseTLS = aux.GRPCUseTLSSnake } @@ -220,6 +225,7 @@ func (c *CheckDefinition) CheckType() *CheckType { DisableRedirects: c.DisableRedirects, OutputMaxSize: c.OutputMaxSize, TCP: c.TCP, + TCPUseTLS: c.TCPUseTLS, UDP: c.UDP, Interval: c.Interval, DockerContainerID: c.DockerContainerID, diff --git a/agent/structs/check_type.go b/agent/structs/check_type.go index 96254f62d86e..61a5a762f7c5 100644 --- a/agent/structs/check_type.go +++ b/agent/structs/check_type.go @@ -42,6 +42,7 @@ type CheckType struct { Body string DisableRedirects bool TCP string + TCPUseTLS bool UDP string Interval time.Duration AliasNode string @@ -87,6 +88,7 @@ func (t *CheckType) UnmarshalJSON(data []byte) (err error) { DockerContainerIDSnake string `json:"docker_container_id"` TLSServerNameSnake string `json:"tls_server_name"` TLSSkipVerifySnake bool `json:"tls_skip_verify"` + TCPUseTLSSnake bool `json:"tcp_use_tls"` GRPCUseTLSSnake bool `json:"grpc_use_tls"` H2PingUseTLSSnake bool `json:"h2ping_use_tls"` @@ -131,6 +133,9 @@ func (t *CheckType) UnmarshalJSON(data []byte) (err error) { if aux.TLSSkipVerifySnake { t.TLSSkipVerify = aux.TLSSkipVerifySnake } + if aux.TCPUseTLSSnake { + t.TCPUseTLS = aux.TCPUseTLSSnake + } if aux.GRPCUseTLSSnake { t.GRPCUseTLS = aux.GRPCUseTLSSnake } diff --git a/agent/structs/structs.go b/agent/structs/structs.go index fbacb36ffe66..5a6fd9511892 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -1879,6 +1879,7 @@ type HealthCheckDefinition struct { Body string `json:",omitempty"` DisableRedirects bool `json:",omitempty"` TCP string `json:",omitempty"` + TCPUseTLS bool `json:",omitempty"` UDP string `json:",omitempty"` H2PING string `json:",omitempty"` OSService string `json:",omitempty"` @@ -2031,6 +2032,7 @@ func (c *HealthCheck) CheckType() *CheckType { Body: c.Definition.Body, DisableRedirects: c.Definition.DisableRedirects, TCP: c.Definition.TCP, + TCPUseTLS: c.Definition.TCPUseTLS, UDP: c.Definition.UDP, H2PING: c.Definition.H2PING, OSService: c.Definition.OSService, diff --git a/agent/txn_endpoint.go b/agent/txn_endpoint.go index 10117a53c500..04dcd7fa3902 100644 --- a/agent/txn_endpoint.go +++ b/agent/txn_endpoint.go @@ -313,6 +313,7 @@ func (s *HTTPHandlers) convertOps(resp http.ResponseWriter, req *http.Request) ( Method: check.Definition.Method, Body: check.Definition.Body, TCP: check.Definition.TCP, + TCPUseTLS: check.Definition.TCPUseTLS, GRPC: check.Definition.GRPC, GRPCUseTLS: check.Definition.GRPCUseTLS, OSService: check.Definition.OSService, diff --git a/api/agent.go b/api/agent.go index b09ed1c1cd75..6775edf4257a 100644 --- a/api/agent.go +++ b/api/agent.go @@ -345,6 +345,7 @@ type AgentServiceCheck struct { Method string `json:",omitempty"` Body string `json:",omitempty"` TCP string `json:",omitempty"` + TCPUseTLS bool `json:",omitempty"` UDP string `json:",omitempty"` Status string `json:",omitempty"` Notes string `json:",omitempty"` diff --git a/api/health.go b/api/health.go index 932317fdb01e..a0230020460d 100644 --- a/api/health.go +++ b/api/health.go @@ -67,6 +67,7 @@ type HealthCheckDefinition struct { TLSServerName string TLSSkipVerify bool TCP string + TCPUseTLS bool UDP string GRPC string OSService string diff --git a/proto/private/pbservice/healthcheck.gen.go b/proto/private/pbservice/healthcheck.gen.go index 092a4ded9e82..1c608d88c7a7 100644 --- a/proto/private/pbservice/healthcheck.gen.go +++ b/proto/private/pbservice/healthcheck.gen.go @@ -21,6 +21,7 @@ func CheckTypeToStructs(s *CheckType, t *structs.CheckType) { t.Body = s.Body t.DisableRedirects = s.DisableRedirects t.TCP = s.TCP + t.TCPUseTLS = s.TCPUseTLS t.UDP = s.UDP t.Interval = structs.DurationFromProto(s.Interval) t.AliasNode = s.AliasNode @@ -59,6 +60,7 @@ func CheckTypeFromStructs(t *structs.CheckType, s *CheckType) { s.Body = t.Body s.DisableRedirects = t.DisableRedirects s.TCP = t.TCP + s.TCPUseTLS = t.TCPUseTLS s.UDP = t.UDP s.Interval = structs.DurationToProto(t.Interval) s.AliasNode = t.AliasNode @@ -142,6 +144,7 @@ func HealthCheckDefinitionToStructs(s *HealthCheckDefinition, t *structs.HealthC t.Body = s.Body t.DisableRedirects = s.DisableRedirects t.TCP = s.TCP + t.TCPUseTLS = s.TCPUseTLS t.UDP = s.UDP t.H2PING = s.H2PING t.OSService = s.OSService @@ -171,6 +174,7 @@ func HealthCheckDefinitionFromStructs(t *structs.HealthCheckDefinition, s *Healt s.Body = t.Body s.DisableRedirects = t.DisableRedirects s.TCP = t.TCP + s.TCPUseTLS = t.TCPUseTLS s.UDP = t.UDP s.H2PING = t.H2PING s.OSService = t.OSService diff --git a/proto/private/pbservice/healthcheck.pb.go b/proto/private/pbservice/healthcheck.pb.go index ba0edbde9d64..0392fd77455b 100644 --- a/proto/private/pbservice/healthcheck.pb.go +++ b/proto/private/pbservice/healthcheck.pb.go @@ -279,6 +279,7 @@ type HealthCheckDefinition struct { Body string `protobuf:"bytes,18,opt,name=Body,proto3" json:"Body,omitempty"` DisableRedirects bool `protobuf:"varint,22,opt,name=DisableRedirects,proto3" json:"DisableRedirects,omitempty"` TCP string `protobuf:"bytes,5,opt,name=TCP,proto3" json:"TCP,omitempty"` + TCPUseTLS bool `protobuf:"varint,25,opt,name=TCPUseTLS,proto3" json:"TCPUseTLS,omitempty"` UDP string `protobuf:"bytes,23,opt,name=UDP,proto3" json:"UDP,omitempty"` OSService string `protobuf:"bytes,24,opt,name=OSService,proto3" json:"OSService,omitempty"` // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto @@ -390,6 +391,13 @@ func (x *HealthCheckDefinition) GetTCP() string { return "" } +func (x *HealthCheckDefinition) GetTCPUseTLS() bool { + if x != nil { + return x.TCPUseTLS + } + return false +} + func (x *HealthCheckDefinition) GetUDP() string { if x != nil { return x.UDP @@ -532,6 +540,7 @@ type CheckType struct { Body string `protobuf:"bytes,26,opt,name=Body,proto3" json:"Body,omitempty"` DisableRedirects bool `protobuf:"varint,31,opt,name=DisableRedirects,proto3" json:"DisableRedirects,omitempty"` TCP string `protobuf:"bytes,8,opt,name=TCP,proto3" json:"TCP,omitempty"` + TCPUseTLS bool `protobuf:"varint,34,opt,name=TCPUseTLS,proto3" json:"TCPUseTLS,omitempty"` UDP string `protobuf:"bytes,32,opt,name=UDP,proto3" json:"UDP,omitempty"` OSService string `protobuf:"bytes,33,opt,name=OSService,proto3" json:"OSService,omitempty"` // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto @@ -677,6 +686,13 @@ func (x *CheckType) GetTCP() string { return "" } +func (x *CheckType) GetTCPUseTLS() bool { + if x != nil { + return x.TCPUseTLS + } + return false +} + func (x *CheckType) GetUDP() string { if x != nil { return x.UDP @@ -884,7 +900,7 @@ var file_private_pbservice_healthcheck_proto_rawDesc = []byte{ 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x92, 0x08, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb0, 0x08, 0x0a, 0x15, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x24, 0x0a, 0x0d, 0x54, @@ -905,153 +921,157 @@ var file_private_pbservice_healthcheck_proto_rawDesc = []byte{ 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, - 0x10, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, - 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x18, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x07, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, + 0x1c, 0x0a, 0x09, 0x54, 0x43, 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x19, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x54, 0x43, 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x10, 0x0a, + 0x03, 0x55, 0x44, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, + 0x1c, 0x0a, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x18, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, + 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, + 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, + 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, + 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, + 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, + 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, + 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, + 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, + 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, + 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, + 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x15, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, + 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, + 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, + 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, + 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, + 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x03, 0x54, 0x54, 0x4c, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xd2, 0x0a, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x54, + 0x54, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x50, + 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x10, + 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, + 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x43, + 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x54, + 0x43, 0x50, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x18, + 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x53, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, + 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, + 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, + 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, 0x6f, + 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, + 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x18, + 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, 0x0a, + 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x1e, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, + 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, + 0x54, 0x4c, 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, + 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, + 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x54, + 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x11, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, + 0x54, 0x54, 0x4c, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, + 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, + 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x18, 0x1d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, + 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, + 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x43, + 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x16, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, + 0x74, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x54, + 0x54, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, + 0x54, 0x54, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x47, 0x52, 0x50, 0x43, + 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x47, 0x52, 0x50, + 0x43, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, - 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x74, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, - 0x66, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, - 0x67, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x41, 0x72, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, - 0x4e, 0x47, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, - 0x12, 0x22, 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, - 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, - 0x65, 0x54, 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, - 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, - 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, - 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, - 0x4c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0xb4, 0x0a, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x48, 0x54, 0x54, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, - 0x12, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, - 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, - 0x50, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x10, 0x0a, 0x03, - 0x55, 0x44, 0x50, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x1c, - 0x0a, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x4f, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x08, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, - 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, - 0x49, 0x4e, 0x47, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, - 0x47, 0x12, 0x22, 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, - 0x53, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, - 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0e, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, - 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, - 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, - 0x4c, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, - 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, - 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, - 0x67, 0x12, 0x36, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, - 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, - 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x47, 0x52, 0x50, 0x43, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x47, 0x52, 0x50, 0x43, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x69, - 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x96, 0x02, 0x0a, 0x25, 0x63, 0x6f, - 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x42, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, 0x48, - 0x43, 0x49, 0x53, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, + 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x96, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, + 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x53, 0xaa, + 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x2d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x61, 0x6c, 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/private/pbservice/healthcheck.proto b/proto/private/pbservice/healthcheck.proto index b3cbf050448b..d75a7fc7c71b 100644 --- a/proto/private/pbservice/healthcheck.proto +++ b/proto/private/pbservice/healthcheck.proto @@ -66,6 +66,7 @@ message HealthCheckDefinition { string Body = 18; bool DisableRedirects = 22; string TCP = 5; + bool TCPUseTLS = 25; string UDP = 23; string OSService = 24; // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto @@ -117,6 +118,7 @@ message CheckType { string Body = 26; bool DisableRedirects = 31; string TCP = 8; + bool TCPUseTLS = 34; string UDP = 32; string OSService = 33; // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto diff --git a/website/content/api-docs/agent/check.mdx b/website/content/api-docs/agent/check.mdx index 03364b6aeb31..5faf7286295f 100644 --- a/website/content/api-docs/agent/check.mdx +++ b/website/content/api-docs/agent/check.mdx @@ -239,6 +239,10 @@ The table below shows this endpoint's support for made to both addresses, and the first successful connection attempt will result in a successful check. +- `TCPUseTLS` `(bool: false)` - Specifies whether to use TLS for this `TCP` health check. + If TLS is enabled, then by default, a valid TLS certificate is expected. Certificate + verification can be turned off by setting `TLSSkipVerify` to `true`. + - `UDP` `(string: "")` - Specifies a `UDP` IP address/hostname and port. The check sends datagrams to the value specified at the interval specified in the `Interval` configuration. If the datagram is sent successfully or a timeout is returned, the check is set to the `passing` state. diff --git a/website/content/docs/dynamic-app-config/watches.mdx b/website/content/docs/dynamic-app-config/watches.mdx index cb6ef644808f..64b52be358cc 100644 --- a/website/content/docs/dynamic-app-config/watches.mdx +++ b/website/content/docs/dynamic-app-config/watches.mdx @@ -535,6 +535,7 @@ An example of the output of this command: "TLSServerName": "", "TLSSkipVerify": false, "TCP": "", + "TCPUseTLS": false, "GRPC": "", "GRPCUseTLS": false }, diff --git a/website/content/docs/ecs/configuration-reference.mdx b/website/content/docs/ecs/configuration-reference.mdx index fed887bc835d..8d2aedd7357e 100644 --- a/website/content/docs/ecs/configuration-reference.mdx +++ b/website/content/docs/ecs/configuration-reference.mdx @@ -189,9 +189,10 @@ Defines the Consul checks for the service. Each `check` object may contain the f | `status` | `string` | optional | Specifies the initial status the health check. Must be one of `passing`, `warning`, `critical`, `maintenance`, or `null`. | | `successBeforePassing` | `integer` | optional | Specifies the number of consecutive successful results required before check status transitions to passing. | | `tcp` | `string` | optional | Specifies this is a TCP check. Must be an IP/hostname plus port to which a TCP connection is made every `interval`. | +| `tcpUseTls` | `boolean` | optional | Specifies whether to use TLS for this `TCP` health check. If TLS is enabled, then by default, a valid TLS certificate is expected. Certificate verification can be disabled by setting `TLSSkipVerify` to `true`. | | `timeout` | `string` | optional | Specifies a timeout for outgoing connections. Applies to script, HTTP, TCP, UDP, and gRPC checks. Must be a duration string, such as `10s` or `5m`. | | `tlsServerName` | `string` | optional | Specifies an optional string used to set the SNI host when connecting via TLS. | -| `tlsSkipVerify` | `boolean` | optional | Specifies if the certificate for an HTTPS check should not be verified. | +| `tlsSkipVerify` | `boolean` | optional | Specifies if the check should verify the chain and hostname of the certificate presented by the server being checked. Set to `true` to disable verification. We recommend setting to `false` for production use. Default is `false`. Supported check types: `HTTP`, `H2Ping`, `gRPC`, and `TCP`| | `ttl` | `string` | optional | Specifies this is a TTL check. Must be a duration string, such as `10s` or `5m`. | | `udp` | `string` | optional | Specifies this is a UDP check. Must be an IP/hostname plus port to which UDP datagrams are sent every `interval`. | diff --git a/website/content/docs/services/configuration/checks-configuration-reference.mdx b/website/content/docs/services/configuration/checks-configuration-reference.mdx index 10934217aacb..c842d334b6bf 100644 --- a/website/content/docs/services/configuration/checks-configuration-reference.mdx +++ b/website/content/docs/services/configuration/checks-configuration-reference.mdx @@ -36,7 +36,7 @@ Specify health check options in the `check` block. To register two or more heath | `h2ping_use_tls` | Boolean value that enables TLS for H2ping checks when set to `true`. |
  • H2ping
  • | | `http` | String value that specifies an HTTP endpoint to send requests to. |
  • HTTP
  • | | `tls_server_name` | String value that specifies the server name used to verify the hostname on the returned certificates unless `tls_skip_verify` is given. Also included in the client's handshake to support SNI. It is recommended that this field be left unspecified. The TLS client will deduce the server name for SNI from the check address unless it's an IP ([RFC 6066, Section 3](https://tools.ietf.org/html/rfc6066#section-3)). There are two common circumstances where supplying a `tls_server_name` can be beneficial:
  • When the check address is an IP, `tls_server_name` can be specified for SNI. Note: setting `tls_server_name` will also override the hostname used to verify the certificate presented by the server being checked.
  • When the hostname in the check address won't be present in the SAN (Subject Alternative Name) field of the certificate presented by the server being checked. Note: setting `tls_server_name` will also override the hostname used for SNI.
  • |
  • HTTP
  • H2Ping
  • gRPC
  • | -| `tls_skip_verify` | Boolean value that determines if the check verifies the chain and hostname of the certificate that the server presents. Set to `true` to disable verification. We recommend setting to `false` for production use. Default is `false`. |
  • HTTP
  • H2Ping
  • gRPC
  • | +| `tls_skip_verify` | Boolean value that determines if the check verifies the chain and hostname of the certificate that the server presents. Set to `true` to disable verification. We recommend setting to `false` for production use. Default is `false`. |
  • HTTP
  • H2Ping
  • gRPC
  • TCP
  • | | `method` | String value that specifies the request method to send during HTTP checks. Default is `GET`. |
  • HTTP
  • | | `header` | Object that specifies header fields to send in HTTP check requests. Each header specified in `header` object contains a list of string values. |
  • HTTP
  • | | `body` | String value that contains JSON attributes to send in HTTP check requests. You must escape the quotation marks around the keys and values for each attribute. |
  • HTTP
  • | @@ -44,6 +44,7 @@ Specify health check options in the `check` block. To register two or more heath | `os_service` | String value that specifies the name of the name of a service to check during an OSService check. |
  • OSService
  • | | `service_id` | String value that specifies the ID of a service instance to associate with an OSService check. That service instance must be on the same node as the check. If not specified, the check verifies the health of the node. |
  • OSService
  • | | `tcp` | String value that specifies an IP address or host and port number for the check establish a TCP connection with. |
  • TCP
  • | +| `tcp_use_tls` | Boolean value that enables TLS for TCP checks when set to `true`. |
  • TCP
  • | | `udp` | String value that specifies an IP address or host and port number for the check to send UDP datagrams to. |
  • UDP
  • | | `ttl` | String value that specifies how long to wait for an update from an external process during a TTL check. |
  • TTL
  • | | `alias_service` | String value that specifies a service or node that the service associated with the health check aliases. |
  • Alias
  • | @@ -52,4 +53,3 @@ Specify health check options in the `check` block. To register two or more heath ## Checks block You can define multiple health checks in a single `checks` block. The `checks` block is an array of objects that contain the configuration options described in the [`check` block configuration reference](#check-block). - From ac27585dd4aeb02cd5e11d8b96314a28226f8b69 Mon Sep 17 00:00:00 2001 From: Ashesh Vidyut <134911583+absolutelightning@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:23:09 +0530 Subject: [PATCH 3/6] Fix windows Ent runner (#18683) * fix windows image for enterprise * added quotesT --- .github/scripts/get_runner_classes_windows.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/scripts/get_runner_classes_windows.sh b/.github/scripts/get_runner_classes_windows.sh index a29ea5debf75..a64c3a8c2845 100755 --- a/.github/scripts/get_runner_classes_windows.sh +++ b/.github/scripts/get_runner_classes_windows.sh @@ -10,11 +10,11 @@ set -euo pipefail case "$GITHUB_REPOSITORY" in *-enterprise) # shellcheck disable=SC2129 - echo "compute-small=['self-hosted', 'windows', 'small']" >>"$GITHUB_OUTPUT" - echo "compute-medium=['self-hosted', 'windows', 'medium']" >>"$GITHUB_OUTPUT" - echo "compute-large=['self-hosted', 'windows', 'large']" >>"$GITHUB_OUTPUT" + echo "compute-small=['self-hosted', 'ondemand', 'os=windows-2019']" >>"$GITHUB_OUTPUT" + echo "compute-medium=['self-hosted', 'ondemand', 'os=windows-2019']" >>"$GITHUB_OUTPUT" + echo "compute-large=['self-hosted', 'ondemand', 'os=windows-2019']" >>"$GITHUB_OUTPUT" # m5d.8xlarge is equivalent to our xl custom runner in CE - echo "compute-xl=['self-hosted', 'ondemand', 'windows', 'type=m6a.2xlarge']" >>"$GITHUB_OUTPUT" + echo "compute-xl=['self-hosted', 'ondemand', 'os=windows-2019']" >>"$GITHUB_OUTPUT" ;; *) # shellcheck disable=SC2129 From 60b0485497aaae5f04de7b58a2dcbeed5b468cd0 Mon Sep 17 00:00:00 2001 From: Ashesh Vidyut <134911583+absolutelightning@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:49:25 +0530 Subject: [PATCH 4/6] Removed nodename and status from consul snapshot save -append-filename command and using leader version in version (#18680) * init * fix tests * fix tests lint * fix api call inside dc * updated doc * address comments --- command/snapshot/save/snapshot_save.go | 51 ++++++++------------- command/snapshot/save/snapshot_save_test.go | 28 +++++------ website/content/commands/snapshot/save.mdx | 16 +++---- 3 files changed, 40 insertions(+), 55 deletions(-) diff --git a/command/snapshot/save/snapshot_save.go b/command/snapshot/save/snapshot_save.go index c774e6d89e1d..ac333e8ca3d3 100644 --- a/command/snapshot/save/snapshot_save.go +++ b/command/snapshot/save/snapshot_save.go @@ -36,7 +36,7 @@ type cmd struct { func (c *cmd) getAppendFileNameFlag() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) fs.Var(&c.appendFileNameFlag, "append-filename", "Append filename flag supports the following "+ - "comma-separated arguments. 1. version, 2. dc. 3. node 4. status. It appends these values to the filename provided in the command") + "comma-separated arguments. 1. version, 2. dc. It appends these values to the filename provided in the command") return fs } @@ -74,50 +74,35 @@ func (c *cmd) Run(args []string) int { appendFileNameFlags := strings.Split(c.appendFileNameFlag.String(), ",") if len(appendFileNameFlags) != 0 && len(c.appendFileNameFlag.String()) > 0 { - agentSelfResponse, err := client.Agent().Self() - if err != nil { - c.UI.Error(fmt.Sprintf("Error connecting to Consul agent and fetching datacenter/version: %s", err)) - return 1 - } - fileExt := filepath.Ext(file) fileNameWithoutExt := strings.TrimSuffix(file, fileExt) if slices.Contains(appendFileNameFlags, "version") { - if config, ok := agentSelfResponse["Config"]; ok { - if version, ok := config["Version"]; ok { - fileNameWithoutExt = fileNameWithoutExt + "-" + version.(string) + operatorHealthResponse, err := client.Operator().AutopilotServerHealth(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error fetching version of Consul agent Leader: %s", err)) + return 1 + } + var version string + for _, server := range operatorHealthResponse.Servers { + if server.Leader { + version = server.Version + break } } + fileNameWithoutExt = fileNameWithoutExt + "-" + version } if slices.Contains(appendFileNameFlags, "dc") { - if config, ok := agentSelfResponse["Config"]; ok { - if datacenter, ok := config["Datacenter"]; ok { - fileNameWithoutExt = fileNameWithoutExt + "-" + datacenter.(string) - } + agentSelfResponse, err := client.Agent().Self() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent and fetching datacenter/version: %s", err)) + return 1 } - } - if slices.Contains(appendFileNameFlags, "node") { if config, ok := agentSelfResponse["Config"]; ok { - if nodeName, ok := config["NodeName"]; ok { - fileNameWithoutExt = fileNameWithoutExt + "-" + nodeName.(string) - } - } - } - - if slices.Contains(appendFileNameFlags, "status") { - if status, ok := agentSelfResponse["Stats"]; ok { - if config, ok := status["consul"]; ok { - configMap := config.(map[string]interface{}) - if leader, ok := configMap["leader"]; ok { - if leader == "true" { - fileNameWithoutExt = fileNameWithoutExt + "-" + "leader" - } else { - fileNameWithoutExt = fileNameWithoutExt + "-" + "follower" - } - } + if datacenter, ok := config["Datacenter"]; ok { + fileNameWithoutExt = fileNameWithoutExt + "-" + datacenter.(string) } } } diff --git a/command/snapshot/save/snapshot_save_test.go b/command/snapshot/save/snapshot_save_test.go index fb672b9993b9..44d07aebb882 100644 --- a/command/snapshot/save/snapshot_save_test.go +++ b/command/snapshot/save/snapshot_save_test.go @@ -88,19 +88,11 @@ func TestSnapshotSaveCommandWithAppendFileNameFlag(t *testing.T) { dir := testutil.TempDir(t, "snapshot") file := filepath.Join(dir, "backup.tgz") args := []string{ - "-append-filename=version,dc,node,status", + "-append-filename=version,dc", "-http-addr=" + a.HTTPAddr(), file, } - stats := a.Stats() - - status := "follower" - - if stats["consul"]["leader"] == "true" { - status = "leader" - } - // We need to use the self endpoint here for ENT, which returns the product suffix (+ent) self, err := client.Agent().Self() require.NoError(t, err) @@ -108,14 +100,22 @@ func TestSnapshotSaveCommandWithAppendFileNameFlag(t *testing.T) { cfg, ok := self["Config"] require.True(t, ok) - versionAny, ok := cfg["Version"] + dc, ok := cfg["Datacenter"] require.True(t, ok) - version, ok := versionAny.(string) - require.True(t, ok) + datacenter := dc.(string) + + operatorHealth, error := client.Operator().AutopilotServerHealth(nil) + require.NoError(t, error) + + var version string + for _, server := range operatorHealth.Servers { + if server.Leader { + version = server.Version + } + } - newFilePath := filepath.Join(dir, "backup"+"-"+version+"-"+a.Config.Datacenter+ - "-"+a.Config.NodeName+"-"+status+".tgz") + newFilePath := filepath.Join(dir, "backup"+"-"+version+"-"+datacenter+".tgz") code := c.Run(args) if code != 0 { diff --git a/website/content/commands/snapshot/save.mdx b/website/content/commands/snapshot/save.mdx index dfd4d4086d45..cf77cd48a695 100644 --- a/website/content/commands/snapshot/save.mdx +++ b/website/content/commands/snapshot/save.mdx @@ -77,20 +77,20 @@ $ consul snapshot save -stale backup.snap # ... ``` -To create snapshot file with consul version, datacenter, node name and leader/follower info, -run +This is useful for situations where a cluster is in a degraded state and no +leader is available. To target a specific server for a snapshot, you can run +the `consul snapshot save` command on that specific server. + +To create snapshot file with consul version and datacenter run ```shell-session -$ consul snapshot save -append-filename node,status,version,dc backup.snap +$ consul snapshot save -append-filename version,dc backup.snap #... ``` -File name created will be like backup-%CONSUL_VERSION%-%DC_NAME%-%NODE_NAME%-%STATUS.snap +File name created will be like backup-%CONSUL_VERSION%-%DC_NAME%.snap example - backup-1.17.0-dc1-local-machine-leader.tgz - -This is useful for situations where a cluster is in a degraded state and no -leader is available. To target a specific server for a snapshot, you can run -the `consul snapshot save` command on that specific server. +Note Version is always the leader's consul version Please see the [HTTP API](/consul/api-docs/snapshot) documentation for more details about snapshot internals. From ec507fe4a8203d2f57a28418d80652b6fecc959b Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Wed, 6 Sep 2023 11:11:43 -0400 Subject: [PATCH 5/6] update guide to reflect tenancy and scope (#18687) * update guide to reflect tenancy and scope * Apply suggestions from code review Co-authored-by: Semir Patel * update ACLHooks signature * Update docs/resources/guide.md Co-authored-by: Semir Patel --------- Co-authored-by: Semir Patel --- docs/resources/guide.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/resources/guide.md b/docs/resources/guide.md index c19566577b72..8d81571f91cf 100644 --- a/docs/resources/guide.md +++ b/docs/resources/guide.md @@ -55,11 +55,15 @@ var BarV1Alpha1Type = &pbresource.Type{ func RegisterTypes(r resource.Registry) { r.Register(resource.Registration{ - Type: BarV1Alpha1Type, + Type: BarV1Alpha1Type, + Scope: resource.ScopePartition, Proto: &pbv1alpha1.Bar{}, }) } ``` +Note that Scope reference the scope of the new resource, `resource.ScopePartition` +mean that resource will be at the partition level and have no namespace, while `resource.ScopeNamespace` mean it will have both a namespace +and a partition. Update the `NewTypeRegistry` method in [`type_registry.go`] to call your package's type registration method: @@ -140,7 +144,8 @@ using a validation hook provided in the type registration: func RegisterTypes(r resource.Registry) { r.Register(resource.Registration{ Type: BarV1Alpha1Type, - Proto: &pbv1alpha1.Bar{}, + Proto: &pbv1alpha1.Bar{}, + Scope: resource.ScopeNamespace, Validate: validateBar, }) } @@ -172,7 +177,8 @@ a set of ACL hooks: func RegisterTypes(r resource.Registry) { r.Register(resource.Registration{ Type: BarV1Alpha1Type, - Proto: &pbv1alpha1.Bar{}, + Proto: &pbv1alpha1.Bar{}, + Scope: resource.ScopeNamespace, ACLs: &resource.ACLHooks{, Read: authzReadBar, Write: authzWriteBar, @@ -181,19 +187,19 @@ func RegisterTypes(r resource.Registry) { }) } -func authzReadBar(authz acl.Authorizer, id *pbresource.ID) error { +func authzReadBar(authz acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID) error { return authz.ToAllowAuthorizer(). - BarReadAllowed(id.Name, resource.AuthorizerContext(id.Tenancy)) + BarReadAllowed(id.Name, authzContext) } -func authzWriteBar(authz acl.Authorizer, id *pbresource.ID) error { +func authzWriteBar(authz acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { return authz.ToAllowAuthorizer(). - BarWriteAllowed(id.Name, resource.AuthorizerContext(id.Tenancy)) + BarWriteAllowed(res.ID().Name, authzContext) } -func authzListBar(authz acl.Authorizer, ten *pbresource.Tenancy) error { +func authzListBar(authz acl.Authorizer, authzContext *acl.AuthorizerContext) error { return authz.ToAllowAuthorizer(). - BarListAllowed(resource.AuthorizerContext(ten)) + BarListAllowed(authzContext) } ``` @@ -210,7 +216,8 @@ by providing a mutation hook: func RegisterTypes(r resource.Registry) { r.Register(resource.Registration{ Type: BarV1Alpha1Type, - Proto: &pbv1alpha1.Bar{}, + Proto: &pbv1alpha1.Bar{}, + Scope: resource.ScopeNamespace, Mutate: mutateBar, }) } From 56917eb4c9688df86e69aa99e13897fa203ecfb0 Mon Sep 17 00:00:00 2001 From: Derek Menteer <105233703+hashi-derek@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:52:45 -0500 Subject: [PATCH 6/6] Add support for querying tokens by service name. (#18667) Add support for querying tokens by service name The consul-k8s endpoints controller has a workflow where it fetches all tokens. This is not performant for large clusters, where there may be a sizable number of tokens. This commit attempts to alleviate that problem and introduces a new way to query by the token's service name. --- .changelog/18667.txt | 3 + agent/acl_endpoint.go | 1 + agent/acl_endpoint_test.go | 32 ++++++ agent/consul/acl_endpoint.go | 14 ++- agent/consul/acl_replication_test.go | 5 + agent/consul/acl_replication_types.go | 1 + agent/consul/state/acl.go | 65 +++++++++--- agent/consul/state/acl_ce.go | 4 + agent/consul/state/acl_schema.go | 25 +++++ agent/consul/state/acl_test.go | 133 ++++++++++++++++++++---- agent/structs/acl.go | 1 + api/acl.go | 45 ++++++++ api/acl_test.go | 83 +++++++++++++++ website/content/api-docs/acl/tokens.mdx | 3 + 14 files changed, 378 insertions(+), 37 deletions(-) create mode 100644 .changelog/18667.txt diff --git a/.changelog/18667.txt b/.changelog/18667.txt new file mode 100644 index 000000000000..c9ef7b455121 --- /dev/null +++ b/.changelog/18667.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: Add support for listing ACL tokens by service name. +``` diff --git a/agent/acl_endpoint.go b/agent/acl_endpoint.go index 9f38f41f15db..afef4330e426 100644 --- a/agent/acl_endpoint.go +++ b/agent/acl_endpoint.go @@ -294,6 +294,7 @@ func (s *HTTPHandlers) ACLTokenList(resp http.ResponseWriter, req *http.Request) args.Policy = req.URL.Query().Get("policy") args.Role = req.URL.Query().Get("role") args.AuthMethod = req.URL.Query().Get("authmethod") + args.ServiceName = req.URL.Query().Get("servicename") if err := parseACLAuthMethodEnterpriseMeta(req, &args.ACLAuthMethodEnterpriseMeta); err != nil { return nil, err } diff --git a/agent/acl_endpoint_test.go b/agent/acl_endpoint_test.go index 82b2a9574fcf..a1aaba52a5c8 100644 --- a/agent/acl_endpoint_test.go +++ b/agent/acl_endpoint_test.go @@ -1328,6 +1328,38 @@ func TestACL_HTTP(t *testing.T) { require.Error(t, err) testutil.RequireErrorContains(t, err, "Only lowercase alphanumeric") }) + + t.Run("Create with valid service identity", func(t *testing.T) { + tokenInput := &structs.ACLToken{ + Description: "token for service identity sn1", + ServiceIdentities: []*structs.ACLServiceIdentity{ + { + ServiceName: "sn1", + }, + }, + } + + req, _ := http.NewRequest("PUT", "/v1/acl/token", jsonBody(tokenInput)) + req.Header.Add("X-Consul-Token", "root") + resp := httptest.NewRecorder() + _, err := a.srv.ACLTokenCreate(resp, req) + require.NoError(t, err) + }) + + t.Run("List by ServiceName", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/acl/tokens?servicename=sn1", nil) + req.Header.Add("X-Consul-Token", "root") + resp := httptest.NewRecorder() + raw, err := a.srv.ACLTokenList(resp, req) + require.NoError(t, err) + tokens, ok := raw.(structs.ACLTokenListStubs) + require.True(t, ok) + require.Len(t, tokens, 1) + token := tokens[0] + require.Equal(t, "token for service identity sn1", token.Description) + require.Len(t, token.ServiceIdentities, 1) + require.Equal(t, "sn1", token.ServiceIdentities[0].ServiceName) + }) }) } diff --git a/agent/consul/acl_endpoint.go b/agent/consul/acl_endpoint.go index 97189bb45d27..ba9a081ea704 100644 --- a/agent/consul/acl_endpoint.go +++ b/agent/consul/acl_endpoint.go @@ -680,8 +680,18 @@ func (a *ACL) TokenList(args *structs.ACLTokenListRequest, reply *structs.ACLTok } return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta, - func(ws memdb.WatchSet, state *state.Store) error { - index, tokens, err := state.ACLTokenList(ws, args.IncludeLocal, args.IncludeGlobal, args.Policy, args.Role, args.AuthMethod, methodMeta, &args.EnterpriseMeta) + func(ws memdb.WatchSet, s *state.Store) error { + index, tokens, err := s.ACLTokenListWithParameters(ws, state.ACLTokenListParameters{ + Local: args.IncludeLocal, + Global: args.IncludeGlobal, + Policy: args.Policy, + Role: args.Role, + MethodName: args.AuthMethod, + ServiceName: args.ServiceName, + MethodMeta: methodMeta, + EnterpriseMeta: &args.EnterpriseMeta, + }) + if err != nil { return err } diff --git a/agent/consul/acl_replication_test.go b/agent/consul/acl_replication_test.go index 7a8e8efa12cb..70ed42672916 100644 --- a/agent/consul/acl_replication_test.go +++ b/agent/consul/acl_replication_test.go @@ -378,8 +378,10 @@ func TestACLReplication_Tokens(t *testing.T) { checkSame := func(t *retry.R) { // only account for global tokens - local tokens shouldn't be replicated + // nolint:staticcheck index, remote, err := s1.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, nil) require.NoError(t, err) + // nolint:staticcheck _, local, err := s2.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, nil) require.NoError(t, err) @@ -483,6 +485,7 @@ func TestACLReplication_Tokens(t *testing.T) { }) // verify dc2 local tokens didn't get blown away + // nolint:staticcheck _, local, err := s2.fsm.State().ACLTokenList(nil, true, false, "", "", "", nil, nil) require.NoError(t, err) require.Len(t, local, 50) @@ -821,9 +824,11 @@ func TestACLReplication_AllTypes(t *testing.T) { checkSameTokens := func(t *retry.R) { // only account for global tokens - local tokens shouldn't be replicated + // nolint:staticcheck index, remote, err := s1.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, nil) require.NoError(t, err) // Query for all of them, so that we can prove that no globals snuck in. + // nolint:staticcheck _, local, err := s2.fsm.State().ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) diff --git a/agent/consul/acl_replication_types.go b/agent/consul/acl_replication_types.go index de9e8cf763a0..8a672cb90d56 100644 --- a/agent/consul/acl_replication_types.go +++ b/agent/consul/acl_replication_types.go @@ -38,6 +38,7 @@ func (r *aclTokenReplicator) FetchRemote(srv *Server, lastRemoteIndex uint64) (i func (r *aclTokenReplicator) FetchLocal(srv *Server) (int, uint64, error) { r.local = nil + // nolint:staticcheck idx, local, err := srv.fsm.State().ACLTokenList(nil, false, true, "", "", "", nil, srv.replicationEnterpriseMeta()) if err != nil { return 0, 0, err diff --git a/agent/consul/state/acl.go b/agent/consul/state/acl.go index f82b671b18b6..5114d09e4643 100644 --- a/agent/consul/state/acl.go +++ b/agent/consul/state/acl.go @@ -623,8 +623,35 @@ func aclTokenGetTxn(tx ReadTxn, ws memdb.WatchSet, value, index string, entMeta return nil, nil } +type ACLTokenListParameters struct { + Local bool + Global bool + Policy string + Role string + ServiceName string + MethodName string + MethodMeta *acl.EnterpriseMeta + EnterpriseMeta *acl.EnterpriseMeta +} + // ACLTokenList return a list of ACL Tokens that match the policy, role, and method. +// This function should be treated as deprecated, and ACLTokenListWithParameters should be preferred. +// +// Deprecated: use ACLTokenListWithParameters func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role, methodName string, methodMeta, entMeta *acl.EnterpriseMeta) (uint64, structs.ACLTokens, error) { + return s.ACLTokenListWithParameters(ws, ACLTokenListParameters{ + Local: local, + Global: global, + Policy: policy, + Role: role, + MethodName: methodName, + MethodMeta: methodMeta, + EnterpriseMeta: entMeta, + }) +} + +// ACLTokenListWithParameters returns a list of ACL Tokens that match the provided parameters. +func (s *Store) ACLTokenListWithParameters(ws memdb.WatchSet, params ACLTokenListParameters) (uint64, structs.ACLTokens, error) { tx := s.db.Txn(false) defer tx.Abort() @@ -637,43 +664,51 @@ func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role needLocalityFilter := false - if policy == "" && role == "" && methodName == "" { - if global == local { - iter, err = aclTokenListAll(tx, entMeta) + if params.Policy == "" && params.Role == "" && params.MethodName == "" && params.ServiceName == "" { + if params.Global == params.Local { + iter, err = aclTokenListAll(tx, params.EnterpriseMeta) } else { - iter, err = aclTokenList(tx, entMeta, local) + iter, err = aclTokenList(tx, params.EnterpriseMeta, params.Local) } - } else if policy != "" && role == "" && methodName == "" { - iter, err = aclTokenListByPolicy(tx, policy, entMeta) + } else if params.Policy != "" && params.Role == "" && params.MethodName == "" && params.ServiceName == "" { + // Find by policy + iter, err = aclTokenListByPolicy(tx, params.Policy, params.EnterpriseMeta) + needLocalityFilter = true + + } else if params.Policy == "" && params.Role != "" && params.MethodName == "" && params.ServiceName == "" { + // Find by role + iter, err = aclTokenListByRole(tx, params.Role, params.EnterpriseMeta) needLocalityFilter = true - } else if policy == "" && role != "" && methodName == "" { - iter, err = aclTokenListByRole(tx, role, entMeta) + } else if params.Policy == "" && params.Role == "" && params.MethodName != "" && params.ServiceName == "" { + // Find by methodName + iter, err = aclTokenListByAuthMethod(tx, params.MethodName, params.MethodMeta, params.EnterpriseMeta) needLocalityFilter = true - } else if policy == "" && role == "" && methodName != "" { - iter, err = aclTokenListByAuthMethod(tx, methodName, methodMeta, entMeta) + } else if params.Policy == "" && params.Role == "" && params.MethodName == "" && params.ServiceName != "" { + // Find by the service identity's serviceName + iter, err = aclTokenListByServiceName(tx, params.ServiceName, params.EnterpriseMeta) needLocalityFilter = true } else { - return 0, nil, fmt.Errorf("can only filter by one of policy, role, or methodName at a time") + return 0, nil, fmt.Errorf("can only filter by one of policy, role, serviceName, or methodName at a time") } if err != nil { return 0, nil, fmt.Errorf("failed acl token lookup: %v", err) } - if needLocalityFilter && global != local { + if needLocalityFilter && params.Global != params.Local { iter = memdb.NewFilterIterator(iter, func(raw interface{}) bool { token, ok := raw.(*structs.ACLToken) if !ok { return true } - if global && !token.Local { + if params.Global && !token.Local { return false - } else if local && token.Local { + } else if params.Local && token.Local { return false } @@ -698,7 +733,7 @@ func (s *Store) ACLTokenList(ws memdb.WatchSet, local, global bool, policy, role } // Get the table index. - idx := aclTokenMaxIndex(tx, nil, entMeta) + idx := aclTokenMaxIndex(tx, nil, params.EnterpriseMeta) return idx, result, nil } diff --git a/agent/consul/state/acl_ce.go b/agent/consul/state/acl_ce.go index ee0a8eb5ee64..e8f6450e09f9 100644 --- a/agent/consul/state/acl_ce.go +++ b/agent/consul/state/acl_ce.go @@ -76,6 +76,10 @@ func aclTokenListByAuthMethod(tx ReadTxn, authMethod string, _, _ *acl.Enterpris return tx.Get(tableACLTokens, indexAuthMethod, AuthMethodQuery{Value: authMethod}) } +func aclTokenListByServiceName(tx ReadTxn, serviceName string, entMeta *acl.EnterpriseMeta) (memdb.ResultIterator, error) { + return tx.Get(tableACLTokens, indexServiceName, Query{Value: serviceName}) +} + func aclTokenDeleteWithToken(tx WriteTxn, token *structs.ACLToken, idx uint64) error { // remove the token if err := tx.Delete(tableACLTokens, token); err != nil { diff --git a/agent/consul/state/acl_schema.go b/agent/consul/state/acl_schema.go index cdee3ed9fff4..17c772b37e01 100644 --- a/agent/consul/state/acl_schema.go +++ b/agent/consul/state/acl_schema.go @@ -22,6 +22,7 @@ const ( indexAccessor = "accessor" indexPolicies = "policies" indexRoles = "roles" + indexServiceName = "service-name" indexAuthMethod = "authmethod" indexLocality = "locality" indexName = "name" @@ -106,6 +107,15 @@ func tokensTableSchema() *memdb.TableSchema { writeIndex: indexExpiresLocalFromACLToken, }, }, + indexServiceName: { + Name: indexServiceName, + AllowMissing: true, + Unique: false, + Indexer: indexerMulti[Query, *structs.ACLToken]{ + readIndex: indexFromQuery, + writeIndexMulti: indexServiceNameFromACLToken, + }, + }, }, } } @@ -398,6 +408,21 @@ func indexExpiresFromACLToken(t *structs.ACLToken, local bool) ([]byte, error) { return b.Bytes(), nil } +func indexServiceNameFromACLToken(token *structs.ACLToken) ([][]byte, error) { + vals := make([][]byte, 0, len(token.ServiceIdentities)) + for _, id := range token.ServiceIdentities { + if id != nil && id.ServiceName != "" { + var b indexBuilder + b.String(strings.ToLower(id.ServiceName)) + vals = append(vals, b.Bytes()) + } + } + if len(vals) == 0 { + return nil, errMissingValueForIndex + } + return vals, nil +} + func authMethodsTableSchema() *memdb.TableSchema { return &memdb.TableSchema{ Name: tableACLAuthMethods, diff --git a/agent/consul/state/acl_test.go b/agent/consul/state/acl_test.go index 330c0689aafc..7614991c4137 100644 --- a/agent/consul/state/acl_test.go +++ b/agent/consul/state/acl_test.go @@ -214,6 +214,7 @@ func TestStateStore_ACLBootstrap(t *testing.T) { require.Equal(t, uint64(3), index) // Make sure the ACLs are in an expected state. + // nolint:staticcheck _, tokens, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) require.Len(t, tokens, 1) @@ -228,6 +229,7 @@ func TestStateStore_ACLBootstrap(t *testing.T) { err = s.ACLBootstrap(32, index, token2.Clone()) require.NoError(t, err) + // nolint:staticcheck _, tokens, err = s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) require.Len(t, tokens, 2) @@ -849,18 +851,36 @@ func TestStateStore_ACLToken_List(t *testing.T) { AuthMethod: "test", Local: true, }, + // the serviceName specific token + &structs.ACLToken{ + AccessorID: "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", + SecretID: "9d229cfd-ec4b-4d31-a6fd-ecbcb2a41d41", + ServiceIdentities: []*structs.ACLServiceIdentity{ + {ServiceName: "sn1"}, + }, + }, + // the serviceName specific token and local + &structs.ACLToken{ + AccessorID: "a14fa45e-0afe-4b44-961d-a430030ccfe2", + SecretID: "17f696b9-448a-4bd3-936b-08c92c66530f", + ServiceIdentities: []*structs.ACLServiceIdentity{ + {ServiceName: "sn1"}, + }, + Local: true, + }, } require.NoError(t, s.ACLTokenBatchSet(2, tokens, ACLTokenSetOptions{})) type testCase struct { - name string - local bool - global bool - policy string - role string - methodName string - accessors []string + name string + local bool + global bool + policy string + role string + methodName string + serviceName string + accessors []string } cases := []testCase{ @@ -876,6 +896,7 @@ func TestStateStore_ACLToken_List(t *testing.T) { "47eea4da-bda1-48a6-901c-3e36d2d9262f", // policy + global "54866514-3cf2-4fec-8a8a-710583831834", // mgmt + global "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global + "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global "a7715fde-8954-4c92-afbc-d84c6ecdc582", // role + global }, }, @@ -889,6 +910,7 @@ func TestStateStore_ACLToken_List(t *testing.T) { accessors: []string{ "211f0360-ef53-41d3-9d4d-db84396eb6c0", // authMethod + local "4915fc9d-3726-4171-b588-6c271f45eecd", // policy + local + "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local "cadb4f13-f62a-49ab-ab3f-5a7e01b925d9", // role + local "f1093997-b6c7-496d-bfb8-6b1b1895641b", // mgmt + local }, @@ -983,6 +1005,30 @@ func TestStateStore_ACLToken_List(t *testing.T) { "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global }, }, + { + name: "ServiceName - Local", + local: true, + global: false, + policy: "", + role: "", + methodName: "", + serviceName: "sn1", + accessors: []string{ + "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local + }, + }, + { + name: "ServiceName - Global", + local: false, + global: true, + policy: "", + role: "", + methodName: "", + serviceName: "sn1", + accessors: []string{ + "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global + }, + }, { name: "All", local: true, @@ -997,6 +1043,8 @@ func TestStateStore_ACLToken_List(t *testing.T) { "4915fc9d-3726-4171-b588-6c271f45eecd", // policy + local "54866514-3cf2-4fec-8a8a-710583831834", // mgmt + global "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global + "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global + "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local "a7715fde-8954-4c92-afbc-d84c6ecdc582", // role + global "cadb4f13-f62a-49ab-ab3f-5a7e01b925d9", // role + local "f1093997-b6c7-496d-bfb8-6b1b1895641b", // mgmt + local @@ -1004,14 +1052,27 @@ func TestStateStore_ACLToken_List(t *testing.T) { }, } - for _, tc := range []struct{ policy, role, methodName string }{ - {testPolicyID_A, testRoleID_A, "test"}, - {"", testRoleID_A, "test"}, - {testPolicyID_A, "", "test"}, - {testPolicyID_A, testRoleID_A, ""}, + for _, tc := range []struct{ policy, role, methodName, serviceName string }{ + {testPolicyID_A, testRoleID_A, "test", ""}, + {"", testRoleID_A, "test", ""}, + {testPolicyID_A, "", "test", ""}, + {testPolicyID_A, testRoleID_A, "", ""}, + {testPolicyID_A, "", "", "test"}, } { - t.Run(fmt.Sprintf("can't filter on more than one: %s/%s/%s", tc.policy, tc.role, tc.methodName), func(t *testing.T) { - _, _, err := s.ACLTokenList(nil, false, false, tc.policy, tc.role, tc.methodName, nil, nil) + t.Run(fmt.Sprintf("can't filter on more than one: %s/%s/%s/%s", tc.policy, tc.role, tc.methodName, tc.serviceName), func(t *testing.T) { + var err error + if tc.serviceName == "" { + // The legacy call can only be tested when the serviceName is not specified + // nolint:staticcheck + _, _, err = s.ACLTokenList(nil, false, false, tc.policy, tc.role, tc.methodName, nil, nil) + require.Error(t, err) + } + _, _, err = s.ACLTokenListWithParameters(nil, ACLTokenListParameters{ + Policy: tc.policy, + Role: tc.role, + MethodName: tc.methodName, + ServiceName: tc.serviceName, + }) require.Error(t, err) }) } @@ -1020,12 +1081,33 @@ func TestStateStore_ACLToken_List(t *testing.T) { tc := tc // capture range variable t.Run(tc.name, func(t *testing.T) { t.Parallel() - _, tokens, err := s.ACLTokenList(nil, tc.local, tc.global, tc.policy, tc.role, tc.methodName, nil, nil) - require.NoError(t, err) - require.Len(t, tokens, len(tc.accessors)) - tokens.Sort() - for i, token := range tokens { - require.Equal(t, tc.accessors[i], token.AccessorID) + // Test old function + if tc.serviceName == "" { + // nolint:staticcheck + _, tokens, err := s.ACLTokenList(nil, tc.local, tc.global, tc.policy, tc.role, tc.methodName, nil, nil) + require.NoError(t, err) + require.Len(t, tokens, len(tc.accessors)) + tokens.Sort() + for i, token := range tokens { + require.Equal(t, tc.accessors[i], token.AccessorID) + } + } + // Test new function + { + _, tokens, err := s.ACLTokenListWithParameters(nil, ACLTokenListParameters{ + Local: tc.local, + Global: tc.global, + Policy: tc.policy, + Role: tc.role, + ServiceName: tc.serviceName, + MethodName: tc.methodName, + }) + require.NoError(t, err) + require.Len(t, tokens, len(tc.accessors)) + tokens.Sort() + for i, token := range tokens { + require.Equal(t, tc.accessors[i], token.AccessorID) + } } }) } @@ -1080,6 +1162,7 @@ func TestStateStore_ACLToken_FixupPolicyLinks(t *testing.T) { require.Equal(t, "node-read-renamed", retrieved.Policies[0].Name) // list tokens without stale links + // nolint:staticcheck _, tokens, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -1124,6 +1207,7 @@ func TestStateStore_ACLToken_FixupPolicyLinks(t *testing.T) { require.Len(t, retrieved.Policies, 0) // list tokens without stale links + // nolint:staticcheck _, tokens, err = s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -1209,6 +1293,7 @@ func TestStateStore_ACLToken_FixupRoleLinks(t *testing.T) { require.Equal(t, "node-read-role-renamed", retrieved.Roles[0].Name) // list tokens without stale links + // nolint:staticcheck _, tokens, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -1253,6 +1338,7 @@ func TestStateStore_ACLToken_FixupRoleLinks(t *testing.T) { require.Len(t, retrieved.Roles, 0) // list tokens without stale links + // nolint:staticcheck _, tokens, err = s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) @@ -2688,16 +2774,19 @@ func TestStateStore_ACLAuthMethod_GlobalNameShadowing_TokenTest(t *testing.T) { } require.True(t, t.Run("list local only", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, false, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC2_tok1, methodDC2_tok2}, toList(got)) })) require.True(t, t.Run("list global only", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, false, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2}, toList(got)) })) require.True(t, t.Run("list both", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2, methodDC2_tok1, methodDC2_tok2}, toList(got)) @@ -2709,16 +2798,19 @@ func TestStateStore_ACLAuthMethod_GlobalNameShadowing_TokenTest(t *testing.T) { })) require.True(t, t.Run("list local only (after dc2 delete)", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, false, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.Empty(t, got) })) require.True(t, t.Run("list global only (after dc2 delete)", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, false, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2}, toList(got)) })) require.True(t, t.Run("list both (after dc2 delete)", func(t *testing.T) { + // nolint:staticcheck _, got, err := s.ACLTokenList(nil, true, true, "", "", "test", defaultEntMeta, defaultEntMeta) require.NoError(t, err) require.ElementsMatch(t, []string{methodDC1_tok1, methodDC1_tok2}, toList(got)) @@ -3509,6 +3601,7 @@ func TestStateStore_ACLTokens_Snapshot_Restore(t *testing.T) { require.NoError(t, s.ACLRoleBatchSet(2, roles, false)) // Read the restored ACLs back out and verify that they match. + // nolint:staticcheck idx, res, err := s.ACLTokenList(nil, true, true, "", "", "", nil, nil) require.NoError(t, err) require.Equal(t, uint64(4), idx) diff --git a/agent/structs/acl.go b/agent/structs/acl.go index 813a3b175843..8b5e041378f7 100644 --- a/agent/structs/acl.go +++ b/agent/structs/acl.go @@ -1305,6 +1305,7 @@ type ACLTokenListRequest struct { Policy string // Policy filter Role string // Role filter AuthMethod string // Auth Method filter + ServiceName string // Service name (from service identities) filter Datacenter string // The datacenter to perform the request within ACLAuthMethodEnterpriseMeta acl.EnterpriseMeta diff --git a/api/acl.go b/api/acl.go index 93087cd31c95..48d2e66ee97f 100644 --- a/api/acl.go +++ b/api/acl.go @@ -272,6 +272,13 @@ type ACLAuthMethod struct { Partition string `json:",omitempty"` } +type ACLTokenFilterOptions struct { + AuthMethod string `json:",omitempty"` + Policy string `json:",omitempty"` + Role string `json:",omitempty"` + ServiceName string `json:",omitempty"` +} + func (m *ACLAuthMethod) MarshalJSON() ([]byte, error) { type Alias ACLAuthMethod exported := &struct { @@ -895,6 +902,44 @@ func (a *ACL) TokenList(q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, erro return entries, qm, nil } +// TokenListFiltered lists all tokens that match the given filter options. +// The listing does not contain any SecretIDs as those may only be retrieved by a call to TokenRead. +func (a *ACL) TokenListFiltered(t ACLTokenFilterOptions, q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, error) { + r := a.c.newRequest("GET", "/v1/acl/tokens") + r.setQueryOptions(q) + + if t.AuthMethod != "" { + r.params.Set("authmethod", t.AuthMethod) + } + if t.Policy != "" { + r.params.Set("policy", t.Policy) + } + if t.Role != "" { + r.params.Set("role", t.Role) + } + if t.ServiceName != "" { + r.params.Set("servicename", t.ServiceName) + } + + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var entries []*ACLTokenListEntry + if err := decodeBody(resp, &entries); err != nil { + return nil, nil, err + } + return entries, qm, nil +} + // PolicyCreate will create a new policy. It is not allowed for the policy parameters // ID field to be set as this will be generated by Consul while processing the request. func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) { diff --git a/api/acl_test.go b/api/acl_test.go index f515878290cd..d5ff37c1f75b 100644 --- a/api/acl_test.go +++ b/api/acl_test.go @@ -553,6 +553,89 @@ func TestAPI_ACLToken_List(t *testing.T) { require.NotNil(t, token5) } +func TestAPI_ACLToken_ListFiltered(t *testing.T) { + t.Parallel() + c, s := makeACLClient(t) + defer s.Stop() + + acl := c.ACL() + s.WaitForSerfCheck(t) + + created1, _, err := acl.TokenCreate(&ACLToken{ + Description: "token1", + ServiceIdentities: []*ACLServiceIdentity{ + {ServiceName: "s1"}, + }, + }, nil) + require.NoError(t, err) + require.NotNil(t, created1) + require.NotEqual(t, "", created1.AccessorID) + require.NotEqual(t, "", created1.SecretID) + + created2, _, err := acl.TokenCreate(&ACLToken{ + Description: "token2", + ServiceIdentities: []*ACLServiceIdentity{ + {ServiceName: "s2"}, + }, + }, nil) + require.NoError(t, err) + require.NotNil(t, created2) + require.NotEqual(t, "", created2.AccessorID) + require.NotEqual(t, "", created2.SecretID) + + created3, _, err := acl.TokenCreate(&ACLToken{ + Description: "token3", + ServiceIdentities: []*ACLServiceIdentity{ + {ServiceName: "s1"}, + {ServiceName: "s2"}, + }, + }, nil) + require.NoError(t, err) + require.NotNil(t, created3) + require.NotEqual(t, "", created3.AccessorID) + require.NotEqual(t, "", created3.SecretID) + + tokens, qm, err := acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "s1", + }, nil) + require.NoError(t, err) + require.NotEqual(t, 0, qm.LastIndex) + require.True(t, qm.KnownLeader) + require.Len(t, tokens, 2) + found := make([]string, 0, 2) + for _, token := range tokens { + found = append(found, token.Description) + } + require.ElementsMatch(t, []string{"token1", "token3"}, found) + + tokens, qm, err = acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "s2", + }, nil) + require.NoError(t, err) + require.NotEqual(t, 0, qm.LastIndex) + require.True(t, qm.KnownLeader) + require.Len(t, tokens, 2) + found = make([]string, 0, 2) + for _, token := range tokens { + found = append(found, token.Description) + } + require.ElementsMatch(t, []string{"token2", "token3"}, found) + + tokens, qm, err = acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "nothing", + }, nil) + require.NoError(t, err) + require.NotEqual(t, 0, qm.LastIndex) + require.True(t, qm.KnownLeader) + require.Empty(t, tokens) + + _, _, err = acl.TokenListFiltered(ACLTokenFilterOptions{ + ServiceName: "s", + AuthMethod: "a", + }, nil) + require.ErrorContains(t, err, "can only filter by one of") +} + func TestAPI_ACLToken_Clone(t *testing.T) { t.Parallel() c, s := makeACLClient(t) diff --git a/website/content/api-docs/acl/tokens.mdx b/website/content/api-docs/acl/tokens.mdx index 42b254ddfff3..d1e6d609af69 100644 --- a/website/content/api-docs/acl/tokens.mdx +++ b/website/content/api-docs/acl/tokens.mdx @@ -682,6 +682,9 @@ The corresponding CLI command is [`consul acl token list`](/consul/commands/acl/ - `role` `(string: "")` - Filters the token list to those tokens that are linked with this specific role ID. +- `servicename` `(string: "")` - Filters the token list to those tokens that are + linked with this specific service name in their service identity. + - `authmethod` `(string: "")` - Filters the token list to those tokens that are linked with this specific named auth method.