diff --git a/edge-apis/authwrapper.go b/edge-apis/authwrapper.go index f8033c35..7afe51f7 100644 --- a/edge-apis/authwrapper.go +++ b/edge-apis/authwrapper.go @@ -6,6 +6,11 @@ import ( "context" "encoding/json" "fmt" + "net/http" + "net/url" + "sync" + "time" + "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" "github.com/go-resty/resty/v2" @@ -28,10 +33,6 @@ import ( "github.com/zitadel/oidc/v3/pkg/client/tokenexchange" "github.com/zitadel/oidc/v3/pkg/oidc" "golang.org/x/oauth2" - "net/http" - "net/url" - "sync" - "time" ) const ( @@ -81,8 +82,25 @@ type ApiSession interface { RequiresRouterTokenUpdate() bool GetRequestHeaders() http.Header + + // GetType returns the authentication method used to establish this session, enabling + // callers to determine whether legacy or OIDC-based authentication is in use. + GetType() ApiSessionType } +// ApiSessionType identifies the authentication mechanism used to establish an API session. +type ApiSessionType string + +const ( + // ApiSessionTypeLegacy indicates a session created using the original Ziti authentication + // with session tokens passed in the zt-session header. + ApiSessionTypeLegacy ApiSessionType = "legacy" + + // ApiSessionTypeOidc indicates a session created using OpenID Connect authentication + // with JWT bearer tokens. + ApiSessionTypeOidc ApiSessionType = "oidc" +) + var _ ApiSession = (*ApiSessionLegacy)(nil) var _ ApiSession = (*ApiSessionOidc)(nil) @@ -93,6 +111,10 @@ type ApiSessionLegacy struct { RequestHeaders http.Header } +func (a *ApiSessionLegacy) GetType() ApiSessionType { + return ApiSessionTypeLegacy +} + func (a *ApiSessionLegacy) GetRequestHeaders() http.Header { return a.RequestHeaders } @@ -170,6 +192,10 @@ type ApiSessionOidc struct { RequestHeaders http.Header } +func (a *ApiSessionOidc) GetType() ApiSessionType { + return ApiSessionTypeOidc +} + func (a *ApiSessionOidc) GetRequestHeaders() http.Header { return a.RequestHeaders } diff --git a/edge-apis/clients.go b/edge-apis/clients.go index 6737775a..385f6c6f 100644 --- a/edge-apis/clients.go +++ b/edge-apis/clients.go @@ -64,10 +64,13 @@ type BaseClient[A ApiType] struct { onControllerListeners []func([]*url.URL) } +// Url returns the URL of the currently active controller endpoint. func (self *BaseClient[A]) Url() url.URL { return *self.AuthEnabledApi.GetClientTransportPool().GetActiveTransport().ApiUrl } +// AddOnControllerUpdateListeners registers a callback that is invoked when the list of +// available controller endpoints changes. func (self *BaseClient[A]) AddOnControllerUpdateListeners(listener func([]*url.URL)) { self.onControllerListeners = append(self.onControllerListeners, listener) } @@ -82,12 +85,15 @@ func (self *BaseClient[A]) GetCurrentApiSession() ApiSession { return *ptr } +// SetUseOidc forces the API client to operate in OIDC mode when true, or legacy mode when false. func (self *BaseClient[A]) SetUseOidc(use bool) { v := any(self.API) apiType := v.(OidcEnabledApi) apiType.SetUseOidc(use) } +// SetAllowOidcDynamicallyEnabled configures whether the client checks the controller for +// OIDC support and switches modes accordingly. func (self *BaseClient[A]) SetAllowOidcDynamicallyEnabled(allow bool) { v := any(self.API) apiType := v.(OidcEnabledApi) @@ -134,6 +140,7 @@ func (self *BaseClient[A]) initializeComponents(config *ApiClientConfig) { self.Components = *components } +// NewRuntime creates an OpenAPI runtime configured for the specified API endpoint. func NewRuntime(apiUrl *url.URL, schemes []string, httpClient *http.Client) *openapiclient.Runtime { return openapiclient.NewWithClient(apiUrl.Host, apiUrl.Path, schemes, httpClient) } @@ -170,6 +177,8 @@ func (self *BaseClient[A]) AuthenticateRequest(request runtime.ClientRequest, re return nil } +// ProcessControllers queries the authenticated controller for its list of peer controllers +// and registers them for high-availability failover. func (self *BaseClient[A]) ProcessControllers(authEnabledApi AuthEnabledApi) { list, err := authEnabledApi.ListControllers() @@ -208,6 +217,7 @@ type ManagementApiClient struct { BaseClient[ZitiEdgeManagement] } +// ApiClientConfig contains configuration options for creating API clients. type ApiClientConfig struct { ApiUrls []*url.URL CaPool *x509.CertPool @@ -235,6 +245,7 @@ func NewManagementApiClient(apiUrls []*url.URL, caPool *x509.CertPool, totpCallb }) } +// NewManagementApiClientWithConfig creates a Management API client using the provided configuration. func NewManagementApiClientWithConfig(config *ApiClientConfig) *ManagementApiClient { ret := &ManagementApiClient{} ret.Schemes = rest_management_api_client.DefaultSchemes @@ -264,6 +275,7 @@ func NewManagementApiClientWithConfig(config *ApiClientConfig) *ManagementApiCli return ret } +// ClientApiClient provides access to the Ziti Edge Client API for identity operations. type ClientApiClient struct { BaseClient[ZitiEdgeClient] } @@ -288,6 +300,7 @@ func NewClientApiClient(apiUrls []*url.URL, caPool *x509.CertPool, totpCallback }) } +// NewClientApiClientWithConfig creates a Client API client using the provided configuration. func NewClientApiClientWithConfig(config *ApiClientConfig) *ClientApiClient { ret := &ClientApiClient{} ret.ApiBinding = "edge-client" diff --git a/edge-apis/component.go b/edge-apis/component.go index f84dc0e9..4bc78999 100644 --- a/edge-apis/component.go +++ b/edge-apis/component.go @@ -9,15 +9,15 @@ import ( "time" ) -// Components provides the basic shared lower level pieces used to assemble go-swagger/openapi clients. These -// components are interconnected and have references to each other. This struct is used to set, move, and manage -// them as a set. +// Components provides the foundational HTTP client infrastructure for OpenAPI clients, +// bundling the HTTP client, transport, and certificate pool as a cohesive unit. type Components struct { HttpClient *http.Client HttpTransport *http.Transport CaPool *x509.CertPool } +// ComponentsConfig contains configuration options for creating Components. type ComponentsConfig struct { Proxy func(*http.Request) (*url.URL, error) } @@ -29,7 +29,7 @@ func NewComponents() *Components { }) } -// NewComponentsWithConfig assembles a new set of components with reasonable production defaults. +// NewComponentsWithConfig assembles a new set of components using the provided configuration. func NewComponentsWithConfig(cfg *ComponentsConfig) *Components { tlsClientConfig, _ := rest_util.NewTlsConfig() diff --git a/edge-apis/oidc.go b/edge-apis/oidc.go index 323f9adc..0af71bc7 100644 --- a/edge-apis/oidc.go +++ b/edge-apis/oidc.go @@ -17,8 +17,12 @@ import ( "time" ) +// JwtTokenPrefix is the standard prefix for JWT tokens, representing the first two characters +// of a Base64URL-encoded JWT header. This prefix is used to identify JWT-format tokens. const JwtTokenPrefix = "ey" +// ServiceAccessClaims represents the JWT claims for service-level access tokens, including +// identity and session binding information specific to a service connection. type ServiceAccessClaims struct { jwt.RegisteredClaims ApiSessionId string `json:"z_asid"` @@ -27,6 +31,8 @@ type ServiceAccessClaims struct { Type string `json:"z_st"` } +// ApiAccessClaims represents the JWT claims for API session access tokens, including +// identity attributes, administrative status, and configuration bindings. type ApiAccessClaims struct { jwt.RegisteredClaims ApiSessionId string `json:"z_asid,omitempty"` @@ -71,6 +77,8 @@ func (r *IdClaims) GetAudience() (jwt.ClaimStrings, error) { return jwt.ClaimStrings(r.Audience), nil } +// localRpServer manages a local HTTP server for OpenID Connect relying party operations, +// handling OAuth callbacks and token exchanges during authentication flows. type localRpServer struct { Server *http.Server Port string @@ -81,11 +89,13 @@ type localRpServer struct { LoginUri string } +// Stop shuts down the local server and closes the token channel. func (t *localRpServer) Stop() { _ = t.Server.Shutdown(context.Background()) close(t.TokenChan) } +// Start launches the local server and waits for it to become available. func (t *localRpServer) Start() { go func() { _ = t.Server.Serve(t.Listener) @@ -118,6 +128,8 @@ func (t *localRpServer) Start() { } } +// newLocalRpServer creates and configures a local HTTP server for handling OpenID Connect +// authentication flows, including callback processing and token exchange. func newLocalRpServer(apiHost string, authMethod string) (*localRpServer, error) { tokenOutChan := make(chan *oidc.Tokens[*oidc.IDTokenClaims], 1) result := &localRpServer{ diff --git a/edge-apis/pool.go b/edge-apis/pool.go index d372cfcb..422de29f 100644 --- a/edge-apis/pool.go +++ b/edge-apis/pool.go @@ -30,35 +30,53 @@ import ( errors "github.com/pkg/errors" ) +// ApiClientTransport wraps a runtime.ClientTransport with its associated API URL, +// enabling tracking of which controller endpoint a transport communicates with. type ApiClientTransport struct { runtime.ClientTransport ApiUrl *url.URL } -// ClientTransportPool abstracts the concept of multiple `runtime.ClientTransport` (openapi interface) representing one -// target OpenZiti network. In situations where controllers are running in HA mode (multiple controllers) this -// interface can attempt to try a different controller during outages or partitioning. +// ClientTransportPool manages multiple runtime.ClientTransport instances representing +// different controller endpoints in a high-availability OpenZiti network. It provides +// automatic failover capabilities when individual controllers become unavailable. type ClientTransportPool interface { runtime.ClientTransport + // Add registers a new transport for the specified API URL. Add(apiUrl *url.URL, transport runtime.ClientTransport) + + // Remove unregisters the transport for the specified API URL. Remove(apiUrl *url.URL) + // GetActiveTransport returns the currently selected transport. GetActiveTransport() *ApiClientTransport + + // SetActiveTransport designates which transport to use for subsequent operations. SetActiveTransport(*ApiClientTransport) + + // GetApiUrls returns all registered API URLs. GetApiUrls() []*url.URL + + // IterateTransportsRandomly provides a channel for iterating through available transports + // in random order. IterateTransportsRandomly() chan<- *ApiClientTransport + // TryTransportsForOp attempts to execute an operation, trying different transports + // on connection failures. TryTransportsForOp(operation *runtime.ClientOperation) (any, error) + + // TryTransportForF executes a callback function, trying different transports + // on connection failures. TryTransportForF(cb func(*ApiClientTransport) (any, error)) (any, error) } var _ runtime.ClientTransport = (ClientTransportPool)(nil) var _ ClientTransportPool = (*ClientTransportPoolRandom)(nil) -// ClientTransportPoolRandom selects a client transport (controller) at random until it is unreachable. Controllers -// are tried at random until a controller is reached. The newly connected controller is set for use on future requests -// until is too becomes unreachable. +// ClientTransportPoolRandom implements a randomized failover strategy for controller selection. +// It maintains an active transport and switches to randomly selected alternatives when the active +// transport becomes unreachable. type ClientTransportPoolRandom struct { pool cmap.ConcurrentMap[string, *ApiClientTransport] current atomic.Pointer[ApiClientTransport] @@ -107,6 +125,7 @@ func (c *ClientTransportPoolRandom) GetActiveTransport() *ApiClientTransport { return active } +// GetApiClientTransports returns a snapshot of all registered transports. func (c *ClientTransportPoolRandom) GetApiClientTransports() []*ApiClientTransport { var result []*ApiClientTransport @@ -117,6 +136,7 @@ func (c *ClientTransportPoolRandom) GetApiClientTransports() []*ApiClientTranspo return result } +// NewClientTransportPoolRandom creates a new transport pool with randomized failover. func NewClientTransportPoolRandom() *ClientTransportPoolRandom { return &ClientTransportPoolRandom{ pool: cmap.New[*ApiClientTransport](), @@ -215,6 +235,7 @@ func (c *ClientTransportPoolRandom) TryTransportForF(cb func(*ApiClientTransport return lastResult, lastErr } +// AnyTransport returns a randomly selected transport from the pool, or nil if empty. func (c *ClientTransportPoolRandom) AnyTransport() *ApiClientTransport { transportBuffer := c.pool.Items() var keys []string @@ -237,6 +258,8 @@ var _ ClientTransportPool = (*ClientTransportPoolRandom)(nil) var opError = &net.OpError{} +// errorIndicatesControllerSwap determines whether an error suggests the need to +// switch to a different controller endpoint. func errorIndicatesControllerSwap(err error) bool { pfxlog.Logger().WithError(err).Debugf("checking for network errror on type (%T) and its wrapped errors", err) diff --git a/example/go.mod b/example/go.mod index f6bdfe7b..c03551a2 100644 --- a/example/go.mod +++ b/example/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/michaelquigley/pfxlog v0.6.10 - github.com/openziti/edge-api v0.26.48 + github.com/openziti/edge-api v0.26.50 github.com/openziti/foundation/v2 v2.0.77 github.com/openziti/runzmd v1.0.83 github.com/openziti/sdk-golang v1.2.6 diff --git a/example/go.sum b/example/go.sum index 17ed7449..867d5736 100644 --- a/example/go.sum +++ b/example/go.sum @@ -368,8 +368,8 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/openziti/channel/v4 v4.2.37 h1:oFlYB7PPRzNS/CcwkM80/l2Rkw7z3FDaNbCjiDhdWeg= github.com/openziti/channel/v4 v4.2.37/go.mod h1:G6UDW+FsTj1NR1vzrOIQEfuShitU9ElHTNlNzkd2dMg= -github.com/openziti/edge-api v0.26.48 h1:u31EKgNOxnepHjcLDqjeNJvLYXYQVvARQPacSlJ1nOE= -github.com/openziti/edge-api v0.26.48/go.mod h1:Sj8HEql6ol2Oqp0yd3ZbGayCg8t/XTlH7q608UDHrwE= +github.com/openziti/edge-api v0.26.50 h1:GNqVfAK4yhIInDl+B58lv1mEFslU0x3yjkDrwePQFys= +github.com/openziti/edge-api v0.26.50/go.mod h1:Sj8HEql6ol2Oqp0yd3ZbGayCg8t/XTlH7q608UDHrwE= github.com/openziti/foundation/v2 v2.0.77 h1:aHB+qJuXFE9FZ+9GOF53laemoBxXmUZ2XnBbDy3fxmE= github.com/openziti/foundation/v2 v2.0.77/go.mod h1:rwLV3heBM+S7CtCKCauiozLWGPPejy2p80M1R65d6Lk= github.com/openziti/go-term-markdown v1.0.1 h1:9uzMpK4tav6OtvRxRt99WwPTzAzCh+Pj9zWU2FBp3Qg= diff --git a/example/influxdb-client-go/go.mod b/example/influxdb-client-go/go.mod index 964937e0..a0b15905 100644 --- a/example/influxdb-client-go/go.mod +++ b/example/influxdb-client-go/go.mod @@ -104,7 +104,7 @@ require ( github.com/muhlemmer/gu v0.3.1 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/openziti/channel/v4 v4.2.37 // indirect - github.com/openziti/edge-api v0.26.48 // indirect + github.com/openziti/edge-api v0.26.50 // indirect github.com/openziti/foundation/v2 v2.0.77 // indirect github.com/openziti/identity v1.0.116 // indirect github.com/openziti/metrics v1.4.2 // indirect diff --git a/example/influxdb-client-go/go.sum b/example/influxdb-client-go/go.sum index 0b5f2987..7b57bd3c 100644 --- a/example/influxdb-client-go/go.sum +++ b/example/influxdb-client-go/go.sum @@ -444,8 +444,8 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/openziti/channel/v4 v4.2.37 h1:oFlYB7PPRzNS/CcwkM80/l2Rkw7z3FDaNbCjiDhdWeg= github.com/openziti/channel/v4 v4.2.37/go.mod h1:G6UDW+FsTj1NR1vzrOIQEfuShitU9ElHTNlNzkd2dMg= -github.com/openziti/edge-api v0.26.48 h1:u31EKgNOxnepHjcLDqjeNJvLYXYQVvARQPacSlJ1nOE= -github.com/openziti/edge-api v0.26.48/go.mod h1:Sj8HEql6ol2Oqp0yd3ZbGayCg8t/XTlH7q608UDHrwE= +github.com/openziti/edge-api v0.26.50 h1:GNqVfAK4yhIInDl+B58lv1mEFslU0x3yjkDrwePQFys= +github.com/openziti/edge-api v0.26.50/go.mod h1:Sj8HEql6ol2Oqp0yd3ZbGayCg8t/XTlH7q608UDHrwE= github.com/openziti/foundation/v2 v2.0.77 h1:aHB+qJuXFE9FZ+9GOF53laemoBxXmUZ2XnBbDy3fxmE= github.com/openziti/foundation/v2 v2.0.77/go.mod h1:rwLV3heBM+S7CtCKCauiozLWGPPejy2p80M1R65d6Lk= github.com/openziti/identity v1.0.116 h1:o+vvH1zw0vaG+sn5sVHPWWnxTelZR59QFr9D+4os19g= diff --git a/go.mod b/go.mod index e4694619..415e8a4e 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/mitchellh/go-ps v1.0.0 github.com/mitchellh/mapstructure v1.5.0 github.com/openziti/channel/v4 v4.2.37 - github.com/openziti/edge-api v0.26.48 + github.com/openziti/edge-api v0.26.50 github.com/openziti/foundation/v2 v2.0.77 github.com/openziti/identity v1.0.116 github.com/openziti/metrics v1.4.2 diff --git a/go.sum b/go.sum index f4f42022..b0c17178 100644 --- a/go.sum +++ b/go.sum @@ -325,8 +325,8 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/openziti/channel/v4 v4.2.37 h1:oFlYB7PPRzNS/CcwkM80/l2Rkw7z3FDaNbCjiDhdWeg= github.com/openziti/channel/v4 v4.2.37/go.mod h1:G6UDW+FsTj1NR1vzrOIQEfuShitU9ElHTNlNzkd2dMg= -github.com/openziti/edge-api v0.26.48 h1:u31EKgNOxnepHjcLDqjeNJvLYXYQVvARQPacSlJ1nOE= -github.com/openziti/edge-api v0.26.48/go.mod h1:Sj8HEql6ol2Oqp0yd3ZbGayCg8t/XTlH7q608UDHrwE= +github.com/openziti/edge-api v0.26.50 h1:GNqVfAK4yhIInDl+B58lv1mEFslU0x3yjkDrwePQFys= +github.com/openziti/edge-api v0.26.50/go.mod h1:Sj8HEql6ol2Oqp0yd3ZbGayCg8t/XTlH7q608UDHrwE= github.com/openziti/foundation/v2 v2.0.77 h1:aHB+qJuXFE9FZ+9GOF53laemoBxXmUZ2XnBbDy3fxmE= github.com/openziti/foundation/v2 v2.0.77/go.mod h1:rwLV3heBM+S7CtCKCauiozLWGPPejy2p80M1R65d6Lk= github.com/openziti/identity v1.0.116 h1:o+vvH1zw0vaG+sn5sVHPWWnxTelZR59QFr9D+4os19g= diff --git a/pb/edge_client_pb/edge_client.pb.go b/pb/edge_client_pb/edge_client.pb.go index 3d37c1a3..8b76b5d8 100644 --- a/pb/edge_client_pb/edge_client.pb.go +++ b/pb/edge_client_pb/edge_client.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v3.21.12 +// protoc v4.23.4 // source: edge_client.proto package edge_client_pb @@ -29,108 +29,111 @@ const ( ContentType_Result ContentType = 2 ContentType_Latency ContentType = 3 // use the same types as xgress uses on links - ContentType_XgPayloadType ContentType = 1100 - ContentType_XgAcknowledgementType ContentType = 1101 - ContentType_XgControlType ContentType = 1102 - ContentType_XgCloseType ContentType = 1103 - ContentType_ConnectType ContentType = 60783 - ContentType_StateConnectedType ContentType = 60784 - ContentType_StateClosedType ContentType = 60785 - ContentType_DataType ContentType = 60786 - ContentType_DialType ContentType = 60787 - ContentType_DialSuccessType ContentType = 60788 - ContentType_DialFailedType ContentType = 60789 - ContentType_BindType ContentType = 60790 - ContentType_UnbindType ContentType = 60791 - ContentType_StateSessionEndedType ContentType = 60792 - ContentType_ProbeType ContentType = 60793 - ContentType_UpdateBindType ContentType = 60794 - ContentType_HealthEventType ContentType = 60795 - ContentType_TraceRouteType ContentType = 60796 - ContentType_TraceRouteResponseType ContentType = 60797 - ContentType_ConnInspectRequest ContentType = 60798 - ContentType_ConnInspectResponse ContentType = 60799 - ContentType_BindSuccess ContentType = 60800 - ContentType_UpdateTokenSuccessType ContentType = 60801 - ContentType_UpdateTokenFailureType ContentType = 60802 - ContentType_UpdateTokenType ContentType = 60803 - ContentType_InspectRequest ContentType = 60804 - ContentType_InspectResponse ContentType = 60805 - ContentType_PostureResponseType ContentType = 10800 - ContentType_PostureResponseSuccessType ContentType = 10801 + ContentType_XgPayloadType ContentType = 1100 + ContentType_XgAcknowledgementType ContentType = 1101 + ContentType_XgControlType ContentType = 1102 + ContentType_XgCloseType ContentType = 1103 + ContentType_ConnectType ContentType = 60783 + ContentType_StateConnectedType ContentType = 60784 + ContentType_StateClosedType ContentType = 60785 + ContentType_DataType ContentType = 60786 + ContentType_DialType ContentType = 60787 + ContentType_DialSuccessType ContentType = 60788 + ContentType_DialFailedType ContentType = 60789 + ContentType_BindType ContentType = 60790 + ContentType_UnbindType ContentType = 60791 + ContentType_StateSessionEndedType ContentType = 60792 + ContentType_ProbeType ContentType = 60793 + ContentType_UpdateBindType ContentType = 60794 + ContentType_HealthEventType ContentType = 60795 + ContentType_TraceRouteType ContentType = 60796 + ContentType_TraceRouteResponseType ContentType = 60797 + ContentType_ConnInspectRequest ContentType = 60798 + ContentType_ConnInspectResponse ContentType = 60799 + ContentType_BindSuccess ContentType = 60800 + ContentType_UpdateTokenSuccessType ContentType = 60801 + ContentType_UpdateTokenFailureType ContentType = 60802 + ContentType_UpdateTokenType ContentType = 60803 + ContentType_InspectRequest ContentType = 60804 + ContentType_InspectResponse ContentType = 60805 + ContentType_PostureResponseType ContentType = 10800 + ContentType_ServicePostureStateRequestType ContentType = 108001 + ContentType_ServicePostureStateResponseType ContentType = 108002 ) // Enum value maps for ContentType. var ( ContentType_name = map[int32]string{ - 0: "Hello", - 1: "Ping", - 2: "Result", - 3: "Latency", - 1100: "XgPayloadType", - 1101: "XgAcknowledgementType", - 1102: "XgControlType", - 1103: "XgCloseType", - 60783: "ConnectType", - 60784: "StateConnectedType", - 60785: "StateClosedType", - 60786: "DataType", - 60787: "DialType", - 60788: "DialSuccessType", - 60789: "DialFailedType", - 60790: "BindType", - 60791: "UnbindType", - 60792: "StateSessionEndedType", - 60793: "ProbeType", - 60794: "UpdateBindType", - 60795: "HealthEventType", - 60796: "TraceRouteType", - 60797: "TraceRouteResponseType", - 60798: "ConnInspectRequest", - 60799: "ConnInspectResponse", - 60800: "BindSuccess", - 60801: "UpdateTokenSuccessType", - 60802: "UpdateTokenFailureType", - 60803: "UpdateTokenType", - 60804: "InspectRequest", - 60805: "InspectResponse", - 10800: "PostureResponseType", - 10801: "PostureResponseSuccessType", + 0: "Hello", + 1: "Ping", + 2: "Result", + 3: "Latency", + 1100: "XgPayloadType", + 1101: "XgAcknowledgementType", + 1102: "XgControlType", + 1103: "XgCloseType", + 60783: "ConnectType", + 60784: "StateConnectedType", + 60785: "StateClosedType", + 60786: "DataType", + 60787: "DialType", + 60788: "DialSuccessType", + 60789: "DialFailedType", + 60790: "BindType", + 60791: "UnbindType", + 60792: "StateSessionEndedType", + 60793: "ProbeType", + 60794: "UpdateBindType", + 60795: "HealthEventType", + 60796: "TraceRouteType", + 60797: "TraceRouteResponseType", + 60798: "ConnInspectRequest", + 60799: "ConnInspectResponse", + 60800: "BindSuccess", + 60801: "UpdateTokenSuccessType", + 60802: "UpdateTokenFailureType", + 60803: "UpdateTokenType", + 60804: "InspectRequest", + 60805: "InspectResponse", + 10800: "PostureResponseType", + 108001: "ServicePostureStateRequestType", + 108002: "ServicePostureStateResponseType", } ContentType_value = map[string]int32{ - "Hello": 0, - "Ping": 1, - "Result": 2, - "Latency": 3, - "XgPayloadType": 1100, - "XgAcknowledgementType": 1101, - "XgControlType": 1102, - "XgCloseType": 1103, - "ConnectType": 60783, - "StateConnectedType": 60784, - "StateClosedType": 60785, - "DataType": 60786, - "DialType": 60787, - "DialSuccessType": 60788, - "DialFailedType": 60789, - "BindType": 60790, - "UnbindType": 60791, - "StateSessionEndedType": 60792, - "ProbeType": 60793, - "UpdateBindType": 60794, - "HealthEventType": 60795, - "TraceRouteType": 60796, - "TraceRouteResponseType": 60797, - "ConnInspectRequest": 60798, - "ConnInspectResponse": 60799, - "BindSuccess": 60800, - "UpdateTokenSuccessType": 60801, - "UpdateTokenFailureType": 60802, - "UpdateTokenType": 60803, - "InspectRequest": 60804, - "InspectResponse": 60805, - "PostureResponseType": 10800, - "PostureResponseSuccessType": 10801, + "Hello": 0, + "Ping": 1, + "Result": 2, + "Latency": 3, + "XgPayloadType": 1100, + "XgAcknowledgementType": 1101, + "XgControlType": 1102, + "XgCloseType": 1103, + "ConnectType": 60783, + "StateConnectedType": 60784, + "StateClosedType": 60785, + "DataType": 60786, + "DialType": 60787, + "DialSuccessType": 60788, + "DialFailedType": 60789, + "BindType": 60790, + "UnbindType": 60791, + "StateSessionEndedType": 60792, + "ProbeType": 60793, + "UpdateBindType": 60794, + "HealthEventType": 60795, + "TraceRouteType": 60796, + "TraceRouteResponseType": 60797, + "ConnInspectRequest": 60798, + "ConnInspectResponse": 60799, + "BindSuccess": 60800, + "UpdateTokenSuccessType": 60801, + "UpdateTokenFailureType": 60802, + "UpdateTokenType": 60803, + "InspectRequest": 60804, + "InspectResponse": 60805, + "PostureResponseType": 10800, + "ServicePostureStateRequestType": 108001, + "ServicePostureStateResponseType": 108002, } ) @@ -198,6 +201,7 @@ const ( HeaderId_XgressCtrlId HeaderId = 1029 HeaderId_XgressAddress HeaderId = 1030 HeaderId_InspectRequestedValues HeaderId = 1031 + HeaderId_SupportsPostureChecks HeaderId = 1032 ) // Enum value maps for HeaderId. @@ -237,6 +241,7 @@ var ( 1029: "XgressCtrlId", 1030: "XgressAddress", 1031: "InspectRequestedValues", + 1032: "SupportsPostureChecks", } HeaderId_value = map[string]int32{ "ZER0": 0, @@ -273,6 +278,7 @@ var ( "XgressCtrlId": 1029, "XgressAddress": 1030, "InspectRequestedValues": 1031, + "SupportsPostureChecks": 1032, } ) @@ -492,6 +498,369 @@ func (Flag) EnumDescriptor() ([]byte, []int) { return file_edge_client_proto_rawDescGZIP(), []int{4} } +type ServicePostureStateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServiceIds []string `protobuf:"bytes,1,rep,name=serviceIds,proto3" json:"serviceIds,omitempty"` +} + +func (x *ServicePostureStateRequest) Reset() { + *x = ServicePostureStateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServicePostureStateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServicePostureStateRequest) ProtoMessage() {} + +func (x *ServicePostureStateRequest) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServicePostureStateRequest.ProtoReflect.Descriptor instead. +func (*ServicePostureStateRequest) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{0} +} + +func (x *ServicePostureStateRequest) GetServiceIds() []string { + if x != nil { + return x.ServiceIds + } + return nil +} + +type ServicePostureStateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + States map[string]*ServicePostureState `protobuf:"bytes,1,rep,name=states,proto3" json:"states,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ServicePostureStateResponse) Reset() { + *x = ServicePostureStateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServicePostureStateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServicePostureStateResponse) ProtoMessage() {} + +func (x *ServicePostureStateResponse) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServicePostureStateResponse.ProtoReflect.Descriptor instead. +func (*ServicePostureStateResponse) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{1} +} + +func (x *ServicePostureStateResponse) GetStates() map[string]*ServicePostureState { + if x != nil { + return x.States + } + return nil +} + +type ServicePostureState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsPassing bool `protobuf:"varint,1,opt,name=isPassing,proto3" json:"isPassing,omitempty"` + PassingPolicyIds []string `protobuf:"bytes,2,rep,name=passingPolicyIds,proto3" json:"passingPolicyIds,omitempty"` + FailingPolicyIds []string `protobuf:"bytes,3,rep,name=failingPolicyIds,proto3" json:"failingPolicyIds,omitempty"` + Policies map[string]*Policy `protobuf:"bytes,4,rep,name=policies,proto3" json:"policies,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ServicePostureState) Reset() { + *x = ServicePostureState{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServicePostureState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServicePostureState) ProtoMessage() {} + +func (x *ServicePostureState) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServicePostureState.ProtoReflect.Descriptor instead. +func (*ServicePostureState) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{2} +} + +func (x *ServicePostureState) GetIsPassing() bool { + if x != nil { + return x.IsPassing + } + return false +} + +func (x *ServicePostureState) GetPassingPolicyIds() []string { + if x != nil { + return x.PassingPolicyIds + } + return nil +} + +func (x *ServicePostureState) GetFailingPolicyIds() []string { + if x != nil { + return x.FailingPolicyIds + } + return nil +} + +func (x *ServicePostureState) GetPolicies() map[string]*Policy { + if x != nil { + return x.Policies + } + return nil +} + +type Policy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + IsPassing bool `protobuf:"varint,2,opt,name=isPassing,proto3" json:"isPassing,omitempty"` + PassingPostureQueryIds []string `protobuf:"bytes,3,rep,name=passingPostureQueryIds,proto3" json:"passingPostureQueryIds,omitempty"` + FailingPostureQueryIds []string `protobuf:"bytes,4,rep,name=failingPostureQueryIds,proto3" json:"failingPostureQueryIds,omitempty"` + PostureQueries map[string]*PostureQuery `protobuf:"bytes,5,rep,name=postureQueries,proto3" json:"postureQueries,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *Policy) Reset() { + *x = Policy{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy) ProtoMessage() {} + +func (x *Policy) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Policy.ProtoReflect.Descriptor instead. +func (*Policy) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{3} +} + +func (x *Policy) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Policy) GetIsPassing() bool { + if x != nil { + return x.IsPassing + } + return false +} + +func (x *Policy) GetPassingPostureQueryIds() []string { + if x != nil { + return x.PassingPostureQueryIds + } + return nil +} + +func (x *Policy) GetFailingPostureQueryIds() []string { + if x != nil { + return x.FailingPostureQueryIds + } + return nil +} + +func (x *Policy) GetPostureQueries() map[string]*PostureQuery { + if x != nil { + return x.PostureQueries + } + return nil +} + +type PostureQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + IsPassing bool `protobuf:"varint,3,opt,name=isPassing,proto3" json:"isPassing,omitempty"` + TimeoutAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=timeoutAt,proto3" json:"timeoutAt,omitempty"` + TimeoutSeconds int32 `protobuf:"varint,5,opt,name=timeoutSeconds,proto3" json:"timeoutSeconds,omitempty"` + TimeoutRemainingSeconds int32 `protobuf:"varint,6,opt,name=timeoutRemainingSeconds,proto3" json:"timeoutRemainingSeconds,omitempty"` + PromptGracePeriodSeconds int32 `protobuf:"varint,7,opt,name=promptGracePeriodSeconds,proto3" json:"promptGracePeriodSeconds,omitempty"` + PromptOnUnlock bool `protobuf:"varint,8,opt,name=promptOnUnlock,proto3" json:"promptOnUnlock,omitempty"` + PromptOnWake bool `protobuf:"varint,9,opt,name=promptOnWake,proto3" json:"promptOnWake,omitempty"` + Processes *PostureQuery_Processes `protobuf:"bytes,10,opt,name=processes,proto3" json:"processes,omitempty"` +} + +func (x *PostureQuery) Reset() { + *x = PostureQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PostureQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PostureQuery) ProtoMessage() {} + +func (x *PostureQuery) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PostureQuery.ProtoReflect.Descriptor instead. +func (*PostureQuery) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{4} +} + +func (x *PostureQuery) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *PostureQuery) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *PostureQuery) GetIsPassing() bool { + if x != nil { + return x.IsPassing + } + return false +} + +func (x *PostureQuery) GetTimeoutAt() *timestamppb.Timestamp { + if x != nil { + return x.TimeoutAt + } + return nil +} + +func (x *PostureQuery) GetTimeoutSeconds() int32 { + if x != nil { + return x.TimeoutSeconds + } + return 0 +} + +func (x *PostureQuery) GetTimeoutRemainingSeconds() int32 { + if x != nil { + return x.TimeoutRemainingSeconds + } + return 0 +} + +func (x *PostureQuery) GetPromptGracePeriodSeconds() int32 { + if x != nil { + return x.PromptGracePeriodSeconds + } + return 0 +} + +func (x *PostureQuery) GetPromptOnUnlock() bool { + if x != nil { + return x.PromptOnUnlock + } + return false +} + +func (x *PostureQuery) GetPromptOnWake() bool { + if x != nil { + return x.PromptOnWake + } + return false +} + +func (x *PostureQuery) GetProcesses() *PostureQuery_Processes { + if x != nil { + return x.Processes + } + return nil +} + type PostureResponses struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -503,7 +872,7 @@ type PostureResponses struct { func (x *PostureResponses) Reset() { *x = PostureResponses{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[0] + mi := &file_edge_client_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -516,7 +885,7 @@ func (x *PostureResponses) String() string { func (*PostureResponses) ProtoMessage() {} func (x *PostureResponses) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[0] + mi := &file_edge_client_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -529,7 +898,7 @@ func (x *PostureResponses) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponses.ProtoReflect.Descriptor instead. func (*PostureResponses) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{0} + return file_edge_client_proto_rawDescGZIP(), []int{5} } func (x *PostureResponses) GetResponses() []*PostureResponse { @@ -553,13 +922,14 @@ type PostureResponse struct { // *PostureResponse_Woken_ // *PostureResponse_Unlocked_ // *PostureResponse_SdkInfo_ + // *PostureResponse_TotpToken_ Type isPostureResponse_Type `protobuf_oneof:"Type"` } func (x *PostureResponse) Reset() { *x = PostureResponse{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[1] + mi := &file_edge_client_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -572,7 +942,7 @@ func (x *PostureResponse) String() string { func (*PostureResponse) ProtoMessage() {} func (x *PostureResponse) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[1] + mi := &file_edge_client_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -585,7 +955,7 @@ func (x *PostureResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse.ProtoReflect.Descriptor instead. func (*PostureResponse) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1} + return file_edge_client_proto_rawDescGZIP(), []int{6} } func (m *PostureResponse) GetType() isPostureResponse_Type { @@ -644,6 +1014,13 @@ func (x *PostureResponse) GetSdkInfo() *PostureResponse_SdkInfo { return nil } +func (x *PostureResponse) GetTotpToken() *PostureResponse_TotpToken { + if x, ok := x.GetType().(*PostureResponse_TotpToken_); ok { + return x.TotpToken + } + return nil +} + type isPostureResponse_Type interface { isPostureResponse_Type() } @@ -676,6 +1053,10 @@ type PostureResponse_SdkInfo_ struct { SdkInfo *PostureResponse_SdkInfo `protobuf:"bytes,7,opt,name=sdkInfo,proto3,oneof"` } +type PostureResponse_TotpToken_ struct { + TotpToken *PostureResponse_TotpToken `protobuf:"bytes,8,opt,name=totpToken,proto3,oneof"` +} + func (*PostureResponse_Macs_) isPostureResponse_Type() {} func (*PostureResponse_Os) isPostureResponse_Type() {} @@ -690,6 +1071,173 @@ func (*PostureResponse_Unlocked_) isPostureResponse_Type() {} func (*PostureResponse_SdkInfo_) isPostureResponse_Type() {} +func (*PostureResponse_TotpToken_) isPostureResponse_Type() {} + +type PostureQuery_Processes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Semantic string `protobuf:"bytes,1,opt,name=semantic,proto3" json:"semantic,omitempty"` + Processes []*PostureQuery_Process `protobuf:"bytes,2,rep,name=processes,proto3" json:"processes,omitempty"` +} + +func (x *PostureQuery_Processes) Reset() { + *x = PostureQuery_Processes{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PostureQuery_Processes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PostureQuery_Processes) ProtoMessage() {} + +func (x *PostureQuery_Processes) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PostureQuery_Processes.ProtoReflect.Descriptor instead. +func (*PostureQuery_Processes) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *PostureQuery_Processes) GetSemantic() string { + if x != nil { + return x.Semantic + } + return "" +} + +func (x *PostureQuery_Processes) GetProcesses() []*PostureQuery_Process { + if x != nil { + return x.Processes + } + return nil +} + +type PostureQuery_Process struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OsType string `protobuf:"bytes,1,opt,name=osType,proto3" json:"osType,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` +} + +func (x *PostureQuery_Process) Reset() { + *x = PostureQuery_Process{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PostureQuery_Process) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PostureQuery_Process) ProtoMessage() {} + +func (x *PostureQuery_Process) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PostureQuery_Process.ProtoReflect.Descriptor instead. +func (*PostureQuery_Process) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *PostureQuery_Process) GetOsType() string { + if x != nil { + return x.OsType + } + return "" +} + +func (x *PostureQuery_Process) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +type PostureResponse_TotpToken struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` +} + +func (x *PostureResponse_TotpToken) Reset() { + *x = PostureResponse_TotpToken{} + if protoimpl.UnsafeEnabled { + mi := &file_edge_client_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PostureResponse_TotpToken) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PostureResponse_TotpToken) ProtoMessage() {} + +func (x *PostureResponse_TotpToken) ProtoReflect() protoreflect.Message { + mi := &file_edge_client_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PostureResponse_TotpToken.ProtoReflect.Descriptor instead. +func (*PostureResponse_TotpToken) Descriptor() ([]byte, []int) { + return file_edge_client_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *PostureResponse_TotpToken) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +func (x *PostureResponse_TotpToken) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + type PostureResponse_Macs struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -701,7 +1249,7 @@ type PostureResponse_Macs struct { func (x *PostureResponse_Macs) Reset() { *x = PostureResponse_Macs{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[2] + mi := &file_edge_client_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -714,7 +1262,7 @@ func (x *PostureResponse_Macs) String() string { func (*PostureResponse_Macs) ProtoMessage() {} func (x *PostureResponse_Macs) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[2] + mi := &file_edge_client_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -727,7 +1275,7 @@ func (x *PostureResponse_Macs) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_Macs.ProtoReflect.Descriptor instead. func (*PostureResponse_Macs) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 0} + return file_edge_client_proto_rawDescGZIP(), []int{6, 1} } func (x *PostureResponse_Macs) GetAddresses() []string { @@ -750,7 +1298,7 @@ type PostureResponse_OperatingSystem struct { func (x *PostureResponse_OperatingSystem) Reset() { *x = PostureResponse_OperatingSystem{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[3] + mi := &file_edge_client_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -763,7 +1311,7 @@ func (x *PostureResponse_OperatingSystem) String() string { func (*PostureResponse_OperatingSystem) ProtoMessage() {} func (x *PostureResponse_OperatingSystem) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[3] + mi := &file_edge_client_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -776,7 +1324,7 @@ func (x *PostureResponse_OperatingSystem) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_OperatingSystem.ProtoReflect.Descriptor instead. func (*PostureResponse_OperatingSystem) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 1} + return file_edge_client_proto_rawDescGZIP(), []int{6, 2} } func (x *PostureResponse_OperatingSystem) GetType() string { @@ -811,7 +1359,7 @@ type PostureResponse_Domain struct { func (x *PostureResponse_Domain) Reset() { *x = PostureResponse_Domain{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[4] + mi := &file_edge_client_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -824,7 +1372,7 @@ func (x *PostureResponse_Domain) String() string { func (*PostureResponse_Domain) ProtoMessage() {} func (x *PostureResponse_Domain) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[4] + mi := &file_edge_client_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -837,7 +1385,7 @@ func (x *PostureResponse_Domain) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_Domain.ProtoReflect.Descriptor instead. func (*PostureResponse_Domain) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 2} + return file_edge_client_proto_rawDescGZIP(), []int{6, 3} } func (x *PostureResponse_Domain) GetName() string { @@ -861,7 +1409,7 @@ type PostureResponse_Process struct { func (x *PostureResponse_Process) Reset() { *x = PostureResponse_Process{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[5] + mi := &file_edge_client_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -874,7 +1422,7 @@ func (x *PostureResponse_Process) String() string { func (*PostureResponse_Process) ProtoMessage() {} func (x *PostureResponse_Process) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[5] + mi := &file_edge_client_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -887,7 +1435,7 @@ func (x *PostureResponse_Process) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_Process.ProtoReflect.Descriptor instead. func (*PostureResponse_Process) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 3} + return file_edge_client_proto_rawDescGZIP(), []int{6, 4} } func (x *PostureResponse_Process) GetPath() string { @@ -929,7 +1477,7 @@ type PostureResponse_ProcessList struct { func (x *PostureResponse_ProcessList) Reset() { *x = PostureResponse_ProcessList{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[6] + mi := &file_edge_client_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -942,7 +1490,7 @@ func (x *PostureResponse_ProcessList) String() string { func (*PostureResponse_ProcessList) ProtoMessage() {} func (x *PostureResponse_ProcessList) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[6] + mi := &file_edge_client_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -955,7 +1503,7 @@ func (x *PostureResponse_ProcessList) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_ProcessList.ProtoReflect.Descriptor instead. func (*PostureResponse_ProcessList) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 4} + return file_edge_client_proto_rawDescGZIP(), []int{6, 5} } func (x *PostureResponse_ProcessList) GetProcesses() []*PostureResponse_Process { @@ -976,7 +1524,7 @@ type PostureResponse_Woken struct { func (x *PostureResponse_Woken) Reset() { *x = PostureResponse_Woken{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[7] + mi := &file_edge_client_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -989,7 +1537,7 @@ func (x *PostureResponse_Woken) String() string { func (*PostureResponse_Woken) ProtoMessage() {} func (x *PostureResponse_Woken) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[7] + mi := &file_edge_client_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1002,7 +1550,7 @@ func (x *PostureResponse_Woken) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_Woken.ProtoReflect.Descriptor instead. func (*PostureResponse_Woken) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 5} + return file_edge_client_proto_rawDescGZIP(), []int{6, 6} } func (x *PostureResponse_Woken) GetTime() *timestamppb.Timestamp { @@ -1023,7 +1571,7 @@ type PostureResponse_Unlocked struct { func (x *PostureResponse_Unlocked) Reset() { *x = PostureResponse_Unlocked{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[8] + mi := &file_edge_client_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1036,7 +1584,7 @@ func (x *PostureResponse_Unlocked) String() string { func (*PostureResponse_Unlocked) ProtoMessage() {} func (x *PostureResponse_Unlocked) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[8] + mi := &file_edge_client_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1049,7 +1597,7 @@ func (x *PostureResponse_Unlocked) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_Unlocked.ProtoReflect.Descriptor instead. func (*PostureResponse_Unlocked) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 6} + return file_edge_client_proto_rawDescGZIP(), []int{6, 7} } func (x *PostureResponse_Unlocked) GetTime() *timestamppb.Timestamp { @@ -1075,7 +1623,7 @@ type PostureResponse_SdkInfo struct { func (x *PostureResponse_SdkInfo) Reset() { *x = PostureResponse_SdkInfo{} if protoimpl.UnsafeEnabled { - mi := &file_edge_client_proto_msgTypes[9] + mi := &file_edge_client_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1088,7 +1636,7 @@ func (x *PostureResponse_SdkInfo) String() string { func (*PostureResponse_SdkInfo) ProtoMessage() {} func (x *PostureResponse_SdkInfo) ProtoReflect() protoreflect.Message { - mi := &file_edge_client_proto_msgTypes[9] + mi := &file_edge_client_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1101,7 +1649,7 @@ func (x *PostureResponse_SdkInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use PostureResponse_SdkInfo.ProtoReflect.Descriptor instead. func (*PostureResponse_SdkInfo) Descriptor() ([]byte, []int) { - return file_edge_client_proto_rawDescGZIP(), []int{1, 7} + return file_edge_client_proto_rawDescGZIP(), []int{6, 8} } func (x *PostureResponse_SdkInfo) GetAppId() string { @@ -1153,204 +1701,316 @@ var file_edge_client_proto_rawDesc = []byte{ 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x10, 0x50, 0x6f, 0x73, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x42, 0x0a, - 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x73, 0x22, 0xaa, 0x09, 0x0a, 0x0f, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x6d, 0x61, 0x63, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x61, 0x63, 0x73, 0x48, 0x00, - 0x52, 0x04, 0x6d, 0x61, 0x63, 0x73, 0x12, 0x46, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x54, - 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, + 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3c, 0x0a, 0x1a, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x49, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x22, 0xd8, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x63, 0x0a, + 0x0b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0xb9, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, + 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, + 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, + 0x73, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x61, 0x73, 0x73, + 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x10, 0x70, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x49, 0x64, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x66, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, + 0x66, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x73, + 0x12, 0x52, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x1a, 0x58, 0x0a, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, + 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, + 0x02, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x50, + 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, + 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x16, 0x70, 0x61, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x64, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x70, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, + 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x64, 0x73, 0x12, + 0x36, 0x0a, 0x16, 0x66, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, + 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x16, 0x66, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x49, 0x64, 0x73, 0x12, 0x57, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x74, 0x75, + 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2f, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x73, + 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0e, 0x70, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, + 0x1a, 0x64, 0x0a, 0x13, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, + 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe8, 0x04, 0x0a, 0x0c, 0x50, 0x6f, 0x73, 0x74, 0x75, + 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, + 0x73, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x69, 0x73, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x41, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x41, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x17, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x47, + 0x72, 0x61, 0x63, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x18, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x47, + 0x72, 0x61, 0x63, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, 0x55, 0x6e, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x6d, 0x70, + 0x74, 0x4f, 0x6e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x72, 0x6f, + 0x6d, 0x70, 0x74, 0x4f, 0x6e, 0x57, 0x61, 0x6b, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4f, 0x6e, 0x57, 0x61, 0x6b, 0x65, 0x12, 0x49, 0x0a, + 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x09, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x70, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, + 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, + 0x63, 0x12, 0x47, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x48, 0x00, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x05, 0x77, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x7a, 0x69, 0x74, + 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x35, 0x0a, 0x07, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x22, 0x56, 0x0a, 0x10, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, + 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, + 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0xb1, 0x0a, 0x0a, 0x0f, 0x50, 0x6f, + 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, + 0x04, 0x6d, 0x61, 0x63, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, + 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x4d, 0x61, 0x63, 0x73, 0x48, 0x00, 0x52, 0x04, 0x6d, 0x61, 0x63, 0x73, 0x12, 0x46, + 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x57, 0x6f, 0x6b, 0x65, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x77, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x4b, 0x0a, 0x08, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, + 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x48, 0x00, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x54, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x7a, 0x69, + 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, + 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, + 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x06, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x7a, + 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, + 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x64, 0x6f, 0x6d, + 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x05, 0x77, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x57, 0x6f, 0x6b, 0x65, 0x6e, 0x48, 0x00, + 0x52, 0x05, 0x77, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x4b, 0x0a, 0x08, 0x75, 0x6e, 0x6c, 0x6f, 0x63, + 0x6b, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x7a, 0x69, 0x74, 0x69, + 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, + 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x48, 0x00, 0x52, 0x08, 0x75, 0x6e, 0x6c, 0x6f, + 0x63, 0x6b, 0x65, 0x64, 0x12, 0x48, 0x0a, 0x07, 0x73, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, + 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x64, 0x6b, 0x49, + 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x07, 0x73, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4e, + 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2e, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, - 0x48, 0x00, 0x52, 0x08, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x48, 0x0a, 0x07, - 0x73, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x07, 0x73, - 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x24, 0x0a, 0x04, 0x4d, 0x61, 0x63, 0x73, 0x12, 0x1c, - 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x55, 0x0a, 0x0f, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, - 0x05, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x1a, 0x1c, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x1a, 0x7f, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x12, - 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, - 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x67, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, - 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x73, 0x1a, 0x59, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x4a, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, - 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x37, 0x0a, - 0x05, 0x57, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x3a, 0x0a, 0x08, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, - 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, - 0x6d, 0x65, 0x1a, 0xa1, 0x01, 0x0a, 0x07, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, - 0x0a, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, - 0x70, 0x70, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x2a, 0xd6, - 0x05, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, - 0x0a, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x69, 0x6e, - 0x67, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x10, 0x02, 0x12, - 0x0b, 0x0a, 0x07, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0d, - 0x58, 0x67, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xcc, 0x08, - 0x12, 0x1a, 0x0a, 0x15, 0x58, 0x67, 0x41, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xcd, 0x08, 0x12, 0x12, 0x0a, 0x0d, - 0x58, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x10, 0xce, 0x08, - 0x12, 0x10, 0x0a, 0x0b, 0x58, 0x67, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, - 0xcf, 0x08, 0x12, 0x11, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xef, 0xda, 0x03, 0x12, 0x18, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf0, 0xda, 0x03, 0x12, - 0x15, 0x0a, 0x0f, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xf1, 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xf2, 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x08, 0x44, 0x69, 0x61, 0x6c, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xf3, 0xda, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x44, 0x69, 0x61, 0x6c, 0x53, 0x75, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf4, 0xda, 0x03, 0x12, 0x14, 0x0a, - 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, - 0xf5, 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x08, 0x42, 0x69, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, - 0xf6, 0xda, 0x03, 0x12, 0x10, 0x0a, 0x0a, 0x55, 0x6e, 0x62, 0x69, 0x6e, 0x64, 0x54, 0x79, 0x70, - 0x65, 0x10, 0xf7, 0xda, 0x03, 0x12, 0x1b, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf8, - 0xda, 0x03, 0x12, 0x0f, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, - 0xf9, 0xda, 0x03, 0x12, 0x14, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x69, 0x6e, - 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xfa, 0xda, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xfb, 0xda, 0x03, - 0x12, 0x14, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xfc, 0xda, 0x03, 0x12, 0x1c, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x10, 0xfd, 0xda, 0x03, 0x12, 0x18, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x73, 0x70, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xfe, 0xda, 0x03, 0x12, 0x19, - 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0xff, 0xda, 0x03, 0x12, 0x11, 0x0a, 0x0b, 0x42, 0x69, 0x6e, - 0x64, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, 0x80, 0xdb, 0x03, 0x12, 0x1c, 0x0a, 0x16, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0x81, 0xdb, 0x03, 0x12, 0x1c, 0x0a, 0x16, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x10, 0x82, 0xdb, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0x83, 0xdb, 0x03, 0x12, - 0x14, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x10, 0x84, 0xdb, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0x85, 0xdb, 0x03, 0x12, 0x18, 0x0a, 0x13, - 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x10, 0xb0, 0x54, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x54, 0x79, 0x70, 0x65, 0x10, 0xb1, 0x54, 0x2a, 0x81, 0x05, 0x0a, 0x08, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x45, 0x52, 0x30, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x04, 0x55, 0x55, 0x49, 0x44, 0x10, 0x80, 0x01, 0x12, 0x0b, 0x0a, 0x06, 0x43, 0x6f, 0x6e, - 0x6e, 0x49, 0x64, 0x10, 0xe8, 0x07, 0x12, 0x08, 0x0a, 0x03, 0x53, 0x65, 0x71, 0x10, 0xe9, 0x07, - 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x10, 0xea, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x10, 0xeb, 0x07, 0x12, 0x09, 0x0a, 0x04, 0x43, 0x6f, 0x73, 0x74, 0x10, 0xec, 0x07, 0x12, 0x0f, - 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x10, 0xed, 0x07, 0x12, - 0x17, 0x0a, 0x12, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x10, 0xee, 0x07, 0x12, 0x1d, 0x0a, 0x18, 0x54, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x10, 0xef, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x65, - 0x72, 0x49, 0x64, 0x10, 0xf0, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x10, 0xf1, 0x07, 0x12, 0x0a, 0x0a, 0x05, 0x46, 0x6c, 0x61, - 0x67, 0x73, 0x10, 0xf2, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, - 0x10, 0xf3, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x64, 0x10, 0xf4, 0x07, 0x12, 0x11, - 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0xf5, - 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x10, 0xf6, - 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x10, 0xf7, - 0x07, 0x12, 0x12, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x48, 0x6f, 0x70, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x10, 0xf8, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x48, 0x6f, - 0x70, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf9, 0x07, 0x12, 0x0f, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, - 0x65, 0x48, 0x6f, 0x70, 0x49, 0x64, 0x10, 0xfa, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, - 0x64, 0x10, 0xfb, 0x07, 0x12, 0x0f, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x10, 0xfc, 0x07, 0x12, 0x0f, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, - 0x72, 0x49, 0x64, 0x10, 0xfd, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x10, 0xfe, 0x07, 0x12, 0x14, 0x0a, 0x0f, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, - 0x73, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x10, 0xff, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x53, - 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x10, 0x80, 0x08, 0x12, 0x15, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x10, 0x81, 0x08, 0x12, 0x0e, 0x0a, 0x09, - 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x49, 0x64, 0x10, 0x82, 0x08, 0x12, 0x14, 0x0a, 0x0f, - 0x53, 0x74, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, - 0x83, 0x08, 0x12, 0x13, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x58, 0x67, 0x72, 0x65, 0x73, 0x73, 0x54, - 0x6f, 0x53, 0x64, 0x6b, 0x10, 0x84, 0x08, 0x12, 0x11, 0x0a, 0x0c, 0x58, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x43, 0x74, 0x72, 0x6c, 0x49, 0x64, 0x10, 0x85, 0x08, 0x12, 0x12, 0x0a, 0x0d, 0x58, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x86, 0x08, 0x12, 0x1b, - 0x0a, 0x16, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x10, 0x87, 0x08, 0x2a, 0x86, 0x02, 0x0a, 0x05, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x0c, 0x0a, - 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x49, - 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x70, 0x69, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, - 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x45, 0x64, 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x46, 0x6f, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x05, 0x12, 0x12, 0x0a, - 0x0e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x10, - 0x06, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x4e, 0x6f, - 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x07, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x10, - 0x08, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x72, 0x65, 0x63, - 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x10, 0x09, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x6e, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x43, 0x6f, 0x73, 0x74, 0x10, 0x0a, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x4d, 0x69, 0x73, 0x73, 0x69, - 0x6e, 0x67, 0x10, 0x0b, 0x2a, 0x38, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, - 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x10, 0x02, 0x2a, 0x57, - 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, - 0x12, 0x07, 0x0a, 0x03, 0x46, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x52, 0x41, - 0x43, 0x45, 0x5f, 0x55, 0x55, 0x49, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x55, 0x4c, - 0x54, 0x49, 0x50, 0x41, 0x52, 0x54, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x45, - 0x41, 0x4d, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x50, 0x41, 0x52, - 0x54, 0x5f, 0x4d, 0x53, 0x47, 0x10, 0x10, 0x42, 0x4b, 0x0a, 0x17, 0x6f, 0x72, 0x67, 0x2e, 0x6f, - 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, - 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x73, 0x64, 0x6b, 0x2d, 0x67, 0x6f, 0x6c, 0x61, - 0x6e, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x6f, 0x74, 0x70, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x48, 0x00, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x35, + 0x0a, 0x09, 0x54, 0x6f, 0x74, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x4d, 0x61, 0x63, 0x73, 0x12, 0x1c, 0x0a, + 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x4f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x1a, 0x1c, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x1a, 0x7f, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, + 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, + 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, + 0x68, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x67, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, + 0x73, 0x1a, 0x59, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x4a, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, 0x64, 0x67, 0x65, 0x5f, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x05, + 0x57, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x04, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x3a, 0x0a, 0x08, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, + 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, 0x6d, + 0x65, 0x1a, 0xa1, 0x01, 0x0a, 0x07, 0x53, 0x64, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, + 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, + 0x70, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x72, + 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x2a, 0x82, 0x06, + 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, + 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, + 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x10, 0x02, 0x12, 0x0b, + 0x0a, 0x07, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0d, 0x58, + 0x67, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xcc, 0x08, 0x12, + 0x1a, 0x0a, 0x15, 0x58, 0x67, 0x41, 0x63, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xcd, 0x08, 0x12, 0x12, 0x0a, 0x0d, 0x58, + 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x10, 0xce, 0x08, 0x12, + 0x10, 0x0a, 0x0b, 0x58, 0x67, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xcf, + 0x08, 0x12, 0x11, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x10, 0xef, 0xda, 0x03, 0x12, 0x18, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf0, 0xda, 0x03, 0x12, 0x15, + 0x0a, 0x0f, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xf1, 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xf2, 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x08, 0x44, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xf3, 0xda, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x44, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf4, 0xda, 0x03, 0x12, 0x14, 0x0a, 0x0e, + 0x44, 0x69, 0x61, 0x6c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf5, + 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x08, 0x42, 0x69, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf6, + 0xda, 0x03, 0x12, 0x10, 0x0a, 0x0a, 0x55, 0x6e, 0x62, 0x69, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, + 0x10, 0xf7, 0xda, 0x03, 0x12, 0x1b, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf8, 0xda, + 0x03, 0x12, 0x0f, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xf9, + 0xda, 0x03, 0x12, 0x14, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x69, 0x6e, 0x64, + 0x54, 0x79, 0x70, 0x65, 0x10, 0xfa, 0xda, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xfb, 0xda, 0x03, 0x12, + 0x14, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x10, 0xfc, 0xda, 0x03, 0x12, 0x1c, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, + 0xfd, 0xda, 0x03, 0x12, 0x18, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x73, 0x70, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xfe, 0xda, 0x03, 0x12, 0x19, 0x0a, + 0x13, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x10, 0xff, 0xda, 0x03, 0x12, 0x11, 0x0a, 0x0b, 0x42, 0x69, 0x6e, 0x64, + 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, 0x80, 0xdb, 0x03, 0x12, 0x1c, 0x0a, 0x16, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x54, 0x79, 0x70, 0x65, 0x10, 0x81, 0xdb, 0x03, 0x12, 0x1c, 0x0a, 0x16, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x10, 0x82, 0xdb, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0x83, 0xdb, 0x03, 0x12, 0x14, + 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x10, 0x84, 0xdb, 0x03, 0x12, 0x15, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0x85, 0xdb, 0x03, 0x12, 0x18, 0x0a, 0x13, 0x50, + 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x10, 0xb0, 0x54, 0x12, 0x24, 0x0a, 0x1e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe1, 0xcb, 0x06, 0x12, 0x25, 0x0a, 0x1f, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0xe2, + 0xcb, 0x06, 0x2a, 0x9d, 0x05, 0x0a, 0x08, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x08, 0x0a, 0x04, 0x5a, 0x45, 0x52, 0x30, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x04, 0x55, 0x55, 0x49, + 0x44, 0x10, 0x80, 0x01, 0x12, 0x0b, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x64, 0x10, 0xe8, + 0x07, 0x12, 0x08, 0x0a, 0x03, 0x53, 0x65, 0x71, 0x10, 0xe9, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xea, 0x07, 0x12, 0x0e, + 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xeb, 0x07, 0x12, 0x09, + 0x0a, 0x04, 0x43, 0x6f, 0x73, 0x74, 0x10, 0xec, 0x07, 0x12, 0x0f, 0x0a, 0x0a, 0x50, 0x72, 0x65, + 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x10, 0xed, 0x07, 0x12, 0x17, 0x0a, 0x12, 0x54, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x10, 0xee, 0x07, 0x12, 0x1d, 0x0a, 0x18, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, + 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x10, + 0xef, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x10, 0xf0, + 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x4d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x10, 0xf1, 0x07, 0x12, 0x0a, 0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0xf2, 0x07, + 0x12, 0x0c, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x10, 0xf3, 0x07, 0x12, 0x19, + 0x0a, 0x14, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, + 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x64, 0x10, 0xf4, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x10, 0xf5, 0x07, 0x12, 0x0e, 0x0a, 0x09, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x10, 0xf6, 0x07, 0x12, 0x0e, 0x0a, 0x09, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x10, 0xf7, 0x07, 0x12, 0x12, 0x0a, 0x0d, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x48, 0x6f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x10, 0xf8, 0x07, + 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x48, 0x6f, 0x70, 0x54, 0x79, 0x70, 0x65, + 0x10, 0xf9, 0x07, 0x12, 0x0f, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x48, 0x6f, 0x70, 0x49, + 0x64, 0x10, 0xfa, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x10, 0xfb, 0x07, 0x12, + 0x0f, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0xfc, 0x07, + 0x12, 0x0f, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x10, 0xfd, + 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x10, 0xfe, 0x07, + 0x12, 0x14, 0x0a, 0x0f, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x49, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x10, 0xff, 0x07, 0x12, 0x18, 0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x73, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10, 0x80, 0x08, + 0x12, 0x15, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, + 0x72, 0x6b, 0x65, 0x72, 0x10, 0x81, 0x08, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x69, 0x72, 0x63, 0x75, + 0x69, 0x74, 0x49, 0x64, 0x10, 0x82, 0x08, 0x12, 0x14, 0x0a, 0x0f, 0x53, 0x74, 0x69, 0x63, 0x6b, + 0x69, 0x6e, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0x83, 0x08, 0x12, 0x13, 0x0a, + 0x0e, 0x55, 0x73, 0x65, 0x58, 0x67, 0x72, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x53, 0x64, 0x6b, 0x10, + 0x84, 0x08, 0x12, 0x11, 0x0a, 0x0c, 0x58, 0x67, 0x72, 0x65, 0x73, 0x73, 0x43, 0x74, 0x72, 0x6c, + 0x49, 0x64, 0x10, 0x85, 0x08, 0x12, 0x12, 0x0a, 0x0d, 0x58, 0x67, 0x72, 0x65, 0x73, 0x73, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x86, 0x08, 0x12, 0x1b, 0x0a, 0x16, 0x49, 0x6e, 0x73, + 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x10, 0x87, 0x08, 0x12, 0x1a, 0x0a, 0x15, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x73, 0x50, 0x6f, 0x73, 0x74, 0x75, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x10, + 0x88, 0x08, 0x2a, 0x86, 0x02, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x06, 0x0a, 0x02, + 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x70, 0x69, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x12, 0x14, 0x0a, + 0x10, 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, + 0x65, 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x45, 0x64, + 0x67, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x10, 0x05, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x75, 0x6e, 0x6e, + 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, + 0x07, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x10, 0x08, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x10, 0x09, 0x12, + 0x0f, 0x0a, 0x0b, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x43, 0x6f, 0x73, 0x74, 0x10, 0x0a, + 0x12, 0x19, 0x0a, 0x15, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, + 0x74, 0x61, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x10, 0x0b, 0x2a, 0x38, 0x0a, 0x0f, 0x50, + 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0b, + 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x10, 0x02, 0x2a, 0x57, 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, 0x0a, + 0x04, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x46, 0x49, 0x4e, 0x10, 0x01, + 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x52, 0x41, 0x43, 0x45, 0x5f, 0x55, 0x55, 0x49, 0x44, 0x10, 0x02, + 0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x50, 0x41, 0x52, 0x54, 0x10, 0x04, 0x12, + 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4d, + 0x55, 0x4c, 0x54, 0x49, 0x50, 0x41, 0x52, 0x54, 0x5f, 0x4d, 0x53, 0x47, 0x10, 0x10, 0x42, 0x4b, + 0x0a, 0x17, 0x6f, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2e, 0x65, + 0x64, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x73, + 0x64, 0x6b, 0x2d, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x65, 0x64, 0x67, + 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1366,42 +2026,63 @@ func file_edge_client_proto_rawDescGZIP() []byte { } var file_edge_client_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_edge_client_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_edge_client_proto_msgTypes = make([]protoimpl.MessageInfo, 21) var file_edge_client_proto_goTypes = []interface{}{ (ContentType)(0), // 0: ziti.edge_client.pb.ContentType (HeaderId)(0), // 1: ziti.edge_client.pb.HeaderId (Error)(0), // 2: ziti.edge_client.pb.Error (PrecedenceValue)(0), // 3: ziti.edge_client.pb.PrecedenceValue (Flag)(0), // 4: ziti.edge_client.pb.Flag - (*PostureResponses)(nil), // 5: ziti.edge_client.pb.PostureResponses - (*PostureResponse)(nil), // 6: ziti.edge_client.pb.PostureResponse - (*PostureResponse_Macs)(nil), // 7: ziti.edge_client.pb.PostureResponse.Macs - (*PostureResponse_OperatingSystem)(nil), // 8: ziti.edge_client.pb.PostureResponse.OperatingSystem - (*PostureResponse_Domain)(nil), // 9: ziti.edge_client.pb.PostureResponse.Domain - (*PostureResponse_Process)(nil), // 10: ziti.edge_client.pb.PostureResponse.Process - (*PostureResponse_ProcessList)(nil), // 11: ziti.edge_client.pb.PostureResponse.ProcessList - (*PostureResponse_Woken)(nil), // 12: ziti.edge_client.pb.PostureResponse.Woken - (*PostureResponse_Unlocked)(nil), // 13: ziti.edge_client.pb.PostureResponse.Unlocked - (*PostureResponse_SdkInfo)(nil), // 14: ziti.edge_client.pb.PostureResponse.SdkInfo - (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp + (*ServicePostureStateRequest)(nil), // 5: ziti.edge_client.pb.ServicePostureStateRequest + (*ServicePostureStateResponse)(nil), // 6: ziti.edge_client.pb.ServicePostureStateResponse + (*ServicePostureState)(nil), // 7: ziti.edge_client.pb.ServicePostureState + (*Policy)(nil), // 8: ziti.edge_client.pb.Policy + (*PostureQuery)(nil), // 9: ziti.edge_client.pb.PostureQuery + (*PostureResponses)(nil), // 10: ziti.edge_client.pb.PostureResponses + (*PostureResponse)(nil), // 11: ziti.edge_client.pb.PostureResponse + nil, // 12: ziti.edge_client.pb.ServicePostureStateResponse.StatesEntry + nil, // 13: ziti.edge_client.pb.ServicePostureState.PoliciesEntry + nil, // 14: ziti.edge_client.pb.Policy.PostureQueriesEntry + (*PostureQuery_Processes)(nil), // 15: ziti.edge_client.pb.PostureQuery.Processes + (*PostureQuery_Process)(nil), // 16: ziti.edge_client.pb.PostureQuery.Process + (*PostureResponse_TotpToken)(nil), // 17: ziti.edge_client.pb.PostureResponse.TotpToken + (*PostureResponse_Macs)(nil), // 18: ziti.edge_client.pb.PostureResponse.Macs + (*PostureResponse_OperatingSystem)(nil), // 19: ziti.edge_client.pb.PostureResponse.OperatingSystem + (*PostureResponse_Domain)(nil), // 20: ziti.edge_client.pb.PostureResponse.Domain + (*PostureResponse_Process)(nil), // 21: ziti.edge_client.pb.PostureResponse.Process + (*PostureResponse_ProcessList)(nil), // 22: ziti.edge_client.pb.PostureResponse.ProcessList + (*PostureResponse_Woken)(nil), // 23: ziti.edge_client.pb.PostureResponse.Woken + (*PostureResponse_Unlocked)(nil), // 24: ziti.edge_client.pb.PostureResponse.Unlocked + (*PostureResponse_SdkInfo)(nil), // 25: ziti.edge_client.pb.PostureResponse.SdkInfo + (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp } var file_edge_client_proto_depIdxs = []int32{ - 6, // 0: ziti.edge_client.pb.PostureResponses.responses:type_name -> ziti.edge_client.pb.PostureResponse - 7, // 1: ziti.edge_client.pb.PostureResponse.macs:type_name -> ziti.edge_client.pb.PostureResponse.Macs - 8, // 2: ziti.edge_client.pb.PostureResponse.os:type_name -> ziti.edge_client.pb.PostureResponse.OperatingSystem - 11, // 3: ziti.edge_client.pb.PostureResponse.processList:type_name -> ziti.edge_client.pb.PostureResponse.ProcessList - 9, // 4: ziti.edge_client.pb.PostureResponse.domain:type_name -> ziti.edge_client.pb.PostureResponse.Domain - 12, // 5: ziti.edge_client.pb.PostureResponse.woken:type_name -> ziti.edge_client.pb.PostureResponse.Woken - 13, // 6: ziti.edge_client.pb.PostureResponse.unlocked:type_name -> ziti.edge_client.pb.PostureResponse.Unlocked - 14, // 7: ziti.edge_client.pb.PostureResponse.sdkInfo:type_name -> ziti.edge_client.pb.PostureResponse.SdkInfo - 10, // 8: ziti.edge_client.pb.PostureResponse.ProcessList.processes:type_name -> ziti.edge_client.pb.PostureResponse.Process - 15, // 9: ziti.edge_client.pb.PostureResponse.Woken.Time:type_name -> google.protobuf.Timestamp - 15, // 10: ziti.edge_client.pb.PostureResponse.Unlocked.Time:type_name -> google.protobuf.Timestamp - 11, // [11:11] is the sub-list for method output_type - 11, // [11:11] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 12, // 0: ziti.edge_client.pb.ServicePostureStateResponse.states:type_name -> ziti.edge_client.pb.ServicePostureStateResponse.StatesEntry + 13, // 1: ziti.edge_client.pb.ServicePostureState.policies:type_name -> ziti.edge_client.pb.ServicePostureState.PoliciesEntry + 14, // 2: ziti.edge_client.pb.Policy.postureQueries:type_name -> ziti.edge_client.pb.Policy.PostureQueriesEntry + 26, // 3: ziti.edge_client.pb.PostureQuery.timeoutAt:type_name -> google.protobuf.Timestamp + 15, // 4: ziti.edge_client.pb.PostureQuery.processes:type_name -> ziti.edge_client.pb.PostureQuery.Processes + 11, // 5: ziti.edge_client.pb.PostureResponses.responses:type_name -> ziti.edge_client.pb.PostureResponse + 18, // 6: ziti.edge_client.pb.PostureResponse.macs:type_name -> ziti.edge_client.pb.PostureResponse.Macs + 19, // 7: ziti.edge_client.pb.PostureResponse.os:type_name -> ziti.edge_client.pb.PostureResponse.OperatingSystem + 22, // 8: ziti.edge_client.pb.PostureResponse.processList:type_name -> ziti.edge_client.pb.PostureResponse.ProcessList + 20, // 9: ziti.edge_client.pb.PostureResponse.domain:type_name -> ziti.edge_client.pb.PostureResponse.Domain + 23, // 10: ziti.edge_client.pb.PostureResponse.woken:type_name -> ziti.edge_client.pb.PostureResponse.Woken + 24, // 11: ziti.edge_client.pb.PostureResponse.unlocked:type_name -> ziti.edge_client.pb.PostureResponse.Unlocked + 25, // 12: ziti.edge_client.pb.PostureResponse.sdkInfo:type_name -> ziti.edge_client.pb.PostureResponse.SdkInfo + 17, // 13: ziti.edge_client.pb.PostureResponse.totpToken:type_name -> ziti.edge_client.pb.PostureResponse.TotpToken + 7, // 14: ziti.edge_client.pb.ServicePostureStateResponse.StatesEntry.value:type_name -> ziti.edge_client.pb.ServicePostureState + 8, // 15: ziti.edge_client.pb.ServicePostureState.PoliciesEntry.value:type_name -> ziti.edge_client.pb.Policy + 9, // 16: ziti.edge_client.pb.Policy.PostureQueriesEntry.value:type_name -> ziti.edge_client.pb.PostureQuery + 16, // 17: ziti.edge_client.pb.PostureQuery.Processes.processes:type_name -> ziti.edge_client.pb.PostureQuery.Process + 21, // 18: ziti.edge_client.pb.PostureResponse.ProcessList.processes:type_name -> ziti.edge_client.pb.PostureResponse.Process + 26, // 19: ziti.edge_client.pb.PostureResponse.Woken.Time:type_name -> google.protobuf.Timestamp + 26, // 20: ziti.edge_client.pb.PostureResponse.Unlocked.Time:type_name -> google.protobuf.Timestamp + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_edge_client_proto_init() } @@ -1411,7 +2092,7 @@ func file_edge_client_proto_init() { } if !protoimpl.UnsafeEnabled { file_edge_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureResponses); i { + switch v := v.(*ServicePostureStateRequest); i { case 0: return &v.state case 1: @@ -1423,7 +2104,7 @@ func file_edge_client_proto_init() { } } file_edge_client_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureResponse); i { + switch v := v.(*ServicePostureStateResponse); i { case 0: return &v.state case 1: @@ -1435,7 +2116,7 @@ func file_edge_client_proto_init() { } } file_edge_client_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureResponse_Macs); i { + switch v := v.(*ServicePostureState); i { case 0: return &v.state case 1: @@ -1447,7 +2128,7 @@ func file_edge_client_proto_init() { } } file_edge_client_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureResponse_OperatingSystem); i { + switch v := v.(*Policy); i { case 0: return &v.state case 1: @@ -1459,7 +2140,7 @@ func file_edge_client_proto_init() { } } file_edge_client_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureResponse_Domain); i { + switch v := v.(*PostureQuery); i { case 0: return &v.state case 1: @@ -1471,7 +2152,7 @@ func file_edge_client_proto_init() { } } file_edge_client_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostureResponse_Process); i { + switch v := v.(*PostureResponses); i { case 0: return &v.state case 1: @@ -1483,6 +2164,102 @@ func file_edge_client_proto_init() { } } file_edge_client_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureQuery_Processes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureQuery_Process); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureResponse_TotpToken); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureResponse_Macs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureResponse_OperatingSystem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureResponse_Domain); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostureResponse_Process); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_edge_client_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureResponse_ProcessList); i { case 0: return &v.state @@ -1494,7 +2271,7 @@ func file_edge_client_proto_init() { return nil } } - file_edge_client_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_edge_client_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureResponse_Woken); i { case 0: return &v.state @@ -1506,7 +2283,7 @@ func file_edge_client_proto_init() { return nil } } - file_edge_client_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_edge_client_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureResponse_Unlocked); i { case 0: return &v.state @@ -1518,7 +2295,7 @@ func file_edge_client_proto_init() { return nil } } - file_edge_client_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_edge_client_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostureResponse_SdkInfo); i { case 0: return &v.state @@ -1531,7 +2308,7 @@ func file_edge_client_proto_init() { } } } - file_edge_client_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_edge_client_proto_msgTypes[6].OneofWrappers = []interface{}{ (*PostureResponse_Macs_)(nil), (*PostureResponse_Os)(nil), (*PostureResponse_ProcessList_)(nil), @@ -1539,6 +2316,7 @@ func file_edge_client_proto_init() { (*PostureResponse_Woken_)(nil), (*PostureResponse_Unlocked_)(nil), (*PostureResponse_SdkInfo_)(nil), + (*PostureResponse_TotpToken_)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -1546,7 +2324,7 @@ func file_edge_client_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_edge_client_proto_rawDesc, NumEnums: 5, - NumMessages: 10, + NumMessages: 21, NumExtensions: 0, NumServices: 0, }, diff --git a/pb/edge_client_pb/edge_client.proto b/pb/edge_client_pb/edge_client.proto index 4925d561..a818ec2e 100644 --- a/pb/edge_client_pb/edge_client.proto +++ b/pb/edge_client_pb/edge_client.proto @@ -45,7 +45,8 @@ enum ContentType { InspectResponse = 60805; PostureResponseType = 10800; - PostureResponseSuccessType = 10801; + ServicePostureStateRequestType = 108001; + ServicePostureStateResponseType = 108002; } enum HeaderId { @@ -83,6 +84,7 @@ enum HeaderId { XgressCtrlId = 1029; XgressAddress = 1030; InspectRequestedValues = 1031; + SupportsPostureChecks = 1032; } enum Error { @@ -122,6 +124,55 @@ enum Flag { MULTIPART_MSG = 16; } +message ServicePostureStateRequest { + repeated string serviceIds = 1; +} + +message ServicePostureStateResponse { + map states = 1; +} + +message ServicePostureState { + bool isPassing = 1; + repeated string passingPolicyIds = 2; + repeated string failingPolicyIds = 3; + map policies = 4; +} + +message Policy { + string id = 1; + bool isPassing = 2; + repeated string passingPostureQueryIds = 3; + repeated string failingPostureQueryIds = 4; + map postureQueries = 5; +} + +message PostureQuery { + string id = 1; + string type = 2; + bool isPassing = 3; + + google.protobuf.Timestamp timeoutAt = 4; + int32 timeoutSeconds = 5; + int32 timeoutRemainingSeconds = 6; + + int32 promptGracePeriodSeconds = 7; + bool promptOnUnlock = 8; + bool promptOnWake = 9; + + Processes processes = 10; + + message Processes { + string semantic = 1; + repeated Process processes = 2; + } + + message Process { + string osType = 1; + string path = 2; + } +} + message PostureResponses { repeated PostureResponse responses = 1; } @@ -135,8 +186,14 @@ message PostureResponse { Woken woken = 5; Unlocked unlocked = 6; SdkInfo sdkInfo = 7; + TotpToken totpToken = 8; }; + message TotpToken { + string token = 1; + string code = 2; + } + message Macs { repeated string addresses = 1; diff --git a/ziti/client.go b/ziti/client.go index 8f6de28b..2a992f09 100644 --- a/ziti/client.go +++ b/ziti/client.go @@ -27,6 +27,7 @@ import ( "fmt" "strings" "sync/atomic" + "time" "github.com/go-openapi/strfmt" "github.com/golang-jwt/jwt/v5" @@ -70,6 +71,44 @@ type CtrlClient struct { capabilitiesLoaded atomic.Bool } +func (self *CtrlClient) RequestTotpToken(code string) <-chan posture.TotpTokenResult { + totpTokenResultChan := make(chan posture.TotpTokenResult) + + go func() { + totpToken, err := self.CreateTotpToken(code) + + if err != nil { + totpTokenResultChan <- posture.TotpTokenResult{ + Err: fmt.Errorf("could not request totp token: %v", err), + } + return + } + + totpTokenResultChan <- posture.TotpTokenResult{ + Token: *totpToken.Token, + IssuedAt: time.Time(*totpToken.IssuedAt), + Err: nil, + } + }() + + return totpTokenResultChan +} + +func (self *CtrlClient) CreateTotpToken(code string) (*rest_model.TotpToken, error) { + params := current_api_session.NewCreateTotpTokenParams() + params.MfaValidation = &rest_model.MfaCode{ + Code: &code, + } + + response, err := self.API.CurrentAPISession.CreateTotpToken(params, nil) + + if err != nil { + return nil, err + } + + return response.Payload.Data, nil +} + func (self *CtrlClient) GetExternalSigners() (rest_model.ClientExternalJWTSignerList, error) { response, err := self.API.ExternalJWTSigner.ListExternalJWTSigners(nil) if err != nil { @@ -166,6 +205,10 @@ func (self *CtrlClient) SendPostureResponse(response rest_model.PostureResponseC // SendPostureResponseBulk provides the same functionality as SendPostureResponse but allows multiple responses // to be sent in a single request. func (self *CtrlClient) SendPostureResponseBulk(responses []rest_model.PostureResponseCreate) error { + if len(responses) == 0 { + return nil + } + params := posture_checks.NewCreatePostureResponseBulkParams() params.PostureResponse = responses _, err := self.API.PostureChecks.CreatePostureResponseBulk(params, self.GetCurrentApiSession()) diff --git a/ziti/contexts.go b/ziti/contexts.go index 0194daa7..31548d4a 100644 --- a/ziti/contexts.go +++ b/ziti/contexts.go @@ -86,7 +86,6 @@ func NewContextWithOpts(cfg *Config, options *Options) (Context, error) { Id: NewId(), routerConnections: cmap.New[edge.RouterConn](), options: options, - authQueryHandlers: map[string]func(query *rest_model.AuthQueryDetail, response MfaCodeResponse) error{}, closeNotify: make(chan struct{}), EventEmmiter: events.New(), routerProxy: cfg.RouterProxy, @@ -95,6 +94,8 @@ func NewContextWithOpts(cfg *Config, options *Options) (Context, error) { services: cmap.New[*rest_model.ServiceDetail](), sessions: cmap.New[*rest_model.SessionDetail](), intercepts: cmap.New[*edge.InterceptV1Config](), + activeBinds: cmap.New[*rest_model.ServiceDetail](), + activeDials: cmap.New[*rest_model.ServiceDetail](), } if newContext.maxDefaultConnections < 1 { @@ -132,25 +133,25 @@ func NewContextWithOpts(cfg *Config, options *Options) (Context, error) { provider := rest_model.MfaProvidersZiti authQuery := &rest_model.AuthQueryDetail{ - Provider: &provider, + TypeID: rest_model.AuthQueryTypeMFA, + Format: rest_model.MfaFormatsAlphaNumeric, + HTTPMethod: http.MethodPost, + HTTPURL: EdgeClientTotpAuthEndpoint, + MaxLength: MaxTotpCodeLength, + MinLength: MinTotpCodeLength, + Provider: &provider, } newContext.Emit(EventAuthQuery, authQuery) if *authQuery.Provider == rest_model.MfaProvidersZiti { - handler := newContext.authQueryHandlers[string(rest_model.MfaProvidersZiti)] - newContext.Emit(EventMfaTotpCode, authQuery, MfaCodeResponse(newContext.authenticateMfa)) - if handler == nil { + if newContext.Events().ListenerCount(EventMfaTotpCode) == 0 { pfxlog.Logger().Debugf("no callback handler registered for provider: %v, event will still be emitted", *authQuery.Provider) return - } - _ = handler(authQuery, func(code string) error { - codeCh <- code - return nil - }) + } } }, Proxy: cfg.CtrlProxy, @@ -167,7 +168,10 @@ func NewContextWithOpts(cfg *Config, options *Options) (Context, error) { } newContext.CtrlClt.SetAllowOidcDynamicallyEnabled(true) - newContext.CtrlClt.PostureCache = posture.NewCache(newContext.CtrlClt, newContext.closeNotify) + + multiSubmitter := posture.NewMultiSubmitter(newContext.CtrlClt, newContext.CtrlClt, newContext) + totpTokenProvider := posture.NewSingularTokenRequestor(newContext, newContext.CtrlClt) + newContext.CtrlClt.PostureCache = posture.NewCache(newContext, multiSubmitter, totpTokenProvider, newContext.closeNotify) newContext.CtrlClt.AddOnControllerUpdateListeners(func(urls []*url.URL) { newContext.Emit(EventControllerUrlsUpdated, urls) diff --git a/ziti/edge/conn.go b/ziti/edge/conn.go index e0b80d75..c0364e86 100644 --- a/ziti/edge/conn.go +++ b/ziti/edge/conn.go @@ -49,6 +49,8 @@ type RouterClient interface { //UpdateToken will attempt to send token updates to the connected router. A success/failure response is expected //within the timeout period. UpdateToken(token []byte, timeout time.Duration) error + + SendPosture(creates []rest_model.PostureResponseCreate) error } type RouterConn interface { diff --git a/ziti/edge/messages.go b/ziti/edge/messages.go index 5dcbc505..d836ced3 100644 --- a/ziti/edge/messages.go +++ b/ziti/edge/messages.go @@ -17,14 +17,22 @@ package edge import ( + "context" "encoding/binary" "encoding/json" + + "github.com/go-openapi/strfmt" + "github.com/michaelquigley/pfxlog" "github.com/openziti/channel/v4" + "github.com/openziti/edge-api/rest_model" + "github.com/openziti/foundation/v2/stringz" "github.com/openziti/foundation/v2/uuidz" "github.com/openziti/sdk-golang/inspect" "github.com/openziti/sdk-golang/pb/edge_client_pb" "github.com/pkg/errors" "github.com/sirupsen/logrus" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -57,7 +65,9 @@ const ( ContentTypeUpdateTokenSuccess = int32(edge_client_pb.ContentType_UpdateTokenSuccessType) ContentTypeUpdateTokenFailure = int32(edge_client_pb.ContentType_UpdateTokenFailureType) - ContentTypePostureResponse = int32(edge_client_pb.ContentType_PostureResponseType) + ContentTypePostureResponse = int32(edge_client_pb.ContentType_PostureResponseType) + ContentTypeServicePostureStateRequestType = int32(edge_client_pb.ContentType_ServicePostureStateRequestType) + ContentTypeServicePostureStateResponseType = int32(edge_client_pb.ContentType_ServicePostureStateResponseType) ContentTypeXgPayload = int32(edge_client_pb.ContentType_XgPayloadType) ContentTypeXgAcknowledgement = int32(edge_client_pb.ContentType_XgAcknowledgementType) @@ -101,6 +111,7 @@ const ( XgressCtrlIdHeader = int32(edge_client_pb.HeaderId_XgressCtrlId) XgressAddressHeader = int32(edge_client_pb.HeaderId_XgressAddress) InspectRequestValuesHeader = int32(edge_client_pb.HeaderId_InspectRequestedValues) + SupportsPostureChecksHeader = int32(edge_client_pb.HeaderId_SupportsPostureChecks) ) const ( @@ -350,6 +361,137 @@ func NewDialFailedMsg(connId uint32, message string) *channel.Message { return newMsg(ContentTypeDialFailed, connId, []byte(message)) } +func NewPostureResponsesMsg(responses []rest_model.PostureResponseCreate) *channel.Message { + protoResponses := &edge_client_pb.PostureResponses{ + Responses: make([]*edge_client_pb.PostureResponse, 0, len(responses)), + } + + for _, response := range responses { + curResponses := postureResponseRestModelToProtos(response) + protoResponses.Responses = append(protoResponses.Responses, curResponses...) + } + + b, _ := proto.Marshal(protoResponses) + message := channel.NewMessage(ContentTypePostureResponse, b) + + return message +} + +func postureResponseRestModelToProtos(response rest_model.PostureResponseCreate) []*edge_client_pb.PostureResponse { + var protoResponses []*edge_client_pb.PostureResponse + + switch typedResp := response.(type) { + case *rest_model.PostureResponseDomainCreate: + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_Domain_{ + Domain: &edge_client_pb.PostureResponse_Domain{ + Name: stringz.OrEmpty(typedResp.Domain), + }, + }, + }) + case *rest_model.PostureResponseMacAddressCreate: + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_Macs_{ + Macs: &edge_client_pb.PostureResponse_Macs{ + Addresses: typedResp.MacAddresses, + }, + }, + }) + case *rest_model.PostureResponseProcessCreate: + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_ProcessList_{ + ProcessList: &edge_client_pb.PostureResponse_ProcessList{ + Processes: []*edge_client_pb.PostureResponse_Process{ + { + Path: typedResp.Path, + IsRunning: typedResp.IsRunning, + Hash: typedResp.Hash, + SignerFingerprints: typedResp.SignerFingerprints, + }, + }, + }, + }, + }) + case *rest_model.PostureResponseOperatingSystemCreate: + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_Os{ + Os: &edge_client_pb.PostureResponse_OperatingSystem{ + Type: stringz.OrEmpty(typedResp.Type), + Version: stringz.OrEmpty(typedResp.Version), + Build: typedResp.Build, + }, + }, + }) + case *rest_model.PostureResponseEndpointStateCreate: + if typedResp.Woken { + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_Woken_{ + Woken: &edge_client_pb.PostureResponse_Woken{ + Time: timestamppb.Now(), + }, + }, + }) + } + if typedResp.Unlocked { + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_Unlocked_{ + Unlocked: &edge_client_pb.PostureResponse_Unlocked{ + Time: timestamppb.Now(), + }, + }, + }) + } + case *PostureResponseTotp: + protoResponses = append(protoResponses, &edge_client_pb.PostureResponse{ + Type: &edge_client_pb.PostureResponse_TotpToken_{ + TotpToken: &edge_client_pb.PostureResponse_TotpToken{ + Token: typedResp.TotpToken, + }, + }, + }) + default: + pfxlog.Logger().Errorf("unknown posture response type: %s", response.TypeID()) + } + + return protoResponses +} + +var _ rest_model.PostureResponseCreate = (*PostureResponseTotp)(nil) + +// PostureCheckTypeTOTP mimics rest_api.PostureCheckType* +const PostureCheckTypeTOTP rest_model.PostureCheckType = "totp" + +// PostureResponseTotp is a posture response that contains a TOTP token. Used to track the last time +// a client has performed TOTP code submission. This exists outside of the REST APIs as it is only +// needed in HA systems and is not used for legacy API Sessions. It does conform to the REST APIs generated +// interfaces in order for it to be included in interface typed slices. +type PostureResponseTotp struct { + TotpToken string //should be a signed, API Session scoped JWT. See common.TotpClaims + Id *string +} + +func (p *PostureResponseTotp) Validate(_ strfmt.Registry) error { + return nil +} + +func (p *PostureResponseTotp) ContextValidate(_ context.Context, _ strfmt.Registry) error { + return nil +} + +func (p *PostureResponseTotp) ID() *string { + return p.Id +} + +func (p *PostureResponseTotp) SetID(id *string) { + p.Id = id +} + +func (p *PostureResponseTotp) TypeID() rest_model.PostureCheckType { + return PostureCheckTypeTOTP +} + +func (p *PostureResponseTotp) SetTypeID(_ rest_model.PostureCheckType) {} + // NewUpdateTokenMsg creates a message sent to edge routers to update the token that // allows the client to stay connection. If the token is not update before the current // one expires, the connection and all service connections through it will be terminated. diff --git a/ziti/edge/network/conn.go b/ziti/edge/network/conn.go index 58bb33d3..328d6001 100644 --- a/ziti/edge/network/conn.go +++ b/ziti/edge/network/conn.go @@ -554,6 +554,7 @@ func (conn *edgeConn) Connect(session *rest_model.SessionDetail, options *edge.D } if replyMsg.ContentType == edge.ContentTypeStateClosed { + // PIRATE-RAWR return nil, errors.Errorf("dial failed: %v", string(replyMsg.Body)) } diff --git a/ziti/edge/network/factory.go b/ziti/edge/network/factory.go index aaef4319..145b54d1 100644 --- a/ziti/edge/network/factory.go +++ b/ziti/edge/network/factory.go @@ -128,6 +128,17 @@ func (conn *routerConn) NewDialConn(service *rest_model.ServiceDetail) *edgeConn return edgeCh } +func (conn *routerConn) SendPosture(responses []rest_model.PostureResponseCreate) error { + message := edge.NewPostureResponsesMsg(responses) + sendErr := message.Send(conn.ch.GetControlSender()) + + if sendErr != nil { + return sendErr + } + + return nil +} + func (conn *routerConn) UpdateToken(token []byte, timeout time.Duration) error { msg := edge.NewUpdateTokenMsg(token) resp, err := msg.WithTimeout(timeout).SendForReply(conn.ch.GetControlSender()) diff --git a/ziti/edge/posture/cache.go b/ziti/edge/posture/cache.go index 41a73a26..e569350f 100644 --- a/ziti/edge/posture/cache.go +++ b/ziti/edge/posture/cache.go @@ -17,26 +17,44 @@ package posture import ( + "net/http" + "strings" + "sync" + "time" + "github.com/go-openapi/runtime" "github.com/michaelquigley/pfxlog" "github.com/openziti/edge-api/rest_model" - "github.com/openziti/foundation/v2/concurrenz" "github.com/openziti/foundation/v2/stringz" + "github.com/openziti/sdk-golang/ziti/edge" cmap "github.com/orcaman/concurrent-map/v2" - "net/http" - "sync" - "sync/atomic" - "time" ) +const ( + // TotpAttemptDelta defines how far in advance of expiration the cache proactively requests + // new TOTP tokens, ensuring tokens remain valid during authentication flows. + TotpAttemptDelta = 5 * time.Minute + + // TotpPostureCheckNoTimeout indicates that a TOTP posture check does not expire and + // does not require periodic token refresh. + TotpPostureCheckNoTimeout = int64(-1) +) + +// CacheData holds the current snapshot of device posture information including running processes, +// network configuration, operating system details, and authentication state. type CacheData struct { Processes cmap.ConcurrentMap[string, ProcessInfo] // map[processPath]ProcessInfo MacAddresses []string Os OsInfo Domain string - Evaluated atomic.Bool //marks whether posture responses for this data have been sent out + TotpToken TotpTokenResult + OnWake WakeEvent + OnUnlock UnlockEvent + Index uint64 + Responses []rest_model.PostureResponseCreate } +// NewCacheData creates an empty posture cache snapshot with initialized collections. func NewCacheData() *CacheData { return &CacheData{ Processes: cmap.New[ProcessInfo](), @@ -46,109 +64,226 @@ func NewCacheData() *CacheData { Version: "", }, Domain: "", + Index: 0, } } +// ActiveServiceProvider supplies information about services currently in use by the client, +// enabling the cache to determine which posture checks are relevant. +type ActiveServiceProvider interface { + GetActiveDialServices() []*rest_model.ServiceDetail + GetActiveBindServices() []*rest_model.ServiceDetail +} + +// ActiveServiceProviderFunc is a function adapter that implements ActiveServiceProvider +// for both dial and bind service queries. +type ActiveServiceProviderFunc func() []*rest_model.ServiceDetail + +func (f ActiveServiceProviderFunc) GetActiveDialServices() []*rest_model.ServiceDetail { + return f() +} + +// Cache manages device posture data collection, tracking changes over time and coordinating +// submission of posture responses when device state changes or policies require updates. type Cache struct { currentData *CacheData previousData *CacheData - watchedProcesses cmap.ConcurrentMap[string, struct{}] //map[processPath]struct{}{} + watchedProcesses cmap.ConcurrentMap[string, string] //map[processPath]queryId - serviceQueryMap concurrenz.AtomicValue[map[string]map[string]rest_model.PostureQuery] //map[serviceId]map[queryId]query - activeServices cmap.ConcurrentMap[string, struct{}] // map[serviceId] + serviceProvider ActiveServiceProvider - lastSent cmap.ConcurrentMap[string, time.Time] //map[type|processQueryId]time.Time - ctrlClient Submitter + lastSent cmap.ConcurrentMap[string, time.Time] //map[type|processQueryId]time.Time + submitter Submitter startOnce sync.Once doSingleSubmissions bool closeNotify <-chan struct{} - DomainFunc func() string - lock sync.Mutex + DomainProvider DomainProvider + MacProvider MacProvider + OsProvider OsProvider + ProcessProvider ProcessProvider + TotpTokenProvider TotpTokenProvider + + lock sync.Mutex + totpTimeout int64 + eventState EventState } -func NewCache(submitter Submitter, closeNotify <-chan struct{}) *Cache { +// NewCache creates a posture cache that monitors device state and coordinates posture response +// submission. The cache uses the provided service provider to determine which posture checks +// are active, the submitter to send responses, and the token provider for TOTP authentication. +func NewCache(activeServiceProvider ActiveServiceProvider, submitter Submitter, totpTokenProvider TotpTokenProvider, closeNotify <-chan struct{}) *Cache { cache := &Cache{ currentData: NewCacheData(), previousData: NewCacheData(), - watchedProcesses: cmap.New[struct{}](), - activeServices: cmap.New[struct{}](), + watchedProcesses: cmap.New[string](), + serviceProvider: activeServiceProvider, lastSent: cmap.New[time.Time](), - ctrlClient: submitter, + submitter: submitter, startOnce: sync.Once{}, closeNotify: closeNotify, - DomainFunc: Domain, + totpTimeout: TotpPostureCheckNoTimeout, + + TotpTokenProvider: totpTokenProvider, + DomainProvider: NewDomainProvider(), + MacProvider: NewMacProvider(), + OsProvider: NewOsProvider(), + ProcessProvider: NewProcessProvider(), + + eventState: NewEventState(), } - cache.serviceQueryMap.Store(map[string]map[string]rest_model.PostureQuery{}) + + cache.currentData.Index = 1 + cache.start() return cache } -// Set the current list of processes paths that are being observed -func (cache *Cache) setWatchedProcesses(processPaths []string) { - processMap := map[string]struct{}{} +// Evaluate refreshes all posture data and determines if new posture responses should be sent out +func (cache *Cache) Evaluate() { + cache.lock.Lock() + defer cache.lock.Unlock() + + activeDialServices := cache.serviceProvider.GetActiveDialServices() + activeBindServices := cache.serviceProvider.GetActiveBindServices() - for _, processPath := range processPaths { - processMap[processPath] = struct{}{} - cache.watchedProcesses.Set(processPath, struct{}{}) + activeQueryTypes, activeProcesses, lowestTotpTimeout := getActiveQueryInfo(activeDialServices, activeBindServices) + + cache.setTotpTimeout(lowestTotpTimeout) + + candidateData := NewCacheData() + candidateData.Index = cache.currentData.Index + 1 + + candidateData.Os = cache.OsProvider.GetOsInfo() + candidateData.Domain = cache.DomainProvider.GetDomain() + candidateData.MacAddresses = sanitizeMacAddresses(cache.MacProvider.GetMacAddresses()) + + for processPath, queryId := range activeProcesses { + processInfo := cache.ProcessProvider.GetProcessInfo(processPath) + processInfo.QueryId = queryId + candidateData.Processes.Set(processPath, processInfo) } - var processesToRemove []string - cache.watchedProcesses.IterCb(func(processPath string, _ struct{}) { - if _, ok := processMap[processPath]; !ok { - processesToRemove = append(processesToRemove, processPath) - } - }) + candidateData.TotpToken = cache.previousData.TotpToken - for _, processPath := range processesToRemove { - cache.watchedProcesses.Remove(processPath) + if cache.TotpTokenProvider != nil && cache.totpTimeoutWindowEntered() { + totpTokenResultCh := cache.TotpTokenProvider.Request() + + if totpTokenResultCh != nil { + select { + case totpTokenResult := <-totpTokenResultCh: + if totpTokenResult.Err != nil { + pfxlog.Logger().Errorf("error requesting totp token: %v", totpTokenResult.Err) + } else { + candidateData.TotpToken = totpTokenResult + } + case <-cache.closeNotify: + return + } + } } -} -// Evaluate refreshes all posture data and determines if new posture responses should be sent out -func (cache *Cache) Evaluate() { - cache.lock.Lock() - defer cache.lock.Unlock() + responses := cache.GetChangedResponses(cache.currentData, candidateData, activeQueryTypes) + if len(responses) > 0 { + cache.previousData = cache.currentData + cache.currentData = candidateData + cache.currentData.Responses = responses - cache.Refresh() - if responses := cache.GetChangedResponses(); len(responses) > 0 { if err := cache.SendResponses(responses); err != nil { pfxlog.Logger().Error(err) } } } -// GetChangedResponses determines if posture responses should be sent out. -func (cache *Cache) GetChangedResponses() []rest_model.PostureResponseCreate { - if !cache.currentData.Evaluated.CompareAndSwap(false, true) { - return nil +func getActiveQueryInfo(dialServices []*rest_model.ServiceDetail, bindServices []*rest_model.ServiceDetail) (map[string]string, map[string]string, int64) { + activeQueryTypes := map[string]string{} // map[queryType]->queryId' + activeProcesses := map[string]string{} // map[processPath]->queryId' + + lowestTotpTimeout := TotpPostureCheckNoTimeout + for _, service := range dialServices { + for _, postureQueryState := range service.PostureQueries { + if postureQueryState.PolicyType == rest_model.DialBindDial { + addQueryInfoToMaps(activeQueryTypes, activeProcesses, postureQueryState) + lowestTotpTimeout = getLowestTotpTimeout(postureQueryState, lowestTotpTimeout) + } + } + } + + for _, service := range bindServices { + for _, postureQueryState := range service.PostureQueries { + if postureQueryState.PolicyType == rest_model.DialBindBind { + addQueryInfoToMaps(activeQueryTypes, activeProcesses, postureQueryState) + lowestTotpTimeout = getLowestTotpTimeout(postureQueryState, lowestTotpTimeout) + } + } } - activeQueryTypes := map[string]string{} // map[queryType|processPath]->queryId - cache.activeServices.IterCb(func(serviceId string, _ struct{}) { - queryMap := cache.serviceQueryMap.Load()[serviceId] + return activeQueryTypes, activeProcesses, lowestTotpTimeout +} + +func getLowestTotpTimeout(postureQueryState *rest_model.PostureQueries, curTimeout int64) int64 { + for _, query := range postureQueryState.PostureQueries { - for queryId, query := range queryMap { - if *query.QueryType != rest_model.PostureCheckTypePROCESS { - activeQueryTypes[string(*query.QueryType)] = queryId - } else { - activeQueryTypes[query.Process.Path] = queryId + if *query.QueryType == rest_model.PostureCheckTypeMFA { + if curTimeout == TotpPostureCheckNoTimeout && query.Timeout != nil && *query.Timeout != TotpPostureCheckNoTimeout { + curTimeout = *query.Timeout + } else if query.Timeout != nil && *query.Timeout < curTimeout { + curTimeout = *query.Timeout } } - }) + } + + return curTimeout +} + +func addQueryInfoToMaps(activeQueryTypes map[string]string, activeProcesses map[string]string, postureQueryState *rest_model.PostureQueries) { + for _, query := range postureQueryState.PostureQueries { + activeQueryTypes[string(*query.QueryType)] = *query.ID + + switch *query.QueryType { + case rest_model.PostureCheckTypePROCESS: + activeQueryTypes[string(rest_model.PostureCheckTypeOS)] = *query.ID + activeProcesses[query.Process.Path] = *query.ID + case rest_model.PostureCheckTypePROCESSMULTI: + activeQueryTypes[string(rest_model.PostureCheckTypeOS)] = *query.ID - if len(activeQueryTypes) == 0 { + for _, process := range query.Processes { + activeProcesses[process.Path] = *query.ID + } + } + } +} + +// GetChangedResponses determines if posture responses should be sent out. +func (cache *Cache) GetChangedResponses(currentData, candidateData *CacheData, activeQueryTypes map[string]string) []rest_model.PostureResponseCreate { + if len(activeQueryTypes) == 0 && candidateData.Processes.Count() == 0 { return nil } var responses []rest_model.PostureResponseCreate - if cache.currentData.Domain != cache.previousData.Domain { + + wakeChanged := !currentData.OnWake.At.Equal(candidateData.OnWake.At) + unlockChanged := !currentData.OnUnlock.At.Equal(candidateData.OnUnlock.At) + + if wakeChanged || unlockChanged { + // TOTP MFA checks are the only checks that care about wake/unlock + if queryId, ok := activeQueryTypes[string(rest_model.PostureCheckTypeMFA)]; ok { + endpointState := &rest_model.PostureResponseEndpointStateCreate{ + Unlocked: unlockChanged, + Woken: wakeChanged, + } + endpointState.SetID(&queryId) + responses = append(responses, endpointState) + } + } + + if currentData.Domain != candidateData.Domain { if queryId, ok := activeQueryTypes[string(rest_model.PostureCheckTypeDOMAIN)]; ok { domainResponse := &rest_model.PostureResponseDomainCreate{ - Domain: &cache.currentData.Domain, + Domain: &candidateData.Domain, } domainResponse.SetID(&queryId) domainResponse.SetTypeID(rest_model.PostureCheckTypeDOMAIN) @@ -157,10 +292,22 @@ func (cache *Cache) GetChangedResponses() []rest_model.PostureResponseCreate { } } - if !stringz.EqualSlices(cache.currentData.MacAddresses, cache.previousData.MacAddresses) { + if currentData.TotpToken.Token != candidateData.TotpToken.Token { + if queryId, ok := activeQueryTypes[string(rest_model.PostureCheckTypeMFA)]; ok { + totpMfaResponse := &edge.PostureResponseTotp{ + TotpToken: candidateData.TotpToken.Token, + } + totpMfaResponse.SetID(&queryId) + totpMfaResponse.SetTypeID(rest_model.PostureCheckTypeMFA) + + responses = append(responses, totpMfaResponse) + } + } + + if !stringz.EqualSlices(currentData.MacAddresses, candidateData.MacAddresses) { if queryId, ok := activeQueryTypes[string(rest_model.PostureCheckTypeMAC)]; ok { macResponse := &rest_model.PostureResponseMacAddressCreate{ - MacAddresses: cache.currentData.MacAddresses, + MacAddresses: candidateData.MacAddresses, } macResponse.SetID(&queryId) macResponse.SetTypeID(rest_model.PostureCheckTypeMAC) @@ -169,11 +316,11 @@ func (cache *Cache) GetChangedResponses() []rest_model.PostureResponseCreate { } } - if cache.previousData.Os.Version != cache.currentData.Os.Version || cache.previousData.Os.Type != cache.currentData.Os.Type { + if candidateData.Os.Version != currentData.Os.Version || candidateData.Os.Type != currentData.Os.Type { if queryId, ok := activeQueryTypes[string(rest_model.PostureCheckTypeOS)]; ok { osResponse := &rest_model.PostureResponseOperatingSystemCreate{ - Type: &cache.currentData.Os.Type, - Version: &cache.currentData.Os.Version, + Type: &candidateData.Os.Type, + Version: &candidateData.Os.Version, Build: "", } osResponse.SetID(&queryId) @@ -183,32 +330,26 @@ func (cache *Cache) GetChangedResponses() []rest_model.PostureResponseCreate { } } - cache.currentData.Processes.IterCb(func(processPath string, curState ProcessInfo) { - queryId, isActive := activeQueryTypes[processPath] - - if !isActive { - return - } - - prevState, ok := cache.previousData.Processes.Get(processPath) + candidateData.Processes.IterCb(func(processPath string, candidateProcessInfo ProcessInfo) { + curProcessInfo, ok := currentData.Processes.Get(processPath) sendResponse := false if !ok { //no prev state send sendResponse = true } else { - sendResponse = prevState.IsRunning != curState.IsRunning || prevState.Hash != curState.Hash || !stringz.EqualSlices(prevState.SignerFingerprints, curState.SignerFingerprints) + sendResponse = curProcessInfo.IsRunning != candidateProcessInfo.IsRunning || curProcessInfo.Hash != candidateProcessInfo.Hash || !stringz.EqualSlices(curProcessInfo.SignerFingerprints, candidateProcessInfo.SignerFingerprints) } if sendResponse { processResponse := &rest_model.PostureResponseProcessCreate{ Path: processPath, - Hash: curState.Hash, - SignerFingerprints: curState.SignerFingerprints, - IsRunning: curState.IsRunning, + Hash: candidateProcessInfo.Hash, + SignerFingerprints: candidateProcessInfo.SignerFingerprints, + IsRunning: candidateProcessInfo.IsRunning, } - processResponse.SetID(&queryId) + processResponse.SetID(&candidateProcessInfo.QueryId) processResponse.SetTypeID(rest_model.PostureCheckTypePROCESS) responses = append(responses, processResponse) } @@ -217,50 +358,35 @@ func (cache *Cache) GetChangedResponses() []rest_model.PostureResponseCreate { return responses } -// Refresh refreshes posture data -func (cache *Cache) Refresh() { - cache.previousData = cache.currentData - - cache.currentData = NewCacheData() - cache.currentData.Os = Os() - - cache.currentData.Domain = cache.DomainFunc() - cache.currentData.MacAddresses = MacAddresses() - - keys := cache.watchedProcesses.Keys() - for _, processPath := range keys { - cache.currentData.Processes.Set(processPath, Process(processPath)) +func (cache *Cache) totpTimeoutWindowEntered() bool { + if cache.totpTimeout == TotpPostureCheckNoTimeout { + return false } -} - -// SetServiceQueryMap receives of a list of serviceId -> queryId -> queries. Used to determine which queries are necessary -// to provide data for on a per-service basis. -func (cache *Cache) SetServiceQueryMap(serviceQueryMap map[string]map[string]rest_model.PostureQuery) { - cache.serviceQueryMap.Store(serviceQueryMap) - var processPaths []string - for _, queryMap := range serviceQueryMap { - for _, query := range queryMap { - if *query.QueryType == rest_model.PostureCheckTypePROCESS && query.Process != nil { - processPaths = append(processPaths, query.Process.Path) - } - } + if cache.previousData.TotpToken.IssuedAt.IsZero() { + return true } - cache.setWatchedProcesses(processPaths) -} -func (cache *Cache) AddActiveService(serviceId string) { - cache.activeServices.Set(serviceId, struct{}{}) - cache.Evaluate() -} + if cache.previousData.TotpToken.Token == "" { + return true + } -func (cache *Cache) RemoveActiveService(serviceId string) { - cache.activeServices.Remove(serviceId) - cache.Evaluate() + effectiveTimeout := time.Duration(cache.totpTimeout)*time.Second - TotpAttemptDelta + return cache.previousData.TotpToken.IssuedAt.Add(effectiveTimeout).Before(time.Now()) } func (cache *Cache) start() { cache.startOnce.Do(func() { + stopWake, err := cache.eventState.ListenForWake(cache.onWake) + if err != nil { + pfxlog.Logger().WithError(err).Error("error starting wake listener for posture") + } + + stopUnlock, err := cache.eventState.ListenForUnlock(cache.OnUnlock) + if err != nil { + pfxlog.Logger().WithError(err).Error("error starting unlock listener for posture") + } + ticker := time.NewTicker(10 * time.Second) go func() { defer func() { @@ -272,8 +398,16 @@ func (cache *Cache) start() { for { select { case <-ticker.C: + cache.Evaluate() case <-cache.closeNotify: + if stopWake != nil { + stopWake() + } + + if stopUnlock != nil { + stopUnlock() + } return } } @@ -285,7 +419,7 @@ func (cache *Cache) SendResponses(responses []rest_model.PostureResponseCreate) if cache.doSingleSubmissions { var allErrors []error for _, response := range responses { - err := cache.ctrlClient.SendPostureResponse(response) + err := cache.submitter.SendPostureResponse(response) if err != nil { allErrors = append(allErrors, err) @@ -295,17 +429,96 @@ func (cache *Cache) SendResponses(responses []rest_model.PostureResponseCreate) return allErrors } else { - err := cache.ctrlClient.SendPostureResponseBulk(responses) + err := cache.submitter.SendPostureResponseBulk(responses) - if apiErr, ok := err.(*runtime.APIError); ok && apiErr.Code == http.StatusNotFound { - cache.doSingleSubmissions = true - return cache.SendResponses(responses) + if err != nil { + if apiErr, ok := err.(*runtime.APIError); ok && apiErr.Code == http.StatusNotFound { + cache.doSingleSubmissions = true + return cache.SendResponses(responses) + } + return []error{err} } - return []error{err} + return nil } } -type Submitter interface { - SendPostureResponse(response rest_model.PostureResponseCreate) error - SendPostureResponseBulk(responses []rest_model.PostureResponseCreate) error +func (cache *Cache) InitializePostureOnEdgeRouter(conn edge.RouterConn) error { + allResponses := cache.GetAllResponses() + return cache.submitter.SendPostureResponseBulk(allResponses) +} + +func (cache *Cache) GetAllResponses() []rest_model.PostureResponseCreate { + cache.lock.Lock() + defer cache.lock.Unlock() + + var allResponses []rest_model.PostureResponseCreate + + allResponses = append(allResponses, cache.currentData.Responses...) + + return allResponses +} + +func (cache *Cache) setTotpTimeout(timeout int64) { + cache.totpTimeout = timeout +} + +func (cache *Cache) onWake(event WakeEvent) { + cache.currentData.OnWake = event +} + +func (cache *Cache) OnUnlock(event UnlockEvent) { + cache.currentData.OnUnlock = event +} + +func (cache *Cache) SimulateWake() { + cache.onWake(WakeEvent{At: time.Now().UTC()}) +} + +func (cache *Cache) SimulateUnlock() { + cache.OnUnlock(UnlockEvent{At: time.Now().UTC()}) +} + +func (cache *Cache) SetTotpToken(token *rest_model.TotpToken) { + cache.currentData.TotpToken = TotpTokenResult{ + Token: *token.Token, + IssuedAt: time.Time(*token.IssuedAt), + } +} + +func (cache *Cache) SetTotpProviderFunc(f func() <-chan TotpTokenResult) { + p := TotpTokenProviderFunc(f) + cache.TotpTokenProvider = &p +} + +func (cache *Cache) SetDomainProviderFunc(f func() string) { + p := DomainProviderFunc(f) + cache.DomainProvider = &p +} + +func (cache *Cache) SetMacProviderFunc(f func() []string) { + p := MacProviderFunc(f) + cache.MacProvider = &p +} + +func (cache *Cache) SetOsProviderFunc(f func() OsInfo) { + p := OsProviderFunc(f) + cache.OsProvider = &p +} + +func (cache *Cache) SetProcessProviderFunc(f func(string) ProcessInfo) { + p := ProcessInfoFunc(f) + cache.ProcessProvider = &p +} + +func sanitizeMacAddresses(addresses []string) []string { + result := make([]string, 0, len(addresses)) + + for _, address := range addresses { + address = strings.TrimSpace(address) + address = strings.ToLower(address) + address = strings.ReplaceAll(address, ":", "") + result = append(result, address) + } + + return result } diff --git a/ziti/edge/posture/domain.go b/ziti/edge/posture/domain.go index 994e3db3..f3156c8a 100644 --- a/ziti/edge/posture/domain.go +++ b/ziti/edge/posture/domain.go @@ -1,5 +1,3 @@ -// +build !windows - /* Copyright 2019 NetFoundry Inc. @@ -18,6 +16,20 @@ package posture -func Domain() string { - return "" +// DomainProvider supplies the Windows domain name that the device is joined to, +// used for domain membership posture checks. +type DomainProvider interface { + GetDomain() string +} + +// DomainFuncAsProvider converts a simple domain-returning function into a DomainProvider. +func DomainFuncAsProvider(f func() string) DomainProvider { + return DomainProviderFunc(f) +} + +// DomainProviderFunc is a function adapter that implements DomainProvider. +type DomainProviderFunc func() string + +func (f DomainProviderFunc) GetDomain() string { + return f() } diff --git a/ziti/edge/posture/domain_notwindows.go b/ziti/edge/posture/domain_notwindows.go new file mode 100644 index 00000000..27746b33 --- /dev/null +++ b/ziti/edge/posture/domain_notwindows.go @@ -0,0 +1,30 @@ +//go:build !windows +// +build !windows + +/* + Copyright 2019 NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package posture + +func NewDomainProvider() DomainProvider { + return &EmptyDomainProvider{} +} + +type EmptyDomainProvider struct{} + +func (p *EmptyDomainProvider) GetDomain() string { + return "" +} diff --git a/ziti/edge/posture/domain_windows.go b/ziti/edge/posture/domain_windows.go index 8ab8d925..42a992e5 100644 --- a/ziti/edge/posture/domain_windows.go +++ b/ziti/edge/posture/domain_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows /* @@ -24,7 +25,13 @@ import ( "unsafe" ) -func Domain() string { +func NewDomainProvider() DomainProvider { + return &WindowsDomainProvider{} +} + +type WindowsDomainProvider struct{} + +func (p *WindowsDomainProvider) GetDomain() string { var domain *uint16 var status uint32 @@ -32,17 +39,20 @@ func Domain() string { if err != nil { return "" } - defer syscall.NetApiBufferFree((*byte)(unsafe.Pointer(domain))) + defer func(buf *byte) { + _ = syscall.NetApiBufferFree(buf) + }((*byte)(unsafe.Pointer(domain))) + //todo: add this back in so that workgroups aren't allowed: status == syscall.NetSetupDomainName && if domain != nil { - domainName := cstringTostring(domain) + domainName := cStringTostring(domain) return domainName } return "" } -func cstringTostring(cs *uint16) (s string) { +func cStringTostring(cs *uint16) (s string) { if cs != nil { us := make([]uint16, 0, 256) for p := uintptr(unsafe.Pointer(cs)); ; p += 2 { diff --git a/ziti/edge/posture/eventstates.go b/ziti/edge/posture/eventstates.go new file mode 100644 index 00000000..f3b4ab24 --- /dev/null +++ b/ziti/edge/posture/eventstates.go @@ -0,0 +1,51 @@ +package posture + +import "time" + +// WakeEvent represents a device wake event from sleep or hibernation, used to trigger +// posture re-evaluation when the system resumes from a suspended state. +type WakeEvent struct { + At time.Time +} + +// UnlockEvent represents a device unlock event after screen lock, used to trigger +// posture re-evaluation when user authentication state changes. +type UnlockEvent struct { + At time.Time +} + +// EventState provides platform-specific monitoring of system events that may affect +// posture compliance, such as waking from sleep or unlocking the device. +type EventState interface { + // ListenForWake registers a callback for system wake events, returning a function + // to stop listening. + ListenForWake(func(WakeEvent)) (stop func(), err error) + + // ListenForUnlock registers a callback for device unlock events, returning a function + // to stop listening. + ListenForUnlock(func(event UnlockEvent)) (stop func(), err error) +} + +var _ EventState = (*NoOpEventState)(nil) + +// NoOpEventState is a placeholder implementation that stores callbacks without actually +// monitoring system events. Platform-specific implementations should be used for +// production deployments. +type NoOpEventState struct { + onWake func(WakeEvent) + onUnlock func(UnlockEvent) +} + +func (n *NoOpEventState) ListenForWake(f func(WakeEvent)) (stop func(), err error) { + n.onWake = f + return func() { + n.onWake = nil + }, nil +} + +func (n *NoOpEventState) ListenForUnlock(f func(event UnlockEvent)) (stop func(), err error) { + n.onUnlock = f + return func() { + n.onUnlock = nil + }, nil +} diff --git a/ziti/edge/posture/eventstates_notwindows.go b/ziti/edge/posture/eventstates_notwindows.go new file mode 100644 index 00000000..2e4be149 --- /dev/null +++ b/ziti/edge/posture/eventstates_notwindows.go @@ -0,0 +1,9 @@ +//go:build !windows +// +build !windows + +package posture + +// NewEvenState is a stand-in for actual non-Windows event watching +func NewEventState() EventState { + return &NoOpEventState{} +} diff --git a/ziti/edge/posture/eventstates_windows.go b/ziti/edge/posture/eventstates_windows.go new file mode 100644 index 00000000..9eb62f73 --- /dev/null +++ b/ziti/edge/posture/eventstates_windows.go @@ -0,0 +1,8 @@ +//go:build windows + +package posture + +// NewEventState is a stand-in for actual Window event watching +func NewEventState() EventState { + return &NoOpEventState{} +} diff --git a/ziti/edge/posture/mac.go b/ziti/edge/posture/mac.go index 3d6ae180..905e7518 100644 --- a/ziti/edge/posture/mac.go +++ b/ziti/edge/posture/mac.go @@ -18,7 +18,28 @@ package posture import "net" -func MacAddresses() []string { +// MacProvider supplies the list of MAC addresses for network interfaces on the device, +// used for MAC address posture checks. +type MacProvider interface { + GetMacAddresses() []string +} + +// MacProviderFunc is a function adapter that implements MacProvider. +type MacProviderFunc func() []string + +func (f MacProviderFunc) GetMacAddresses() []string { + return f() +} + +// NewMacProvider creates the default MAC address provider that queries system network interfaces. +func NewMacProvider() MacProvider { + return &DefaultMacProvider{} +} + +// DefaultMacProvider queries the system's network interfaces to collect MAC addresses. +type DefaultMacProvider struct{} + +func (p *DefaultMacProvider) GetMacAddresses() []string { netInterfaces, err := net.Interfaces() if err != nil { return nil diff --git a/ziti/edge/posture/os.go b/ziti/edge/posture/os.go index a0683ed8..b366dd54 100644 --- a/ziti/edge/posture/os.go +++ b/ziti/edge/posture/os.go @@ -24,12 +24,33 @@ import ( "github.com/shirou/gopsutil/v3/host" ) +// OsProvider supplies operating system type and version information for OS posture checks. +type OsProvider interface { + GetOsInfo() OsInfo +} + +// OsInfo contains the operating system type and semantic version. type OsInfo struct { Type string Version string } -func Os() OsInfo { +// OsProviderFunc is a function adapter that implements OsProvider. +type OsProviderFunc func() OsInfo + +func (f OsProviderFunc) GetOsInfo() OsInfo { + return f() +} + +// NewOsProvider creates the default OS information provider that queries system details. +func NewOsProvider() OsProvider { + return &DefaultOsProvider{} +} + +// DefaultOsProvider queries platform information to determine OS type and version. +type DefaultOsProvider struct{} + +func (provider DefaultOsProvider) GetOsInfo() OsInfo { osType := runtime.GOOS osVersion := "unknown" diff --git a/ziti/edge/posture/process.go b/ziti/edge/posture/process.go index f740d41b..cbb1f7fd 100644 --- a/ziti/edge/posture/process.go +++ b/ziti/edge/posture/process.go @@ -16,8 +16,24 @@ package posture +// ProcessProvider supplies information about specific processes running on the device, +// including execution state, binary hash, and code signing details for process posture checks. +type ProcessProvider interface { + GetProcessInfo(path string) ProcessInfo +} + +// ProcessInfo contains details about a specific process including whether it's running, +// its binary hash, and code signing fingerprints. type ProcessInfo struct { IsRunning bool Hash string SignerFingerprints []string + QueryId string +} + +// ProcessInfoFunc is a function adapter that implements ProcessProvider. +type ProcessInfoFunc func(path string) ProcessInfo + +func (f ProcessInfoFunc) GetProcessInfo(path string) ProcessInfo { + return f(path) } diff --git a/ziti/edge/posture/process_js.go b/ziti/edge/posture/process_js.go index 7fb282f4..b7daf41d 100644 --- a/ziti/edge/posture/process_js.go +++ b/ziti/edge/posture/process_js.go @@ -16,7 +16,13 @@ package posture -func Process(providedPath string) ProcessInfo { +func NewProcessProvider() ProcessProvider { + return &EmptyProcessProvider{} +} + +type EmptyProcessProvider struct{} + +func (p *EmptyProcessProvider) GetProcessInfo(providedPath string) ProcessInfo { return ProcessInfo{ IsRunning: false, Hash: "", diff --git a/ziti/edge/posture/process_notjs.go b/ziti/edge/posture/process_notjs.go index 51398bdc..bd3dbbfc 100644 --- a/ziti/edge/posture/process_notjs.go +++ b/ziti/edge/posture/process_notjs.go @@ -21,15 +21,22 @@ package posture import ( "crypto/sha512" "fmt" - "github.com/michaelquigley/pfxlog" - "github.com/mitchellh/go-ps" - "github.com/shirou/gopsutil/v3/process" "os" "path/filepath" "strings" + + "github.com/michaelquigley/pfxlog" + "github.com/mitchellh/go-ps" + "github.com/shirou/gopsutil/v3/process" ) -func Process(providedPath string) ProcessInfo { +func NewProcessProvider() ProcessProvider { + return &DefaultProcessProvider{} +} + +type DefaultProcessProvider struct{} + +func (p *DefaultProcessProvider) GetProcessInfo(providedPath string) ProcessInfo { expectedPath := filepath.Clean(providedPath) processes, err := ps.Processes() diff --git a/ziti/edge/posture/submitter.go b/ziti/edge/posture/submitter.go new file mode 100644 index 00000000..08383d33 --- /dev/null +++ b/ziti/edge/posture/submitter.go @@ -0,0 +1,166 @@ +package posture + +import ( + "fmt" + + "github.com/openziti/edge-api/rest_model" + edge_apis "github.com/openziti/sdk-golang/edge-apis" + "github.com/openziti/sdk-golang/ziti/edge" +) + +// Submitter handles transmission of posture response data to authentication and policy +// enforcement endpoints. +type Submitter interface { + SendPostureResponse(response rest_model.PostureResponseCreate) error + SendPostureResponseBulk(responses []rest_model.PostureResponseCreate) error +} + +// RouterConnectionProvider supplies active router connections for submitting posture data +// directly to edge routers in high-availability deployments. +type RouterConnectionProvider interface { + GetRouterConnections() []edge.RouterConn +} + +// ApiSessionProvider supplies the current API session, enabling submitters to determine +// the appropriate destination for posture responses based on authentication type. +type ApiSessionProvider interface { + GetCurrentApiSession() edge_apis.ApiSession +} + +var _ Submitter = (*MultiSubmitter)(nil) + +// MultiSubmitter routes posture responses to appropriate destinations based on session type +// and router capabilities. Legacy sessions always submit to the controller, while OIDC sessions +// submit to routers that support posture checks and fall back to the controller for older routers. +type MultiSubmitter struct { + ApiSessionProvider ApiSessionProvider + LegacySubmitter Submitter + RouterConnectionProvider RouterConnectionProvider +} + +// NewMultiSubmitter creates a submitter that intelligently routes posture responses based on +// session authentication method and router capabilities. +func NewMultiSubmitter(apiSessionProvider ApiSessionProvider, legacySubmitter Submitter, routerConnectionProvider RouterConnectionProvider) *MultiSubmitter { + return &MultiSubmitter{ + ApiSessionProvider: apiSessionProvider, + LegacySubmitter: legacySubmitter, + RouterConnectionProvider: routerConnectionProvider, + } +} + +func (m *MultiSubmitter) SendPostureResponse(response rest_model.PostureResponseCreate) error { + if response == nil { + return nil + } + return m.SendPostureResponseBulk([]rest_model.PostureResponseCreate{response}) +} + +func (m *MultiSubmitter) SendPostureResponseBulk(responses []rest_model.PostureResponseCreate) error { + if len(responses) == 0 { + return nil + } + + apiSession := m.ApiSessionProvider.GetCurrentApiSession() + + //legacy api sessions do not use router posture always goes to the controller + if apiSession.GetType() == edge_apis.ApiSessionTypeLegacy { + return m.LegacySubmitter.SendPostureResponseBulk(responses) + } + + sendToController := false + + routerConns := m.RouterConnectionProvider.GetRouterConnections() + errors := &MultiDestinationError{ + routerErrors: map[edge.RouterConn]error{}, + controllerError: nil, + } + + for _, routerConn := range routerConns { + if routerConn.GetBoolHeader(edge.SupportsPostureChecksHeader) { + err := routerConn.SendPosture(responses) + if err != nil { + errors.routerErrors[routerConn] = err + } + } else { + sendToController = true + } + } + + if sendToController { + legacyResponse := filterToLegacyPostureResponses(responses) + + errors.controllerError = m.LegacySubmitter.SendPostureResponseBulk(legacyResponse) + + } + + if errors.HasErrors() { + return errors + } + + return nil +} + +// filterToLegacyPostureResponses removes responses from the provided list, returning +// only posture response types supported by older controller versions that do not handle +// newer types supported by routers. +func filterToLegacyPostureResponses(responses []rest_model.PostureResponseCreate) []rest_model.PostureResponseCreate { + legacyResponse := make([]rest_model.PostureResponseCreate, 0, len(responses)) + + for _, response := range responses { + if response.TypeID() != edge.PostureCheckTypeTOTP { + legacyResponse = append(legacyResponse, response) + } + } + + return legacyResponse +} + +// MultiDestinationError aggregates errors from posture response submission attempts +// to multiple destinations (controller and routers), providing detailed failure information. +type MultiDestinationError struct { + routerErrors map[edge.RouterConn]error + controllerError error +} + +// Error formats all submission failures into a comprehensive error message identifying +// which destinations failed and why. +func (e *MultiDestinationError) Error() string { + result := "" + + if !e.HasErrors() { + if e == nil { + return "" + } + panic("unexpected error state, there are no errors, but treated as an error") + } + + if e.controllerError != nil { + result = "failed to send posture response to controller: " + e.controllerError.Error() + } + + if len(e.routerErrors) > 0 { + if result != "" { + result += " and " + } + + routerErrStr := "" + + for routerConn, err := range e.routerErrors { + if routerErrStr != "" { + routerErrStr += ", " + } + + routerErrStr = routerErrStr + fmt.Sprintf("router [%s]: %s", routerConn.GetRouterName(), err.Error()) + } + + result = result + fmt.Sprintf("failed to send posture response to %d routers: %s", len(e.routerErrors), routerErrStr) + } + + return result +} + +// HasErrors returns true if any submission attempts failed, either to the controller +// or to any routers. +func (e *MultiDestinationError) HasErrors() bool { + return len(e.routerErrors) > 0 || e.controllerError != nil +} diff --git a/ziti/edge/posture/totp.go b/ziti/edge/posture/totp.go new file mode 100644 index 00000000..5903c115 --- /dev/null +++ b/ziti/edge/posture/totp.go @@ -0,0 +1,128 @@ +package posture + +import ( + "errors" + "fmt" + "strings" + "sync" + "time" +) + +// TotpCodeResult represents the outcome of requesting a TOTP code from a user or provider, +// containing either the code string or an error if the request failed. +type TotpCodeResult struct { + Code string + Err error +} + +// TotpTokenResult represents the outcome of exchanging a TOTP code for a session token, +// including the token value, issuance timestamp, and any errors encountered. +type TotpTokenResult struct { + Token string + IssuedAt time.Time + Err error +} + +// TotpCodeProvider defines the interface for obtaining TOTP codes, typically implemented +// by user interaction handlers that prompt for authenticator app codes. +type TotpCodeProvider interface { + GetTotpCode() <-chan TotpCodeResult +} + +// TotpTokenRequestor defines the interface for exchanging TOTP codes with the authentication +// service to obtain session tokens. +type TotpTokenRequestor interface { + RequestTotpToken(code string) <-chan TotpTokenResult +} + +// TotpTokenProvider abstracts the complete TOTP authentication flow, handling both code +// acquisition and token exchange. +type TotpTokenProvider interface { + Request() <-chan TotpTokenResult +} + +// TotpTokenProviderFunc is a function adapter that implements TotpTokenProvider, allowing +// simple functions to satisfy the interface. +type TotpTokenProviderFunc func() <-chan TotpTokenResult + +func (f TotpTokenProviderFunc) Request() <-chan TotpTokenResult { + return f() +} + +// SingularTokenRequestor ensures only one TOTP token request is active at a time, +// preventing duplicate authentication attempts when multiple operations require TOTP. +type SingularTokenRequestor struct { + isRequesting sync.Mutex + codeProvider TotpCodeProvider + tokenRequestor TotpTokenRequestor +} + +const totpCodeProviderTimeout = 5 * time.Minute +const totpTokenRequestorTimeout = 30 * time.Second + +// NewSingularTokenRequestor creates a requestor that coordinates TOTP code collection +// and token exchange while preventing concurrent requests. +func NewSingularTokenRequestor(codeProvider TotpCodeProvider, tokenRequestor TotpTokenRequestor) *SingularTokenRequestor { + return &SingularTokenRequestor{ + codeProvider: codeProvider, + tokenRequestor: tokenRequestor, + } +} + +// Request initiates a TOTP token request if none is in progress, returning nil if a request +// is already active. The returned channel delivers the token result once the code is +// collected and exchanged, or an error if the process times out or fails. +func (r *SingularTokenRequestor) Request() <-chan TotpTokenResult { + if lockObtained := r.isRequesting.TryLock(); !lockObtained { + //outstanding request don't do anything + return nil + } + + tokenCh := make(chan TotpTokenResult) + codeCh := r.codeProvider.GetTotpCode() + + go func() { + defer r.isRequesting.Unlock() + + select { + case codeResult := <-codeCh: + if codeResult.Err != nil { + tokenCh <- TotpTokenResult{ + Token: "", + Err: fmt.Errorf("error getting totp code: %v", codeResult.Err), + } + return + } + code := strings.TrimSpace(codeResult.Code) + + if code == "" { + tokenCh <- TotpTokenResult{ + Token: "", + Err: errors.New("empty totp code entered"), + } + return + } + + select { + case tokenResult := <-r.tokenRequestor.RequestTotpToken(code): + tokenCh <- tokenResult + case <-time.After(totpTokenRequestorTimeout): + tokenCh <- TotpTokenResult{ + Token: "", + Err: errors.New("timed out waiting for totp token"), + } + return + } + + return + case <-time.After(totpCodeProviderTimeout): + tokenCh <- TotpTokenResult{ + Token: "", + Err: errors.New("timed out waiting for totp code"), + } + return + } + }() + + return tokenCh +} diff --git a/ziti/ziti.go b/ziti/ziti.go index ca237936..3f8e3fdd 100644 --- a/ziti/ziti.go +++ b/ziti/ziti.go @@ -23,6 +23,7 @@ import ( "math" "math/rand" "net" + "net/http" "net/url" "reflect" "slices" @@ -44,6 +45,7 @@ import ( "github.com/openziti/foundation/v2/stringz" apis "github.com/openziti/sdk-golang/edge-apis" "github.com/openziti/sdk-golang/xgress" + "github.com/openziti/sdk-golang/ziti/edge/posture" "github.com/openziti/secretstream/kx" "github.com/zitadel/oidc/v3/pkg/oidc" @@ -76,6 +78,11 @@ const ( SessionDial = rest_model.DialBindDial SessionBind = rest_model.DialBindBind + + EdgeClientTotpAuthEndpoint = "/edge/client/v1/authenticate/mfa" + EdgeClientTotpTokenEndpoint = "/edge/client/v1/current-api-session/totp-token" + MaxTotpCodeLength = 6 + MinTotpCodeLength = 6 ) // MfaCodeResponse is a handler used to return a string (TOTP) code @@ -195,13 +202,15 @@ type ContextImpl struct { sessions cmap.ConcurrentMap[string, *rest_model.SessionDetail] // svcID:type -> Session intercepts cmap.ConcurrentMap[string, *edge.InterceptV1Config] + activeDials cmap.ConcurrentMap[string, *rest_model.ServiceDetail] + activeBinds cmap.ConcurrentMap[string, *rest_model.ServiceDetail] + metrics metrics.Registry firstAuthOnce sync.Once - closed atomic.Bool - closeNotify chan struct{} - authQueryHandlers map[string]func(query *rest_model.AuthQueryDetail, response MfaCodeResponse) error + closed atomic.Bool + closeNotify chan struct{} events.EventEmmiter authAttemptLock sync.Mutex @@ -215,6 +224,107 @@ type ContextImpl struct { xgressEnv xgress.Env } +func (context *ContextImpl) GetActiveDialServices() []*rest_model.ServiceDetail { + var result []*rest_model.ServiceDetail + + services := map[string]struct{}{} + context.services.IterCb(func(id string, svc *rest_model.ServiceDetail) { + services[*svc.ID] = struct{}{} + }) + + var toRemove []string + context.activeDials.IterCb(func(id string, svc *rest_model.ServiceDetail) { + if _, ok := services[id]; !ok { + toRemove = append(toRemove, id) + } else { + result = append(result, svc) + } + }) + + for _, toRemoveId := range toRemove { + context.activeDials.Remove(toRemoveId) + } + + return result +} + +func (context *ContextImpl) GetActiveBindServices() []*rest_model.ServiceDetail { + var result []*rest_model.ServiceDetail + + services := map[string]struct{}{} + context.services.IterCb(func(id string, svc *rest_model.ServiceDetail) { + services[*svc.ID] = struct{}{} + }) + + var toRemove []string + context.activeBinds.IterCb(func(id string, svc *rest_model.ServiceDetail) { + if _, ok := services[id]; !ok { + toRemove = append(toRemove, id) + } else { + result = append(result, svc) + } + }) + + for _, toRemoveId := range toRemove { + context.activeBinds.Remove(toRemoveId) + } + + return result +} + +func (context *ContextImpl) addActiveDialService(svc *rest_model.ServiceDetail) { + context.activeDials.Set(*svc.ID, svc) + context.CtrlClt.PostureCache.Evaluate() +} + +func (context *ContextImpl) addActiveBindService(svc *rest_model.ServiceDetail) { + context.activeBinds.Set(*svc.ID, svc) + context.CtrlClt.PostureCache.Evaluate() +} + +func (context *ContextImpl) GetTotpCode() <-chan posture.TotpCodeResult { + totpCodeResultChan := make(chan posture.TotpCodeResult) + + if context.ListenerCount(EventMfaTotpCode) == 0 { + totpCodeResultChan <- posture.TotpCodeResult{ + Code: "", + Err: errors.New("no MFA TOTP code providers have been added via zitiContext.Events().AddMfaTotpCodeListener()"), + } + + return totpCodeResultChan + } + + provider := rest_model.MfaProvidersZiti + authQuery := &rest_model.AuthQueryDetail{ + TypeID: rest_model.AuthQueryTypeMFA, + Format: rest_model.MfaFormatsAlphaNumeric, + HTTPMethod: http.MethodPost, + HTTPURL: EdgeClientTotpTokenEndpoint, + MaxLength: MaxTotpCodeLength, + MinLength: MinTotpCodeLength, + Provider: &provider, + } + + context.Emit(EventMfaTotpCode, authQuery, MfaCodeResponse(func(code string) error { + totpCodeResultChan <- posture.TotpCodeResult{ + Code: code, + } + return nil + })) + + return totpCodeResultChan +} + +func (context *ContextImpl) GetRouterConnections() []edge.RouterConn { + var result []edge.RouterConn + + for tuple := range context.routerConnections.IterBuffered() { + result = append(result, tuple.Val) + } + + return result +} + func (context *ContextImpl) AddServiceAddedListener(handler func(Context, *rest_model.ServiceDetail)) func() { listener := func(args ...interface{}) { details, ok := args[0].(*rest_model.ServiceDetail) @@ -557,8 +667,6 @@ func (context *ContextImpl) processServiceUpdates(services []*rest_model.Service for _, s := range services { context.processServiceAddOrUpdated(s) } - - context.refreshServiceQueryMap() } func (context *ContextImpl) processSingleServiceUpdate(name string, s *rest_model.ServiceDetail) { @@ -584,8 +692,6 @@ func (context *ContextImpl) processSingleServiceUpdate(name string, s *rest_mode // Adds and Updates context.processServiceAddOrUpdated(s) } - - context.refreshServiceQueryMap() } func (context *ContextImpl) processServiceAddOrUpdated(s *rest_model.ServiceDetail) { @@ -637,26 +743,6 @@ func (context *ContextImpl) processServiceAddOrUpdated(s *rest_model.ServiceDeta } } -func (context *ContextImpl) refreshServiceQueryMap() { - serviceQueryMap := map[string]map[string]rest_model.PostureQuery{} //serviceId -> queryId -> query - - context.services.IterCb(func(key string, svc *rest_model.ServiceDetail) { - for _, querySets := range svc.PostureQueries { - for _, query := range querySets.PostureQueries { - var queryMap map[string]rest_model.PostureQuery - var ok bool - if queryMap, ok = serviceQueryMap[*svc.ID]; !ok { - queryMap = map[string]rest_model.PostureQuery{} - serviceQueryMap[*svc.ID] = queryMap - } - queryMap[*query.ID] = *query - } - } - }) - - context.CtrlClt.PostureCache.SetServiceQueryMap(serviceQueryMap) -} - func (context *ContextImpl) refreshSessions() { log := pfxlog.Logger() edgeRouters := make(map[string]string) @@ -1146,7 +1232,12 @@ func (context *ContextImpl) onFullAuth(apiSession apis.ApiSession) error { } func (context *ContextImpl) AddZitiMfaHandler(handler func(query *rest_model.AuthQueryDetail, response MfaCodeResponse) error) { - context.authQueryHandlers[string(rest_model.MfaProvidersZiti)] = handler + context.AddMfaTotpCodeListener(func(context Context, detail *rest_model.AuthQueryDetail, response MfaCodeResponse) { + err := handler(detail, response) + if err != nil { + pfxlog.Logger().WithError(err).Error("error while handling TOTP MFA handler added through AddZitiMfaHandler") + } + }) } func (context *ContextImpl) authenticateMfa(code string) error { @@ -1160,6 +1251,18 @@ func (context *ContextImpl) authenticateMfa(code string) error { return err } + if newApiSession.GetType() == apis.ApiSessionTypeOidc { + totpToken, err := context.CtrlClt.CreateTotpToken(code) + + if err != nil { + pfxlog.Logger().WithError(err).Error("error while creating totp token after authenticate") + } + + if totpToken != nil { + context.CtrlClt.PostureCache.SetTotpToken(totpToken) + } + } + updateErr := context.updateTokenOnAllErs(newApiSession) if updateErr != nil { @@ -1183,16 +1286,13 @@ func (context *ContextImpl) handleAuthQuery(authQuery *rest_model.AuthQueryDetai } if *authQuery.Provider == rest_model.MfaProvidersZiti { - handler := context.authQueryHandlers[string(rest_model.MfaProvidersZiti)] - - context.Emit(EventMfaTotpCode, authQuery, MfaCodeResponse(context.authenticateMfa)) - if handler == nil { - pfxlog.Logger().Debugf("no callback handler registered for provider: %v, event will still be emitted", *authQuery.Provider) - } else { - return handler(authQuery, context.authenticateMfa) + if context.ListenerCount(EventMfaTotpCode) == 0 { + return errors.New("no MFA TOTP code providers have been added via zitiContext.Events().AddMfaTotpCodeListener()") } + context.Emit(EventMfaTotpCode, authQuery, MfaCodeResponse(context.authenticateMfa)) + return nil } @@ -1225,7 +1325,7 @@ func (context *ContextImpl) DialWithOptions(serviceName string, options *DialOpt return nil, fmt.Errorf("service '%s' not found", serviceName) } - context.CtrlClt.PostureCache.AddActiveService(*svc.ID) + context.addActiveDialService(svc) edgeDialOptions.CallerId = context.CtrlClt.GetCurrentApiSession().GetIdentityName() @@ -1372,6 +1472,8 @@ func (context *ContextImpl) ListenWithOptions(serviceName string, options *Liste } func (context *ContextImpl) listenSession(service *rest_model.ServiceDetail, options *ListenOptions) (edge.Listener, error) { + context.addActiveBindService(service) + edgeListenOptions := edge.NewListenOptions() edgeListenOptions.Cost = options.Cost edgeListenOptions.Precedence = edge.Precedence(options.Precedence) @@ -1395,11 +1497,20 @@ func (context *ContextImpl) listenSession(service *rest_model.ServiceDetail, opt edgeListenOptions.SdkFlowControl = (options.SdkFlowControl != nil && *options.SdkFlowControl) || context.maxDefaultConnections > 1 - if listenerMgr, err := newListenerManager(service, context, edgeListenOptions, options.WaitForNEstablishedListeners); err != nil { + listenerMgr, err := newListenerManager(service, context, edgeListenOptions, options.WaitForNEstablishedListeners) + if err != nil { return nil, err - } else { - return listenerMgr.listener, nil } + + if listenerMgr == nil { + return nil, errors.New("failed to create listener, manager is nil") + } + + if listenerMgr.listener == nil { + return nil, errors.New("failed to create listener, listener is nil") + } + + return listenerMgr.listener, nil } func (context *ContextImpl) getEdgeRouterConn(session *rest_model.SessionDetail, options edge.ConnOptions) (edge.RouterConn, error) { @@ -1655,6 +1766,15 @@ func (context *ContextImpl) connectEdgeRouter(routerName, ingressUrl string) *ed return newV }) + apiSession := context.CtrlClt.GetCurrentApiSession() + if useConn.GetBoolHeader(edge.SupportsPostureChecksHeader) && apiSession != nil && apiSession.GetType() == apis.ApiSessionTypeOidc { + err = context.CtrlClt.PostureCache.InitializePostureOnEdgeRouter(useConn) + + if err != nil { + pfxlog.Logger().Errorf("unable to initialize posture on edge router %s: %v", ingressUrl, err) + } + } + if useConn == edgeConn { context.Emit(EventRouterConnected, edgeConn.GetRouterName(), edgeConn.Key()) } @@ -1730,7 +1850,6 @@ func (context *ContextImpl) getOrCreateSession(serviceId string, sessionType Ses } } - context.CtrlClt.PostureCache.AddActiveService(serviceId) session, err := context.CtrlClt.CreateSession(serviceId, sessionType) if err != nil { @@ -1778,7 +1897,6 @@ func (context *ContextImpl) createSessionWithBackoff(service *rest_model.Service } if session != nil { - context.CtrlClt.PostureCache.AddActiveService(*service.ID) context.cacheSession("create", session) } diff --git a/ziti/ziti_test.go b/ziti/ziti_test.go index 5b6f18e5..e768a33c 100644 --- a/ziti/ziti_test.go +++ b/ziti/ziti_test.go @@ -2,13 +2,14 @@ package ziti import ( "fmt" + "testing" + "github.com/kataras/go-events" "github.com/openziti/edge-api/rest_model" "github.com/openziti/sdk-golang/ziti/edge" "github.com/openziti/sdk-golang/ziti/edge/posture" cmap "github.com/orcaman/concurrent-map/v2" "github.com/stretchr/testify/assert" - "testing" ) func ToPtr[T any](s T) *T { @@ -30,15 +31,16 @@ func Test_contextImpl_processServiceUpdates(t *testing.T) { options: &Options{ OnServiceUpdate: servUpdate, }, - services: cmap.New[*rest_model.ServiceDetail](), - sessions: cmap.New[*rest_model.SessionDetail](), - intercepts: cmap.New[*edge.InterceptV1Config](), - CtrlClt: &CtrlClient{ - PostureCache: posture.NewCache(nil, closeNotify), - }, + services: cmap.New[*rest_model.ServiceDetail](), + sessions: cmap.New[*rest_model.SessionDetail](), + intercepts: cmap.New[*edge.InterceptV1Config](), EventEmmiter: events.New(), } + ctx.CtrlClt = &CtrlClient{ + PostureCache: posture.NewCache(ctx, nil, nil, closeNotify), + } + var services []*rest_model.ServiceDetail for i := 0; i < 5; i++ { @@ -177,15 +179,16 @@ func Test_AddressMatch(t *testing.T) { } ctx := &ContextImpl{ - options: &Options{}, - services: cmap.New[*rest_model.ServiceDetail](), - sessions: cmap.New[*rest_model.SessionDetail](), - intercepts: cmap.New[*edge.InterceptV1Config](), - CtrlClt: &CtrlClient{ - PostureCache: posture.NewCache(nil, nil), - }, + options: &Options{}, + services: cmap.New[*rest_model.ServiceDetail](), + sessions: cmap.New[*rest_model.SessionDetail](), + intercepts: cmap.New[*edge.InterceptV1Config](), EventEmmiter: events.New(), } + + ctx.CtrlClt = &CtrlClient{ + PostureCache: posture.NewCache(ctx, nil, nil, nil), + } ctx.processServiceUpdates(services) type args struct {