From e739136a1903d1fa0ee639ec3c034395dd32c5ab Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Fri, 5 Dec 2025 00:08:28 +1000 Subject: [PATCH 01/11] Support ADFS which gives the OIDC claims in the access token. --- .github/workflows/musl.yaml | 8 ++-- api/authenticators/claims.go | 8 +++- api/authenticators/oidc.go | 39 ++++++++++++++++--- docs/references/server.config.yaml | 19 +++++---- .../notebooks/notebook-cell-renderer.jsx | 3 +- .../notebooks/notebook-navigator.css | 6 ++- 6 files changed, 60 insertions(+), 23 deletions(-) diff --git a/.github/workflows/musl.yaml b/.github/workflows/musl.yaml index 74032fcc094..dfb8c338fa2 100644 --- a/.github/workflows/musl.yaml +++ b/.github/workflows/musl.yaml @@ -1,9 +1,9 @@ # Only trigger when a PR is committed. name: Linux Build Musl Static -#on: [pull_request] -on: - pull_request: - types: [closed] +on: [pull_request] +#on: +# pull_request: +# types: [closed] jobs: build: diff --git a/api/authenticators/claims.go b/api/authenticators/claims.go index 28f07eaa70b..c0de66ad77d 100644 --- a/api/authenticators/claims.go +++ b/api/authenticators/claims.go @@ -43,6 +43,12 @@ func (self *OidcAuthenticator) NewClaims( return nil, err } + return self.newClaimsFromDict(ctx, claims) +} + +func (self *OidcAuthenticator) newClaimsFromDict( + ctx context.Context, claims *ordereddict.Dict) (*Claims, error) { + if self.authenticator.OidcDebug { logging.GetLogger(self.config_obj, &logging.GUIComponent). Debug("OidcAuthenticator: Parsing claims from OIDC Claims: %#v", claims) @@ -89,7 +95,7 @@ func (self *OidcAuthenticator) NewClaims( logger := logging.GetLogger(self.config_obj, &logging.GUIComponent) // First check the user exist at all. - _, err = user_manager.GetUser(ctx, email, email) + _, err := user_manager.GetUser(ctx, email, email) if utils.IsNotFound(err) { // If the user does not exist at all, create it. user_record := &api_proto.VelociraptorUser{ diff --git a/api/authenticators/oidc.go b/api/authenticators/oidc.go index 28745d17f36..8552624ccaa 100644 --- a/api/authenticators/oidc.go +++ b/api/authenticators/oidc.go @@ -2,16 +2,20 @@ package authenticators import ( "context" + "encoding/base64" "net/http" "strings" + "github.com/Velocidex/ordereddict" oidc "github.com/coreos/go-oidc/v3/oidc" "github.com/sirupsen/logrus" "golang.org/x/oauth2" "www.velocidex.com/golang/velociraptor/acls" api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/json" "www.velocidex.com/golang/velociraptor/logging" + utils "www.velocidex.com/golang/velociraptor/utils" ) type OIDCConnector interface { @@ -172,6 +176,27 @@ func (self *OidcAuthenticator) oauthOidcLogin( }) } +func (self *OidcAuthenticator) maybeGetClaimsFromToken( + ctx context.Context, token *oauth2.Token) (*Claims, error) { + data, err := base64.StdEncoding.DecodeString(token.AccessToken) + if err != nil { + return nil, utils.InvalidArgError + } + + if self.authenticator.OidcDebug { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Debug("OidcAuthenticator: Getting claims from access token: %s", data) + } + + claims := ordereddict.NewDict() + err = json.Unmarshal(data, claims) + if err != nil { + return nil, err + } + + return self.newClaimsFromDict(ctx, claims) +} + func (self *OidcAuthenticator) oauthOidcCallback( provider *oidc.Provider) http.Handler { return api_utils.HandlerFunc(nil, @@ -229,11 +254,15 @@ func (self *OidcAuthenticator) oauthOidcCallback( // Map the OIDC claims to our own claims. claims, err := self.NewClaims(ctx, userInfo) if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("oauthOidcCallback: Unable to parse claims: %v", err) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return + new_claims, err1 := self.maybeGetClaimsFromToken(ctx, oauthToken) + if err1 != nil { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Error("oauthOidcCallback: Unable to parse claims: %v", err) + http.Redirect(w, r, api_utils.Homepage(self.config_obj), + http.StatusTemporaryRedirect) + return + } + claims = new_claims } cookie, err := getSignedJWTTokenCookie( diff --git a/docs/references/server.config.yaml b/docs/references/server.config.yaml index 819537d32db..5700df13c3d 100644 --- a/docs/references/server.config.yaml +++ b/docs/references/server.config.yaml @@ -183,19 +183,18 @@ Client: ## from different orgs have different nonce. nonce: rKNKAYam310= - ## The following are the locations to write the writeback file- this - ## file is used to keep client state (See Writeback section). In the - ## default configuration, writeback files persist across - ## uninstall/reinstall cycles to keep the client id consistent. If - ## you don't want this you can change the location of the writeback - ## to be inside the inside the tempdir_windows directory (it will be - ## removed on uninstall). + ## The following are the locations to write the writeback file - + ## this file is used to keep client state. In the default + ## configuration, writeback files persist across uninstall/reinstall + ## cycles to keep the client id consistent. If you don't want this + ## you can change the location of the writeback to be inside the + ## tempdir_windows directory (it will be removed on uninstall). writeback_darwin: /etc/velociraptor.writeback.yaml writeback_linux: /tmp/velociraptor.writeback.yaml - ## From 0.7.0-3: On Windows if the writeback path starts with HKLM\ - ## the path will be interpreted as a registry key that will be used - ## to store the writeback instead of files on disk. + ## On Windows, if the writeback path starts with HKLM\ the path will + ## be interpreted as a registry key that will be used to store the + ## writeback instead of files on disk. writeback_windows: $ProgramFiles\Velociraptor\velociraptor.writeback.yaml # If this value is specified, Velociraptor will create a level 2 diff --git a/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.jsx b/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.jsx index 50928fe981e..0d555d12d4a 100644 --- a/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.jsx +++ b/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.jsx @@ -1035,8 +1035,7 @@ export default class NotebookCellRenderer extends React.Component { ); return ( -
+
{ this.state.showAddCellFromHunt && { diff --git a/gui/velociraptor/src/components/notebooks/notebook-navigator.css b/gui/velociraptor/src/components/notebooks/notebook-navigator.css index b77250c1edc..0a8d9ccdc74 100644 --- a/gui/velociraptor/src/components/notebooks/notebook-navigator.css +++ b/gui/velociraptor/src/components/notebooks/notebook-navigator.css @@ -4,7 +4,7 @@ div.notebook_nav { height: -webkit-fill-available; overflow-y: auto; margin-bottom: 50px; - margin-left: -10px; + margin-left: -5px; } div.notebook_nav.uncollapsed { @@ -13,6 +13,10 @@ div.notebook_nav.uncollapsed { background: var(--color-sidebar-background); } +div.notebook_nav.collapsed { + width: 34px; +} + div.notebook_nav.collapsed .notebook-outline { display: none; } From 0eb0f281b54389c053609c1d9d1274bd22a11050 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Fri, 5 Dec 2025 00:11:29 +1000 Subject: [PATCH 02/11] Build it now --- .github/workflows/musl.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/musl.yaml b/.github/workflows/musl.yaml index dfb8c338fa2..5974bb80dd6 100644 --- a/.github/workflows/musl.yaml +++ b/.github/workflows/musl.yaml @@ -7,7 +7,7 @@ on: [pull_request] jobs: build: - if: github.event.pull_request.merged + #if: github.event.pull_request.merged name: Build runs-on: ubuntu-latest steps: From 5caf6bcf219e214b5d3eb4abc80b424776d1a671 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Fri, 5 Dec 2025 00:23:25 +1000 Subject: [PATCH 03/11] Improve error handling. --- api/authenticators/claims.go | 24 ++++++++++++++++++ api/authenticators/oidc.go | 48 ++++++++++++++---------------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/api/authenticators/claims.go b/api/authenticators/claims.go index c0de66ad77d..1ccf882de70 100644 --- a/api/authenticators/claims.go +++ b/api/authenticators/claims.go @@ -2,14 +2,17 @@ package authenticators import ( "context" + "encoding/base64" "errors" "fmt" "time" "github.com/Velocidex/ordereddict" oidc "github.com/coreos/go-oidc/v3/oidc" + "golang.org/x/oauth2" acl_proto "www.velocidex.com/golang/velociraptor/acls/proto" api_proto "www.velocidex.com/golang/velociraptor/api/proto" + "www.velocidex.com/golang/velociraptor/json" "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/services" "www.velocidex.com/golang/velociraptor/utils" @@ -35,6 +38,27 @@ func (self *Claims) Valid() error { return nil } +func (self *OidcAuthenticator) maybeGetClaimsFromToken( + ctx context.Context, token *oauth2.Token) (*Claims, error) { + data, err := base64.StdEncoding.DecodeString(token.AccessToken) + if err != nil { + return nil, utils.InvalidArgError + } + + if self.authenticator.OidcDebug { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Debug("OidcAuthenticator: Getting claims from access token: %s", data) + } + + claims := ordereddict.NewDict() + err = json.Unmarshal(data, claims) + if err != nil { + return nil, utils.InvalidArgError + } + + return self.newClaimsFromDict(ctx, claims) +} + func (self *OidcAuthenticator) NewClaims( ctx context.Context, user_info *oidc.UserInfo) (*Claims, error) { claims := ordereddict.NewDict() diff --git a/api/authenticators/oidc.go b/api/authenticators/oidc.go index 8552624ccaa..1bb54a1425e 100644 --- a/api/authenticators/oidc.go +++ b/api/authenticators/oidc.go @@ -2,18 +2,15 @@ package authenticators import ( "context" - "encoding/base64" "net/http" "strings" - "github.com/Velocidex/ordereddict" oidc "github.com/coreos/go-oidc/v3/oidc" "github.com/sirupsen/logrus" "golang.org/x/oauth2" "www.velocidex.com/golang/velociraptor/acls" api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" - "www.velocidex.com/golang/velociraptor/json" "www.velocidex.com/golang/velociraptor/logging" utils "www.velocidex.com/golang/velociraptor/utils" ) @@ -176,27 +173,6 @@ func (self *OidcAuthenticator) oauthOidcLogin( }) } -func (self *OidcAuthenticator) maybeGetClaimsFromToken( - ctx context.Context, token *oauth2.Token) (*Claims, error) { - data, err := base64.StdEncoding.DecodeString(token.AccessToken) - if err != nil { - return nil, utils.InvalidArgError - } - - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("OidcAuthenticator: Getting claims from access token: %s", data) - } - - claims := ordereddict.NewDict() - err = json.Unmarshal(data, claims) - if err != nil { - return nil, err - } - - return self.newClaimsFromDict(ctx, claims) -} - func (self *OidcAuthenticator) oauthOidcCallback( provider *oidc.Provider) http.Handler { return api_utils.HandlerFunc(nil, @@ -254,15 +230,29 @@ func (self *OidcAuthenticator) oauthOidcCallback( // Map the OIDC claims to our own claims. claims, err := self.NewClaims(ctx, userInfo) if err != nil { + // Try to get the claims from the AccessToken. ADFS + // passes user info in the token instead of the user + // info endpoint (https://stackoverflow.com/questions/45058571/adfs-4-0-userinfo-endpoint-returns-only-sub-claim) new_claims, err1 := self.maybeGetClaimsFromToken(ctx, oauthToken) - if err1 != nil { + if err1 == nil { + // Fallback method worked! Lets use it. + claims = new_claims + + // No claims in AccessToken - report original error + } else if err1 == utils.InvalidArgError { logging.GetLogger(self.config_obj, &logging.GUIComponent). Error("oauthOidcCallback: Unable to parse claims: %v", err) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return + + // Failed to parse the AccessToken claims, report both errors. + } else { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Error("oauthOidcCallback: Unable to parse claims: %v, "+ + "and then parsing AccessToken: %v", err1) } - claims = new_claims + + http.Redirect(w, r, api_utils.Homepage(self.config_obj), + http.StatusTemporaryRedirect) + return } cookie, err := getSignedJWTTokenCookie( From 721de92f6df042a6d08bbcbd5a36a710302524db Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Fri, 5 Dec 2025 07:24:27 +1000 Subject: [PATCH 04/11] Adding debugging messages --- api/authenticators/claims.go | 5 +++++ api/authenticators/oidc.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/api/authenticators/claims.go b/api/authenticators/claims.go index 1ccf882de70..b5cc229dc5b 100644 --- a/api/authenticators/claims.go +++ b/api/authenticators/claims.go @@ -40,6 +40,11 @@ func (self *Claims) Valid() error { func (self *OidcAuthenticator) maybeGetClaimsFromToken( ctx context.Context, token *oauth2.Token) (*Claims, error) { + if self.authenticator.OidcDebug { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Debug("OidcAuthenticator: Will try to get claims from token: %#v", token) + } + data, err := base64.StdEncoding.DecodeString(token.AccessToken) if err != nil { return nil, utils.InvalidArgError diff --git a/api/authenticators/oidc.go b/api/authenticators/oidc.go index 1bb54a1425e..d7184a63165 100644 --- a/api/authenticators/oidc.go +++ b/api/authenticators/oidc.go @@ -247,7 +247,7 @@ func (self *OidcAuthenticator) oauthOidcCallback( } else { logging.GetLogger(self.config_obj, &logging.GUIComponent). Error("oauthOidcCallback: Unable to parse claims: %v, "+ - "and then parsing AccessToken: %v", err1) + "and then parsing AccessToken: %v", err, err1) } http.Redirect(w, r, api_utils.Homepage(self.config_obj), From e4cb401e4d22535561146eaf0feb6be145609238 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Tue, 9 Dec 2025 12:15:45 +1000 Subject: [PATCH 05/11] Major refactoring of oidc authenticators. This allows better testing and better visibility of oauth interactions. 1. The OidcDebug flag now enables full network inspection to see what the server has sent. 2. Tests can include relayed responses to ensure we have full support to what the IDP provides. Combined with 1 we can get quick feedback for unusualy IDP transactions in future so we can support non-compliant IDPs better. 3. Removed the oidc-cognito authenticator because the upstream library now support cognito natively. 4. Refactored all oauth style authenticators to use the same oidc authenticator. This makes code simpler and more consistent. It also adds logging and debugging to other non-oidc authenticators like github and google. --- api/authenticators/auth.go | 134 +- api/authenticators/azure.go | 186 +- api/authenticators/claims.go | 145 +- api/authenticators/claims_test.go | 226 ++ api/authenticators/common.go | 113 - .../fixtures/TestProvider.golden | 80 + api/authenticators/github.go | 202 +- api/authenticators/google.go | 350 +-- api/authenticators/http.go | 92 +- api/authenticators/logoff.go | 45 + api/authenticators/multiple.go | 39 +- api/authenticators/oidc.go | 253 +- api/authenticators/oidc_cognito.go | 176 -- api/authenticators/orgs.go | 3 +- api/authenticators/provider.go | 152 ++ api/authenticators/router.go | 76 + api/authenticators/verify.go | 231 ++ config/proto/config.pb.go | 2285 +++++++++-------- config/proto/config.proto | 6 + 19 files changed, 2486 insertions(+), 2308 deletions(-) create mode 100644 api/authenticators/claims_test.go create mode 100644 api/authenticators/fixtures/TestProvider.golden create mode 100644 api/authenticators/logoff.go delete mode 100644 api/authenticators/oidc_cognito.go create mode 100644 api/authenticators/provider.go create mode 100644 api/authenticators/router.go create mode 100644 api/authenticators/verify.go diff --git a/api/authenticators/auth.go b/api/authenticators/auth.go index 6c5f1fec745..88c0cacbdd0 100644 --- a/api/authenticators/auth.go +++ b/api/authenticators/auth.go @@ -1,6 +1,7 @@ package authenticators import ( + "context" "crypto/x509" "errors" "fmt" @@ -16,9 +17,13 @@ import ( var ( mu sync.Mutex + // Factory dispatcher auth_dispatcher = make(map[string]func( + ctx *HTTPClientContext, config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error)) + + auth_cache Authenticator ) // All SSO Authenticators implement this interface. @@ -44,11 +49,35 @@ func NewAuthenticator(config_obj *config_proto.Config) (Authenticator, error) { return nil, errors.New("GUI not configured") } - return getAuthenticatorByType(config_obj, config_obj.GUI.Authenticator) + mu.Lock() + cached := auth_cache + mu.Unlock() + + if cached != nil { + return cached, nil + } + + ctx, err := ClientContext(context.Background(), config_obj, + DefaultTransforms(config_obj, config_obj.GUI.Authenticator)) + if err != nil { + return nil, err + } + + new_auth, err := getAuthenticatorByType( + ctx, config_obj, config_obj.GUI.Authenticator) + if err == nil { + mu.Lock() + auth_cache = new_auth + mu.Unlock() + } + + return new_auth, err } func RegisterAuthenticator(name string, - handler func(config_obj *config_proto.Config, + handler func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error)) { mu.Lock() defer mu.Unlock() @@ -57,14 +86,19 @@ func RegisterAuthenticator(name string, } func getAuthenticatorByType( + ctx *HTTPClientContext, config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { mu.Lock() - handler, pres := auth_dispatcher[strings.ToLower(auth_config.Type)] + key := strings.ToLower(auth_config.Type) + handler, pres := auth_dispatcher[key] mu.Unlock() if pres { - return handler(config_obj, auth_config) + // Make sure the dispatcher lock is unlocked during call to + // handler - the multi authenticator needs to access the + // other types. + return handler(ctx, config_obj, auth_config) } return nil, errors.New("No valid authenticator found") } @@ -79,55 +113,89 @@ func configRequirePublicUrl(config_obj *config_proto.Config) error { } func init() { - RegisterAuthenticator("azure", func(config_obj *config_proto.Config, + RegisterAuthenticator("azure", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { err := configRequirePublicUrl(config_obj) if err != nil { return nil, err } - return &AzureAuthenticator{ + router := &AzureOidcRouter{ config_obj: config_obj, authenticator: auth_config, - }, nil + } + claims_getter := &AzureClaimsGetter{ + config_obj: config_obj, + router: router, + } + return NewOidcAuthenticator( + config_obj, auth_config, router, claims_getter), nil }) - RegisterAuthenticator("github", func(config_obj *config_proto.Config, + RegisterAuthenticator("github", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { err := configRequirePublicUrl(config_obj) if err != nil { return nil, err } - return &GitHubAuthenticator{ - config_obj: config_obj, - authenticator: auth_config, - }, nil + + router := &GithubOidcRouter{ + config_obj: config_obj, + } + claims_getter := &GithubClaimsGetter{ + config_obj: config_obj, + } + return NewOidcAuthenticator( + config_obj, auth_config, router, claims_getter), nil }) - RegisterAuthenticator("google", func(config_obj *config_proto.Config, + // This is now basically an alias for a generic OIDC connector + // since Google is pretty good about following the standards. + RegisterAuthenticator("google", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { err := configRequirePublicUrl(config_obj) if err != nil { return nil, err } - return &GoogleAuthenticator{ - config_obj: config_obj, - authenticator: auth_config, - }, nil + + router := &GoogleOidcRouter{ + config_obj: config_obj, + } + + claims_getter, err := NewOidcClaimsGetter( + ctx, config_obj, auth_config, router) + if err != nil { + return nil, err + } + + return NewOidcAuthenticator( + config_obj, auth_config, router, claims_getter), nil }) - RegisterAuthenticator("saml", func(config_obj *config_proto.Config, + RegisterAuthenticator("saml", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { return NewSamlAuthenticator(config_obj, auth_config) }) - RegisterAuthenticator("basic", func(config_obj *config_proto.Config, + RegisterAuthenticator("basic", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { return &BasicAuthenticator{ config_obj: config_obj, }, nil }) - RegisterAuthenticator("certs", func(config_obj *config_proto.Config, + RegisterAuthenticator("certs", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { if config_obj.GUI == nil || config_obj.GUI.UsePlainHttp { return nil, errors.New("'Certs' authenticator must use TLS!") @@ -146,20 +214,34 @@ func init() { return result, nil }) - RegisterAuthenticator("oidc", func(config_obj *config_proto.Config, + RegisterAuthenticator("oidc", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { err := configRequirePublicUrl(config_obj) if err != nil { return nil, err } - return &OidcAuthenticator{ - config_obj: config_obj, + + router := &DefaultOidcRouter{ authenticator: auth_config, - }, nil + config_obj: config_obj, + } + + claims_getter, err := NewOidcClaimsGetter( + ctx, config_obj, auth_config, router) + if err != nil { + return nil, err + } + + return NewOidcAuthenticator( + config_obj, auth_config, router, claims_getter), nil }) - RegisterAuthenticator("multi", func(config_obj *config_proto.Config, + RegisterAuthenticator("multi", func( + ctx *HTTPClientContext, + config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { - return NewMultiAuthenticator(config_obj, auth_config) + return NewMultiAuthenticator(ctx, config_obj, auth_config) }) } diff --git a/api/authenticators/azure.go b/api/authenticators/azure.go index d8c8cdd010a..4f9cfffa062 100644 --- a/api/authenticators/azure.go +++ b/api/authenticators/azure.go @@ -18,188 +18,90 @@ along with this program. If not, see . package authenticators import ( - "context" "encoding/base64" "fmt" "net/http" - "github.com/sirupsen/logrus" "golang.org/x/oauth2" "golang.org/x/oauth2/microsoft" - "www.velocidex.com/golang/velociraptor/acls" api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/constants" "www.velocidex.com/golang/velociraptor/json" - "www.velocidex.com/golang/velociraptor/logging" utils "www.velocidex.com/golang/velociraptor/utils" ) +const ( + AzureIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TpUWqDnYQcchQxcEuKiJOtQpFqBBqhVYdTC79giYNSYuLo+BacPBjserg4qyrg6sgCH6AuAtOii5S4v+SQosYD4778e7e4+4dIDTKTLO6YoCmV81UIi5msqti4BUhBNGHWYzJzDLmJCkJz/F1Dx9f76I8y/vcn6NXzVkM8InEMWaYVeIN4unNqsF5nzjMirJKfE48btIFiR+5rrj8xrngsMAzw2Y6NU8cJhYLHax0MCuaGvEUcUTVdMoXMi6rnLc4a+Uaa92TvzCU01eWuU5zGAksYgkSRCiooYQyqojSqpNiIUX7cQ//kOOXyKWQqwRGjgVUoEF2/OB/8LtbKz854SaF4kD3i21/jACBXaBZt+3vY9tungD+Z+BKb/srDWDmk/R6W4scAf3bwMV1W1P2gMsdYPDJkE3Zkfw0hXweeD+jb8oCA7dAz5rbW2sfpw9AmrpK3gAHh8BogbLXPd4d7Ozt3zOt/n4A6eJy1kar81QAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfpDAgOOyNpkJZEAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAACbxJREFUaN7tWltsFNcZ/s45s7u2WWwcg20uAXNJSxMCbRNIQhI1LSlV2rSqWrUF5SUvfcpLlYe+t5GivrbqS9WLGiWRmiqqIiQIEJMACaGAsU1siPEVY6/Xu971eu+XmTmnD7uzczuzuybYCJXRvOyxd/b/zv/93385Q4QQuJ8vivv8egDgXl/KV/y+zkUmX9QFhN/X+LcIIYQSAjQR0kTvHYBUtvDPY//95MpYWtf0vbux73GwBswRUBTmY5QA2/301xsD+4LKvQHw71NXX3/7oq6VoKsYvoXWduzaUdt0ABACKqByCCDPRwr8vd3BDh9Z7RjI5EtvnxzSQUAYCIMODF6DVJRF9RaVfzBXcK6gDyXVexDEw6OzfZEMCAUt3wr6vkQu52m3EJWP3LaoCXwYK+lidQEI4Mzl0RwHCAGhIBSUoaBjYtI0HXa7q2DgXPxPRo8U+aoCiC1lP+yfLQsKKAVloBRMQf8wdC6zG5JFVBbHNX51SV1VANcnwxfmMyDE9ABhoAomQ0gkpFSRgOEmqU4l1BJfLQCazs8P3ILOAQIQIwwYKEO2hKkZL6rI/SAAIU6ktXBRXyUAiXT++NXbxvYTACCs4gTCcHMcmuqiSi0KAZgq8YE70qI7AfDlrejlcBqEGB4goNVI8GHsNlIZF1VkFDJ1SUCI3lhJFSsPQAh81j8FgYrpFSdQUFbhUrqA2ZDNPnjYbXfL+aR2B1q0bADJbOH4pSnD7nL6NEK57ATmx/URM0Dl1BcuhGJY48OLpRUHMDwauhLLm+RxOKF835hCOiNRGy8PcAEhhBCno4Xlsmh5ALgQH12eUAUMu1FBAgJqyWiqwMSEY4O9PVDWK0Dg3aQ2n9NWEEA0kT02OOcij4GEGE5gCoZGoHEpVSxInMEd1cWlxZJYOQBD4/OD8byLPMQMgwoGBbNRJBalVKmd2o5HiyoXKwJA0/mZ/mlU+VMlD0HlIyEmgIKO6RkvqtSI79Mp7XZOXxEAC8nciWtzht2QeYCAWpwwNglVq5F9ZalNzKm8L15cEQDDE9HheM5ptwNJtbpmCqbnkUrZTOQ1SyMhyuVTb7RYbJhFtHH9Odt/S8CoHUA8kNBKWUEZChpCIXsr45XabEXHhaQ21zCLGgUQT+Z7B0K2LTca9IoKmVwqV6YMig8jY+C8Uf4Y6yMqvxYr3mUAQ2PhK0slJ1ukYUCIUVYoZCrcms16UcUFxsTTGy40yKKGAOhc9F6ZEsKSthxZzFaZVuOY7e9s/ePX2r2oUkOX/rKkhjPaXQMwH8+8fy1qp4ori1nZRSstzpFDe5/ZFKTE0SJb8MhdAU0Xn0eL4m4BGByPjGWKFvIQT/KYLQ6Dohz89iOb1yhHg0r97syxyMUH4UKxgVa/PgBV56f7ZyCM7acOW60xbcVGD/V07Hp4fYtCvrfe79mdwSO+gbMpdSqt3QUA4cXsyRtRG3lMJHA6wWQXO/zEtnXBJgo82eHfTEm9xtLph5gqLkULdwHAF+OR8WTRXvDYuWT1ieGBJr/y3N6tjFIAO9b6DrYweRXEPfVUCNEbLuTqsagOAI2LM/0z3JZu4SyBQNw+eW7j2q/3dJYfElTI9zcEiAdVaqS2i0l1ph6L6gBYWMqdu7HgWTg4s1hVhcjhb27qWNtUfc7zXU3riMVE7pjSyUN5UuWDkfxXAnBtdH4grTamPAa7QNZQeujJ7dbn7GxVXgwqponu6Z2HnvaGCoWaLKK19af3yrSldpBmMRe7CNnfHdyzs9P6KB8lr2xpriWdHqntb4ul2ZR6hwDCscw7N+IWQ6VZzMUu4Ojz232MOZ62r7OplcLUU6/pL3e2OJ/N5cUdABBA32gkktMt88PGspjCDjy2hbjG/Z0t7FfrfKZ93Mtup8i+P5svaGLZBxyqxk/0z1WoUiZrWW0gIAgAUAp/s1mWGj+xp70pnGf5iZS5FUJAcMH11lIBghqLcHzRPFuw/+nzpDq2VNq7PrA8ADOxTO/YosENYcAwVBRAWxeCD0n6HuDlf82aDhAcugqtgFKeB3TsfxRMkdjtjWdJw4W5/OPrA2RZFBoYi85kVXv9bC0cCITnFI0DevUmRAfVCdMpE5kSMjnv2Zb8VEEIfBzKZ1S+jBgo6fzM4ByHK2StjXw6hswi6h/0GyMjqoAwLCSkB021Sm4hLi6p0x6jXzmAyGLu07GEc8utikkIBJBaQCZeH0OlQ6BQ/IgkoHPJ6QF3HUBZRsIhTQzM5ZYBYGA0cj2rVQaGUqmpNsfpOFILdTBUe2WqIKcik63X4kh09tTtXE7jDQEoavyjvpC8WnbXDgCyCSQj4Lwmi4xOn/oQicmqIO/RCwQE3o2r04lSQwDmYpm/3lySZV/vlVwKyQjAazmhPG5RfFhYgqpJqWLLD6566fztnKgLQACXRqJFlRsNrnvoIPdJi55763DHgVbFm0WswqIiRzrjueWeoxfx3nQu69IiJ4CSqh/rn7eXBg008iA/3tH20wMb//FKzwsdfjmLqs0+URBLSA6aPClU+dif0kZc4xYngKlo5tx0ymPLCUC9Sonv7ukONimPblnz5yPbfrIx4MEiY16USEPVXKcH9hbHpUspnX8642SRE0Df6MJ8Qa+IT+3S37LSHVCe+kY3JYQAj21q+dPRnle3NsvFlFAwBQUNtnlRzRbH0CXBcXYmn7QfQ9kAFFT+8RdR7lV4Onoxy8rTm9fu2tRWfc62jqY/HOl5decaZ0lnPVGOJ9xnlXWmFcDFpdLUYtETwFw8e/5WCoTKTpAgI0+FUT/8VnewyRa+XW3+N3++9bXda+UsYj7Ek9B1eQpztDgWXVrQRN9M1hNA/83oRF63Tz+9hg5mTLcQ8p19m9yc39jm//3Ptv7uiXWujEZBFZQ4Mpm6g153i3NiKpe1HOpTC3/0kwMR2+BW0shLkLy8a9327lapeLa3KK//aMsbT7UHqEuLmA8LcduWo6GD8Q/ipQmLFpkA0tnS3yfTMtNRs4nBL57e4vN+USsYYL/5weY3n+2o/Iv1HC2dA+ceKcw7tQE3LZ2++cMKozubFVBjziNF4mJXV7Nv364NtWu5YIC99uLmtw53GXMXQ4v8zZU2o4FSAhb5bPZTCYC2YOCNl7Z3+hktv5FXvSsdJTEu4yMl7T762xe2busM1p2OBRTyy4Nd77zUtS3AKKWEMvj82NRlM13WEpDybcSin+BoV+DZHaY2EOubu6rOr04ujoXSOhe27khI3n0jhPR0BQ88sr7Zzxo9JuRiaDZ3PZQtlFRdYcLHTNPhaizLG8yo32fq20Mt7JmH12xoYXIA9+P14M3dBwD+3wH8D1fWkeojxAXbAAAAAElFTkSuQmCC" +) + type AzureUser struct { Mail string `json:"userPrincipalName"` Name string `json:"displayName"` Picture string `json:"picture"` } -type AzureAuthenticator struct { +type AzureOidcRouter struct { config_obj *config_proto.Config authenticator *config_proto.Authenticator } -// The URL that will be used to log in. -func (self *AzureAuthenticator) LoginURL() string { - return "/auth/azure/login" +func (self *AzureOidcRouter) Name() string { + return "Azure" } -func (self *AzureAuthenticator) IsPasswordLess() bool { - return true +func (self *AzureOidcRouter) LoginHandler() string { + return "/auth/azure/login" } -func (self *AzureAuthenticator) RequireClientCerts() bool { - return false +func (self *AzureOidcRouter) CallbackHandler() string { + return "/auth/azure/callback" } -func (self *AzureAuthenticator) AuthRedirectTemplate() string { - return self.authenticator.AuthRedirectTemplate +func (self *AzureOidcRouter) Scopes() []string { + return []string{"User.Read"} } -func (self *AzureAuthenticator) AddHandlers(mux *api_utils.ServeMux) error { - mux.Handle(api_utils.GetBasePath(self.config_obj, self.LoginURL()), - IpFilter(self.config_obj, self.oauthAzureLogin())) - - mux.Handle(api_utils.GetBasePath(self.config_obj, "/auth/azure/callback"), - IpFilter(self.config_obj, self.oauthAzureCallback())) - - return nil +func (self *AzureOidcRouter) Issuer() string { + return "" } -func (self *AzureAuthenticator) AddLogoff(mux *api_utils.ServeMux) error { - installLogoff(self.config_obj, mux) - return nil +func (self *AzureOidcRouter) Endpoint() oauth2.Endpoint { + return microsoft.AzureADEndpoint(self.authenticator.Tenant) } -// Check that the user is proerly authenticated. -func (self *AzureAuthenticator) AuthenticateUserHandler( - parent http.Handler, - permission acls.ACL_PERMISSION, -) http.Handler { - - return authenticateUserHandle( - self.config_obj, permission, - func(w http.ResponseWriter, r *http.Request, err error, username string) { - reject_with_username(self.config_obj, w, r, err, username, - self.LoginURL(), "Microsoft O365/Azure AD") - }, - parent) -} +func (self *AzureOidcRouter) SetEndpoint(oauth2.Endpoint) {} -func (self *AzureAuthenticator) GetGenOauthConfig() (*oauth2.Config, error) { - return &oauth2.Config{ - RedirectURL: api_utils.GetPublicURL(self.config_obj, "/auth/azure/callback"), - ClientID: self.authenticator.OauthClientId, - ClientSecret: self.authenticator.OauthClientSecret, - Scopes: []string{"User.Read"}, - Endpoint: microsoft.AzureADEndpoint(self.authenticator.Tenant), - }, nil +func (self *AzureOidcRouter) Avatar() string { + return AzureIcon } -func (self *AzureAuthenticator) oauthAzureLogin() http.Handler { - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - azureOauthConfig, _ := self.GetGenOauthConfig() - - // Create oauthState cookie - oauthState, err := r.Cookie("oauthstate") - if err != nil { - oauthState = generateStateOauthCookie(self.config_obj, w) - } - - u := azureOauthConfig.AuthCodeURL(oauthState.Value) - http.Redirect(w, r, u, http.StatusTemporaryRedirect) - }) +func (self *AzureOidcRouter) LoginURL() string { + return api_utils.PublicURL(self.config_obj, self.LoginHandler()) } -func (self *AzureAuthenticator) oauthAzureCallback() http.Handler { - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - // Read oauthState from Cookie - oauthState, _ := r.Cookie("oauthstate") - - if oauthState == nil || r.FormValue("state") != oauthState.Value { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid oauth azure state") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - ctx, err := ClientContext(r.Context(), self.config_obj) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid client context of OIDC: %v", err) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - user_info, err := self.getUserDataFromAzure(ctx, r.FormValue("code")) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromAzure") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - // Create a new token object, specifying signing method and the claims - // you would like it to contain. - cookie, err := getSignedJWTTokenCookie( - self.config_obj, self.authenticator, - &Claims{ - Username: user_info.Mail, - }, r) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromAzure") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - http.SetCookie(w, cookie) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - }) +type AzureClaimsGetter struct { + config_obj *config_proto.Config + router OidcRouter } -func (self *AzureAuthenticator) getUserDataFromAzure( - ctx context.Context, code string) (*AzureUser, error) { +func (self *AzureClaimsGetter) GetClaims( + ctx *HTTPClientContext, token *oauth2.Token) (claims *Claims, err error) { - // Use code to get token and get user info from Azure. - azureOauthConfig, err := self.GetGenOauthConfig() - if err != nil { - return nil, err + oauthConfig := &oauth2.Config{ + Endpoint: self.router.Endpoint(), } - token, err := azureOauthConfig.Exchange(ctx, code) + client := oauthConfig.Client(ctx, token) + response, err := client.Get("https://graph.microsoft.com/v1.0/me/") if err != nil { - return nil, fmt.Errorf("code exchange wrong: %s", err.Error()) - } - - response, err := azureOauthConfig.Client(ctx, token).Get( - "https://graph.microsoft.com/v1.0/me/") - if err != nil { - return nil, fmt.Errorf("failed getting user info: %s", err.Error()) + return nil, fmt.Errorf("failed getting user info: %v", err) } defer response.Body.Close() contents, err := utils.ReadAllWithLimit(response.Body, constants.MAX_MEMORY) if err != nil { - return nil, fmt.Errorf("failed read response: %s", err.Error()) + return nil, fmt.Errorf("failed read response: %v", err) } user_info := &AzureUser{} @@ -210,24 +112,20 @@ func (self *AzureAuthenticator) getUserDataFromAzure( username := user_info.Mail if username != "" { - setUserPicture(ctx, username, self.getAzurePicture(ctx, token)) + picture := self.getAzurePicture(client) + if picture != "" { + setUserPicture(ctx, username, picture) + } } - user_info.Picture = "" // Server will fill it from the user record anyway. - - return user_info, nil + return &Claims{ + Username: user_info.Mail, + }, nil } // Best effort - if anything fails we just dont show the picture. -func (self *AzureAuthenticator) getAzurePicture( - ctx context.Context, token *oauth2.Token) string { - azureOauthConfig, err := self.GetGenOauthConfig() - if err != nil { - return "" - } - - response, err := azureOauthConfig.Client(ctx, token).Get( - "https://graph.microsoft.com/v1.0/me/photos/48x48/$value") +func (self *AzureClaimsGetter) getAzurePicture(client *http.Client) string { + response, err := client.Get("https://graph.microsoft.com/v1.0/me/photos/48x48/$value") if err != nil { return "" } diff --git a/api/authenticators/claims.go b/api/authenticators/claims.go index b5cc229dc5b..87cc827dd72 100644 --- a/api/authenticators/claims.go +++ b/api/authenticators/claims.go @@ -2,17 +2,17 @@ package authenticators import ( "context" - "encoding/base64" "errors" "fmt" "time" "github.com/Velocidex/ordereddict" oidc "github.com/coreos/go-oidc/v3/oidc" + jwt "github.com/golang-jwt/jwt/v4" "golang.org/x/oauth2" acl_proto "www.velocidex.com/golang/velociraptor/acls/proto" api_proto "www.velocidex.com/golang/velociraptor/api/proto" - "www.velocidex.com/golang/velociraptor/json" + config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/services" "www.velocidex.com/golang/velociraptor/utils" @@ -38,50 +38,131 @@ func (self *Claims) Valid() error { return nil } -func (self *OidcAuthenticator) maybeGetClaimsFromToken( - ctx context.Context, token *oauth2.Token) (*Claims, error) { - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("OidcAuthenticator: Will try to get claims from token: %#v", token) +// A ClaimsGetter is responsible for fetching a claim from the oauth +// server. Depending on the server type the claims are encoded +// differently or fetched from different locations using different +// methods. +type ClaimsGetter interface { + GetClaims(ctx *HTTPClientContext, token *oauth2.Token) (*Claims, error) +} + +// The ClaimsGetter for standard OIDC endpoints. This fetches the +// claims from: +// 1. The standard OIDC UserInfo endpoint +// 2. Attempts to decode the claim from the AccessToken if it is a JWT. +// This behaviour was observed on ADFS. +type OidcClaimsGetter struct { + config_obj *config_proto.Config + authenticator *config_proto.Authenticator + router OidcRouter + + provider *oidc.Provider +} + +func NewOidcClaimsGetter( + ctx *HTTPClientContext, + config_obj *config_proto.Config, + authenticator *config_proto.Authenticator, + router OidcRouter) (*OidcClaimsGetter, error) { + + delegate, err := oidc.NewProvider(ctx, router.Issuer()) + if err != nil { + return nil, err } + router.SetEndpoint(delegate.Endpoint()) + + return &OidcClaimsGetter{ + config_obj: config_obj, + authenticator: authenticator, + router: router, + provider: delegate, + }, nil +} + +func (self *OidcClaimsGetter) maybeGetClaimsFromToken( + ctx context.Context, token *oauth2.Token) (*ordereddict.Dict, error) { + + // The token came from the ADFS server and will be used again to + // get the UserInfo so it must be valid. We do not need to check + // its signature. + claims := jwt.MapClaims{} + _, _, err := jwt.NewParser().ParseUnverified(token.AccessToken, claims) + if err != nil { + return nil, err + } + res := ordereddict.NewDict() + for k, v := range claims { + res.Set(k, v) + } + return res, nil +} - data, err := base64.StdEncoding.DecodeString(token.AccessToken) +func (self *OidcClaimsGetter) UserInfo( + ctx context.Context, + token *oauth2.Token) (*oidc.UserInfo, error) { + user_info, err := self.provider.UserInfo( + ctx, oauth2.StaticTokenSource(token)) if err != nil { - return nil, utils.InvalidArgError + return nil, err } + return user_info, err +} +func (self *OidcClaimsGetter) Debug(message string, args ...interface{}) { if self.authenticator.OidcDebug { logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("OidcAuthenticator: Getting claims from access token: %s", data) + Debug(message, args...) } +} - claims := ordereddict.NewDict() - err = json.Unmarshal(data, claims) +func (self *OidcClaimsGetter) GetClaims( + ctx *HTTPClientContext, token *oauth2.Token) (claims *Claims, err error) { + + claims_dict, err := self.getClaims(ctx, token) if err != nil { - return nil, utils.InvalidArgError + self.Debug("Unable to parse claims from user info: %v", err) + + // Fallsback to try to get the claims from the token + token_claims_dict, err1 := self.maybeGetClaimsFromToken(ctx, token) + if err1 != nil { + return nil, err + } + self.Debug("Unwrapped claims from AccessToken: %v", token_claims_dict) + claims_dict = token_claims_dict } - return self.newClaimsFromDict(ctx, claims) + return self.newClaimsFromDict(ctx, self.config_obj, claims_dict) } -func (self *OidcAuthenticator) NewClaims( - ctx context.Context, user_info *oidc.UserInfo) (*Claims, error) { - claims := ordereddict.NewDict() - err := user_info.Claims(&claims) +func (self *OidcClaimsGetter) getClaims( + ctx context.Context, token *oauth2.Token) (claims *ordereddict.Dict, err error) { + + user_info, err := self.UserInfo(ctx, token) + if err != nil { + return nil, fmt.Errorf("can not get UserInfo from OIDC provider: %v", err) + } + + // Make sure the user's email is verified because this is what we + // use as the identity. + if !user_info.EmailVerified && + (self.authenticator.Claims == nil || + !self.authenticator.Claims.AllowUnverifiedEmail) { + return nil, fmt.Errorf("Email %v is not verified", user_info.Email) + } + + claims = ordereddict.NewDict() + err = user_info.Claims(&claims) if err != nil { return nil, err } - return self.newClaimsFromDict(ctx, claims) + return claims, nil } -func (self *OidcAuthenticator) newClaimsFromDict( - ctx context.Context, claims *ordereddict.Dict) (*Claims, error) { - - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("OidcAuthenticator: Parsing claims from OIDC Claims: %#v", claims) - } +func (self *OidcClaimsGetter) newClaimsFromDict( + ctx context.Context, + config_obj *config_proto.Config, + claims *ordereddict.Dict) (*Claims, error) { username_field := "email" roles_field := "" @@ -89,6 +170,7 @@ func (self *OidcAuthenticator) newClaimsFromDict( if self.authenticator.Claims != nil { if self.authenticator.Claims.Username != "" { username_field = self.authenticator.Claims.Username + self.Debug("Using field %v in claims for username", username_field) } if self.authenticator.Claims.Roles != "" { @@ -121,7 +203,7 @@ func (self *OidcAuthenticator) newClaimsFromDict( user_manager := services.GetUserManager() - logger := logging.GetLogger(self.config_obj, &logging.GUIComponent) + logger := logging.GetLogger(config_obj, &logging.GUIComponent) // First check the user exist at all. _, err := user_manager.GetUser(ctx, email, email) @@ -131,7 +213,7 @@ func (self *OidcAuthenticator) newClaimsFromDict( Name: email, } - err = services.LogAudit(ctx, self.config_obj, email, + err = services.LogAudit(ctx, config_obj, email, "Create User From OIDC Roles", ordereddict.NewDict().Set("Claims", claims)) if err != nil { @@ -172,10 +254,7 @@ func (self *OidcAuthenticator) newClaimsFromDict( for _, oidc_role := range roles { acl_spec, pres := self.authenticator.Claims.RoleMap[oidc_role] if !pres { - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("No allowed claim role map for OIDC claim %#v", oidc_role) - } + self.Debug("No allowed claim role map for OIDC claim %#v", oidc_role) continue } @@ -196,7 +275,7 @@ func (self *OidcAuthenticator) newClaimsFromDict( // Only set the roles if we need to - note we can only // ever add roles to the existing roles. if len(new_roles) > len(existing_acls.Roles) { - err = services.LogAudit(ctx, self.config_obj, email, + err = services.LogAudit(ctx, config_obj, email, "Grant User Role From OIDC Claim", ordereddict.NewDict(). Set("Roles", new_roles). diff --git a/api/authenticators/claims_test.go b/api/authenticators/claims_test.go new file mode 100644 index 00000000000..72de23dbb57 --- /dev/null +++ b/api/authenticators/claims_test.go @@ -0,0 +1,226 @@ +package authenticators + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + "testing" + + "github.com/Velocidex/ordereddict" + "www.velocidex.com/golang/velociraptor/config" + config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/json" + "www.velocidex.com/golang/velociraptor/vtesting/assert" + "www.velocidex.com/golang/velociraptor/vtesting/goldie" +) + +type StaticURLReplayer struct { + name string + err_regex string + responses map[string]string + URLs []string + + authenticator *config_proto.Authenticator +} + +func (self *StaticURLReplayer) GetRoundTrip(rt RoundTripFunc) RoundTripFunc { + return func(req *http.Request) (*http.Response, error) { + resp, pres := self.responses[req.URL.String()] + if !pres { + fmt.Printf("Unknown request: %v\n", req.URL.String()) + } + + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewReader([]byte(resp))), + }, nil + } +} + +var ( + testUrlReplayerCases = []StaticURLReplayer{ + StaticURLReplayer{ + name: "Typical Flow", + responses: map[string]string{ + // These are the responses for a typical oidc flow: + + // 1. First the provider queries the well known config endpoint. + `https://www.example.com/.well-known/openid-configuration`: ` +{"issuer": "https://www.example.com", + "authorization_endpoint": "https://www.example.com/o/oauth2/v2/auth", + "token_endpoint": "https://www.example.com/token", + "userinfo_endpoint": "https://www.example.com/v1/userinfo" +} +`, + // 2. Next we get the token + "https://www.example.com/token": ` +{"access_token": "This is an access token", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer", + "id_token": "XXXX" +} +`, + // 3. Finally we fetch the user info endpoint. + "https://www.example.com/v1/userinfo": ` +{"sub": "100439259231459671911", + "email": "user@example.com", + "email_verified": true +} +`, + }, + }, + + StaticURLReplayer{ + // AWS Cognito does not follow the spec and encode + // email_verified as a string. We used to have special + // handling for it but it seems now the upstream library + // transparently fixed support. We test is anyway. + name: "AWS congnito", + responses: map[string]string{ + // These are the responses for a typical oidc flow: + + // 1. First the provider queries the well known config endpoint. + `https://www.example.com/.well-known/openid-configuration`: ` +{"issuer": "https://www.example.com", + "authorization_endpoint": "https://www.example.com/o/oauth2/v2/auth", + "token_endpoint": "https://www.example.com/token", + "userinfo_endpoint": "https://www.example.com/v1/userinfo" +} +`, + // 2. Next we get the token + "https://www.example.com/token": ` +{"access_token": "This is an access token", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer", + "id_token": "XXXX" +} +`, + // 3. Finally we fetch the user info endpoint. + "https://www.example.com/v1/userinfo": ` +{"sub": "100439259231459671911", + "email": "user@example.com", + "email_verified": "true" +} +`, + }, + }, + + StaticURLReplayer{ + // ADFS seems to encode the user info in the AccessToken + // itself and returns a useless response to the UserInfo + // endpoint. We support this behavior implicitly. + name: "MS ADFS", + responses: map[string]string{ + `https://www.example.com/.well-known/openid-configuration`: ` +{"issuer": "https://www.example.com", + "authorization_endpoint": "https://www.example.com/o/oauth2/v2/auth", + "token_endpoint": "https://www.example.com/token", + "userinfo_endpoint": "https://www.example.com/v1/userinfo" +} +`, + // access_token contains a JWT with the email claim. + "https://www.example.com/token": ` +{"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBpZCI6IngxMjMiLCJlbWFpbCI6Im5vb25lQG5vd2hlcmUuY29tIiwiZXhwIjoxNzY0OTM3NDgzLCJzY3AiOiJlbWFpbCBvcGVuaWQifQ.3AjZi1Cxpbvscxh6HrDQ9iHOwom6G9RP-iRhv3vHLBo", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer", + "id_token": "XXXX" +}`, + + // ADFS sends a minimal userinfo because most of the + // claims are encoded in the token. + "https://www.example.com/v1/userinfo": ` +{"sub": "100439259231459671911"}`, + }, + }, + + StaticURLReplayer{ + name: "Email is not verified", + err_regex: "Email .+ is not verified", + responses: map[string]string{ + `https://www.example.com/.well-known/openid-configuration`: ` +{"issuer": "https://www.example.com", + "authorization_endpoint": "https://www.example.com/o/oauth2/v2/auth", + "token_endpoint": "https://www.example.com/token", + "userinfo_endpoint": "https://www.example.com/v1/userinfo" +} +`, + "https://www.example.com/token": ` +{"access_token": "This is an access token", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer", + "id_token": "XXXX" +} +`, + "https://www.example.com/v1/userinfo": ` +{"sub": "100439259231459671911", + "email": "user@example.com", + "email_verified": false +} +`, + }, + }, + } +) + +type TestRouter struct { + DefaultOidcRouter +} + +func (self *TestRouter) Issuer() string { + return "https://www.example.com" +} + +func TestProvider(t *testing.T) { + config_obj := config.GetDefaultConfig() + golden := ordereddict.NewDict() + + for _, tc := range testUrlReplayerCases { + g := ordereddict.NewDict() + golden.Set(tc.name, g) + + authenticator := tc.authenticator + if authenticator == nil { + authenticator = &config_proto.Authenticator{ + Type: "oidc", + OauthClientId: "ClientIdXXXX", + OauthClientSecret: "ClientSecrect1234", + OidcIssuer: "https://www.example.com", + } + } + + ctx, err := ClientContext( + context.Background(), config_obj, + []Transformer{tc.GetRoundTrip}) + assert.NoError(t, err) + + auther, err := getAuthenticatorByType(ctx, config_obj, authenticator) + assert.NoError(t, err) + + oidc_auther, ok := auther.(*OidcAuthenticator) + assert.True(t, ok) + + provider, err := oidc_auther.Provider() + assert.NoError(t, err) + + // See the redirect URL. + redirect := provider.GetRedirectURL(nil, "StateString") + g.Set("Redirect URL", redirect) + + cookie, claims, err := provider.GetJWT(ctx, "code") + if tc.err_regex != "" { + assert.Regexp(t, tc.err_regex, err.Error()) + continue + } + assert.NoError(t, err) + g.Set("Cookie", cookie) + g.Set("Claims", claims) + } + + goldie.Assert(t, "TestProvider", json.MustMarshalIndent(golden)) +} diff --git a/api/authenticators/common.go b/api/authenticators/common.go index 5b243c42811..6d81e3b3534 100644 --- a/api/authenticators/common.go +++ b/api/authenticators/common.go @@ -1,114 +1 @@ package authenticators - -import ( - "errors" - "fmt" - "net/http" - "time" - - "github.com/Velocidex/ordereddict" - jwt "github.com/golang-jwt/jwt/v4" - utils "www.velocidex.com/golang/velociraptor/api/utils" - config_proto "www.velocidex.com/golang/velociraptor/config/proto" - "www.velocidex.com/golang/velociraptor/logging" - "www.velocidex.com/golang/velociraptor/services" -) - -var ( - reauthError = errors.New(`Authentication cookie not found, invalid or expired. -You probably need to re-authenticate in a new tab or refresh this page.`) -) - -func getSignedJWTTokenCookie( - config_obj *config_proto.Config, - authenticator *config_proto.Authenticator, - claims *Claims, - r *http.Request) (*http.Cookie, error) { - if config_obj.Frontend == nil { - return nil, errors.New("config has no Frontend") - } - - expiry_min := authenticator.DefaultSessionExpiryMin - if expiry_min == 0 { - expiry_min = 60 * 24 // 1 Day by default - } - - // We force expiry in the JWT **as well** as the session - // cookie. The JWT expiry is most important as the browser can - // replay session cookies past expiry. - expiry := time.Now().Add(time.Minute * time.Duration(expiry_min)) - - // Enforce the JWT to expire - claims.Expires = float64(expiry.Unix()) - - // Make a JWT and sign it. - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - if authenticator.OidcDebug { - logging.GetLogger(config_obj, &logging.GUIComponent). - Debug("getSignedJWTTokenCookie: Creating JWT with claims: %#v", claims) - } - - tokenString, err := token.SignedString([]byte(config_obj.Frontend.PrivateKey)) - if err != nil { - return nil, err - } - - // Log a successful login. - err = services.LogAudit(r.Context(), - config_obj, claims.Username, "Login", - ordereddict.NewDict(). - Set("remote", r.RemoteAddr). - Set("authenticator", authenticator.Type). - Set("url", r.URL.Path)) - if err != nil { - logger := logging.GetLogger(config_obj, &logging.FrontendComponent) - logger.Error("getSignedJWTTokenCookie LogAudit: Login %v %v", - claims.Username, r.RemoteAddr) - } - - // Sets the cookie on the browser so it is only valid from the - // base down. - return &http.Cookie{ - Name: "VelociraptorAuth", - Value: tokenString, - Path: utils.GetBaseDirectory(config_obj), - Secure: true, - HttpOnly: true, - Expires: expiry, - }, nil -} - -// Ensure the JWT is properly validated and contains all the required fields. -func getDetailsFromCookie( - config_obj *config_proto.Config, - r *http.Request) (*Claims, error) { - - claims := &Claims{} - - // We store the user name and their details in a local - // cookie. It is stored as a JWT so we can trust it. - auth_cookie, err := r.Cookie("VelociraptorAuth") - if err != nil { - return claims, reauthError - } - - // Parse the JWT. - token, err := jwt.ParseWithClaims(auth_cookie.Value, claims, - func(token *jwt.Token) (interface{}, error) { - _, ok := token.Method.(*jwt.SigningMethodHMAC) - if !ok { - return claims, errors.New("invalid signing method") - } - return []byte(config_obj.Frontend.PrivateKey), nil - }) - if err != nil { - return claims, fmt.Errorf("%w: %v", err, reauthError.Error()) - } - - claims, ok := token.Claims.(*Claims) - if ok && token.Valid { - return claims, nil - } - - return claims, reauthError -} diff --git a/api/authenticators/fixtures/TestProvider.golden b/api/authenticators/fixtures/TestProvider.golden new file mode 100644 index 00000000000..f2e33666530 --- /dev/null +++ b/api/authenticators/fixtures/TestProvider.golden @@ -0,0 +1,80 @@ +{ + "Typical Flow": { + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTMzMjg4MywidG9rZW4iOiIifQ.BIFTWv4-EdpbquR-q5pTWsorIuNi8XU2HPAl2P683Bc", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T02:14:43.535488646Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "user@example.com", + "picture": "", + "expires": 1765332883, + "token": "" + } + }, + "AWS congnito": { + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTMzMjg4MywidG9rZW4iOiIifQ.BIFTWv4-EdpbquR-q5pTWsorIuNi8XU2HPAl2P683Bc", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T02:14:43.535571883Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "user@example.com", + "picture": "", + "expires": 1765332883, + "token": "" + } + }, + "MS ADFS": { + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5vb25lQG5vd2hlcmUuY29tIiwicGljdHVyZSI6IiIsImV4cGlyZXMiOjE3NjUzMzI4ODMsInRva2VuIjoiIn0.DvvFEks85ou3bDb1G4xPyH9XK4HIfUJK3rozVGmJpYA", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T02:14:43.53585395Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "noone@nowhere.com", + "picture": "", + "expires": 1765332883, + "token": "" + } + }, + "Email is not verified": { + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString" + } +} \ No newline at end of file diff --git a/api/authenticators/github.go b/api/authenticators/github.go index ebc27cccf39..0348e90c365 100644 --- a/api/authenticators/github.go +++ b/api/authenticators/github.go @@ -18,207 +18,101 @@ along with this program. If not, see . package authenticators import ( - "context" "fmt" - "net/http" - "github.com/sirupsen/logrus" "golang.org/x/oauth2" "golang.org/x/oauth2/github" - "www.velocidex.com/golang/velociraptor/acls" api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/constants" "www.velocidex.com/golang/velociraptor/json" - "www.velocidex.com/golang/velociraptor/logging" utils "www.velocidex.com/golang/velociraptor/utils" ) -type GitHubUser struct { - Login string `json:"login"` - AvatarUrl string `json:"avatar_url"` +const ( + GithubIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAACXBIWXMAADddAAA3XQEZgEZdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABiOSURBVHgB7Z2/cxtHlsffG0BnytqqxdpeexWZqiXvSO+WCGWXCcw2s5ztRaKyyyRll4nMLpP0F4jKLhMZXiQou8xDl21qTboMZ7pbn01XnS3aBKavXxOwYRk/Zgbzo9/M91NFE6IJkQL62+9Hv36PCAAAAAAAAAAAAAAAAAAAAIBfwQRUsrbWXh40qGWYWmxoefR1M/Z4EszUk89RRCfcsB+GThoDOnn+POwRUAcE7CHLy+3WhUtOiG1DIlCzYYXZYvmzFSzZx5QHTCf27+7ZRyd2KwiJg2/tzw2DgHpHn4QhAe+AgEtGxNq4SB0OrGAjc53PRbtMfiIi7lkzfiDCvmA/YLnLBQIumNU/tUWgHbGq1tp1PBZrLOwC6hkRdsDP7OMuLHWxQMA5I7Fqv0E3xLraV7uTm/vrC+dueJcD3rexdRcWOl8g4BxY+XO7Q4PofSa+od3CLsq5hTZ71Aj2jz8OuwQyBQLOiJFobXy4VXkrmxJ28TN1TcCPIeZsgIAXwIk2iq7bl/EORJuMkZgbEe/AzU4PBJwQyRo3L9GWjWnft3/sEMiC0MbMD8++o71eLzwhEBsIOCYuexxFN+Ei54hNgNkFuQerHB8IeA7nsa25R7C2RdOlBu8gVp4NBDwFCNcPXKwc8I49X94l8Csg4FewrrLEt/fqfvzjGxDyZCDgIWJxeWAeQbh+AyH/ktoLGK6yTlyBSINv1T1Grq2AXYkjm0cE4aqGmXbrnLWunYDdOe7r0W0yvE2gOrDZ7n8fPKzbOXKDasQf19s3mhfME/tu3yBQMbjTuEB/ffOdy99+/fcXtbkRVQsLDHe5XtTJra68BV5dv3o7Cug/7MM1AnWhHTFtvfH7yz98/dWL/6IKU1kLDKsLhnSbhm9V1RpX0gL/49rVm4OA9ghWF9i8pWG6UdXYuFIW2GWYL0b33PU+AF4lMA/63wU7VcpUV0bAcluIIvMElVRgFlIA0jC8WRWXuhIutCSqrHB37cM/EACzaVUpwaVewCvrV+/bfXXbPlwiAOIha+Uvb7zzTuvrv//3f5Ji1LrQwyzzE/uwTQCkJ7RZ6g+0utQqBezGirB5ingXZIHmuDggZcjtoX5gPoR4QVbIWrLe3IdSakvKUBUDS7LKvtpSVYV4F2TNkrXEf7XJrW81JbfUCHhl7eo9Yv53AiBf/vLG2++QTW49IwWoEPBQvNsEQCFwR4uIvRewOyZi/jcCoFB0iNhrAa++t/HIvpD/SgCUAnfefPsPy1bE++Qp3gpYxGsMbREA5dL2WcReCnhYXQXLC3zBWxF7J+BhwgoxL/CNto8xsVcCRrYZ+I1/iS1vBAzxAh34JWIvBCwdNAzzAwJABdx5663Lvf/96sUBlUzplxnOx3aaDwkAXZxwwJtHn4Sltukp9TKD3CqSLhoEgD5asnbdGi6R0iyw9K+6cBG3ioBu5Cri2Uu+VlafrdIscPN1TAIE+pE13Lzo2heXQilJLJdxRqEGqA5rZWWmC3ehh+M8nxIAVaPBm0WPOy1UwGiFAyrOSdPwtSJb8zSpQIajTpapTNim/w3/lHAwbFo2kGkR0MfwvTT2s30PT1imMJBZpvJoDdf4JhVEYRbYj0or7h4fhr96cd1EhyVq21dDPq6zMW14CZ7hRMqhFeozK9jwgqFwkqVbWbMhGpcdovFdu84KKUwqRMDDFrBfUMnY3frW0fNwN873SoFJFNFWQOZ9iLkkxMIS75mIHvdPKYx7VLOyviEC7lCZFBQP5y5gn857+y/5d2nO687HttAd626/D3e7CLjLAT0++4720rxfK+vtOzY4uk8lUtT5cO4CHt7t9WDYGO9bt2ahtqFuM1qiG9aU34NVzhhrbY3hx2xo7/j5YpZruW1Doh/MN1Q2gXlw/MlHdylHchWwT0dGSdznOKyutbcg5AyQ2Dbih9ZFfpCltfLCjRZydqVzrcTiQXkVKq/SIOpShshmcHR4cEU2BnGXCCTjPCm10/+er1iLu525q2nYi+t+ogHx3CgnchOwZJ29sU48OWOZBRBycph5txnxtVyE+zNd8gBXavk65RZC5uJC+5J1HmGIH35+GBYSh9tjjG0b+9xGsmsS3LWvy86iMW4cXBz8o12DnrwPTcNX8jAiuRRy9AObATTkE10qCLEqdgPbHTBtGzI3KSPscUpPzj/tjntiX9ovXeFCYB8PqMcNOmkMyFmy01M6mWXVxJ1bWqLWoEEt+1y3uO3zl41xHy1metctejbtzBa/HAdFfDfLHMQ8emF4svLeRo88mV6ZV4FH5hbYHrlsmcif2FfggK+VcfFahmXZc+T7sUMJiQutUO2bEloxHdjn9aYVLBSBy7pfomV7Hr7M7ISwIV8mY2KLQryfwUvaLuO6nX39HzBZb8gT7GvxgfUE9yhDshfw+sYXvmVmjw8PSu084txqm7F+9etiVe1/uvZDEi5h2d0d4vJT5Vpgs7yGrk+y1pIPsMdCt4pwl6fhw3nwOHmcDWfqQnuVuBph3U4qmZFb3Q/oibWsz4KAwrRFCj4w/L27NBaanLdGcsc2Url20C/J6o4jHkzpPaPGGEtobVNGZPbv8/em0eT6Z1B9fEumDjnpv+QrWW1umR0jDQI/ixps7NYjUEtOl8hHD6eV5bFSJgKWnc7XOUYuYwtqiWSiyUeMuZ1VM7xMBCzWlwDwEE+La1pZaWZhAftsfQHwFdFMFlZ4YQHD+gKQjjNePBZeSMCwvgCkh8ncXPSiw0IChvUFYCEWzkinFrDz340H9y3nYHCpoNZ4f1/bZqQXscKpBTxoUEfDZfaA6bcEaoncSCL/WcgKp3ehIx3us6H4hfegWlz4Tke3FDbpb62lErDcstHSSobhQteWqKljjYqWXPupFKQSMGd4zzVv5MXJs6UJ8JfhFUgdDNJ5tIkFPDx8vkGKaP5G0RsJssOYDdJDJ42hSSzgPusSryPyP1sOcoB1ve9pklmJBexTh4PYGHOdQK1YXW1n1xKoINIksxIJWObOKO2D3EEcXC9MU5/XlSaZlUjAHOhJXr3KhUsKXX+QHta5Vs0g2TpN5kIrqLyaivRuArXAFXAYnYnLpCc8sQWs2H12d0IbEe0QqAVykV8a7ZNOWknc6NgC1uo+O/Ea3iyrNSsoB9eD2rDKTTuJGx3fhVbqPkcDvgvx1hPpBkqejFhJQhI3OpaAJSWv0n1m3vn8s2wbaQNd9F/jDxTOrIrtRscSsLmgL4Mrb9rxp24HBjVG4mGjMR6OWXwUz4VWWAghcS8BQM6V7sqIF9JETM3NFfDwTmWHNGFdZ8S9YJzBa7StzJWOVXw0V8CNH3SJV96k/vf0gAAYQ1zpiPguKaJxcb724rjQHdKEPTrQOnMI5MtwMmCX9NCZ9w1zBcysJ/4V61vkDFqgEEVnw3G0N1PA6krSlB7cg+IYjjvtkgas9ubFwTMF3DzVI15YXxAbRRv9vGYUs13oQFH8C+sLYiJWWE1GerCIgBWd/zYUlsyB8jCGH5MOOrP+52wBq2kKxvs49wVJ6C/pOGpkmt3Xa6qAhwksFV0s2BDqnUEihrODu+Q587qqThWwpgTW2SkEDNLA+6SAWQUd011oPe5zF4UbIA1NJZ4bz7gJOFXAiq4PqthFgX9I3kRDNpqZpsbBUwU8L3j2hgaFBEBq+Bl5zqz5Xupd6OOPXWUNAOkI/E9kzZrvNV3AKjLQ3CUAFuFH/z24WZnoiQJ2Xe0VYP9hBwTAApxd0lGRtbRE8QVsGkrOf/X1OgKe4VrQKlhHZ1NC2okC5oaauao9AmBBNKyjIEhigY2S4d0NwvkvWBgm/pI8Z5ompwlYhQvd7MMCg8WJyH9DME2TwZQvqhDw6SksMFgcZv/XUcD024lfn/RFe3D8LikAJZQgE4wKC7w86euJB3wDUDU4UODJsYnvQrPSKYQAVBVOEgMDAHQwOQZmHUksAOqCoSQWWMkxEgBZoKTuoXoudJzZMQBUGdUCnlbgDUBdQBIL1B4tlYeTUC3gfhPHXWBxtFQeTkK1gM0ALjRYHC2Vh5NQLeBpV6wASITiY9PJAlZQ3C1oufYIvGeZ/GeiJieXUioo7haYSK3rAzxCQRKLkwhYC9YC/44AWAAt/d+mMa2UUokFVtK7GniLlv5vhrg36evTSil1xMBzBj8BMBc1I4QmM+U6of89gkZcuIREFkgPsw4vjnly+6iJAtbQI2gM1TsoKBctJxmRoW8nfX2yBVYSAwtRBAGDheiQAqZpcpqAe6QE6wJdJwBSsLLW7pASkrnQkSIX2lAbiSyQCkUJLJNEwBeMrpGdzd/AjQZp0OO9TSuumijg0yVd/ZbNgG4QAElhHfGvcPRJONGoThSwloFPIxAHg6S4+FfPPeCpBnVqKaWWaiwH4mCQELu+FXltPDWknSpgNqxq9m7zIm0RADEJyLxPSpg1BzuY8SRViSxS9IaAchH32SgaXjArnJ0l4B7porP6J903S0AxcGBukiYalNyFHrxGXVKGMchGgxgYPdlnof9/KQQsmWgtnTl+wpjbSGaBWVgvbUub+zxrCufsC/1GnRVuNV+nOwTANCJzjxRhaHYyeY6AdWWiBTbK4htQGNqsr4NnJ5PntdTpkjLkDZI3igB4FWXW1xHM1uBMAfeXtB0lnWMicx+xMBhHpfWl2QksYaaAh4ksjSJGLAx+iUbra7U3K4ElzO1KaQw/I43YjPTaWnuZQO1ZWbt6T6P1jaO9OG1lu6STVp/NIwK1xm3izNukk+68b5grYI0FHWN0VtbbcKVrzIDNU1LK4GUGAnZxsF4rbDH3UGJZT1bWr97X6Dqfw9158a8QbzKD1jj4nJZNYDxBVrperK5fvW1FoNn72o/zTXFHq3RJMbILNy+aJwRqgXhcRm/c6+AgnuaYYrLy3sY3ijoYTCYwD44/+egugcoiSSuJe/W6zuf1z0eHB1fifG/s4WY2pf2YtBPxnZX3ruo7DwSxqIJ4HczduN8aW8BsaI+qgOFtiLh6VEa8FhNQbGMZ24UWKuFGj4A7XRncKYNNVFZBvEncZyHRfOBKuNEjxJ1e3/gQ1Vq6+eN6+4Yx1bC8jgTus5BIwJVxo3+mLW4XRKwTKZFksqcLVfEKKZn7LCRyoYXV9Y0vKrPbjcNm+/jTj3YIeI9suMMy2Q5ViKTus5DIAguVcqPHkeTW+gassedIgUY/MB9SxcTrMJzYgCQWcH+JHlB16did/Qtkqf1j5c/tjmywhvhBlVzmcRopCqYSu9CCvJBUxR1wDNeLN+Cdo0/CXQKl4Y6HAnPPmKo37uf948MwcVfVxBbYkcLUa0PifBOZRxLzo0VP8YhwV9/beCQeUfXFS2J+U3m2qSywkO+ZMHdlnEQQ/NwNxETUElHZX3jD/qlDBTOyyI0BdZ8/D3sEckFcZRq47hkdqglpklcjmpSWiB/azG2msaL8QxqGN+cJxLlV8gbbn19URtz9HGuR+/aXtJZhNzK8//lhWLVjtVKQm2LN1yO5PXTDird+Vz8X8GhTW+Dltn3RfzRfZGqFmXeOPw23kzxldc26twUKeRxnlZm6JuDHxx+HXQKxcUdBDbphN0WZadWhmiJr6OwlX4tz93fK89OzstbeztgKd48PDzYpIbKZNH6gbXuof5vKQqZYGOpywHKPM5w2kLmuOCv7G2rTILKC5Y79EposkNgs3j36NLxFKVlIwM4K/2C+oSxZoKBCrLEJzH0fjhlkZ3UTHgN+Jt0FpT1o2l1WIy7MaVDHRNEGBDudpuEri+RUFhKwsLre3jWU8TSEBUTs+a0UscpWxCbkIDgwTD3NwharurRErTOmNgc2wWjMhs0Yt+2qWq7qWW2WLGp93d9BCzIsa/uCsiYwD/rfBTtpFrfSq2V7/Zd8S4OY5QIBSykjRLoQi1pfoUEL8tVXL07e/P1lSYFn6yIZ/ufGBfrr7y5f/vKb/3nxPMlT5Xd6+63L+9bCycG494tM3G37Zv7L8XH4ghTwzVcvnr/x5uWL9hfvEEiFWN/PDsOFy5IXtsBCblZ4CDPtNiLeSbpbud5Ixjz12lLY5Fcz4msaz5ZX3tuQm0CJq4dANtZXSFeJ9QruF8mxOksqcdJc+3OZ4IHnVWMm+cbkC/1/4FvuKA0kQqxvVu95JgIW3CWHHAeCSzybRsTHfwsfGOKH5CW8d3wYqr0cIj3DjeGFkjB1wxUrRZSZUclMwK4BfJSvUEYiTtrjefCanBH7ZymahtS39Dl+7gpYugRiYZgfZ+lxZSZgQaxw3kJJ0+PZR0uRpRtVOjW43JIFoo2klYbzyFTAIpSIuAir0ln509X7SZ7gLAX70xIoSzeqbGCFY5LDRpepgIVhgX+X8kaa0snNlQT4k3Th6t1oghWeA+8dPc/+bnnmAhaaBbmrPDCPksTDvrjSbJI1LtPA0MOpTaloUvLKd+Qi4LyPlUa4ePhSlOgyhVtoEZeaPGpU1N2sbL+0ReH8jgpzEbBQRELLkcKVlqOl8ly+CrrPP9Ml8AvySFyNk5uAC3VXB8mvNFpLvF2GiKXTCFUU5cPg8yHgDyhHchOwIO5qQUUUnTR9q0oScZcqimzaqMz6GVn7ed8Lz1XAQlFFFCYy99MM8R6KeLOohRcEVV/gqofBZ4asp8FL2qacyV3ABbrSrebrlGoiu3gKDSfivJMw3K16pw6540yAZD0VcTU0dwELhWV+jbmdxgoLklg6Ogy35JZIpkK2RytSdSVW/vgw3KSKwxBwrlnnX/0oKpBiGsLz3SwuCIw6X1qLcjNpG1u7AfQion0ZBtc/rVcrHXfZn5KVulYL7ha5UadvK5vmh1lX2s21yfV+rutyuLCAhzvorny4hmxLrlWMfLTsrvfuL34i0ZdDyxOefUe9Ogn2VYI+9Uyhq8ofztsiU6GFQoVaYGFlrS39nJ9SnjSsu4o2r6WQd3MHnzED/uDzz4rtFV5IDDyOi4fzProZZNtwHoC52Li3aPEKhQtYcEc3+d4M6iStzgIgNcx7eVZbzaIUAQu53wyCFQYFIGu4/32xce84pQlYzocb+RZQdFbW26nOhQGIw2iWV5lJy9IELLhMr9SK5nYNzdyHKw1yw67dsi+mlCpgQSqTOM8ij4F5krQRHgDzYHsk6kNVXekCFlyngvwy06003SwBmIrNOOfRXSMNXghYyPNmkFz8t2eTH6a5sQTAL0gxAjdPFh6tkiVff/Wi+8ZblzmnkR1LMkXgjXfeab395uW/yfgVApnz1lt/aEVM1UweeiZewRsLPEIsca53iCO+Iy41rDFIglxw8U28QuGllHFZXb+6a4Wc7djSV3BHWAHvNAZU5TY3hVLFUkoRr9xUIw/xVsBCESIeY48D3s9LzKMkWtU3iqoJ2GfxCl4LWFhZa2/bnH2hVVVimY0M42Y+MIZCbtBJs0+901M6mXRoPxp0PWhQK4poOQioZZ+3zGTeHR94bTcIOXrYpQpTJQH7Ll7B+4tfEhNbEVORIh4OBreiMzfcDjcg6tsHzYvuTvPEZ/TlU3S+I5rop7/nlQdADXJU5GHM+yreJbEmUVYHSVBTPMw2T0OFgAUn4pIbsoM6wHe1iFdQI2Bh2JB9EyM8QOZI7zLDt7TNa1YlYEEaAjQjvob+wyArZC0x86Yv5ZFJUCdgQY5iGueWuNItWkEhhLKWtLb7VSlgQUR8/OnBNSS3QFqk4q//kjc1n82rFfCIn5JbiItBIvju54fhHe0dRNULWJDkFuJiEAcX7wZ8TVuyahqVELAgbtDZa3ytoGFqqZDqLALlwbx39pKvVWm8TaVacEufLfvpzupaO5TKrWFFFSiQvo+vuYRXxhVnVMLqjlMZCzyOHAcUM6wM+A+7Y8equMyvUtkhGMPM4pa1xl1Y4xoysroVFe6ISlrgcWCN60i1re44tRhDBWtcE2pidcepvAUeR6zx0eHBFRR/VA9XlPE9X6mTeIVaCXiEFH9kPsgblATLsLzNKhRlpKGWAhbErZZuC9zna6ip1ocr2rHClWHabuJlTamtgEccHYWh1FTLVTJUcilgeO1PQqE6C3dE7QU8YhQfQ8ieMkxQSZyr8dpfXtQiC52E4eLYtRnrLcN006ZHOgRK47zBoCSoaLeOMe48IOApjIS8stbuMNOWIbNwe1uOqm/Z+0sUNn+gDJDkFMkMoi6BqXjfVtYXpF3qgGnbWuTrac+RJfNdhwbyK+sbT+2nDiXl3E0W4T5EfBsPCDgFqdxrRZ0OF0W8FmLzNP4zOLSi3e+f0gO4ycmAgBdArPIZ052AzPuzrLLEcHJOSTVi5Z/adygw96d+g7W2xvBjNrQHa5seCDgjxOpYqyyN4M87v7sFSl/WeYGONjj3mjC17E52YvMJPRPRY2ttQ1hbAAAAAAAAAAAAAAAAAAAAAAAA4Jf8P8WdqoAaqCHmAAAAAElFTkSuQmCC" +) + +type GithubOidcRouter struct { + config_obj *config_proto.Config } -type GitHubAuthenticator struct { - config_obj *config_proto.Config - authenticator *config_proto.Authenticator +func (self *GithubOidcRouter) Name() string { + return "GitHub" } -// The URL that will be used to log in. -func (self *GitHubAuthenticator) LoginURL() string { +func (self *GithubOidcRouter) LoginHandler() string { return "/auth/github/login" } -func (self *GitHubAuthenticator) CallbackHandler() string { +func (self *GithubOidcRouter) CallbackHandler() string { return "/auth/github/callback" } -func (self *GitHubAuthenticator) IsPasswordLess() bool { - return true +func (self *GithubOidcRouter) Scopes() []string { + return []string{"user:email"} } -func (self *GitHubAuthenticator) RequireClientCerts() bool { - return false +func (self *GithubOidcRouter) Issuer() string { + return "https://github.com/login/oauth" } -func (self *GitHubAuthenticator) AuthRedirectTemplate() string { - return self.authenticator.AuthRedirectTemplate +func (self *GithubOidcRouter) Endpoint() oauth2.Endpoint { + return github.Endpoint } -func (self *GitHubAuthenticator) AddHandlers(mux *api_utils.ServeMux) error { - mux.Handle(api_utils.GetBasePath(self.config_obj, self.LoginURL()), - IpFilter(self.config_obj, self.oauthGithubLogin())) - mux.Handle(api_utils.GetBasePath(self.config_obj, self.CallbackHandler()), - IpFilter(self.config_obj, self.oauthGithubCallback())) - return nil -} +func (self *GithubOidcRouter) SetEndpoint(oauth2.Endpoint) {} -func (self *GitHubAuthenticator) AddLogoff(mux *api_utils.ServeMux) error { - installLogoff(self.config_obj, mux) - return nil +func (self *GithubOidcRouter) Avatar() string { + return GithubIcon } -// Check that the user is proerly authenticated. -func (self *GitHubAuthenticator) AuthenticateUserHandler( - parent http.Handler, - permission acls.ACL_PERMISSION, -) http.Handler { - - return authenticateUserHandle( - self.config_obj, permission, - func(w http.ResponseWriter, r *http.Request, err error, username string) { - reject_with_username(self.config_obj, w, r, err, username, - api_utils.GetBasePath(self.config_obj, "/auth/github/login"), "Github") - }, - parent) +func (self *GithubOidcRouter) LoginURL() string { + return api_utils.PublicURL(self.config_obj, self.LoginHandler()) } -func (self *GitHubAuthenticator) GetGenOauthConfig() (*oauth2.Config, error) { - return &oauth2.Config{ - RedirectURL: api_utils.GetPublicURL(self.config_obj, "/auth/github/callback"), - ClientID: self.authenticator.OauthClientId, - ClientSecret: self.authenticator.OauthClientSecret, - Scopes: []string{"user:email"}, - Endpoint: github.Endpoint, - }, nil -} - -func (self *GitHubAuthenticator) oauthGithubLogin() http.Handler { - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - githubOauthConfig, _ := self.GetGenOauthConfig() - - // Create oauthState cookie - oauthState, err := r.Cookie("oauthstate") - if err != nil { - oauthState = generateStateOauthCookie(self.config_obj, w) - } +// Github does not actually support oidc so we need a pure oauth2 +// claims getter. - u := githubOauthConfig.AuthCodeURL(oauthState.Value, oauth2.ApprovalForce) - http.Redirect(w, r, u, http.StatusTemporaryRedirect) - }) +type GitHubUser struct { + Login string `json:"login"` + AvatarUrl string `json:"avatar_url"` } -func (self *GitHubAuthenticator) oauthGithubCallback() http.Handler { - - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - // Read oauthState from Cookie - oauthState, _ := r.Cookie("oauthstate") - - if oauthState == nil || r.FormValue("state") != oauthState.Value { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid oauth github state") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - formError := r.FormValue("error") - if formError != "" { - desc := r.FormValue("error_description") - if desc != "" { - formError = desc - } - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": formError, - }).Error("getUserDataFromGithub") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - data, err := self.getUserDataFromGithub(r.Context(), r.FormValue("code")) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromGithub") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - user_info := &GitHubUser{} - err = json.Unmarshal(data, &user_info) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromGithub") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - // Update the user picture in the datastore if we can - it - // will be populated from there for each GetUserUITraits - // call. This keeps our cookie smaller. - setUserPicture(r.Context(), user_info.Login, user_info.AvatarUrl) - - cookie, err := getSignedJWTTokenCookie( - self.config_obj, self.authenticator, - &Claims{ - Username: user_info.Login, - }, r) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromGithub") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - http.SetCookie(w, cookie) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - }) +type GithubClaimsGetter struct { + config_obj *config_proto.Config } -func (self *GitHubAuthenticator) getUserDataFromGithub( - ctx context.Context, code string) ([]byte, error) { +func (self *GithubClaimsGetter) GetClaims( + ctx *HTTPClientContext, token *oauth2.Token) (claims *Claims, err error) { - // Use code to get token and get user info from GitHub. - githubOauthConfig, _ := self.GetGenOauthConfig() - - token, err := githubOauthConfig.Exchange(ctx, code) - if err != nil { - return nil, fmt.Errorf("code exchange wrong: %s", err.Error()) + githubOauthConfig := &oauth2.Config{ + Endpoint: github.Endpoint, } response, err := githubOauthConfig.Client(ctx, token).Get("https://api.github.com/user") if err != nil { - return nil, fmt.Errorf("failed getting user info: %s", err.Error()) + return nil, fmt.Errorf("failed getting user info: %v", err) } defer response.Body.Close() contents, err := utils.ReadAllWithLimit(response.Body, constants.MAX_MEMORY) if err != nil { - return nil, fmt.Errorf("failed read response: %s", err.Error()) + return nil, fmt.Errorf("failed read response: %v", err) } - return contents, nil + user_info := &GitHubUser{} + err = json.Unmarshal(contents, &user_info) + if err != nil { + return nil, err + } + + // Update the user picture in the datastore if we can - it + // will be populated from there for each GetUserUITraits + // call. This keeps our cookie smaller. + setUserPicture(ctx, user_info.Login, user_info.AvatarUrl) + + return &Claims{ + Username: user_info.Login, + }, nil } diff --git a/api/authenticators/google.go b/api/authenticators/google.go index b7c04ff2f9a..393b790425e 100644 --- a/api/authenticators/google.go +++ b/api/authenticators/google.go @@ -18,362 +18,46 @@ along with this program. If not, see . package authenticators import ( - "context" - "crypto/rand" - "encoding/base64" - "fmt" - "net/http" - "time" - - "github.com/Velocidex/ordereddict" - "github.com/gorilla/csrf" - "github.com/sirupsen/logrus" "golang.org/x/oauth2" "golang.org/x/oauth2/google" - "www.velocidex.com/golang/velociraptor/acls" - api_proto "www.velocidex.com/golang/velociraptor/api/proto" api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" - "www.velocidex.com/golang/velociraptor/constants" - "www.velocidex.com/golang/velociraptor/gui/velociraptor" - "www.velocidex.com/golang/velociraptor/json" - "www.velocidex.com/golang/velociraptor/logging" - "www.velocidex.com/golang/velociraptor/services" - utils "www.velocidex.com/golang/velociraptor/utils" ) -const oauthGoogleUrlAPI = "https://www.googleapis.com/oauth2/v2/userinfo?access_token=" - -type GoogleAuthenticator struct { - config_obj *config_proto.Config - authenticator *config_proto.Authenticator +type GoogleOidcRouter struct { + config_obj *config_proto.Config } -func (self *GoogleAuthenticator) LoginHandler() string { - return "/auth/google/login" +func (self *GoogleOidcRouter) Name() string { + return "Google" } -// The URL that will be used to log in. -func (self *GoogleAuthenticator) LoginURL() string { +func (self *GoogleOidcRouter) LoginHandler() string { return "/auth/google/login" } -func (self *GoogleAuthenticator) CallbackHandler() string { +func (self *GoogleOidcRouter) CallbackHandler() string { return "/auth/google/callback" } -func (self *GoogleAuthenticator) CallbackURL() string { - return "/auth/google/callback" -} - -func (self *GoogleAuthenticator) ProviderName() string { - return "Google" -} - -func (self *GoogleAuthenticator) AddHandlers(mux *api_utils.ServeMux) error { - mux.Handle(api_utils.GetBasePath(self.config_obj, self.LoginHandler()), - IpFilter(self.config_obj, self.oauthGoogleLogin())) - mux.Handle(api_utils.GetBasePath(self.config_obj, self.CallbackHandler()), - IpFilter(self.config_obj, self.oauthGoogleCallback())) - - return nil -} - -func (self *GoogleAuthenticator) AddLogoff(mux *api_utils.ServeMux) error { - installLogoff(self.config_obj, mux) - return nil -} - -func (self *GoogleAuthenticator) IsPasswordLess() bool { - return true +func (self *GoogleOidcRouter) Scopes() []string { + return []string{"https://www.googleapis.com/auth/userinfo.email"} } -func (self *GoogleAuthenticator) RequireClientCerts() bool { - return false +func (self *GoogleOidcRouter) Issuer() string { + return "https://accounts.google.com" } -func (self *GoogleAuthenticator) AuthRedirectTemplate() string { - return self.authenticator.AuthRedirectTemplate +func (self *GoogleOidcRouter) Endpoint() oauth2.Endpoint { + return google.Endpoint } -// Check that the user is proerly authenticated. -func (self *GoogleAuthenticator) AuthenticateUserHandler( - parent http.Handler, - permission acls.ACL_PERMISSION, -) http.Handler { +func (self *GoogleOidcRouter) SetEndpoint(oauth2.Endpoint) {} - return authenticateUserHandle( - self.config_obj, - permission, - func(w http.ResponseWriter, r *http.Request, err error, username string) { - reject_with_username(self.config_obj, w, r, err, - username, self.LoginURL(), self.ProviderName()) - }, - parent) +func (self *GoogleOidcRouter) Avatar() string { + return "" } -func (self *GoogleAuthenticator) oauthGoogleLogin() http.Handler { - - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - googleOauthConfig, _ := self.GetGenOauthConfig() - - // Create oauthState cookie - oauthState, err := r.Cookie("oauthstate") - if err != nil { - oauthState = generateStateOauthCookie(self.config_obj, w) - } - - u := googleOauthConfig.AuthCodeURL(oauthState.Value, oauth2.ApprovalForce) - http.Redirect(w, r, u, http.StatusTemporaryRedirect) - }) -} - -func generateStateOauthCookie( - config_obj *config_proto.Config, - w http.ResponseWriter) *http.Cookie { - // Do not expire from the browser - we will expire it anyway. - var expiration = time.Now().Add(365 * 24 * time.Hour) - - b := make([]byte, 16) - _, _ = rand.Read(b) - state := base64.URLEncoding.EncodeToString(b) - cookie := http.Cookie{ - Name: "oauthstate", - Path: api_utils.GetBasePath(config_obj), - Value: state, - Secure: true, - HttpOnly: true, - Expires: expiration} - http.SetCookie(w, &cookie) - return &cookie -} - -func (self *GoogleAuthenticator) oauthGoogleCallback() http.Handler { - - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - // Read oauthState from Cookie - oauthState, _ := r.Cookie("oauthstate") - if oauthState == nil || r.FormValue("state") != oauthState.Value { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid oauth google state") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - data, err := self.getUserDataFromGoogle(r.Context(), r.FormValue("code")) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromGoogle") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - user_info := &api_proto.VelociraptorUser{} - err = json.Unmarshal(data, &user_info) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromGoogle") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - // Update the user picture in the datastore if we can - it - // will be populated from there for each GetUserUITraits - // call. This keeps our cookie smaller. - setUserPicture(r.Context(), user_info.Email, user_info.Picture) - - // Sign and get the complete encoded token as a string using the secret - cookie, err := getSignedJWTTokenCookie( - self.config_obj, self.authenticator, - &Claims{ - Username: user_info.Email, - }, r) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("getUserDataFromGoogle") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - http.SetCookie(w, cookie) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - }) -} - -func (self *GoogleAuthenticator) GetGenOauthConfig() (*oauth2.Config, error) { - res := &oauth2.Config{ - RedirectURL: api_utils.GetPublicURL(self.config_obj, self.CallbackURL()), - ClientID: self.authenticator.OauthClientId, - ClientSecret: self.authenticator.OauthClientSecret, - Scopes: []string{"https://www.googleapis.com/auth/userinfo.email"}, - Endpoint: google.Endpoint, - } - return res, nil -} - -func (self *GoogleAuthenticator) getUserDataFromGoogle( - ctx context.Context, code string) ([]byte, error) { - - // Use code to get token and get user info from Google. - googleOauthConfig, _ := self.GetGenOauthConfig() - - token, err := googleOauthConfig.Exchange(ctx, code) - if err != nil { - return nil, fmt.Errorf("code exchange wrong: %s", err.Error()) - } - response, err := http.Get(oauthGoogleUrlAPI + token.AccessToken) - if err != nil { - return nil, fmt.Errorf("failed getting user info: %s", err.Error()) - } - defer response.Body.Close() - - contents, err := utils.ReadAllWithLimit(response.Body, constants.MAX_MEMORY) - if err != nil { - return nil, fmt.Errorf("failed read response: %s", err.Error()) - } - - return contents, nil -} - -func installLogoff(config_obj *config_proto.Config, mux *api_utils.ServeMux) { - mux.Handle(api_utils.GetBasePath(config_obj, "/app/logoff.html"), - IpFilter(config_obj, - api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - old_username, ok := params["username"] - username := "" - if ok && len(old_username) == 1 { - err := services.LogAudit(r.Context(), - config_obj, old_username[0], "LogOff", ordereddict.NewDict()) - if err != nil { - logger := logging.GetLogger( - config_obj, &logging.FrontendComponent) - logger.Error("LogAudit: LogOff %v", old_username[0]) - } - username = old_username[0] - } - - // Clear the cookie - http.SetCookie(w, &http.Cookie{ - Name: "VelociraptorAuth", - Path: api_utils.GetBaseDirectory(config_obj), - Value: "deleted", - Secure: true, - HttpOnly: true, - Expires: time.Unix(0, 0), - }) - - renderLogoffMessage(config_obj, w, username) - }))) -} - -func authenticateUserHandle( - config_obj *config_proto.Config, - permission acls.ACL_PERMISSION, - reject_cb func(w http.ResponseWriter, r *http.Request, - err error, username string), - parent http.Handler) http.Handler { - - logger := GetLoggingHandler(config_obj)(parent) - - return api_utils.HandlerFunc(parent, - func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("X-CSRF-Token", csrf.Token(r)) - - claims, err := getDetailsFromCookie(config_obj, r) - if err != nil { - reject_cb(w, r, err, claims.Username) - return - } - - username := claims.Username - - // Now check if the user is allowed to log in. - users := services.GetUserManager() - user_record, err := users.GetUser(r.Context(), username, username) - if err != nil { - reject_cb(w, r, fmt.Errorf("Invalid user: %v", err), username) - return - } - - // Does the user have access to the specified org? - err = CheckOrgAccess(config_obj, r, user_record, permission) - if err != nil { - reject_cb(w, r, fmt.Errorf("Insufficient permissions: %v", err), user_record.Name) - return - } - - // Checking is successful - user authorized. Here we - // build a token to pass to the underlying GRPC - // service with metadata about the user. - user_info := &api_proto.VelociraptorUser{ - Name: user_record.Name, - } - - // NOTE: This context is NOT the same context that is received - // by the API handlers. This context sits on the incoming side - // of the GRPC gateway. We stuff our data into the - // GRPC_USER_CONTEXT of the context and the code will convert - // this value into a GRPC metadata. - - // Must use json encoding because grpc can not handle - // binary data in metadata. - serialized, _ := json.Marshal(user_info) - ctx := context.WithValue( - r.Context(), constants.GRPC_USER_CONTEXT, string(serialized)) - - // Need to call logging after auth so it can access - // the contextKeyUser value in the context. - logger.ServeHTTP(w, r.WithContext(ctx)) - }).AddChild("GetLoggingHandler") -} - -func reject_with_username( - config_obj *config_proto.Config, - w http.ResponseWriter, r *http.Request, - err error, username, login_url, provider string) { - - // Log failed login to the audit log only if there is an actual - // user. First redirect will have username blank. - if username != "" { - err := services.LogAudit(r.Context(), - config_obj, username, "User rejected by GUI", - ordereddict.NewDict(). - Set("remote", r.RemoteAddr). - Set("method", r.Method). - Set("url", r.URL.String()). - Set("err", err.Error())) - if err != nil { - logger := logging.GetLogger( - config_obj, &logging.FrontendComponent) - logger.Error("LogAudit: User rejected by GUI %v %v", - username, r.RemoteAddr) - } - - } - - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.WriteHeader(http.StatusUnauthorized) - - renderRejectionMessage(config_obj, - r, w, err, username, []velociraptor.AuthenticatorInfo{ - { - LoginURL: api_utils.PublicURL(config_obj, login_url), - ProviderName: provider, - }, - }) +func (self *GoogleOidcRouter) LoginURL() string { + return api_utils.PublicURL(self.config_obj, self.LoginHandler()) } diff --git a/api/authenticators/http.go b/api/authenticators/http.go index e4bb7f0c9e8..eaeae323f92 100644 --- a/api/authenticators/http.go +++ b/api/authenticators/http.go @@ -1,24 +1,104 @@ package authenticators import ( + "bytes" "context" + "io" "net/http" oidc "github.com/coreos/go-oidc/v3/oidc" config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/vql/networking" ) +type transformerTransport struct { + transport http.RoundTripper + transformers []Transformer +} + +func (self *transformerTransport) RoundTrip( + req *http.Request) (*http.Response, error) { + + rt := self.transport.RoundTrip + if rt == nil { + rt = http.DefaultTransport.RoundTrip + } + + for _, t := range self.transformers { + rt = t(rt) + } + + return rt(req) +} + +// The OIDC libraries force us to embed the http client inside the +// context but this is error prone because we can accidentally feed +// them a regular context (without a custom http client). This +// transparently uses the default http client which breaks in cases we +// need proxies etc. +// To fix this we require a new type for a HTTP adorned context. +type HTTPClientContext struct { + context.Context + HTTPClient *http.Client +} + // Update the HTTP client in the context honoring proxy and TLS -// settings in the config file. This is needed to pass to -// oidc.NewProvider -func ClientContext(ctx context.Context, - config_obj *config_proto.Config) (context.Context, error) { +// settings in the config file. This is needed to pass to oidc +// functions that will make HTTP calls. +func ClientContext( + ctx context.Context, + config_obj *config_proto.Config, + transformers []Transformer) (*HTTPClientContext, error) { transport, err := networking.GetHttpTransport(config_obj.Client, "") if err != nil { return nil, err } - client := &http.Client{Transport: transport} - return oidc.ClientContext(ctx, client), nil + // Allow the context to be spied on if needed. + transport = networking.MaybeSpyOnTransport(config_obj, transport) + + client := &http.Client{ + Transport: &transformerTransport{ + transport: transport, + transformers: transformers, + }, + } + + return &HTTPClientContext{ + Context: oidc.ClientContext(ctx, client), + HTTPClient: client, + }, nil +} + +func DefaultTransforms( + config_obj *config_proto.Config, + authenticator *config_proto.Authenticator) []Transformer { + if authenticator.OidcDebug { + return []Transformer{traceNetwork(config_obj)} + } + return nil +} + +func traceNetwork(config_obj *config_proto.Config) func(rt RoundTripFunc) RoundTripFunc { + return func(rt RoundTripFunc) RoundTripFunc { + return func(req *http.Request) (*http.Response, error) { + res, err := rt(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + bs, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + logger := logging.GetLogger(config_obj, &logging.GUIComponent) + logger.Debug("oidc: Calling URL: %v, Response: %v", req.URL, string(bs)) + + res.Body = io.NopCloser(bytes.NewReader(bs)) + return res, nil + } + } } diff --git a/api/authenticators/logoff.go b/api/authenticators/logoff.go new file mode 100644 index 00000000000..711ceb53d39 --- /dev/null +++ b/api/authenticators/logoff.go @@ -0,0 +1,45 @@ +package authenticators + +import ( + "net/http" + "time" + + "github.com/Velocidex/ordereddict" + api_utils "www.velocidex.com/golang/velociraptor/api/utils" + config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/logging" + "www.velocidex.com/golang/velociraptor/services" +) + +func installLogoff(config_obj *config_proto.Config, mux *api_utils.ServeMux) { + mux.Handle(api_utils.GetBasePath(config_obj, "/app/logoff.html"), + IpFilter(config_obj, + api_utils.HandlerFunc(nil, + func(w http.ResponseWriter, r *http.Request) { + params := r.URL.Query() + old_username, ok := params["username"] + username := "" + if ok && len(old_username) == 1 { + err := services.LogAudit(r.Context(), + config_obj, old_username[0], "LogOff", ordereddict.NewDict()) + if err != nil { + logger := logging.GetLogger( + config_obj, &logging.FrontendComponent) + logger.Error("LogAudit: LogOff %v", old_username[0]) + } + username = old_username[0] + } + + // Clear the cookie + http.SetCookie(w, &http.Cookie{ + Name: "VelociraptorAuth", + Path: api_utils.GetBaseDirectory(config_obj), + Value: "deleted", + Secure: true, + HttpOnly: true, + Expires: time.Unix(0, 0), + }) + + renderLogoffMessage(config_obj, w, username) + }))) +} diff --git a/api/authenticators/multiple.go b/api/authenticators/multiple.go index 55855c05d3f..4a7d32c0212 100644 --- a/api/authenticators/multiple.go +++ b/api/authenticators/multiple.go @@ -90,54 +90,27 @@ func (self *MultiAuthenticator) AuthRedirectTemplate() string { } func NewMultiAuthenticator( + ctx *HTTPClientContext, config_obj *config_proto.Config, auth_config *config_proto.Authenticator) (Authenticator, error) { result := &MultiAuthenticator{ config_obj: config_obj, } for _, authenticator_config := range auth_config.SubAuthenticators { - auth, err := getAuthenticatorByType(config_obj, authenticator_config) + auth, err := getAuthenticatorByType( + ctx, config_obj, authenticator_config) if err != nil { return nil, err } // Only accept supported sub types. switch t := auth.(type) { - case *GitHubAuthenticator: - result.delegate_info = append(result.delegate_info, - velociraptor.AuthenticatorInfo{ - LoginURL: t.LoginURL(), - ProviderName: "Github", - }) - - case *GoogleAuthenticator: - result.delegate_info = append(result.delegate_info, - velociraptor.AuthenticatorInfo{ - LoginURL: t.LoginURL(), - ProviderName: `Google`, - }) - - case *AzureAuthenticator: - result.delegate_info = append(result.delegate_info, - velociraptor.AuthenticatorInfo{ - LoginURL: t.LoginURL(), - ProviderName: `Microsoft`, - }) - case *OidcAuthenticator: result.delegate_info = append(result.delegate_info, velociraptor.AuthenticatorInfo{ - LoginURL: t.LoginURL(), - ProviderName: t.authenticator.OidcName, - ProviderAvatar: t.authenticator.Avatar, - }) - - case *OidcAuthenticatorCognito: - result.delegate_info = append(result.delegate_info, - velociraptor.AuthenticatorInfo{ - LoginURL: t.LoginURL(), - ProviderName: t.authenticator.OidcName, - ProviderAvatar: t.authenticator.Avatar, + LoginURL: t.router.LoginURL(), + ProviderName: t.router.Name(), + ProviderAvatar: t.router.Avatar(), }) default: diff --git a/api/authenticators/oidc.go b/api/authenticators/oidc.go index d7184a63165..aab59f3dabb 100644 --- a/api/authenticators/oidc.go +++ b/api/authenticators/oidc.go @@ -1,25 +1,23 @@ package authenticators import ( - "context" + "crypto/rand" + "encoding/base64" "net/http" - "strings" + "time" - oidc "github.com/coreos/go-oidc/v3/oidc" - "github.com/sirupsen/logrus" + "github.com/Velocidex/ordereddict" "golang.org/x/oauth2" "www.velocidex.com/golang/velociraptor/acls" api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/logging" - utils "www.velocidex.com/golang/velociraptor/utils" + "www.velocidex.com/golang/velociraptor/services" ) -type OIDCConnector interface { - GetGenOauthConfig() (*oauth2.Config, error) -} - type OidcAuthenticator struct { + router OidcRouter + claims_getter ClaimsGetter config_obj *config_proto.Config authenticator *config_proto.Authenticator } @@ -36,59 +34,31 @@ func (self *OidcAuthenticator) AuthRedirectTemplate() string { return self.authenticator.AuthRedirectTemplate } -func (self *OidcAuthenticator) Name() string { - name := self.authenticator.OidcName - if name == "" { - return "Generic OIDC Connector" - } - return name -} - -func (self *OidcAuthenticator) LoginHandler() string { - name := self.authenticator.OidcName - if name != "" { - return api_utils.Join("/auth/oidc/", name, "/login") - } - return "/auth/oidc/login" -} - -func (self *OidcAuthenticator) LoginURL() string { - return self.LoginHandler() -} - -func (self *OidcAuthenticator) CallbackHandler() string { - name := self.authenticator.OidcName - if name != "" { - return api_utils.Join("/auth/oidc/", name, "/callback") - } - return "/auth/oidc/callback" -} - -func (self *OidcAuthenticator) CallbackURL() string { - return self.LoginHandler() -} - -func (self *OidcAuthenticator) GetProvider() (*oidc.Provider, error) { - ctx, err := ClientContext(context.Background(), self.config_obj) +func (self *OidcAuthenticator) Provider() (ProviderInterface, error) { + oauth_config, err := self.GetGenOauthConfig() if err != nil { return nil, err } - return oidc.NewProvider(ctx, self.authenticator.OidcIssuer) + + return NewProvider( + self.config_obj, oauth_config, self.authenticator, self.router, + self.claims_getter) } func (self *OidcAuthenticator) AddHandlers(mux *api_utils.ServeMux) error { - provider, err := self.GetProvider() + provider, err := self.Provider() if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Errorf("can not get information from OIDC provider, "+ - "check %v/.well-known/openid-configuration is correct and accessible from the server.", - self.authenticator.OidcIssuer) + self.Error("can not get information from OIDC provider, "+ + "check %v/.well-known/openid-configuration is correct and accessible from the server.", + self.authenticator.OidcIssuer) return err } - mux.Handle(api_utils.GetBasePath(self.config_obj, self.LoginHandler()), + mux.Handle(api_utils.GetBasePath( + self.config_obj, self.router.LoginHandler()), IpFilter(self.config_obj, self.oauthOidcLogin(provider))) - mux.Handle(api_utils.GetBasePath(self.config_obj, self.CallbackHandler()), + mux.Handle(api_utils.GetBasePath( + self.config_obj, self.router.CallbackHandler()), IpFilter(self.config_obj, self.oauthOidcCallback(provider))) return nil } @@ -106,49 +76,51 @@ func (self *OidcAuthenticator) AuthenticateUserHandler( self.config_obj, permission, func(w http.ResponseWriter, r *http.Request, err error, username string) { reject_with_username(self.config_obj, w, r, err, username, - self.LoginURL(), self.Name()) + self.router.LoginHandler(), self.router.Name()) }, parent) } func (self *OidcAuthenticator) GetGenOauthConfig() (*oauth2.Config, error) { - callback := self.CallbackHandler() - - var scope []string - switch strings.ToLower(self.authenticator.Type) { - case "oidc", "oidc-cognito": - scope = []string{oidc.ScopeOpenID, "email"} - } - + callback := self.router.CallbackHandler() res := &oauth2.Config{ RedirectURL: api_utils.GetPublicURL(self.config_obj, callback), ClientID: self.authenticator.OauthClientId, ClientSecret: self.authenticator.OauthClientSecret, - Scopes: scope, - } - - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("OidcAuthenticator: OIDC configuration: %#v", res) + Scopes: self.router.Scopes(), } + self.Debug("OidcAuthenticator: OIDC configuration: %#v", res) return res, nil } -func (self *OidcAuthenticator) oauthOidcLogin( - provider *oidc.Provider) http.Handler { +// Ensure an XSRF protection for the auth flow by ensuring the +// callback is matched with the redirect by setting a cookie on the +// browser. +func generateStateOauthCookie( + config_obj *config_proto.Config, + w http.ResponseWriter) *http.Cookie { + var expiration = time.Now().Add(time.Hour) + + b := make([]byte, 16) + _, _ = rand.Read(b) + state := base64.URLEncoding.EncodeToString(b) + cookie := http.Cookie{ + Name: "oauthstate", + Path: api_utils.GetBasePath(config_obj), + Value: state, + Secure: true, + HttpOnly: true, + Expires: expiration} + http.SetCookie(w, &cookie) + return &cookie +} + +func (self *OidcAuthenticator) oauthOidcLogin(provider ProviderInterface) http.Handler { return api_utils.HandlerFunc(nil, func(w http.ResponseWriter, r *http.Request) { - oidcOauthConfig, err := self.GetGenOauthConfig() - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("GetGenOauthConfig: %v", err) - http.Error(w, "rejected", http.StatusUnauthorized) - } - oidcOauthConfig.Endpoint = provider.Endpoint() - // Create oauthState cookie oauthState, err := r.Cookie("oauthstate") if err != nil { @@ -162,118 +134,91 @@ func (self *OidcAuthenticator) oauthOidcLogin( options = append(options, oauth2.SetAuthURLParam(k, v)) } - url := oidcOauthConfig.AuthCodeURL(oauthState.Value, options...) + url := provider.GetRedirectURL(options, oauthState.Value) - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("OidcAuthenticator: Redirecting to: %#v", url) - } + self.Debug("OidcAuthenticator: Redirecting to: %#v", url) http.Redirect(w, r, url, http.StatusFound) }) } +func (self *OidcAuthenticator) Debug(message string, args ...interface{}) { + if self.authenticator.OidcDebug { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Debug(message, args...) + } +} + +func (self *OidcAuthenticator) Error(message string, args ...interface{}) { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Error(message, args...) +} + func (self *OidcAuthenticator) oauthOidcCallback( - provider *oidc.Provider) http.Handler { + provider ProviderInterface) http.Handler { return api_utils.HandlerFunc(nil, func(w http.ResponseWriter, r *http.Request) { - // Read oauthState from Cookie + self.Debug("OidcAuthenticator: Received OIDC Callback %#v", r) + + // Read oauthState from Cookie and make sure the state + // that is passed back from the server are actually the + // same. oauthState, _ := r.Cookie("oauthstate") if oauthState == nil || r.FormValue("state") != oauthState.Value { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid oauth state of OIDC") + self.Error("invalid oauth state of OIDC: %v %v", + oauthState, r.FormValue("state")) http.Redirect(w, r, api_utils.Homepage(self.config_obj), http.StatusTemporaryRedirect) return } - oidcOauthConfig, err := self.GetGenOauthConfig() - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("GetGenOauthConfig: %v", err) - http.Error(w, "rejected", http.StatusUnauthorized) - } - oidcOauthConfig.Endpoint = provider.Endpoint() - - ctx, err := ClientContext(r.Context(), self.config_obj) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid client context of OIDC: %v", err) - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - oauthToken, err := oidcOauthConfig.Exchange(ctx, r.FormValue("code")) + ctx, err := ClientContext(r.Context(), self.config_obj, + DefaultTransforms(self.config_obj, self.authenticator)) if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("can not get oauthToken from OIDC provider: %v", err) + self.Error("OidcAuthenticator: %v", err) http.Redirect(w, r, api_utils.Homepage(self.config_obj), http.StatusTemporaryRedirect) return } - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("oauthOidcCallback: Exchanged token with %#v", oauthToken) - } - - userInfo, err := provider.UserInfo( - ctx, oauth2.StaticTokenSource(oauthToken)) + code := r.FormValue("code") + cookie, claims, err := provider.GetJWT(ctx, code) if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("can not get UserInfo from OIDC provider: %v", err) + self.Error("OidcAuthenticator: %v", err) http.Redirect(w, r, api_utils.Homepage(self.config_obj), http.StatusTemporaryRedirect) return } - // Map the OIDC claims to our own claims. - claims, err := self.NewClaims(ctx, userInfo) + // Log a successful login. + err = services.LogAudit(r.Context(), + self.config_obj, claims.Username, "Login", + ordereddict.NewDict(). + Set("remote", r.RemoteAddr). + Set("authenticator", self.authenticator.Type). + Set("url", r.URL.Path)) if err != nil { - // Try to get the claims from the AccessToken. ADFS - // passes user info in the token instead of the user - // info endpoint (https://stackoverflow.com/questions/45058571/adfs-4-0-userinfo-endpoint-returns-only-sub-claim) - new_claims, err1 := self.maybeGetClaimsFromToken(ctx, oauthToken) - if err1 == nil { - // Fallback method worked! Lets use it. - claims = new_claims - - // No claims in AccessToken - report original error - } else if err1 == utils.InvalidArgError { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("oauthOidcCallback: Unable to parse claims: %v", err) - - // Failed to parse the AccessToken claims, report both errors. - } else { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("oauthOidcCallback: Unable to parse claims: %v, "+ - "and then parsing AccessToken: %v", err, err1) - } - - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return + self.Error("getSignedJWTTokenCookie LogAudit: Login %v %v", + claims.Username, r.RemoteAddr) } - cookie, err := getSignedJWTTokenCookie( - self.config_obj, self.authenticator, claims, r) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("can not get a signed tokenString") - http.Redirect(w, r, api_utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - if self.authenticator.OidcDebug { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Debug("oauthOidcCallback: Success! Setting cookie %#v", cookie) - } + self.Debug("oauthOidcCallback: Success! Setting cookie %#v", cookie) http.SetCookie(w, cookie) http.Redirect(w, r, api_utils.Homepage(self.config_obj), http.StatusTemporaryRedirect) }) } + +func NewOidcAuthenticator( + config_obj *config_proto.Config, + authenticator *config_proto.Authenticator, + router OidcRouter, + claims_getter ClaimsGetter) *OidcAuthenticator { + return &OidcAuthenticator{ + router: router, + claims_getter: claims_getter, + config_obj: config_obj, + authenticator: authenticator, + } +} diff --git a/api/authenticators/oidc_cognito.go b/api/authenticators/oidc_cognito.go deleted file mode 100644 index 32ba964410c..00000000000 --- a/api/authenticators/oidc_cognito.go +++ /dev/null @@ -1,176 +0,0 @@ -package authenticators - -import ( - "bytes" - "context" - "fmt" - "io" - "net/http" - "strconv" - "strings" - - oidc "github.com/coreos/go-oidc/v3/oidc" - "github.com/sirupsen/logrus" - "golang.org/x/oauth2" - api_utils "www.velocidex.com/golang/velociraptor/api/utils" - utils "www.velocidex.com/golang/velociraptor/api/utils" - config_proto "www.velocidex.com/golang/velociraptor/config/proto" - "www.velocidex.com/golang/velociraptor/json" - "www.velocidex.com/golang/velociraptor/logging" -) - -// AWS Cognito needs a special authenticator because they do not -// follow the oauth2 spec properly. See -// https://github.com/coreos/go-oidc/pull/249 -type OidcAuthenticatorCognito struct { - OidcAuthenticator -} - -func (self *OidcAuthenticatorCognito) AddHandlers(mux *api_utils.ServeMux) error { - provider, err := self.GetProvider() - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Errorf("can not get information from OIDC provider, "+ - "check %v/.well-known/openid-configuration is correct and accessible from the server.", - self.authenticator.OidcIssuer) - return err - } - - mux.Handle(api_utils.GetBasePath(self.config_obj, self.LoginHandler()), - IpFilter(self.config_obj, self.oauthOidcLogin(provider))) - mux.Handle(api_utils.GetBasePath(self.config_obj, self.CallbackHandler()), - IpFilter(self.config_obj, self.oauthOidcCallback(provider))) - return nil -} - -func (self *OidcAuthenticatorCognito) oauthOidcCallback( - provider *oidc.Provider) http.Handler { - - return api_utils.HandlerFunc(nil, - func(w http.ResponseWriter, r *http.Request) { - // Read oauthState from Cookie - oauthState, _ := r.Cookie("oauthstate") - if oauthState == nil || r.FormValue("state") != oauthState.Value { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("invalid oauth state of OIDC") - http.Redirect(w, r, utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - oidcOauthConfig, err := self.GetGenOauthConfig() - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("GetGenOauthConfig: %v", err) - http.Error(w, "rejected", http.StatusUnauthorized) - } - oidcOauthConfig.Endpoint = provider.Endpoint() - - oauthToken, err := oidcOauthConfig.Exchange(r.Context(), r.FormValue("code")) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("can not get oauthToken from OIDC provider: %v", err) - http.Redirect(w, r, utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - userInfo, err := getUserInfo( - r.Context(), provider, oauth2.StaticTokenSource(oauthToken)) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - Error("can not get UserInfo from OIDC provider: %v", err) - http.Redirect(w, r, utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - cookie, err := getSignedJWTTokenCookie( - self.config_obj, self.authenticator, - &Claims{ - Username: userInfo.Email, - }, r) - if err != nil { - logging.GetLogger(self.config_obj, &logging.GUIComponent). - WithFields(logrus.Fields{ - "err": err.Error(), - }).Error("can not get a signed tokenString") - http.Redirect(w, r, utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - return - } - - http.SetCookie(w, cookie) - http.Redirect(w, r, utils.Homepage(self.config_obj), - http.StatusTemporaryRedirect) - }) -} - -func init() { - RegisterAuthenticator("oidc-cognito", func(config_obj *config_proto.Config, - auth_config *config_proto.Authenticator) (Authenticator, error) { - return &OidcAuthenticatorCognito{OidcAuthenticator{ - config_obj: config_obj, - authenticator: auth_config, - }}, nil - }) -} - -// The following is taken from https://github.com/pomerium/pomerium/blob/0b0fba06b3374557ed7427d165190570ce4997f1/internal/identity/oidc/userinfo.go - -// getUserInfo gets the user info for OIDC. We wrap the underlying call because AWS Cognito chose to violate the spec -// and return data in an invalid format. By using our own custom http client, we're able to modify the response to -// make it compliant, and then the rest of the library works as expected. -func getUserInfo(ctx context.Context, provider *oidc.Provider, tokenSource oauth2.TokenSource) (*oidc.UserInfo, error) { - originalClient := http.DefaultClient - if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok { - originalClient = c - } - - client := new(http.Client) - *client = *originalClient - client.Transport = &userInfoRoundTripper{underlying: client.Transport} - - ctx = context.WithValue(ctx, oauth2.HTTPClient, client) - return provider.UserInfo(ctx, tokenSource) -} - -type userInfoRoundTripper struct { - underlying http.RoundTripper -} - -func (transport *userInfoRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - underlying := transport.underlying - if underlying == nil { - underlying = http.DefaultTransport - } - - res, err := underlying.RoundTrip(req) - if err != nil { - return nil, err - } - defer res.Body.Close() - - bs, err := io.ReadAll(res.Body) - if err != nil { - return nil, err - } - - var userInfo map[string]interface{} - if err := json.Unmarshal(bs, &userInfo); err == nil { - // AWS Cognito returns email_verified as a string, so we'll make it a bool - if ev, ok := userInfo["email_verified"]; ok { - userInfo["email_verified"], _ = strconv.ParseBool(fmt.Sprint(ev)) - } - - // Some providers (ping) have a "mail" claim instead of "email" - email, mail := userInfo["email"], userInfo["mail"] - if email == nil && mail != nil && strings.Contains(fmt.Sprint(mail), "@") { - userInfo["email"] = mail - } - - bs, _ = json.Marshal(userInfo) - } - - res.Body = io.NopCloser(bytes.NewReader(bs)) - return res, nil -} diff --git a/api/authenticators/orgs.go b/api/authenticators/orgs.go index 0bcb66a7d0d..a8f2204daae 100644 --- a/api/authenticators/orgs.go +++ b/api/authenticators/orgs.go @@ -63,7 +63,8 @@ func CheckOrgAccess( // otherwise we need to give the user a more specific error that // they are not authorized for this org. if !utils.IsRootOrg(org_id) && - !errors.Is(err, services.OrgNotFoundError) { + !errors.Is(err, services.OrgNotFoundError) && + !errors.Is(err, utils.NoAccessToOrgError) { return err } diff --git a/api/authenticators/provider.go b/api/authenticators/provider.go new file mode 100644 index 00000000000..bc9424c6b29 --- /dev/null +++ b/api/authenticators/provider.go @@ -0,0 +1,152 @@ +package authenticators + +import ( + "context" + "fmt" + "net/http" + "time" + + jwt "github.com/golang-jwt/jwt/v4" + "golang.org/x/oauth2" + utils "www.velocidex.com/golang/velociraptor/api/utils" + config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/logging" +) + +// Abstract oauth and oidc authenticators so we can reuse them in +// different types. + +// Transformers allow for stacking of round trippers. +type RoundTripFunc func(req *http.Request) (*http.Response, error) + +// A transformer can intercept network communications and change +// them. This is used to add debugging (to see what the oauth server +// is sending) and to mock out the network comms for testing. +type Transformer func(rt RoundTripFunc) RoundTripFunc + +// The provider's external methods. For oauth2 we only need two steps +// from the provider: The first is to form the redirect URL to the +// IDP, the second is to process the callback from the IDP and produce +// a JWT which we will store in a session cookie. By abstracting the +// provider we can easily test it. +type ProviderInterface interface { + GetRedirectURL(options []oauth2.AuthCodeOption, state string) string + GetJWT(ctx *HTTPClientContext, code string) (*http.Cookie, *Claims, error) +} + +// Compose the provider from various interfaces: +// The OidcRouter explains the different endpoints we need to access. + +// The ClaimsGetter is used to fetch claims from the server and decode +// the username from them. Velociraptor only cares about how to +// extract the username from the claims. +type Provider struct { + router OidcRouter + claims_getter ClaimsGetter + config_obj *config_proto.Config + oauth_config *oauth2.Config + authenticator *config_proto.Authenticator +} + +// Where to redirect to the +func (self *Provider) GetRedirectURL( + options []oauth2.AuthCodeOption, state string) string { + self.oauth_config.Endpoint = self.router.Endpoint() + return self.oauth_config.AuthCodeURL(state, options...) +} + +// GetJWT contacts the oauth server to fetch claims, creates a user +// object which is encoded in a JWT. The JWT can be verified on each +// subsequent request to ensure the user is logged on. +func (self *Provider) GetJWT( + ctx *HTTPClientContext, code string) (*http.Cookie, *Claims, error) { + + token, err := self.Exchange(ctx, self.oauth_config, code) + if err != nil { + return nil, nil, fmt.Errorf( + "can not get oauthToken from OIDC provider with code %v: %v", + code, err) + } + + claims, err := self.claims_getter.GetClaims(ctx, token) + if err != nil { + self.Debug("oauthOidcCallback: Unable to get claims: %v", err) + return nil, nil, err + } + + cookie, err := self.getSignedJWTTokenCookie(self.config_obj, claims) + if err != nil { + return nil, nil, err + } + + return cookie, claims, err +} + +func (self *Provider) getSignedJWTTokenCookie( + config_obj *config_proto.Config, + claims *Claims) (*http.Cookie, error) { + expiry_min := self.authenticator.DefaultSessionExpiryMin + if expiry_min == 0 { + expiry_min = 60 * 24 // 1 Day by default + } + + // We force expiry in the JWT **as well** as the session + // cookie. The JWT expiry is most important as the browser can + // replay session cookies past expiry. + expiry := time.Now().Add(time.Minute * time.Duration(expiry_min)) + + // Enforce the JWT to expire + claims.Expires = float64(expiry.Unix()) + + // Make a JWT and sign it. + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + self.Debug("getSignedJWTTokenCookie: Creating JWT with claims: %#v", claims) + + tokenString, err := token.SignedString([]byte(config_obj.Frontend.PrivateKey)) + if err != nil { + return nil, err + } + + // Sets the cookie on the browser so it is only valid from the + // base down. + return &http.Cookie{ + Name: "VelociraptorAuth", + Value: tokenString, + Path: utils.GetBaseDirectory(config_obj), + Secure: true, + HttpOnly: true, + Expires: expiry, + }, nil +} + +// Gets an oidc token from the server. +func (self *Provider) Exchange( + ctx context.Context, + oauth_config *oauth2.Config, code string) (*oauth2.Token, error) { + + oauth_config.Endpoint = self.router.Endpoint() + return oauth_config.Exchange(ctx, code) +} + +// Potentially log debug messages depending on the debug setting. +func (self *Provider) Debug(message string, args ...interface{}) { + if self.authenticator.OidcDebug { + logging.GetLogger(self.config_obj, &logging.GUIComponent). + Debug(message, args...) + } +} + +func NewProvider( + config_obj *config_proto.Config, + oauth_config *oauth2.Config, + authenticator *config_proto.Authenticator, + router OidcRouter, + claims_getter ClaimsGetter) (ProviderInterface, error) { + return &Provider{ + router: router, + config_obj: config_obj, + oauth_config: oauth_config, + authenticator: authenticator, + claims_getter: claims_getter, + }, nil +} diff --git a/api/authenticators/router.go b/api/authenticators/router.go new file mode 100644 index 00000000000..4083390480e --- /dev/null +++ b/api/authenticators/router.go @@ -0,0 +1,76 @@ +package authenticators + +import ( + oidc "github.com/coreos/go-oidc/v3/oidc" + "golang.org/x/oauth2" + api_utils "www.velocidex.com/golang/velociraptor/api/utils" + config_proto "www.velocidex.com/golang/velociraptor/config/proto" +) + +// The router gives all the URLs to the relevant endpoints +type OidcRouter interface { + Name() string + LoginHandler() string + CallbackHandler() string + Scopes() []string + Issuer() string + Endpoint() oauth2.Endpoint + SetEndpoint(oauth2.Endpoint) + Avatar() string + + LoginURL() string +} + +type DefaultOidcRouter struct { + authenticator *config_proto.Authenticator + config_obj *config_proto.Config + endpoint oauth2.Endpoint +} + +func (self *DefaultOidcRouter) Name() string { + name := self.authenticator.OidcName + if name == "" { + return "Generic OIDC Connector" + } + return name +} + +func (self *DefaultOidcRouter) LoginHandler() string { + name := self.authenticator.OidcName + if name != "" { + return api_utils.Join("/auth/oidc/", name, "/login") + } + return "/auth/oidc/login" +} + +func (self *DefaultOidcRouter) LoginURL() string { + return api_utils.PublicURL(self.config_obj, self.LoginHandler()) +} + +func (self *DefaultOidcRouter) CallbackHandler() string { + name := self.authenticator.OidcName + if name != "" { + return api_utils.Join("/auth/oidc/", name, "/callback") + } + return "/auth/oidc/callback" +} + +func (self *DefaultOidcRouter) Scopes() []string { + return []string{oidc.ScopeOpenID, "email"} +} + +func (self *DefaultOidcRouter) Issuer() string { + return self.authenticator.OidcIssuer +} + +func (self *DefaultOidcRouter) Endpoint() oauth2.Endpoint { + return self.endpoint +} + +func (self *DefaultOidcRouter) SetEndpoint(ep oauth2.Endpoint) { + self.endpoint = ep +} + +func (self *DefaultOidcRouter) Avatar() string { + return self.authenticator.Avatar +} diff --git a/api/authenticators/verify.go b/api/authenticators/verify.go new file mode 100644 index 00000000000..e61afe0e219 --- /dev/null +++ b/api/authenticators/verify.go @@ -0,0 +1,231 @@ +package authenticators + +import ( + "context" + "errors" + "fmt" + "net/http" + "time" + + "github.com/Velocidex/ordereddict" + jwt "github.com/golang-jwt/jwt/v4" + "github.com/gorilla/csrf" + "www.velocidex.com/golang/velociraptor/acls" + api_proto "www.velocidex.com/golang/velociraptor/api/proto" + api_utils "www.velocidex.com/golang/velociraptor/api/utils" + utils "www.velocidex.com/golang/velociraptor/api/utils" + config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/constants" + "www.velocidex.com/golang/velociraptor/gui/velociraptor" + "www.velocidex.com/golang/velociraptor/json" + "www.velocidex.com/golang/velociraptor/logging" + "www.velocidex.com/golang/velociraptor/services" +) + +var ( + reauthError = errors.New(`Authentication cookie not found, invalid or expired. +You probably need to re-authenticate in a new tab or refresh this page.`) +) + +// Middleware function to enforce the request is authenticated. +// 1. Extract the claims from the JWT cookie +// 2. Make sure the user has the required permission on the specified org. +// 3. If user is authorized we pass a token to the gRPC gateway so it +// can become available inside the API server. This way the HTTP +// handler can identify the user, and pass that fact to the API +// backend without needing to re-auth the user again. +func authenticateUserHandle( + config_obj *config_proto.Config, + permission acls.ACL_PERMISSION, + reject_cb func(w http.ResponseWriter, r *http.Request, + err error, username string), + parent http.Handler) http.Handler { + + logger := GetLoggingHandler(config_obj)(parent) + + return api_utils.HandlerFunc(parent, + func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-CSRF-Token", csrf.Token(r)) + + claims, err := getDetailsFromCookie(config_obj, r) + if err != nil { + reject_cb(w, r, err, claims.Username) + return + } + + username := claims.Username + + // Now check if the user is allowed to log in. + users := services.GetUserManager() + user_record, err := users.GetUser(r.Context(), username, username) + if err != nil { + reject_cb(w, r, fmt.Errorf("Invalid user: %v", err), username) + return + } + + // Does the user have access to the specified org? + err = CheckOrgAccess(config_obj, r, user_record, permission) + if err != nil { + reject_cb(w, r, fmt.Errorf("Insufficient permissions: %v", err), user_record.Name) + return + } + + // Checking is successful - user authorized. Here we + // build a token to pass to the underlying GRPC + // service with metadata about the user. + user_info := &api_proto.VelociraptorUser{ + Name: user_record.Name, + } + + // NOTE: This context is NOT the same context that is received + // by the API handlers. This context sits on the incoming side + // of the GRPC gateway. We stuff our data into the + // GRPC_USER_CONTEXT of the context and the code will convert + // this value into a GRPC metadata. + + // Must use json encoding because grpc can not handle + // binary data in metadata. + serialized, _ := json.Marshal(user_info) + ctx := context.WithValue( + r.Context(), constants.GRPC_USER_CONTEXT, string(serialized)) + + // Need to call logging after auth so it can access + // the contextKeyUser value in the context. + logger.ServeHTTP(w, r.WithContext(ctx)) + }).AddChild("GetLoggingHandler") +} + +// Reject the user with a message and also add to the audit log. +func reject_with_username( + config_obj *config_proto.Config, + w http.ResponseWriter, r *http.Request, + err error, username, login_url, provider string) { + + // Log failed login to the audit log only if there is an actual + // user. First redirect will have username blank. + if username != "" { + err := services.LogAudit(r.Context(), + config_obj, username, "User rejected by GUI", + ordereddict.NewDict(). + Set("remote", r.RemoteAddr). + Set("method", r.Method). + Set("url", r.URL.String()). + Set("err", err.Error())) + if err != nil { + logger := logging.GetLogger( + config_obj, &logging.FrontendComponent) + logger.Error("LogAudit: User rejected by GUI %v %v", + username, r.RemoteAddr) + } + + } + + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusUnauthorized) + + renderRejectionMessage(config_obj, + r, w, err, username, []velociraptor.AuthenticatorInfo{ + { + LoginURL: api_utils.PublicURL(config_obj, login_url), + ProviderName: provider, + }, + }) +} + +// Create a new JWT cookie embedding the claims in it. +// The JWT is signed with the server's private key so we can verify it +// easily and it can not be modified. +func getSignedJWTTokenCookie( + config_obj *config_proto.Config, + authenticator *config_proto.Authenticator, + claims *Claims, r *http.Request) (*http.Cookie, error) { + if config_obj.Frontend == nil { + return nil, errors.New("config has no Frontend") + } + + expiry_min := authenticator.DefaultSessionExpiryMin + if expiry_min == 0 { + expiry_min = 60 * 24 // 1 Day by default + } + + // We force expiry in the JWT **as well** as the session + // cookie. The JWT expiry is most important as the browser can + // replay session cookies past expiry. + expiry := time.Now().Add(time.Minute * time.Duration(expiry_min)) + + // Enforce the JWT to expire + claims.Expires = float64(expiry.Unix()) + + // Make a JWT and sign it. + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + if authenticator.OidcDebug { + logging.GetLogger(config_obj, &logging.GUIComponent). + Debug("getSignedJWTTokenCookie: Creating JWT with claims: %#v", claims) + } + + tokenString, err := token.SignedString([]byte(config_obj.Frontend.PrivateKey)) + if err != nil { + return nil, err + } + + // Log a successful login. + err = services.LogAudit(r.Context(), + config_obj, claims.Username, "Login", + ordereddict.NewDict(). + Set("remote", r.RemoteAddr). + Set("authenticator", authenticator.Type). + Set("url", r.URL.Path)) + if err != nil { + logger := logging.GetLogger(config_obj, &logging.FrontendComponent) + logger.Error("getSignedJWTTokenCookie LogAudit: Login %v %v", + claims.Username, r.RemoteAddr) + } + + // Sets the cookie on the browser so it is only valid from the + // base down. + return &http.Cookie{ + Name: "VelociraptorAuth", + Value: tokenString, + Path: utils.GetBaseDirectory(config_obj), + Secure: true, + HttpOnly: true, + Expires: expiry, + }, nil +} + +// Extracts the claims from the VelociraptorAuth cookie: +// Ensure the JWT is properly validated and contains all the +// required fields. +func getDetailsFromCookie( + config_obj *config_proto.Config, + r *http.Request) (*Claims, error) { + + claims := &Claims{} + + // We store the user name and their details in a local + // cookie. It is stored as a JWT so we can trust it. + auth_cookie, err := r.Cookie("VelociraptorAuth") + if err != nil { + return claims, reauthError + } + + // Parse the JWT. + token, err := jwt.ParseWithClaims(auth_cookie.Value, claims, + func(token *jwt.Token) (interface{}, error) { + _, ok := token.Method.(*jwt.SigningMethodHMAC) + if !ok { + return claims, errors.New("invalid signing method") + } + return []byte(config_obj.Frontend.PrivateKey), nil + }) + if err != nil { + return claims, fmt.Errorf("%w: %v", err, reauthError.Error()) + } + + claims, ok := token.Claims.(*Claims) + if ok && token.Valid { + return claims, nil + } + + return claims, reauthError +} diff --git a/config/proto/config.pb.go b/config/proto/config.pb.go index 018e089cc92..cd8d6d1b673 100644 --- a/config/proto/config.pb.go +++ b/config/proto/config.pb.go @@ -1519,6 +1519,11 @@ type OIDCClaims struct { // roles: // - reader RoleMap map[string]*OIDCACL `protobuf:"bytes,3,rep,name=role_map,json=roleMap,proto3" json:"role_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Velociraptor usually requires the email_verified claim before + // we can trust the email claim and use it as the + // username. However, some IDP (e.g. Azure) do not set this. If + // you want to ignore this requirement, set the below to true. + AllowUnverifiedEmail bool `protobuf:"varint,4,opt,name=allow_unverified_email,json=allowUnverifiedEmail,proto3" json:"allow_unverified_email,omitempty"` } func (x *OIDCClaims) Reset() { @@ -1574,6 +1579,13 @@ func (x *OIDCClaims) GetRoleMap() map[string]*OIDCACL { return nil } +func (x *OIDCClaims) GetAllowUnverifiedEmail() bool { + if x != nil { + return x.AllowUnverifiedEmail + } + return false +} + type Authenticator struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -5784,7 +5796,7 @@ var file_config_proto_rawDesc = []byte{ 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x1f, 0x0a, 0x07, 0x4f, 0x49, 0x44, 0x43, 0x41, 0x43, 0x4c, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x0a, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x0a, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, @@ -5792,1148 +5804,1151 @@ var file_config_proto_rawDesc = []byte{ 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, - 0x72, 0x6f, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x1a, 0x4a, 0x0a, 0x0c, 0x52, 0x6f, 0x6c, 0x65, 0x4d, - 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x41, 0x43, 0x4c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0xae, 0x0d, 0x0a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0xb9, 0x01, 0x0a, 0x0b, 0x6f, 0x69, - 0x64, 0x63, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x97, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x90, 0x01, 0x12, 0x8d, 0x01, 0x55, 0x52, 0x4c, 0x20, - 0x74, 0x6f, 0x20, 0x4f, 0x49, 0x44, 0x43, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x6f, 0x69, - 0x64, 0x63, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x20, 0x2b, 0x20, 0x2f, 0x2e, 0x77, 0x65, - 0x6c, 0x6c, 0x2d, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x64, 0x2d, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x20, 0x65, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x20, 0x52, 0x0a, 0x6f, 0x69, 0x64, 0x63, 0x49, - 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x69, 0x64, 0x63, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x14, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, - 0x75, 0x72, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x18, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x55, - 0x72, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6f, - 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x58, 0x0a, 0x0f, 0x6f, 0x61, 0x75, 0x74, - 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x30, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2a, 0x12, 0x28, 0x49, 0x66, 0x20, 0x73, 0x65, - 0x74, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x20, 0x61, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x52, 0x0d, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x60, 0x0a, 0x13, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x30, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2a, 0x12, 0x28, 0x49, 0x66, 0x20, 0x73, 0x65, 0x74, 0x20, - 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x20, 0x61, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x52, 0x11, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x19, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x49, 0x44, - 0x43, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x06, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, - 0x1d, 0x0a, 0x0a, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x1a, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x69, 0x64, 0x63, 0x44, 0x65, 0x62, 0x75, 0x67, 0x12, 0x16, - 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x19, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x13, 0x12, 0x11, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x0f, 0x73, 0x61, 0x6d, - 0x6c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x10, - 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x13, 0x12, 0x11, - 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, - 0x2e, 0x52, 0x0e, 0x73, 0x61, 0x6d, 0x6c, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, - 0x79, 0x12, 0x5f, 0x0a, 0x15, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x55, 0x52, 0x4c, 0x2e, 0x52, 0x12, - 0x73, 0x61, 0x6d, 0x6c, 0x49, 0x64, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, - 0x72, 0x6c, 0x12, 0x3a, 0x0a, 0x0d, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, - 0x75, 0x72, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x42, 0x16, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, - 0x10, 0x12, 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x55, 0x52, 0x4c, - 0x2e, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x70, - 0x0a, 0x13, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x42, 0x40, 0xe2, 0xfc, 0xe3, - 0xc4, 0x01, 0x3a, 0x12, 0x38, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x11, 0x73, - 0x61, 0x6d, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x12, 0xa9, 0x01, 0x0a, 0x0f, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, - 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x09, 0x42, 0x80, 0x01, 0xe2, 0xfc, 0xe3, - 0xc4, 0x01, 0x7a, 0x12, 0x78, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x6f, 0x6c, - 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x61, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x53, 0x41, 0x4d, 0x4c, 0x20, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, - 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x72, 0x73, 0x20, 0x77, - 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, - 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x2e, 0x52, 0x0d, 0x73, - 0x61, 0x6d, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x18, - 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x42, 0x26, - 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x49, 0x64, - 0x50, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x53, 0x41, 0x4d, 0x4c, - 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x15, 0x73, 0x61, 0x6d, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, - 0x77, 0x49, 0x64, 0x70, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x12, 0x43, 0x0a, - 0x12, 0x73, 0x75, 0x62, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x6f, 0x72, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, - 0x11, 0x73, 0x75, 0x62, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x12, 0x69, 0x0a, 0x16, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x15, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x33, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2d, 0x12, 0x2b, 0x55, 0x52, 0x4c, 0x20, - 0x74, 0x6f, 0x20, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6f, - 0x6e, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x41, - 0x50, 0x49, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x52, 0x14, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x42, 0x0a, - 0x1e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5f, 0x66, - 0x6f, 0x72, 0x5f, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, - 0x16, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, - 0x6c, 0x65, 0x73, 0x46, 0x6f, 0x72, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x69, 0x6e, 0x1a, 0x44, - 0x0a, 0x16, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x50, 0x61, 0x72, - 0x61, 0x6d, 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, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x89, 0x0c, 0x0a, 0x09, 0x47, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x75, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, - 0x6f, 0x12, 0x6d, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, - 0x6e, 0x64, 0x20, 0x47, 0x55, 0x49, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, - 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x75, 0x73, 0x75, - 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x31, 0x32, 0x37, - 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, - 0x65, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x69, 0x74, 0x2e, - 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x35, 0x0a, - 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x42, 0x18, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x12, 0x12, 0x10, 0x50, 0x6f, 0x72, 0x74, 0x20, 0x74, - 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x2e, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, - 0x63, 0x69, 0x64, 0x72, 0x18, 0x17, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x64, 0x43, 0x69, 0x64, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x66, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x65, 0x64, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x0a, - 0x0e, 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x48, - 0x74, 0x74, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x12, 0xc3, 0x01, 0x0a, 0x0e, 0x67, 0x77, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9b, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, - 0x01, 0x94, 0x01, 0x12, 0x91, 0x01, 0x54, 0x68, 0x65, 0x20, 0x47, 0x55, 0x49, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x73, 0x20, 0x61, 0x20, 0x48, 0x54, 0x54, 0x50, 0x20, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x52, - 0x50, 0x43, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x54, 0x68, 0x69, - 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, - 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x52, 0x50, 0x43, 0x20, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x0d, 0x67, 0x77, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x0e, 0x67, 0x77, 0x5f, 0x70, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x45, - 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3f, 0x12, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, - 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x65, - 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x50, 0x45, 0x4d, 0x20, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x52, 0x0c, 0x67, 0x77, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x75, 0x72, - 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, - 0x1e, 0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x55, 0x52, 0x4c, 0x20, - 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, - 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x55, 0x72, 0x6c, 0x12, 0x63, 0x0a, 0x0d, 0x72, 0x65, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, - 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x23, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x1d, 0x12, 0x1b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, - 0x2e, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, - 0x55, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x55, 0x49, 0x4c, 0x69, 0x6e, 0x6b, 0x42, 0x2f, - 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x29, 0x12, 0x27, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x65, 0x73, - 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x55, 0x49, 0x2e, 0x52, - 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x33, 0x0a, 0x0d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x55, 0x49, 0x55, 0x73, 0x65, 0x72, 0x52, 0x0c, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x3a, 0x0a, 0x0c, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x6f, 0x72, 0x67, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x4f, 0x72, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x61, 0x6c, 0x4f, 0x72, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, - 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x14, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x19, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x61, - 0x6d, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a, - 0x10, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x61, 0x6d, 0x6c, 0x50, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x15, 0x73, 0x61, 0x6d, 0x6c, 0x5f, + 0x72, 0x6f, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x5f, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x6e, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x1a, 0x4a, 0x0a, + 0x0c, 0x52, 0x6f, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x41, 0x43, 0x4c, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xae, 0x0d, 0x0a, 0x0d, 0x41, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0xb9, 0x01, 0x0a, 0x0b, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x97, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x90, 0x01, 0x12, + 0x8d, 0x01, 0x55, 0x52, 0x4c, 0x20, 0x74, 0x6f, 0x20, 0x4f, 0x49, 0x44, 0x43, 0x20, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, + 0x65, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x27, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x20, + 0x2b, 0x20, 0x2f, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x2d, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x6f, + 0x70, 0x65, 0x6e, 0x69, 0x64, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x27, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x20, 0x52, + 0x0a, 0x6f, 0x69, 0x64, 0x63, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x6f, + 0x69, 0x64, 0x63, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x6f, 0x69, 0x64, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x14, 0x6f, 0x69, 0x64, 0x63, + 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x18, 0x18, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x4f, 0x69, 0x64, + 0x63, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x11, 0x6f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, + 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x58, + 0x0a, 0x0f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2a, 0x12, + 0x28, 0x49, 0x66, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, + 0x61, 0x75, 0x74, 0x68, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x0d, 0x6f, 0x61, 0x75, 0x74, 0x68, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x60, 0x0a, 0x13, 0x6f, 0x61, 0x75, 0x74, + 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2a, 0x12, 0x28, 0x49, + 0x66, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x61, 0x75, + 0x74, 0x68, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x11, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6c, + 0x61, 0x69, 0x6d, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x06, 0x63, + 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x64, 0x65, + 0x62, 0x75, 0x67, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x69, 0x64, 0x63, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x10, + 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x13, 0x12, 0x11, + 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x2e, 0x52, 0x0f, 0x73, 0x61, 0x6d, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xe2, 0xfc, + 0xe3, 0xc4, 0x01, 0x13, 0x12, 0x11, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x2e, 0x52, 0x0e, 0x73, 0x61, 0x6d, 0x6c, 0x50, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x5f, 0x0a, 0x15, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x61, 0x6d, 0x6c, 0x49, 0x64, 0x70, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x72, 0x6c, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x61, - 0x6d, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x2e, - 0x0a, 0x13, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x61, 0x6d, - 0x6c, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x33, - 0x0a, 0x16, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x6f, 0x61, - 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x4f, - 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, - 0x22, 0x67, 0x0a, 0x07, 0x47, 0x55, 0x49, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x48, 0x61, 0x73, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x5f, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x53, 0x61, 0x6c, 0x74, 0x22, 0xa3, 0x01, 0x0a, 0x08, 0x43, 0x41, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x96, 0x01, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x75, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x6f, 0x12, 0x6d, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x41, 0x20, - 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x50, 0x45, 0x4d, 0x2e, 0x20, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x43, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x2e, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, - 0x5f, 0x0a, 0x12, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x21, 0x0a, - 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, - 0x22, 0xe8, 0x02, 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x1e, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x64, 0x6e, 0x73, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x64, - 0x6e, 0x73, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x64, - 0x6e, 0x73, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x64, 0x64, 0x6e, 0x73, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, - 0x23, 0x0a, 0x0d, 0x64, 0x64, 0x6e, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x64, 0x6e, 0x73, 0x48, 0x6f, 0x73, 0x74, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x55, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x70, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x70, 0x55, - 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6e, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x6e, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x69, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, - 0x0a, 0x09, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x7a, 0x6f, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9d, 0x09, 0x0a, 0x17, - 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x38, 0x0a, - 0x18, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, - 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x16, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x65, - 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x65, 0x6e, 0x72, 0x6f, 0x6c, - 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x20, 0x0a, - 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, - 0x28, 0x0a, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x63, 0x6f, 0x6e, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x18, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x60, 0x0a, 0x0f, 0x6d, 0x61, - 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x38, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x32, 0x12, 0x30, 0x4d, 0x61, 0x78, - 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x52, 0x0d, 0x6d, - 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x70, 0x0a, 0x10, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x42, 0x45, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3f, 0x12, 0x3d, - 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, - 0x6f, 0x66, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x20, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x29, 0x52, 0x0f, 0x65, - 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, - 0x0a, 0x16, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x70, 0x6c, - 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, - 0x70, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, - 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x75, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, - 0x65, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x78, - 0x57, 0x61, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x19, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x5f, 0x62, - 0x61, 0x74, 0x63, 0x68, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, - 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x38, - 0x0a, 0x18, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x16, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x6c, 0x72, 0x75, 0x5f, 0x74, 0x74, 0x6c, 0x18, - 0x1b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x4c, 0x72, 0x75, 0x54, 0x74, 0x6c, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x1d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x57, 0x72, 0x69, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x14, 0x6d, 0x61, 0x78, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x42, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x1f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, - 0x6f, 0x67, 0x42, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x48, 0x0a, 0x21, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, - 0x67, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x20, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4d, - 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x6f, 0x67, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, - 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, - 0x6c, 0x65, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0xc6, 0x13, 0x0a, 0x0e, - 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, - 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, - 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x19, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, - 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x18, 0x18, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x48, 0x74, - 0x74, 0x70, 0x12, 0x3e, 0x0a, 0x1b, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x5f, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x73, 0x18, 0x24, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x21, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x35, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x4e, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, 0x58, 0x35, - 0x30, 0x39, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x6f, - 0x66, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, - 0x66, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, + 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, + 0x55, 0x52, 0x4c, 0x2e, 0x52, 0x12, 0x73, 0x61, 0x6d, 0x6c, 0x49, 0x64, 0x70, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x72, 0x6c, 0x12, 0x3a, 0x0a, 0x0d, 0x73, 0x61, 0x6d, 0x6c, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x16, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x10, 0x12, 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x72, 0x6f, + 0x6f, 0x74, 0x20, 0x55, 0x52, 0x4c, 0x2e, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x6c, 0x52, 0x6f, 0x6f, + 0x74, 0x55, 0x72, 0x6c, 0x12, 0x70, 0x0a, 0x13, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x40, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3a, 0x12, 0x38, 0x53, 0x41, 0x4d, 0x4c, 0x20, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, + 0x73, 0x65, 0x72, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x11, 0x73, 0x61, 0x6d, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0xa9, 0x01, 0x0a, 0x0f, 0x73, 0x61, 0x6d, 0x6c, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x09, + 0x42, 0x80, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x7a, 0x12, 0x78, 0x4c, 0x69, 0x73, 0x74, 0x20, + 0x6f, 0x66, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x20, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x20, 0x75, + 0x73, 0x65, 0x72, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, + 0x6c, 0x79, 0x2e, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, + 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x18, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x18, 0x1b, + 0x20, 0x01, 0x28, 0x08, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x41, 0x6c, + 0x6c, 0x6f, 0x77, 0x20, 0x49, 0x64, 0x50, 0x2d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x53, 0x41, 0x4d, 0x4c, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x15, 0x73, 0x61, + 0x6d, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x70, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x74, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x12, 0x73, 0x75, 0x62, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, + 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x11, 0x73, 0x75, 0x62, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x69, 0x0a, 0x16, 0x61, 0x75, 0x74, 0x68, + 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2d, + 0x12, 0x2b, 0x55, 0x52, 0x4c, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x20, 0x41, 0x50, 0x49, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x52, 0x14, 0x61, + 0x75, 0x74, 0x68, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x12, 0x42, 0x0a, 0x1e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, + 0x6f, 0x6c, 0x65, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x16, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1a, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x46, 0x6f, 0x72, 0x55, 0x6e, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, + 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, + 0x79, 0x4d, 0x69, 0x6e, 0x1a, 0x44, 0x0a, 0x16, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, + 0x55, 0x72, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 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, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x89, 0x0c, 0x0a, 0x09, 0x47, + 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x0c, 0x62, 0x69, 0x6e, + 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x75, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x6f, 0x12, 0x6d, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x47, 0x55, 0x49, 0x20, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, + 0x6c, 0x64, 0x20, 0x75, 0x73, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, + 0x62, 0x65, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x20, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, + 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x20, 0x69, 0x74, 0x2e, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x35, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x18, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x12, 0x12, 0x10, + 0x50, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x2e, + 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x17, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x43, 0x69, 0x64, 0x72, 0x12, 0x34, 0x0a, + 0x16, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x66, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6c, 0x61, 0x69, 0x6e, + 0x5f, 0x68, 0x74, 0x74, 0x70, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, + 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x48, 0x74, 0x74, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x73, + 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, + 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0xc3, 0x01, 0x0a, 0x0e, 0x67, 0x77, 0x5f, 0x63, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x9b, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x94, 0x01, 0x12, 0x91, 0x01, 0x54, 0x68, 0x65, 0x20, + 0x47, 0x55, 0x49, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x73, 0x20, 0x61, 0x20, 0x48, 0x54, + 0x54, 0x50, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x67, 0x52, 0x50, 0x43, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x2e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, + 0x52, 0x50, 0x43, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x0d, 0x67, + 0x77, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x0e, + 0x67, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x45, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3f, 0x12, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, - 0x50, 0x45, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x52, 0x0a, 0x70, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x18, 0x74, 0x6c, 0x73, 0x5f, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x74, 0x6c, 0x73, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x37, 0x0a, 0x18, 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x1d, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x15, 0x74, 0x6c, 0x73, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, - 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x64, 0x6e, - 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x1f, 0x12, 0x1d, 0x54, 0x68, 0x65, 0x20, 0x44, 0x4e, 0x53, 0x20, 0x6e, 0x61, - 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x64, 0x2e, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0xbb, 0x02, 0x0a, - 0x19, 0x64, 0x6f, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, - 0x42, 0xff, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0xf8, 0x01, 0x12, 0xf5, 0x01, 0x57, 0x68, 0x65, - 0x6e, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, - 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, - 0x65, 0x62, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x3a, 0x20, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, - 0x68, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, - 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x69, 0x73, 0x63, - 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, - 0x64, 0x2e, 0x52, 0x16, 0x64, 0x6f, 0x4e, 0x6f, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x5a, 0x0a, 0x07, 0x64, 0x79, - 0x6e, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, 0x49, 0x66, 0x20, 0x73, 0x65, 0x74, - 0x20, 0x77, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x79, - 0x6e, 0x20, 0x64, 0x6e, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x06, - 0x64, 0x79, 0x6e, 0x44, 0x6e, 0x73, 0x12, 0x64, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x41, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x3b, 0x12, 0x39, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x64, 0x65, 0x66, - 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, - 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x86, 0x01, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x42, 0x37, 0xe2, 0xfc, 0xe3, 0xc4, - 0x01, 0x31, 0x12, 0x2f, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, - 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x6f, - 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x73, 0x2e, 0x52, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, - 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x1f, 0x20, - 0x03, 0x28, 0x09, 0x42, 0x3e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x38, 0x12, 0x36, 0x41, 0x64, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, - 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x6d, 0x6f, - 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x73, 0x2e, 0x52, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x73, 0x18, 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, - 0x7e, 0x0a, 0x0b, 0x72, 0x75, 0x6e, 0x5f, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x5e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x58, 0x12, 0x56, 0x54, 0x68, - 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, - 0x72, 0x75, 0x6e, 0x20, 0x61, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, - 0x65, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, - 0x61, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x41, 0x73, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x2b, 0x0a, 0x12, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x47, 0x52, 0x50, - 0x43, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2b, 0x0a, 0x12, - 0x47, 0x52, 0x50, 0x43, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, - 0x69, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x47, 0x52, 0x50, 0x43, 0x50, 0x6f, - 0x6f, 0x6c, 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x12, 0x3c, 0x0a, 0x09, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x09, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x6d, 0x69, - 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4d, 0x69, - 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x60, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x42, 0x3e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, - 0x38, 0x12, 0x36, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, - 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x2e, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x60, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x38, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x32, 0x12, 0x30, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, - 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x77, - 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x20, 0x75, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x70, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x03, 0x42, 0x45, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3f, 0x12, 0x3d, 0x45, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x29, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x70, 0x65, - 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, - 0x72, 0x61, 0x74, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x70, 0x65, 0x72, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, - 0x2c, 0x0a, 0x12, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, - 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, - 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, - 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, - 0x12, 0x44, 0x0a, 0x1e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x64, 0x65, 0x66, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x79, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1c, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, - 0x63, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, - 0x18, 0x23, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0f, - 0x64, 0x6f, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, - 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x64, 0x6f, 0x4e, 0x6f, 0x74, 0x52, 0x65, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x22, 0xc2, 0x08, 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6d, 0x70, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x13, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, - 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x38, 0x0a, 0x19, 0x6d, 0x69, 0x6e, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, - 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x62, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x15, 0x6d, 0x69, 0x6e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, 0x69, - 0x6c, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x62, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x69, 0x73, - 0x6b, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x79, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x69, 0x73, - 0x6b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x53, - 0x65, 0x63, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x73, 0x69, - 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x72, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, - 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x12, 0x43, 0x0a, 0x1e, - 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6d, - 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x12, 0x45, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, - 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x6d, 0x65, 0x6d, 0x63, + 0x50, 0x45, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x52, 0x0c, 0x67, 0x77, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe2, + 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x55, 0x72, 0x6c, + 0x12, 0x63, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x42, 0x23, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1d, 0x12, 0x1b, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x20, 0x70, + 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, 0x2e, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x55, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x55, 0x49, + 0x4c, 0x69, 0x6e, 0x6b, 0x42, 0x2f, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x29, 0x12, 0x27, 0x41, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x55, 0x49, 0x2e, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x33, 0x0a, 0x0d, + 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x11, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x55, 0x49, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x12, 0x3a, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x6f, 0x72, 0x67, + 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4f, 0x72, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, + 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4f, 0x72, 0x67, 0x73, 0x12, 0x3a, 0x0a, + 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, + 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x73, 0x18, 0x19, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x61, 0x6d, 0x6c, + 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x73, 0x61, 0x6d, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, + 0x61, 0x6d, 0x6c, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x31, 0x0a, + 0x15, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x69, 0x64, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x61, + 0x6d, 0x6c, 0x49, 0x64, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x72, 0x6c, + 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x75, 0x72, + 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x6c, 0x52, 0x6f, 0x6f, + 0x74, 0x55, 0x72, 0x6c, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x61, 0x6d, 0x6c, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x11, 0x73, 0x61, 0x6d, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x6f, + 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x4f, 0x61, 0x75, 0x74, + 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x5f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x67, 0x0a, 0x07, 0x47, 0x55, 0x49, 0x55, 0x73, 0x65, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x53, 0x61, 0x6c, 0x74, 0x22, + 0xa3, 0x01, 0x0a, 0x08, 0x43, 0x41, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x96, 0x01, 0x0a, + 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x75, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x6f, 0x12, 0x6d, 0x54, 0x68, 0x65, 0x20, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x41, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, + 0x20, 0x50, 0x45, 0x4d, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, + 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x5f, 0x0a, 0x12, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x75, 0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x22, 0xe8, 0x02, 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x44, 0x4e, + 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x68, + 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, + 0x64, 0x6e, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x64, 0x64, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x64, 0x6e, 0x73, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x64, 0x6e, 0x73, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x64, 0x6e, 0x73, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x64, + 0x6e, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x66, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x69, 0x70, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x69, 0x70, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6e, 0x73, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x6e, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x69, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x7a, 0x6f, 0x6e, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0x9d, 0x09, 0x0a, 0x17, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x34, 0x0a, + 0x16, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x65, 0x72, + 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x34, 0x0a, + 0x16, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, + 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x65, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, + 0x2f, 0x0a, 0x13, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x6f, + 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x12, 0x60, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x42, 0x38, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, + 0x32, 0x12, 0x30, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, + 0x66, 0x6f, 0x72, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x70, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x42, 0x45, 0xe2, 0xfc, + 0xe3, 0xc4, 0x01, 0x3f, 0x12, 0x3d, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x29, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x15, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x70, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, + 0x18, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x19, 0x6d, 0x69, + 0x6e, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, + 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x69, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, + 0x18, 0x1a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2d, + 0x0a, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x6c, 0x72, + 0x75, 0x5f, 0x74, 0x74, 0x6c, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x4c, 0x72, 0x75, 0x54, 0x74, 0x6c, 0x12, 0x31, 0x0a, + 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x33, 0x0a, 0x16, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x6a, 0x6f, 0x75, + 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x1c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x4a, 0x6f, 0x75, 0x72, 0x6e, + 0x61, 0x6c, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x16, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, 0x6f, 0x67, 0x42, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x48, 0x0a, 0x21, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6d, 0x6f, 0x6e, + 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1d, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4c, + 0x6f, 0x67, 0x42, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x64, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x75, 0x66, 0x66, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x22, 0xc6, 0x13, 0x0a, 0x0e, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x69, 0x6e, + 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, 0x6e, + 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x5f, + 0x68, 0x74, 0x74, 0x70, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x50, + 0x6c, 0x61, 0x69, 0x6e, 0x48, 0x74, 0x74, 0x70, 0x12, 0x3e, 0x0a, 0x1b, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x35, + 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x25, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x26, 0x12, 0x24, 0x58, 0x35, 0x30, 0x39, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x66, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x45, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x3f, 0x12, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, + 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x50, 0x45, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x2e, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x38, 0x0a, + 0x18, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x16, 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x46, + 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x74, 0x6c, 0x73, 0x5f, 0x70, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x74, 0x6c, 0x73, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x40, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x25, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1f, 0x12, 0x1d, 0x54, 0x68, 0x65, 0x20, + 0x44, 0x4e, 0x53, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x2e, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0xbb, 0x02, 0x0a, 0x19, 0x64, 0x6f, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x42, 0xff, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0xf8, 0x01, + 0x12, 0xf5, 0x01, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x64, + 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x20, + 0x4e, 0x6f, 0x74, 0x65, 0x3a, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x6e, 0x61, 0x6d, + 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x64, 0x69, 0x73, 0x63, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x20, 0x69, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x6e, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x16, 0x64, 0x6f, 0x4e, 0x6f, 0x74, 0x43, + 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x12, 0x5a, 0x0a, 0x07, 0x64, 0x79, 0x6e, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x44, 0x4e, 0x53, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, + 0x49, 0x66, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x64, 0x79, 0x6e, 0x20, 0x64, 0x6e, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x52, 0x06, 0x64, 0x79, 0x6e, 0x44, 0x6e, 0x73, 0x12, 0x64, 0x0a, 0x0c, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x41, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3b, 0x12, 0x39, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, + 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x86, 0x01, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, + 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, + 0x42, 0x37, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x31, 0x12, 0x2f, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x52, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x23, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x09, 0x42, 0x3e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, + 0x38, 0x12, 0x36, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x52, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x7e, 0x0a, 0x0b, 0x72, 0x75, 0x6e, 0x5f, 0x61, 0x73, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x42, 0x5e, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x58, 0x12, 0x56, 0x54, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x73, + 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x61, 0x73, 0x2e, 0x20, 0x49, 0x66, + 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x41, + 0x73, 0x55, 0x73, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x12, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x70, 0x6f, + 0x6f, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0f, 0x47, 0x52, 0x50, 0x43, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x61, 0x78, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x2b, 0x0a, 0x12, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, + 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, + 0x47, 0x52, 0x50, 0x43, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x12, + 0x3c, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x72, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x69, 0x73, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x69, 0x73, 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x60, 0x0a, 0x0b, 0x63, 0x6f, + 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x3e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x38, 0x12, 0x36, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x2e, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x60, 0x0a, 0x0f, + 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x04, 0x42, 0x38, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x32, 0x12, 0x30, 0x4d, + 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x52, + 0x0d, 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x70, + 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x42, 0x45, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3f, + 0x12, 0x3d, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x20, + 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x29, 0x52, + 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, + 0x12, 0x33, 0x0a, 0x16, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x13, 0x70, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, + 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, + 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x18, 0x17, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, + 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x12, 0x44, 0x0a, 0x1e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1c, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x34, 0x0a, 0x16, + 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x23, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x63, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x67, + 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x6f, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x64, 0x6f, 0x4e, + 0x6f, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, 0xc2, 0x08, 0x0a, 0x0f, 0x44, + 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, + 0x0a, 0x0e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x13, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x12, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x19, 0x6d, 0x69, 0x6e, 0x5f, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, + 0x6d, 0x62, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6d, 0x69, 0x6e, 0x41, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x62, 0x12, + 0x37, 0x0a, 0x18, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x66, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x15, 0x64, 0x69, 0x73, 0x6b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x46, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x65, 0x63, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, + 0x64, 0x69, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, + 0x6d, 0x61, 0x78, 0x44, 0x69, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x65, + 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x65, 0x6d, + 0x63, 0x61, 0x63, 0x68, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x65, 0x63, 0x12, 0x43, 0x0a, 0x1e, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x75, + 0x66, 0x66, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x6d, 0x65, 0x6d, 0x63, - 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, - 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6d, 0x65, 0x6d, - 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x4d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x69, 0x6e, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6d, 0x65, - 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x41, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, + 0x6e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, 0x63, 0x61, + 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x1c, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4d, + 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x72, 0x73, 0x12, 0x39, + 0x0a, 0x19, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x16, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x4d, 0x61, 0x78, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x12, - 0x3d, 0x0a, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x44, 0x61, - 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x46, - 0x0a, 0x20, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x73, 0x69, - 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, - 0x68, 0x65, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x74, - 0x65, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x44, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, - 0x68, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x4d, 0x61, 0x78, 0x44, 0x69, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x41, 0x0a, 0x1d, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x5f, 0x72, 0x70, 0x63, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x1a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x52, 0x70, 0x63, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, - 0x33, 0x0a, 0x15, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, - 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, - 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x14, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x01, 0x0a, 0x0c, 0x4d, 0x69, - 0x6e, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x6f, - 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, - 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xaa, 0x03, 0x0a, - 0x0a, 0x4d, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x65, 0x0a, 0x04, 0x66, - 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x51, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, - 0x4b, 0x12, 0x49, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6d, 0x61, - 0x69, 0x6c, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x6e, - 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, - 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, - 0x74, 0x68, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x04, 0x66, 0x72, - 0x6f, 0x6d, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x23, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1d, 0x12, 0x1b, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x4d, 0x54, 0x50, 0x20, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, - 0x40, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x1f, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x19, 0x12, 0x17, 0x50, 0x6f, - 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x72, - 0x74, 0x12, 0x48, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1d, - 0x12, 0x1b, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x0c, 0x61, - 0x75, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0d, 0x61, - 0x75, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x2e, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, - 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x69, 0x70, - 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, - 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x22, 0x72, 0x0a, 0x16, 0x4c, 0x6f, 0x67, - 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x72, 0x6f, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, - 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x41, 0x67, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xfb, 0x05, - 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x75, 0x0a, 0x10, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x4a, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, - 0x44, 0x12, 0x42, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x74, 0x6f, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, - 0x65, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x6e, 0x6f, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x7a, 0x0a, 0x1b, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, - 0x74, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x70, - 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x42, 0x3b, 0xe2, 0xfc, 0xe3, - 0xc4, 0x01, 0x35, 0x12, 0x33, 0x49, 0x66, 0x20, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x65, 0x61, 0x63, - 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, - 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, - 0x74, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x18, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, - 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, - 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0d, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, - 0x20, 0x12, 0x1e, 0x48, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x74, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, - 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x2e, 0x52, 0x0c, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x6b, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x52, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x4c, 0x12, 0x40, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, - 0x6d, 0x20, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, - 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, - 0x68, 0x69, 0x73, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x29, 0x2e, 0x32, 0x08, 0x33, 0x31, 0x35, 0x33, - 0x36, 0x30, 0x30, 0x30, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x05, - 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, - 0x67, 0x12, 0x31, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, - 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x14, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, - 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x53, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x6c, - 0x6f, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x79, 0x73, 0x6c, 0x6f, - 0x67, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x99, 0x02, 0x0a, 0x10, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x9f, 0x01, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x7c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x76, 0x12, - 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, - 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, - 0x64, 0x20, 0x75, 0x73, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, - 0x65, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x20, 0x6f, 0x74, 0x68, - 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, - 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x73, 0x65, 0x63, 0x75, 0x72, - 0x65, 0x20, 0x69, 0x74, 0x2e, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x25, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1f, 0x12, 0x1d, 0x50, - 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x52, 0x08, 0x62, 0x69, - 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x55, 0x72, 0x6c, 0x22, 0x68, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x6f, 0x45, - 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, - 0x76, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x76, 0x12, 0x42, 0x0a, - 0x14, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x13, 0x61, 0x72, - 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x22, 0xc1, 0x09, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x75, - 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x68, 0x75, 0x6e, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x27, 0x0a, - 0x0f, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x75, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x70, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, - 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, - 0x2b, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, - 0x72, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x72, - 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x79, 0x6e, 0x5f, 0x64, - 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x79, 0x6e, 0x44, 0x6e, 0x73, - 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x79, - 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x73, 0x61, 0x6e, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x1f, 0x0a, - 0x0b, 0x76, 0x66, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x76, 0x66, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2d, - 0x0a, 0x12, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, - 0x0a, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, - 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, - 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x75, 0x69, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x67, 0x75, 0x69, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, - 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0e, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, - 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x31, 0x0a, 0x14, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x13, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x11, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x19, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x69, - 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, - 0x65, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, - 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x18, 0x17, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x6e, - 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, - 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, - 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x10, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x62, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x68, 0x74, - 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, - 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x68, 0x74, 0x74, 0x70, 0x43, 0x6f, 0x6d, 0x6d, 0x75, - 0x6e, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x1c, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xe3, 0x14, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x79, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x68, - 0x75, 0x6e, 0x74, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x48, 0x6f, 0x75, 0x72, 0x73, 0x12, 0x3d, - 0x0a, 0x1b, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x72, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x2b, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x18, 0x68, 0x75, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x72, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x65, 0x63, 0x12, 0x42, 0x0a, - 0x1e, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, - 0x39, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x6f, 0x77, - 0x73, 0x12, 0x39, 0x0a, 0x19, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x63, 0x65, - 0x6c, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x65, - 0x6c, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x1e, - 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, - 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x24, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, - 0x6d, 0x6f, 0x72, 0x79, 0x4c, 0x6f, 0x77, 0x57, 0x61, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x72, 0x6b, - 0x12, 0x44, 0x0a, 0x1f, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x6d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x5f, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x6d, - 0x61, 0x72, 0x6b, 0x18, 0x25, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1b, 0x6e, 0x6f, 0x74, 0x65, 0x62, - 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x48, 0x69, 0x67, 0x68, 0x57, 0x61, 0x74, - 0x65, 0x72, 0x4d, 0x61, 0x72, 0x6b, 0x12, 0x45, 0x0a, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, - 0x6f, 0x6b, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, - 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x73, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x1b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x57, 0x61, 0x69, 0x74, 0x54, 0x69, - 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4d, 0x73, 0x12, 0x46, 0x0a, - 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x73, 0x18, 0x26, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, - 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, - 0x6b, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x18, 0x27, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, - 0x6b, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, - 0x2b, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x6f, 0x74, 0x65, - 0x62, 0x6f, 0x6f, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, - 0x63, 0x73, 0x76, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x73, 0x76, 0x44, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, - 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, - 0x61, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x12, 0x31, 0x0a, 0x15, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x6a, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x78, - 0x57, 0x61, 0x69, 0x74, 0x4a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x1f, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x1b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x66, 0x73, 0x5f, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x13, 0x6d, 0x61, 0x78, 0x56, 0x66, 0x73, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x48, 0x0a, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x1e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, - 0x32, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, - 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x62, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x12, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x42, 0x79, 0x12, 0x2d, 0x0a, 0x13, 0x61, 0x63, 0x6c, 0x5f, 0x6c, 0x72, 0x75, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x10, 0x61, 0x63, 0x6c, 0x4c, 0x72, 0x75, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, - 0x65, 0x63, 0x12, 0x45, 0x0a, 0x1f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x72, 0x75, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x75, 0x6e, 0x61, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4c, 0x72, 0x75, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x61, 0x78, - 0x5f, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6d, 0x61, 0x78, 0x53, 0x70, - 0x61, 0x72, 0x73, 0x65, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x32, - 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x1b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x14, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x19, 0x64, 0x69, 0x73, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x71, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x5f, 0x62, - 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x51, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x42, 0x75, - 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, - 0x74, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, - 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, - 0x52, 0x6f, 0x77, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x6f, 0x67, 0x73, - 0x18, 0x38, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x4c, 0x6f, 0x67, 0x73, 0x12, - 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, - 0x78, 0x52, 0x6f, 0x77, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, - 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x77, 0x61, 0x69, 0x74, - 0x18, 0x23, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x57, 0x61, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, - 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x28, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x11, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x12, 0x33, 0x0a, 0x16, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6d, 0x61, - 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x29, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x13, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x61, 0x78, 0x54, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x12, 0x34, 0x0a, 0x16, 0x77, 0x61, 0x74, 0x63, - 0x68, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, - 0x63, 0x79, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x77, 0x61, 0x74, 0x63, 0x68, 0x50, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x37, - 0x0a, 0x18, 0x77, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x15, 0x77, 0x61, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x62, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x18, 0x2f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x65, - 0x72, 0x69, 0x6f, 0x64, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x68, 0x6f, 0x75, 0x73, 0x65, - 0x6b, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x30, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x48, 0x6f, 0x75, 0x73, 0x65, 0x6b, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x69, - 0x6f, 0x64, 0x12, 0x3a, 0x0a, 0x19, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x6e, - 0x69, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, - 0x31, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x6e, - 0x69, 0x63, 0x6f, 0x64, 0x65, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, - 0x0a, 0x16, 0x72, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, - 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x32, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, - 0x72, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x33, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x1e, - 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, - 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x34, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x49, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, - 0x69, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x35, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x13, 0x77, 0x72, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, - 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x2b, - 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, - 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x6e, 0x69, - 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x36, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, - 0x29, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x37, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x69, 0x65, - 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, - 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x18, 0x3a, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, - 0x6e, 0x5f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x20, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6c, 0x6f, 0x63, 0x6b, - 0x64, 0x6f, 0x77, 0x6e, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x61, - 0x79, 0x73, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x44, 0x61, 0x79, - 0x73, 0x12, 0x58, 0x0a, 0x29, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x76, - 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x22, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x6e, 0x76, - 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0xad, 0x04, 0x0a, 0x0c, - 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, - 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x73, 0x12, 0x7f, 0x0a, 0x17, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x68, 0x75, 0x6d, 0x62, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x46, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x40, 0x12, 0x3e, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, 0x74, 0x68, 0x75, - 0x6d, 0x62, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x2e, 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x12, 0xd5, 0x01, 0x0a, - 0x1d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x90, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x89, 0x01, 0x12, 0x86, - 0x01, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, - 0x20, 0x69, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x56, 0x65, 0x6c, 0x6f, 0x63, 0x69, - 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, - 0x54, 0x4c, 0x53, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, - 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x3a, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x29, 0x2c, 0x20, 0x50, 0x4b, 0x49, 0x5f, 0x4f, 0x52, 0x5f, 0x54, 0x48, 0x55, 0x4d, - 0x42, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x2c, 0x20, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x50, 0x52, 0x49, - 0x4e, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x52, 0x1b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x65, - 0x61, 0x6b, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x65, 0x61, 0x6b, 0x54, 0x6c, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x1e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x72, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x5d, 0x0a, 0x0a, 0x4d, - 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1b, 0x0a, - 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x22, 0xf0, 0x02, 0x0a, 0x0f, 0x52, - 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x66, 0x72, - 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x04, 0x66, 0x72, 0x6f, - 0x6d, 0x12, 0x21, 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x02, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x51, 0x4c, 0x45, 0x6e, 0x76, 0x52, 0x03, - 0x65, 0x6e, 0x76, 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x22, 0xd6, 0x06, - 0x0a, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x1c, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3d, 0x0a, 0x1b, 0x64, - 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x3b, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x18, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, - 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, - 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x39, 0x0a, 0x19, 0x64, 0x65, 0x6e, 0x69, 0x65, - 0x64, 0x5f, 0x66, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x3c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x64, 0x65, 0x6e, 0x69, - 0x65, 0x64, 0x46, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x18, 0x0c, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x36, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, - 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, - 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x37, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x46, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x69, 0x65, - 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x18, 0x3a, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, - 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x64, - 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x20, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, - 0x6e, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, - 0x21, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x44, 0x61, 0x79, 0x73, 0x12, 0x58, - 0x0a, 0x29, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, - 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x25, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, - 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x73, 0x5f, 0x64, 0x65, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, - 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x44, 0x65, 0x6b, 0x12, 0x2f, 0x0a, 0x14, 0x76, 0x71, 0x6c, - 0x5f, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x76, 0x71, 0x6c, 0x4d, 0x75, 0x73, 0x74, - 0x55, 0x73, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x68, - 0x61, 0x64, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x65, 0x64, 0x45, - 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x22, 0xc3, 0x0d, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x2b, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e, - 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x46, - 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, - 0x1c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x16, 0x12, 0x14, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x1d, 0xe2, 0xfc, 0xe3, - 0xc4, 0x01, 0x17, 0x12, 0x15, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x06, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x03, 0x41, 0x50, 0x49, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x50, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x52, 0x50, - 0x43, 0x20, 0x41, 0x50, 0x49, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, - 0x03, 0x41, 0x50, 0x49, 0x12, 0x22, 0x0a, 0x03, 0x47, 0x55, 0x49, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x55, 0x49, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x03, 0x47, 0x55, 0x49, 0x12, 0x1f, 0x0a, 0x02, 0x43, 0x41, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x41, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x02, 0x43, 0x41, 0x12, 0x31, 0x0a, 0x08, 0x46, 0x72, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x08, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x12, 0x3d, 0x0a, 0x0e, - 0x45, 0x78, 0x74, 0x72, 0x61, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x73, 0x18, 0x1f, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x72, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x45, 0x78, 0x74, - 0x72, 0x61, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x44, - 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x12, 0x32, 0x0a, 0x09, 0x57, 0x72, 0x69, 0x74, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x04, 0x4d, 0x61, 0x69, 0x6c, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x61, 0x69, 0x6c, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x2e, 0x0a, 0x07, - 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x07, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x06, - 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x06, 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x62, 0x6f, 0x73, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, - 0x01, 0x20, 0x12, 0x1e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x76, 0x65, 0x72, 0x62, 0x6f, - 0x73, 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x2e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x13, 0x61, - 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x63, 0x61, 0x63, - 0x68, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, - 0x12, 0x24, 0x50, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x11, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, - 0x43, 0x65, 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x6e, 0x0a, 0x0a, 0x4d, 0x6f, 0x6e, - 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x35, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2f, 0x12, 0x2d, - 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x70, 0x72, - 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, - 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x0a, 0x4d, - 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x7f, 0x0a, 0x0a, 0x61, 0x70, 0x69, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x69, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x48, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x42, 0x12, 0x40, 0x49, - 0x66, 0x20, 0x77, 0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x70, 0x69, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x77, 0x65, 0x20, 0x6c, 0x6f, - 0x61, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, - 0x09, 0x61, 0x70, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x8f, 0x01, 0x0a, 0x08, 0x61, - 0x75, 0x74, 0x6f, 0x65, 0x78, 0x65, 0x63, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x42, 0x5c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x56, 0x12, 0x54, 0x49, 0x66, - 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x20, 0x77, 0x65, 0x20, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, - 0x79, 0x2e, 0x52, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x65, 0x78, 0x65, 0x63, 0x12, 0x50, 0x0a, 0x0b, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x2f, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x29, 0x12, 0x27, 0x54, 0x79, 0x70, 0x65, 0x20, - 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x28, 0x6c, 0x69, 0x6e, 0x75, 0x78, - 0x2c, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x72, 0x77, 0x69, - 0x6e, 0x29, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2b, - 0x0a, 0x11, 0x6f, 0x62, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, - 0x6e, 0x63, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x62, 0x66, 0x75, 0x73, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x08, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x6e, 0x61, 0x6c, - 0x79, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x22, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x12, 0x36, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x23, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x72, - 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, - 0x5f, 0x69, 0x64, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, - 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x25, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, - 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, - 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, - 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x27, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x42, 0x34, 0x5a, 0x32, - 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x72, - 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x41, 0x67, 0x65, 0x12, + 0x44, 0x0a, 0x1f, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, + 0x65, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, + 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, + 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x61, 0x78, 0x41, 0x67, 0x65, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, + 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x6d, 0x65, 0x6d, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x61, 0x78, + 0x53, 0x69, 0x7a, 0x65, 0x12, 0x46, 0x0a, 0x20, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, + 0x5f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x69, + 0x74, 0x65, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, + 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x4d, 0x61, 0x78, 0x49, 0x74, 0x65, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x44, 0x0a, 0x1f, + 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6d, 0x65, 0x6d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x44, + 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x61, 0x78, 0x44, 0x69, 0x72, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x64, 0x61, 0x74, + 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x70, 0x63, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, + 0x69, 0x6e, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x70, 0x63, 0x44, 0x65, 0x61, + 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x33, 0x0a, 0x15, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x49, 0x6d, 0x70, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x6d, 0x61, + 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x6d, 0x61, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x90, 0x01, 0x0a, 0x0c, 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x6e, 0x6f, 0x74, 0x65, + 0x62, 0x6f, 0x6f, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x6e, 0x6f, 0x74, 0x65, + 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6e, 0x6f, 0x74, 0x65, + 0x62, 0x6f, 0x6f, 0x6b, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x22, 0xaa, 0x03, 0x0a, 0x0a, 0x4d, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x65, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x51, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x4b, 0x12, 0x49, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x62, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x2e, 0x20, 0x49, 0x66, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x2e, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1d, + 0x12, 0x1b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x06, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, + 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x1f, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x19, 0x12, 0x17, 0x50, 0x6f, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x53, 0x4d, 0x54, 0x50, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x48, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, + 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x1d, 0x12, 0x1b, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x75, 0x6e, 0x64, + 0x65, 0x72, 0x2e, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x4b, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, + 0x12, 0x1e, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x2e, + 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1f, + 0x0a, 0x0b, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x22, + 0x72, 0x0a, 0x16, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0c, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x17, + 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x6d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x22, 0xfb, 0x05, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x75, 0x0a, 0x10, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x4a, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x44, 0x12, 0x42, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x6c, + 0x6f, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, + 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x6e, 0x6f, + 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x0f, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x7a, 0x0a, 0x1b, + 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x70, 0x65, + 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x42, 0x3b, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x35, 0x12, 0x33, 0x49, 0x66, 0x20, 0x73, 0x65, + 0x74, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, + 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, + 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x18, + 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x65, 0x72, 0x43, + 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0d, 0x72, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x48, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x74, + 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x0c, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x6b, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x52, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x4c, 0x12, 0x40, + 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65, + 0x61, 0x63, 0x68, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x20, 0x61, + 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x29, 0x2e, + 0x32, 0x08, 0x33, 0x31, 0x35, 0x33, 0x36, 0x30, 0x30, 0x30, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x41, + 0x67, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x12, 0x31, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, + 0x67, 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x30, 0x0a, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x6c, + 0x6f, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x5f, 0x73, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x53, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, + 0x73, 0x22, 0x99, 0x02, 0x0a, 0x10, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x9f, 0x01, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x7c, 0xe2, + 0xfc, 0xe3, 0xc4, 0x01, 0x76, 0x12, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, + 0x67, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x75, 0x73, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, + 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, + 0x31, 0x2c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x65, 0x20, + 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, + 0x20, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x69, 0x74, 0x2e, 0x52, 0x0b, 0x62, 0x69, 0x6e, + 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x25, 0xe2, 0xfc, 0xe3, + 0xc4, 0x01, 0x1f, 0x12, 0x1d, 0x50, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, + 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x55, 0x72, 0x6c, 0x22, 0x68, 0x0a, + 0x0e, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x76, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, + 0x72, 0x67, 0x76, 0x12, 0x42, 0x0a, 0x14, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x52, 0x13, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xc1, 0x09, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x75, 0x6e, 0x74, 0x4d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x75, + 0x6e, 0x74, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, + 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x17, 0x0a, + 0x07, 0x64, 0x79, 0x6e, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x64, 0x79, 0x6e, 0x44, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, + 0x6f, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, + 0x73, 0x61, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x61, 0x6e, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x66, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x76, 0x66, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x72, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, + 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2d, 0x0a, 0x12, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x11, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x66, 0x72, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, + 0x75, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x67, 0x75, 0x69, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x27, 0x0a, + 0x0f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x14, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, + 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x72, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x74, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, + 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, + 0x72, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, + 0x72, 0x12, 0x29, 0x0a, 0x10, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6e, 0x6f, 0x74, + 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x11, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x2b, 0x0a, 0x11, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x68, 0x74, 0x74, + 0x70, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2c, 0x0a, + 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xe3, 0x14, 0x0a, 0x08, + 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x75, 0x6e, 0x74, + 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x68, 0x75, 0x6e, 0x74, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x48, + 0x6f, 0x75, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, + 0x73, 0x65, 0x63, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x68, 0x75, 0x6e, 0x74, 0x44, + 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, + 0x53, 0x65, 0x63, 0x12, 0x42, 0x0a, 0x1e, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x65, 0x6c, 0x6c, + 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x39, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x6e, 0x6f, 0x74, + 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x65, 0x77, 0x43, + 0x65, 0x6c, 0x6c, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x6e, 0x6f, 0x74, 0x65, 0x62, + 0x6f, 0x6f, 0x6b, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6e, 0x6f, 0x74, 0x65, + 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, + 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x1e, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x6d, + 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, + 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x24, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x6e, 0x6f, 0x74, 0x65, + 0x62, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4c, 0x6f, 0x77, 0x57, 0x61, 0x74, + 0x65, 0x72, 0x4d, 0x61, 0x72, 0x6b, 0x12, 0x44, 0x0a, 0x1f, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, + 0x6f, 0x6b, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x77, + 0x61, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x25, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x1b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x48, + 0x69, 0x67, 0x68, 0x57, 0x61, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x72, 0x6b, 0x12, 0x45, 0x0a, 0x20, + 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x73, + 0x18, 0x2e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, + 0x57, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, + 0x72, 0x4d, 0x73, 0x12, 0x46, 0x0a, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, + 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x26, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x6e, + 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x6e, + 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x70, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x27, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6e, + 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x69, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, + 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x10, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x73, 0x76, 0x5f, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x73, 0x76, 0x44, 0x65, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x12, 0x31, 0x0a, + 0x15, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, + 0x6a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x78, 0x57, 0x61, 0x69, 0x74, 0x4a, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x12, 0x44, 0x0a, 0x1f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x41, 0x6c, 0x6c, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x66, + 0x73, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6d, 0x61, 0x78, 0x56, 0x66, 0x73, 0x44, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x48, 0x0a, 0x20, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, + 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x5f, + 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x62, 0x79, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x4d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x79, 0x12, 0x2d, 0x0a, 0x13, 0x61, 0x63, 0x6c, + 0x5f, 0x6c, 0x72, 0x75, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x61, 0x63, 0x6c, 0x4c, 0x72, 0x75, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x12, 0x45, 0x0a, 0x1f, 0x75, 0x6e, 0x61, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x72, 0x75, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x1c, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x64, 0x4c, 0x72, 0x75, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x12, + 0x33, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x65, 0x78, + 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x13, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, + 0x53, 0x69, 0x7a, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x1a, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x75, 0x74, 0x68, + 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x61, 0x75, 0x74, 0x68, 0x52, 0x65, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x3a, + 0x0a, 0x19, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x71, 0x75, 0x61, 0x72, 0x61, 0x6e, + 0x74, 0x69, 0x6e, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x18, 0x1c, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x51, 0x75, 0x61, 0x72, 0x61, 0x6e, + 0x74, 0x69, 0x6e, 0x65, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x68, 0x65, 0x6d, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x1e, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, + 0x78, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x38, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, + 0x78, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, + 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x1f, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, + 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x18, 0x23, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x61, + 0x78, 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x61, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x18, 0x28, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, + 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x33, 0x0a, 0x16, 0x65, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, + 0x73, 0x65, 0x63, 0x18, 0x29, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x65, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x4d, 0x61, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x12, 0x34, + 0x0a, 0x16, 0x77, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x66, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, + 0x77, 0x61, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x6e, 0x63, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x77, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x2d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x77, 0x61, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x32, 0x0a, + 0x15, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, + 0x5f, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x6b, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, + 0x72, 0x69, 0x6f, 0x64, 0x18, 0x30, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x6f, 0x75, 0x73, 0x65, 0x6b, 0x65, 0x65, 0x70, 0x69, + 0x6e, 0x67, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x3a, 0x0a, 0x19, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x31, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x55, 0x6e, 0x69, 0x63, 0x6f, 0x64, 0x65, 0x55, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, + 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x32, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x72, 0x65, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x50, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x33, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x43, 0x0a, 0x1e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x73, 0x18, 0x34, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x66, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3b, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x69, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x35, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x77, 0x72, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x50, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, + 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x25, + 0x0a, 0x0e, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, + 0x18, 0x36, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, + 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x37, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x6f, 0x72, 0x73, 0x18, 0x3a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x69, + 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x6c, + 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x20, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x19, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, + 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x69, 0x74, 0x79, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x69, 0x74, 0x79, 0x44, 0x61, 0x79, 0x73, 0x12, 0x58, 0x0a, 0x29, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x22, 0xad, 0x04, 0x0a, 0x0c, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x73, 0x12, 0x7f, 0x0a, 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x5f, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x42, 0x46, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x40, 0x12, 0x3e, 0x53, 0x48, 0x41, 0x32, + 0x35, 0x36, 0x20, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x20, 0x6f, + 0x66, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, + 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x54, 0x68, 0x75, 0x6d, 0x62, 0x70, 0x72, 0x69, 0x6e, + 0x74, 0x73, 0x12, 0xd5, 0x01, 0x0a, 0x1d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x90, 0x01, 0xe2, 0xfc, 0xe3, + 0xc4, 0x01, 0x89, 0x01, 0x12, 0x86, 0x01, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, + 0x56, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x54, 0x4c, 0x53, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3a, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x28, 0x74, 0x68, 0x65, + 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x29, 0x2c, 0x20, 0x50, 0x4b, 0x49, 0x5f, 0x4f, + 0x52, 0x5f, 0x54, 0x48, 0x55, 0x4d, 0x42, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x2c, 0x20, 0x54, 0x48, + 0x55, 0x4d, 0x42, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x52, 0x1b, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x65, 0x61, 0x6b, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x57, 0x65, 0x61, 0x6b, 0x54, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x0a, + 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x1e, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x22, 0x5d, 0x0a, 0x0a, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, + 0x22, 0xf0, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, + 0x6f, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x12, 0x25, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x21, 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, + 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x02, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0e, 0x0a, 0x02, + 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x51, + 0x4c, 0x45, 0x6e, 0x76, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x46, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x73, 0x22, 0xd6, 0x06, 0x0a, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x12, 0x3f, 0x0a, 0x1c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, + 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, + 0x69, 0x6c, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x12, 0x3d, 0x0a, 0x1b, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, + 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x3b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x73, 0x5f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, 0x73, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x39, 0x0a, + 0x19, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x3c, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x16, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x46, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x6f, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, + 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x6f, 0x72, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, + 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x36, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x37, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, + 0x6e, 0x69, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, + 0x10, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, + 0x73, 0x18, 0x3a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x6c, 0x6f, 0x63, 0x6b, + 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x20, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6c, + 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x63, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, + 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, + 0x44, 0x61, 0x79, 0x73, 0x12, 0x58, 0x0a, 0x29, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x5f, 0x64, 0x65, 0x6b, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x44, 0x65, 0x6b, 0x12, + 0x2f, 0x0a, 0x14, 0x76, 0x71, 0x6c, 0x5f, 0x6d, 0x75, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x5f, + 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x76, + 0x71, 0x6c, 0x4d, 0x75, 0x73, 0x74, 0x55, 0x73, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, + 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x76, + 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x68, 0x61, + 0x64, 0x6f, 0x77, 0x65, 0x64, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x22, 0xc3, 0x0d, 0x0a, + 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x63, + 0x65, 0x72, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x44, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x46, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x1c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x16, 0x12, 0x14, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x06, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x42, 0x1d, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x17, 0x12, 0x15, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x03, 0x41, 0x50, 0x49, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x50, + 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x2c, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, + 0x24, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x67, 0x52, 0x50, 0x43, 0x20, 0x41, 0x50, 0x49, 0x20, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x03, 0x41, 0x50, 0x49, 0x12, 0x22, 0x0a, 0x03, 0x47, 0x55, + 0x49, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x47, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x47, 0x55, 0x49, 0x12, 0x1f, + 0x0a, 0x02, 0x43, 0x41, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x43, 0x41, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x02, 0x43, 0x41, 0x12, + 0x31, 0x0a, 0x08, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x64, 0x12, 0x3d, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x46, 0x72, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x64, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x0e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, + 0x73, 0x12, 0x34, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x44, 0x61, + 0x74, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x62, 0x61, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x09, 0x57, 0x72, 0x69, 0x74, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x04, 0x4d, + 0x61, 0x69, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x4d, 0x61, 0x69, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, 0x4d, 0x61, + 0x69, 0x6c, 0x12, 0x2e, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x18, 0x17, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x67, + 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x4c, 0x6f, 0x67, 0x67, 0x69, + 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x06, 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x28, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x69, 0x6e, 0x69, 0x6f, + 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x4d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x12, + 0x40, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, + 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, + 0x65, 0x12, 0x5c, 0x0a, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x63, 0x65, + 0x72, 0x74, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2c, + 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x26, 0x12, 0x24, 0x50, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x20, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x11, 0x61, 0x75, + 0x74, 0x6f, 0x63, 0x65, 0x72, 0x74, 0x43, 0x65, 0x72, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, + 0x6e, 0x0a, 0x0a, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x19, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x35, 0xe2, 0xfc, + 0xe3, 0xc4, 0x01, 0x2f, 0x12, 0x2d, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, + 0x69, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x20, 0x6d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x2e, 0x52, 0x0a, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, + 0x7f, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x70, 0x69, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x48, 0xe2, 0xfc, 0xe3, + 0xc4, 0x01, 0x42, 0x12, 0x40, 0x49, 0x66, 0x20, 0x77, 0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x65, + 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x69, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x20, 0x77, 0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, + 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x09, 0x61, 0x70, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x8f, 0x01, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x65, 0x78, 0x65, 0x63, 0x18, 0x1c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x6f, + 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x5c, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x56, 0x12, 0x54, 0x49, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, + 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77, 0x65, 0x20, 0x6c, 0x61, 0x75, 0x6e, + 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x2e, 0x52, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x65, 0x78, + 0x65, 0x63, 0x12, 0x50, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x29, 0x12, + 0x27, 0x54, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x28, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2c, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2c, + 0x20, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x29, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x62, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x10, 0x6f, 0x62, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x21, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x73, 0x52, 0x08, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x27, + 0x0a, 0x0f, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, + 0x73, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x23, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x15, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x67, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x67, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x29, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x37, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x26, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, + 0x77, 0x6e, 0x18, 0x27, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, + 0x77, 0x6e, 0x42, 0x34, 0x5a, 0x32, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, + 0x64, 0x65, 0x78, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x76, + 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/config/proto/config.proto b/config/proto/config.proto index 29545d0997c..a9015979a24 100644 --- a/config/proto/config.proto +++ b/config/proto/config.proto @@ -475,6 +475,12 @@ message OIDCClaims { // roles: // - reader map role_map = 3; + + // Velociraptor usually requires the email_verified claim before + // we can trust the email claim and use it as the + // username. However, some IDP (e.g. Azure) do not set this. If + // you want to ignore this requirement, set the below to true. + bool allow_unverified_email = 4; } message Authenticator { From 7d28f332d7b5df01febe62ad2e7d85f6a2f6b00c Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Tue, 9 Dec 2025 16:51:14 +1000 Subject: [PATCH 06/11] Added more tests --- api/authenticators/claims.go | 25 +- api/authenticators/claims_test.go | 220 +++++++++++++++++- .../fixtures/TestProvider.golden | 151 ++++++++++-- api/authenticators/http.go | 5 +- 4 files changed, 380 insertions(+), 21 deletions(-) diff --git a/api/authenticators/claims.go b/api/authenticators/claims.go index 87cc827dd72..60ad6701439 100644 --- a/api/authenticators/claims.go +++ b/api/authenticators/claims.go @@ -69,7 +69,8 @@ func NewOidcClaimsGetter( if err != nil { return nil, err } - router.SetEndpoint(delegate.Endpoint()) + ep := delegate.Endpoint() + router.SetEndpoint(ep) return &OidcClaimsGetter{ config_obj: config_obj, @@ -134,6 +135,25 @@ func (self *OidcClaimsGetter) GetClaims( return self.newClaimsFromDict(ctx, self.config_obj, claims_dict) } +func (self *OidcClaimsGetter) shouldRequireEmailVerify( + authenticator *config_proto.Authenticator) bool { + if authenticator.Claims == nil { + return true + } + + if authenticator.Claims.AllowUnverifiedEmail { + return false + } + + // If the user wants to use a different claim than email then + // email verified is not relevant. + if authenticator.Claims.Username != "" { + return false + } + + return true +} + func (self *OidcClaimsGetter) getClaims( ctx context.Context, token *oauth2.Token) (claims *ordereddict.Dict, err error) { @@ -145,8 +165,7 @@ func (self *OidcClaimsGetter) getClaims( // Make sure the user's email is verified because this is what we // use as the identity. if !user_info.EmailVerified && - (self.authenticator.Claims == nil || - !self.authenticator.Claims.AllowUnverifiedEmail) { + self.shouldRequireEmailVerify(self.authenticator) { return nil, fmt.Errorf("Email %v is not verified", user_info.Email) } diff --git a/api/authenticators/claims_test.go b/api/authenticators/claims_test.go index 72de23dbb57..cc8f9f46022 100644 --- a/api/authenticators/claims_test.go +++ b/api/authenticators/claims_test.go @@ -6,16 +6,21 @@ import ( "fmt" "io" "net/http" + "strings" "testing" "github.com/Velocidex/ordereddict" + "github.com/stretchr/testify/suite" "www.velocidex.com/golang/velociraptor/config" config_proto "www.velocidex.com/golang/velociraptor/config/proto" + "www.velocidex.com/golang/velociraptor/file_store/test_utils" "www.velocidex.com/golang/velociraptor/json" "www.velocidex.com/golang/velociraptor/vtesting/assert" "www.velocidex.com/golang/velociraptor/vtesting/goldie" ) +// Replay responses to HTTP requests. Allows us to mock out the HTTP +// transactions. type StaticURLReplayer struct { name string err_regex string @@ -31,11 +36,23 @@ func (self *StaticURLReplayer) GetRoundTrip(rt RoundTripFunc) RoundTripFunc { if !pres { fmt.Printf("Unknown request: %v\n", req.URL.String()) } + resp = strings.TrimSpace(resp) - return &http.Response{ + result := &http.Response{ StatusCode: 200, + Header: make(map[string][]string), Body: io.NopCloser(bytes.NewReader([]byte(resp))), - }, nil + } + + if strings.HasPrefix(resp, "{") { + result.Header["Content-Type"] = []string{ + "application/json; charset=utf-8"} + } else { + result.Header["Content-Type"] = []string{ + "application/x-www-form-urlencoded; charset=utf-8"} + } + + return result, nil } } @@ -77,7 +94,7 @@ var ( // AWS Cognito does not follow the spec and encode // email_verified as a string. We used to have special // handling for it but it seems now the upstream library - // transparently fixed support. We test is anyway. + // transparently fixed support. We test it anyway. name: "AWS congnito", responses: map[string]string{ // These are the responses for a typical oidc flow: @@ -139,6 +156,9 @@ var ( }, StaticURLReplayer{ + // Usually we require the email_verified claim to be able + // to use the email but some IDPs do not set it. We reject + // such uers. name: "Email is not verified", err_regex: "Email .+ is not verified", responses: map[string]string{ @@ -165,6 +185,184 @@ var ( `, }, }, + StaticURLReplayer{ + // Usually we require the email_verified claim to be able + // to use the email but some IDPs do not set it. We reject + // such uers. + name: "Email is not verified but it is allowed", + authenticator: &config_proto.Authenticator{ + Type: "oidc", + OauthClientId: "ClientIdXXXX", + OauthClientSecret: "ClientSecrect1234", + OidcIssuer: "https://www.example.com", + Claims: &config_proto.OIDCClaims{ + AllowUnverifiedEmail: true, + }, + }, + responses: map[string]string{ + `https://www.example.com/.well-known/openid-configuration`: ` +{"issuer": "https://www.example.com", + "authorization_endpoint": "https://www.example.com/o/oauth2/v2/auth", + "token_endpoint": "https://www.example.com/token", + "userinfo_endpoint": "https://www.example.com/v1/userinfo" +} +`, + "https://www.example.com/token": ` +{"access_token": "This is an access token", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer", + "id_token": "XXXX" +} +`, + "https://www.example.com/v1/userinfo": ` +{"sub": "100439259231459671911", + "email": "user@example.com", + "email_verified": false +} +`, + }, + }, + StaticURLReplayer{ + // Usually we use the email claim but some IDPs use other + // claims to identify the user. + name: "Unusual claim name", + authenticator: &config_proto.Authenticator{ + Type: "oidc", + OauthClientId: "ClientIdXXXX", + OauthClientSecret: "ClientSecrect1234", + OidcIssuer: "https://www.example.com", + Claims: &config_proto.OIDCClaims{ + Username: "SomeWeirdClaim", + }, + }, + responses: map[string]string{ + `https://www.example.com/.well-known/openid-configuration`: ` +{"issuer": "https://www.example.com", + "authorization_endpoint": "https://www.example.com/o/oauth2/v2/auth", + "token_endpoint": "https://www.example.com/token", + "userinfo_endpoint": "https://www.example.com/v1/userinfo" +} +`, + "https://www.example.com/token": ` +{"access_token": "This is an access token", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer" +} +`, + "https://www.example.com/v1/userinfo": ` +{"sub": "100439259231459671911", + "SomeWeirdClaim": "user@example.com" +} +`, + }, + }, + StaticURLReplayer{ + name: "Google Authenticator", + authenticator: &config_proto.Authenticator{ + Type: "google", + OauthClientId: "ClientIdXXXX", + OauthClientSecret: "ClientSecrect1234", + }, + responses: map[string]string{ + `https://accounts.google.com/.well-known/openid-configuration`: ` +{ + "issuer": "https://accounts.google.com", + "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth", + "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code", + "token_endpoint": "https://oauth2.googleapis.com/token", + "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo", + "revocation_endpoint": "https://oauth2.googleapis.com/revoke", + "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs" +} +`, + "https://oauth2.googleapis.com/token": ` +{"access_token": "This is an access token", + "expires_in": 3598, + "scope": "openid https://www.googleapis.com/auth/userinfo.email", + "token_type": "Bearer" +} +`, + "https://openidconnect.googleapis.com/v1/userinfo": ` +{"sub": "100439259231459671911", + "picture": "https://lh3.googleusercontent.com/a-/XXXXXX", + "email": "user@example.com", + "email_verified": true, + "hd": "example.com" +} +`, + }, + }, + StaticURLReplayer{ + name: "Github Authenticator", + authenticator: &config_proto.Authenticator{ + Type: "github", + OauthClientId: "ClientIdXXXX", + OauthClientSecret: "ClientSecrect1234", + }, + responses: map[string]string{ + "https://github.com/login/oauth/access_token": `access_token=XXXX&scope=user%3Aemail&token_type=bearer`, + "https://api.github.com/user": ` +{"login":"gh_user", + "id":12345, + "node_id":"XXXX=", + "avatar_url":"https://avatars.githubusercontent.com/u/3856546?v=4", + "gravatar_id":"","url":"https://api.github.com/users/gh_user", + "html_url":"https://github.com/gh_user", + "followers_url":"https://api.github.com/users/gh_user/followers", + "following_url":"https://api.github.com/users/gh_user/following{/other_user}", + "gists_url":"https://api.github.com/users/gh_user/gists{/gist_id}", + "starred_url":"https://api.github.com/users/gh_user/starred{/owner}{/repo}", + "subscriptions_url":"https://api.github.com/users/gh_user/subscriptions", + "organizations_url":"https://api.github.com/users/gh_user/orgs", + "repos_url":"https://api.github.com/users/gh_user/repos", + "events_url":"https://api.github.com/users/gh_user/events{/privacy}", + "received_events_url":"https://api.github.com/users/gh_user/received_events", + "type":"User", + "user_view_type":"public", + "site_admin":false, + "name":"Mike Cohen", + "company":"@Velocidex ", + "blog":"", + "location":"Australia" +} +`, + }, + }, + StaticURLReplayer{ + name: "Azure Authenticator", + authenticator: &config_proto.Authenticator{ + Type: "azure", + OauthClientId: "ClientIdXXXX", + OauthClientSecret: "ClientSecrect1234", + Tenant: "F1234", + }, + responses: map[string]string{ + "https://login.microsoftonline.com/F1234/oauth2/v2.0/token": ` +{"token_type":"Bearer", + "scope":"profile User.Read openid email", + "expires_in":4471, + "ext_expires_in":4471, + "access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBpZCI6IngxMjMiLCJlbWFpbCI6Im5vb25lQG5vd2hlcmUuY29tIiwiZXhwIjoxNzY0OTM3NDgzLCJzY3AiOiJlbWFpbCBvcGVuaWQifQ.3AjZi1Cxpbvscxh6HrDQ9iHOwom6G9RP-iRhv3vHLBo" +}`, + "https://graph.microsoft.com/v1.0/me/": ` +{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users/$entity", + "businessPhones":["0470238491"], + "displayName":"Mike Cohen", + "givenName":"Mike", + "jobTitle":null, + "mail":"user@example.com", + "mobilePhone":null, + "officeLocation":null, + "preferredLanguage":"en-US", + "surname":"Cohen", + "userPrincipalName":"user@example.com", + "id":"bcb8e2a7-b2d6-49e1-a6c0-327fc8ea1058"} +`, + "https://graph.microsoft.com/v1.0/me/photos/48x48/$value": `My Picture`, + }, + }, } ) @@ -176,11 +374,21 @@ func (self *TestRouter) Issuer() string { return "https://www.example.com" } -func TestProvider(t *testing.T) { +type OauthTestSuire struct { + test_utils.TestSuite +} + +func (self *OauthTestSuire) TestProvider() { + t := self.T() + config_obj := config.GetDefaultConfig() golden := ordereddict.NewDict() for _, tc := range testUrlReplayerCases { + if false && tc.name != "Azure Authenticator" { + continue + } + g := ordereddict.NewDict() golden.Set(tc.name, g) @@ -224,3 +432,7 @@ func TestProvider(t *testing.T) { goldie.Assert(t, "TestProvider", json.MustMarshalIndent(golden)) } + +func TestOIDC(t *testing.T) { + suite.Run(t, &OauthTestSuire{}) +} diff --git a/api/authenticators/fixtures/TestProvider.golden b/api/authenticators/fixtures/TestProvider.golden index f2e33666530..a565745a07d 100644 --- a/api/authenticators/fixtures/TestProvider.golden +++ b/api/authenticators/fixtures/TestProvider.golden @@ -1,13 +1,13 @@ { "Typical Flow": { - "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTMzMjg4MywidG9rZW4iOiIifQ.BIFTWv4-EdpbquR-q5pTWsorIuNi8XU2HPAl2P683Bc", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T02:14:43.535488646Z", + "Expires": "2025-12-10T06:50:44.526917084Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -20,19 +20,19 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765332883, + "expires": 1765349444, "token": "" } }, "AWS congnito": { - "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTMzMjg4MywidG9rZW4iOiIifQ.BIFTWv4-EdpbquR-q5pTWsorIuNi8XU2HPAl2P683Bc", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T02:14:43.535571883Z", + "Expires": "2025-12-10T06:50:44.527044138Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -45,19 +45,19 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765332883, + "expires": 1765349444, "token": "" } }, "MS ADFS": { - "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5vb25lQG5vd2hlcmUuY29tIiwicGljdHVyZSI6IiIsImV4cGlyZXMiOjE3NjUzMzI4ODMsInRva2VuIjoiIn0.DvvFEks85ou3bDb1G4xPyH9XK4HIfUJK3rozVGmJpYA", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5vb25lQG5vd2hlcmUuY29tIiwicGljdHVyZSI6IiIsImV4cGlyZXMiOjE3NjUzNDk0NDQsInRva2VuIjoiIn0.7G7TqzqkDZyZlMhi9AYEUIj0blsKxJUv9jozqQaSPA0", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T02:14:43.53585395Z", + "Expires": "2025-12-10T06:50:44.527137146Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -70,11 +70,136 @@ "Claims": { "username": "noone@nowhere.com", "picture": "", - "expires": 1765332883, + "expires": 1765349444, "token": "" } }, "Email is not verified": { - "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=%2F\u0026response_type=code\u0026scope=openid+email\u0026state=StateString" + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString" + }, + "Email is not verified but it is allowed": { + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T06:50:44.527262295Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "user@example.com", + "picture": "", + "expires": 1765349444, + "token": "" + } + }, + "Unusual claim name": { + "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T06:50:44.527323394Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "user@example.com", + "picture": "", + "expires": 1765349444, + "token": "" + } + }, + "Google Authenticator": { + "Redirect URL": "https://accounts.google.com/o/oauth2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fgoogle%2Fcallback\u0026response_type=code\u0026scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T06:50:44.527411488Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "user@example.com", + "picture": "", + "expires": 1765349444, + "token": "" + } + }, + "Github Authenticator": { + "Redirect URL": "https://github.com/login/oauth/authorize?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fgithub%2Fcallback\u0026response_type=code\u0026scope=user%3Aemail\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImdoX3VzZXIiLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.uzaXYAl1D_z_gbxjy1v6A278sMBpV5iPO4a6oLhJC-w", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T06:50:44.527527893Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "gh_user", + "picture": "", + "expires": 1765349444, + "token": "" + } + }, + "Azure Authenticator": { + "Redirect URL": "https://login.microsoftonline.com/F1234/oauth2/v2.0/authorize?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fazure%2Fcallback\u0026response_type=code\u0026scope=User.Read\u0026state=StateString", + "Cookie": { + "Name": "VelociraptorAuth", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Quoted": false, + "Path": "/", + "Domain": "", + "Expires": "2025-12-10T06:50:44.527597932Z", + "RawExpires": "", + "MaxAge": 0, + "Secure": true, + "HttpOnly": true, + "SameSite": 0, + "Partitioned": false, + "Raw": "", + "Unparsed": null + }, + "Claims": { + "username": "user@example.com", + "picture": "", + "expires": 1765349444, + "token": "" + } } } \ No newline at end of file diff --git a/api/authenticators/http.go b/api/authenticators/http.go index eaeae323f92..242ab83fb5f 100644 --- a/api/authenticators/http.go +++ b/api/authenticators/http.go @@ -89,13 +89,16 @@ func traceNetwork(config_obj *config_proto.Config) func(rt RoundTripFunc) RoundT } defer res.Body.Close() + ct, _ := res.Header["Content-Type"] + bs, err := io.ReadAll(res.Body) if err != nil { return nil, err } logger := logging.GetLogger(config_obj, &logging.GUIComponent) - logger.Debug("oidc: Calling URL: %v, Response: %v", req.URL, string(bs)) + logger.Debug("oidc: Calling URL: %v, Response: %v (CT %v)", + req.URL, string(bs), ct) res.Body = io.NopCloser(bytes.NewReader(bs)) return res, nil From 540d7db3050217ee88adb610c7e339ac8d58705d Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Tue, 9 Dec 2025 16:59:23 +1000 Subject: [PATCH 07/11] Fixed tests --- api/authenticators/certs.go | 3 +- api/authenticators/claims.go | 3 +- api/authenticators/claims_test.go | 4 ++ .../fixtures/TestProvider.golden | 48 +++++++++---------- api/authenticators/oidc.go | 3 +- api/authenticators/provider.go | 7 +-- api/authenticators/verify.go | 6 +-- 7 files changed, 39 insertions(+), 35 deletions(-) diff --git a/api/authenticators/certs.go b/api/authenticators/certs.go index 6bfd977c7de..5c9c19a6087 100644 --- a/api/authenticators/certs.go +++ b/api/authenticators/certs.go @@ -78,7 +78,6 @@ import ( "errors" "fmt" "net/http" - "time" "github.com/Velocidex/ordereddict" "github.com/gorilla/csrf" @@ -139,7 +138,7 @@ func (self *CertAuthenticator) AuthRedirectTemplate() string { func (self *CertAuthenticator) getUserNameFromTLSCerts(r *http.Request) (string, error) { // We only trust certs issued by the Velociraptor CA. x509_opts := x509.VerifyOptions{ - CurrentTime: time.Now(), + CurrentTime: utils.GetTime().Now(), Roots: self.x509_roots, } diff --git a/api/authenticators/claims.go b/api/authenticators/claims.go index 60ad6701439..fa84a546b31 100644 --- a/api/authenticators/claims.go +++ b/api/authenticators/claims.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "time" "github.com/Velocidex/ordereddict" oidc "github.com/coreos/go-oidc/v3/oidc" @@ -32,7 +31,7 @@ func (self *Claims) Valid() error { return errors.New("username not present") } - if self.Expires < float64(time.Now().Unix()) { + if self.Expires < float64(utils.GetTime().Now().Unix()) { return errors.New("the JWT is expired - reauthenticate") } return nil diff --git a/api/authenticators/claims_test.go b/api/authenticators/claims_test.go index cc8f9f46022..97cba9ffb48 100644 --- a/api/authenticators/claims_test.go +++ b/api/authenticators/claims_test.go @@ -15,6 +15,7 @@ import ( config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/file_store/test_utils" "www.velocidex.com/golang/velociraptor/json" + utils "www.velocidex.com/golang/velociraptor/utils" "www.velocidex.com/golang/velociraptor/vtesting/assert" "www.velocidex.com/golang/velociraptor/vtesting/goldie" ) @@ -379,6 +380,9 @@ type OauthTestSuire struct { } func (self *OauthTestSuire) TestProvider() { + closer := utils.MockTime(&utils.IncClock{NowTime: 1765349444}) + defer closer() + t := self.T() config_obj := config.GetDefaultConfig() diff --git a/api/authenticators/fixtures/TestProvider.golden b/api/authenticators/fixtures/TestProvider.golden index a565745a07d..0783910f99d 100644 --- a/api/authenticators/fixtures/TestProvider.golden +++ b/api/authenticators/fixtures/TestProvider.golden @@ -3,11 +3,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg0NiwidG9rZW4iOiIifQ.miaqZPf7x5_Rylp2smIeERM3Oj426GeTiuV1m1zYeK0", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.526917084Z", + "Expires": "2025-12-11T06:50:46Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -20,7 +20,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765349444, + "expires": 1765435846, "token": "" } }, @@ -28,11 +28,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg0NywidG9rZW4iOiIifQ.IbVVxFTo1fEPLUL0s-GgQX9bLVEP_FtnABtUpMhVe9E", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527044138Z", + "Expires": "2025-12-11T06:50:47Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -45,7 +45,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765349444, + "expires": 1765435847, "token": "" } }, @@ -53,11 +53,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5vb25lQG5vd2hlcmUuY29tIiwicGljdHVyZSI6IiIsImV4cGlyZXMiOjE3NjUzNDk0NDQsInRva2VuIjoiIn0.7G7TqzqkDZyZlMhi9AYEUIj0blsKxJUv9jozqQaSPA0", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5vb25lQG5vd2hlcmUuY29tIiwicGljdHVyZSI6IiIsImV4cGlyZXMiOjE3NjU0MzU4NDgsInRva2VuIjoiIn0.aZaVuUudlxRKztvIwEAtGFpgyieWpsJ6sHqNfovIL7Q", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527137146Z", + "Expires": "2025-12-11T06:50:48Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -70,7 +70,7 @@ "Claims": { "username": "noone@nowhere.com", "picture": "", - "expires": 1765349444, + "expires": 1765435848, "token": "" } }, @@ -81,11 +81,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg0OSwidG9rZW4iOiIifQ.c7Lz-C2CjcDe3vp40FjKiUoQy4_9OjwDiLrsDsnl4yw", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527262295Z", + "Expires": "2025-12-11T06:50:49Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -98,7 +98,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765349444, + "expires": 1765435849, "token": "" } }, @@ -106,11 +106,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MCwidG9rZW4iOiIifQ.j26ToyNfXmbAELWPfymDG9CDrIvSMJAH_Nm8uA7cg0g", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527323394Z", + "Expires": "2025-12-11T06:50:50Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -123,7 +123,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765349444, + "expires": 1765435850, "token": "" } }, @@ -131,11 +131,11 @@ "Redirect URL": "https://accounts.google.com/o/oauth2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fgoogle%2Fcallback\u0026response_type=code\u0026scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MSwidG9rZW4iOiIifQ.QJOOXjiIAX0RbyaGndIiMHCIa-RoKaqLsjCVRpUchT4", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527411488Z", + "Expires": "2025-12-11T06:50:51Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -148,7 +148,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765349444, + "expires": 1765435851, "token": "" } }, @@ -156,11 +156,11 @@ "Redirect URL": "https://github.com/login/oauth/authorize?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fgithub%2Fcallback\u0026response_type=code\u0026scope=user%3Aemail\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImdoX3VzZXIiLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.uzaXYAl1D_z_gbxjy1v6A278sMBpV5iPO4a6oLhJC-w", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImdoX3VzZXIiLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MiwidG9rZW4iOiIifQ.feRQ1jL_8-XGNFnurPXIRxWAO8-pQfau13uxanTNcuY", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527527893Z", + "Expires": "2025-12-11T06:50:52Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -173,7 +173,7 @@ "Claims": { "username": "gh_user", "picture": "", - "expires": 1765349444, + "expires": 1765435852, "token": "" } }, @@ -181,11 +181,11 @@ "Redirect URL": "https://login.microsoftonline.com/F1234/oauth2/v2.0/authorize?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fazure%2Fcallback\u0026response_type=code\u0026scope=User.Read\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTM0OTQ0NCwidG9rZW4iOiIifQ.Z8YSevpGGoNADxa5VW6Wi5gcdEz-uvUjf_IkapBCXUY", + "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MywidG9rZW4iOiIifQ.s8dk_qf8lvWoFzjpaoBf2PA3w0Tj8zm7WOoGDNwxp7s", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-10T06:50:44.527597932Z", + "Expires": "2025-12-11T06:50:53Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -198,7 +198,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765349444, + "expires": 1765435853, "token": "" } } diff --git a/api/authenticators/oidc.go b/api/authenticators/oidc.go index aab59f3dabb..d0fd2049103 100644 --- a/api/authenticators/oidc.go +++ b/api/authenticators/oidc.go @@ -13,6 +13,7 @@ import ( config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/services" + utils "www.velocidex.com/golang/velociraptor/utils" ) type OidcAuthenticator struct { @@ -101,7 +102,7 @@ func (self *OidcAuthenticator) GetGenOauthConfig() (*oauth2.Config, error) { func generateStateOauthCookie( config_obj *config_proto.Config, w http.ResponseWriter) *http.Cookie { - var expiration = time.Now().Add(time.Hour) + var expiration = utils.GetTime().Now().Add(time.Hour) b := make([]byte, 16) _, _ = rand.Read(b) diff --git a/api/authenticators/provider.go b/api/authenticators/provider.go index bc9424c6b29..b1c7520e4be 100644 --- a/api/authenticators/provider.go +++ b/api/authenticators/provider.go @@ -8,9 +8,10 @@ import ( jwt "github.com/golang-jwt/jwt/v4" "golang.org/x/oauth2" - utils "www.velocidex.com/golang/velociraptor/api/utils" + api_utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/logging" + utils "www.velocidex.com/golang/velociraptor/utils" ) // Abstract oauth and oidc authenticators so we can reuse them in @@ -93,7 +94,7 @@ func (self *Provider) getSignedJWTTokenCookie( // We force expiry in the JWT **as well** as the session // cookie. The JWT expiry is most important as the browser can // replay session cookies past expiry. - expiry := time.Now().Add(time.Minute * time.Duration(expiry_min)) + expiry := utils.GetTime().Now().Add(time.Minute * time.Duration(expiry_min)) // Enforce the JWT to expire claims.Expires = float64(expiry.Unix()) @@ -112,7 +113,7 @@ func (self *Provider) getSignedJWTTokenCookie( return &http.Cookie{ Name: "VelociraptorAuth", Value: tokenString, - Path: utils.GetBaseDirectory(config_obj), + Path: api_utils.GetBaseDirectory(config_obj), Secure: true, HttpOnly: true, Expires: expiry, diff --git a/api/authenticators/verify.go b/api/authenticators/verify.go index e61afe0e219..8fef17e8150 100644 --- a/api/authenticators/verify.go +++ b/api/authenticators/verify.go @@ -13,13 +13,13 @@ import ( "www.velocidex.com/golang/velociraptor/acls" api_proto "www.velocidex.com/golang/velociraptor/api/proto" api_utils "www.velocidex.com/golang/velociraptor/api/utils" - utils "www.velocidex.com/golang/velociraptor/api/utils" config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/constants" "www.velocidex.com/golang/velociraptor/gui/velociraptor" "www.velocidex.com/golang/velociraptor/json" "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/services" + utils "www.velocidex.com/golang/velociraptor/utils" ) var ( @@ -151,7 +151,7 @@ func getSignedJWTTokenCookie( // We force expiry in the JWT **as well** as the session // cookie. The JWT expiry is most important as the browser can // replay session cookies past expiry. - expiry := time.Now().Add(time.Minute * time.Duration(expiry_min)) + expiry := utils.GetTime().Now().Add(time.Minute * time.Duration(expiry_min)) // Enforce the JWT to expire claims.Expires = float64(expiry.Unix()) @@ -186,7 +186,7 @@ func getSignedJWTTokenCookie( return &http.Cookie{ Name: "VelociraptorAuth", Value: tokenString, - Path: utils.GetBaseDirectory(config_obj), + Path: api_utils.GetBaseDirectory(config_obj), Secure: true, HttpOnly: true, Expires: expiry, From d5086b0c9001fae6a386ff8d8e7df7c385dfb206 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Mon, 8 Dec 2025 09:53:58 +0000 Subject: [PATCH 08/11] fix: upgrade axios from 1.13.1 to 1.13.2 Snyk has created this PR to upgrade axios from 1.13.1 to 1.13.2. See this package in npm: axios See this project in Snyk: https://app.snyk.io/org/scudette/project/76f4d127-566b-42ef-86f4-bdcbc92b90b4?utm_source=github&utm_medium=referral&page=upgrade-pr --- gui/velociraptor/package-lock.json | 20 ++++++++++---------- gui/velociraptor/package.json | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gui/velociraptor/package-lock.json b/gui/velociraptor/package-lock.json index e411ac4ad41..11439e8f994 100644 --- a/gui/velociraptor/package-lock.json +++ b/gui/velociraptor/package-lock.json @@ -15,14 +15,14 @@ "@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/react-fontawesome": "0.2.6", "@popperjs/core": "^2.11.8", - "axios": "^1.13.1", - "ace-builds": "^1.43.4", + "ace-builds": "1.43.4", + "axios": "^1.13.2", "axios-retry": "3.9.1", "bootstrap": "5.3.8", "classnames": "^2.5.1", "csv-parse": "4.16.3", "csv-stringify": "5.6.5", - "dompurify": "^3.3.0", + "dompurify": "3.3.0", "env-cmd": "^10.1.0", "hosted-git-info": "^2.8.9", "html-react-parser": "^0.14.3", @@ -54,7 +54,7 @@ "recharts": "^2.15.4", "sprintf-js": "1.1.3", "url-parse": "^1.5.10", - "webpack": "^5.102.1" + "webpack": "5.102.1" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -5693,9 +5693,9 @@ } }, "node_modules/axios": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", - "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -19327,9 +19327,9 @@ "dev": true }, "axios": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", - "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", diff --git a/gui/velociraptor/package.json b/gui/velociraptor/package.json index d39ebf450c0..1fb20abdf60 100644 --- a/gui/velociraptor/package.json +++ b/gui/velociraptor/package.json @@ -10,7 +10,7 @@ "@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/react-fontawesome": "0.2.6", "@popperjs/core": "^2.11.8", - "axios": ">=1.13.1", + "axios": ">=1.13.2", "ace-builds": "1.43.4", "axios-retry": "3.9.1", "bootstrap": "5.3.8", From 2050d33ddc5f18a11aed0325352ae3905d6baa5f Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Tue, 9 Dec 2025 17:05:40 +1000 Subject: [PATCH 09/11] Fix action to build binaries only on merge --- .github/workflows/musl.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/musl.yaml b/.github/workflows/musl.yaml index 5974bb80dd6..7acce14d494 100644 --- a/.github/workflows/musl.yaml +++ b/.github/workflows/musl.yaml @@ -1,13 +1,13 @@ -# Only trigger when a PR is committed. name: Linux Build Musl Static -on: [pull_request] -#on: -# pull_request: -# types: [closed] +#on: [pull_request] +on: + pull_request: + types: [closed] jobs: build: - #if: github.event.pull_request.merged + # Only trigger when a PR is committed. + if: github.event.pull_request.merged name: Build runs-on: ubuntu-latest steps: From 5ceb92629995e9d415126afb90abc991892b9cd2 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Tue, 9 Dec 2025 17:21:11 +1000 Subject: [PATCH 10/11] fixed test --- api/authenticators/claims_test.go | 5 +- .../fixtures/TestProvider.golden | 48 +++++++++---------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/api/authenticators/claims_test.go b/api/authenticators/claims_test.go index 97cba9ffb48..f42ed86e482 100644 --- a/api/authenticators/claims_test.go +++ b/api/authenticators/claims_test.go @@ -8,6 +8,7 @@ import ( "net/http" "strings" "testing" + "time" "github.com/Velocidex/ordereddict" "github.com/stretchr/testify/suite" @@ -380,7 +381,7 @@ type OauthTestSuire struct { } func (self *OauthTestSuire) TestProvider() { - closer := utils.MockTime(&utils.IncClock{NowTime: 1765349444}) + closer := utils.MockTime(utils.NewMockClock(time.Unix(1765349444, 0))) defer closer() t := self.T() @@ -430,6 +431,8 @@ func (self *OauthTestSuire) TestProvider() { continue } assert.NoError(t, err) + cookie.Value = fmt.Sprintf("String of length %v", len(cookie.Value)) + g.Set("Cookie", cookie) g.Set("Claims", claims) } diff --git a/api/authenticators/fixtures/TestProvider.golden b/api/authenticators/fixtures/TestProvider.golden index 0783910f99d..9c431b86220 100644 --- a/api/authenticators/fixtures/TestProvider.golden +++ b/api/authenticators/fixtures/TestProvider.golden @@ -3,11 +3,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg0NiwidG9rZW4iOiIifQ.miaqZPf7x5_Rylp2smIeERM3Oj426GeTiuV1m1zYeK0", + "Value": "String of length 183", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:46Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -20,7 +20,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765435846, + "expires": 1765435844, "token": "" } }, @@ -28,11 +28,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg0NywidG9rZW4iOiIifQ.IbVVxFTo1fEPLUL0s-GgQX9bLVEP_FtnABtUpMhVe9E", + "Value": "String of length 183", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:47Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -45,7 +45,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765435847, + "expires": 1765435844, "token": "" } }, @@ -53,11 +53,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im5vb25lQG5vd2hlcmUuY29tIiwicGljdHVyZSI6IiIsImV4cGlyZXMiOjE3NjU0MzU4NDgsInRva2VuIjoiIn0.aZaVuUudlxRKztvIwEAtGFpgyieWpsJ6sHqNfovIL7Q", + "Value": "String of length 184", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:48Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -70,7 +70,7 @@ "Claims": { "username": "noone@nowhere.com", "picture": "", - "expires": 1765435848, + "expires": 1765435844, "token": "" } }, @@ -81,11 +81,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg0OSwidG9rZW4iOiIifQ.c7Lz-C2CjcDe3vp40FjKiUoQy4_9OjwDiLrsDsnl4yw", + "Value": "String of length 183", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:49Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -98,7 +98,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765435849, + "expires": 1765435844, "token": "" } }, @@ -106,11 +106,11 @@ "Redirect URL": "https://www.example.com/o/oauth2/v2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Foidc%2Fcallback\u0026response_type=code\u0026scope=openid+email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MCwidG9rZW4iOiIifQ.j26ToyNfXmbAELWPfymDG9CDrIvSMJAH_Nm8uA7cg0g", + "Value": "String of length 183", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:50Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -123,7 +123,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765435850, + "expires": 1765435844, "token": "" } }, @@ -131,11 +131,11 @@ "Redirect URL": "https://accounts.google.com/o/oauth2/auth?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fgoogle%2Fcallback\u0026response_type=code\u0026scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MSwidG9rZW4iOiIifQ.QJOOXjiIAX0RbyaGndIiMHCIa-RoKaqLsjCVRpUchT4", + "Value": "String of length 183", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:51Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -148,7 +148,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765435851, + "expires": 1765435844, "token": "" } }, @@ -156,11 +156,11 @@ "Redirect URL": "https://github.com/login/oauth/authorize?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fgithub%2Fcallback\u0026response_type=code\u0026scope=user%3Aemail\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImdoX3VzZXIiLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MiwidG9rZW4iOiIifQ.feRQ1jL_8-XGNFnurPXIRxWAO8-pQfau13uxanTNcuY", + "Value": "String of length 171", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:52Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -173,7 +173,7 @@ "Claims": { "username": "gh_user", "picture": "", - "expires": 1765435852, + "expires": 1765435844, "token": "" } }, @@ -181,11 +181,11 @@ "Redirect URL": "https://login.microsoftonline.com/F1234/oauth2/v2.0/authorize?client_id=ClientIdXXXX\u0026redirect_uri=https%3A%2F%2Flocalhost%3A8889%2Fauth%2Fazure%2Fcallback\u0026response_type=code\u0026scope=User.Read\u0026state=StateString", "Cookie": { "Name": "VelociraptorAuth", - "Value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJAZXhhbXBsZS5jb20iLCJwaWN0dXJlIjoiIiwiZXhwaXJlcyI6MTc2NTQzNTg1MywidG9rZW4iOiIifQ.s8dk_qf8lvWoFzjpaoBf2PA3w0Tj8zm7WOoGDNwxp7s", + "Value": "String of length 183", "Quoted": false, "Path": "/", "Domain": "", - "Expires": "2025-12-11T06:50:53Z", + "Expires": "2025-12-11T06:50:44Z", "RawExpires": "", "MaxAge": 0, "Secure": true, @@ -198,7 +198,7 @@ "Claims": { "username": "user@example.com", "picture": "", - "expires": 1765435853, + "expires": 1765435844, "token": "" } } From 8f6d4253133b3c8f83bf4b43971d9acaddb801f4 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Tue, 9 Dec 2025 17:44:29 +1000 Subject: [PATCH 11/11] Fixed tests --- api/authenticators/auth.go | 6 +++++ api/authenticators/oidc.go | 4 +++ api/fixtures/TestMultiAuthenticator.golden | 29 ++++++++-------------- api/proxy_test.go | 14 +++++------ 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/api/authenticators/auth.go b/api/authenticators/auth.go index 88c0cacbdd0..23d7b31983f 100644 --- a/api/authenticators/auth.go +++ b/api/authenticators/auth.go @@ -26,6 +26,12 @@ var ( auth_cache Authenticator ) +func ResetAuthCache() { + mu.Lock() + defer mu.Unlock() + auth_cache = nil +} + // All SSO Authenticators implement this interface. type Authenticator interface { AddHandlers(mux *utils.ServeMux) error diff --git a/api/authenticators/oidc.go b/api/authenticators/oidc.go index d0fd2049103..86624fb52e2 100644 --- a/api/authenticators/oidc.go +++ b/api/authenticators/oidc.go @@ -23,6 +23,10 @@ type OidcAuthenticator struct { authenticator *config_proto.Authenticator } +func (self *OidcAuthenticator) Name() string { + return self.router.Name() +} + func (self *OidcAuthenticator) IsPasswordLess() bool { return true } diff --git a/api/fixtures/TestMultiAuthenticator.golden b/api/fixtures/TestMultiAuthenticator.golden index ff50894310d..49921d6f271 100644 --- a/api/fixtures/TestMultiAuthenticator.golden +++ b/api/fixtures/TestMultiAuthenticator.golden @@ -1,9 +1,8 @@ { - "Redirect Provider *authenticators.OidcAuthenticator": "https://www.example.com/velociraptor/auth/oidc/callback", - "Redirect Provider *authenticators.GoogleAuthenticator": "https://www.example.com/velociraptor/auth/google/callback", - "Redirect Provider *authenticators.GitHubAuthenticator": "https://www.example.com/velociraptor/auth/github/callback", - "Redirect Provider *authenticators.OidcAuthenticatorCognito": "https://www.example.com/velociraptor/auth/oidc/cognito/callback", - "Redirect Provider *authenticators.AzureAuthenticator": "https://www.example.com/velociraptor/auth/azure/callback", + "Redirect Provider *authenticators.OidcAuthenticator Generic OIDC Connector": "https://www.example.com/velociraptor/auth/oidc/callback", + "Redirect Provider *authenticators.OidcAuthenticator Google": "https://www.example.com/velociraptor/auth/google/callback", + "Redirect Provider *authenticators.OidcAuthenticator GitHub": "https://www.example.com/velociraptor/auth/github/callback", + "Redirect Provider *authenticators.OidcAuthenticator Azure": "https://www.example.com/velociraptor/auth/azure/callback", "Mux": { "/favicon.png": [ "*http.redirectHandler" @@ -66,40 +65,32 @@ ], "/velociraptor/auth/azure/callback": [ "authenticators.IpFilter", - " authenticators.(*AzureAuthenticator).oauthAzureCallback" + " authenticators.(*OidcAuthenticator).oauthOidcCallback" ], "/velociraptor/auth/azure/login": [ "authenticators.IpFilter", - " authenticators.(*AzureAuthenticator).oauthAzureLogin" + " authenticators.(*OidcAuthenticator).oauthOidcLogin" ], "/velociraptor/auth/github/callback": [ "authenticators.IpFilter", - " authenticators.(*GitHubAuthenticator).oauthGithubCallback" + " authenticators.(*OidcAuthenticator).oauthOidcCallback" ], "/velociraptor/auth/github/login": [ "authenticators.IpFilter", - " authenticators.(*GitHubAuthenticator).oauthGithubLogin" + " authenticators.(*OidcAuthenticator).oauthOidcLogin" ], "/velociraptor/auth/google/callback": [ "authenticators.IpFilter", - " authenticators.(*GoogleAuthenticator).oauthGoogleCallback" + " authenticators.(*OidcAuthenticator).oauthOidcCallback" ], "/velociraptor/auth/google/login": [ "authenticators.IpFilter", - " authenticators.(*GoogleAuthenticator).oauthGoogleLogin" + " authenticators.(*OidcAuthenticator).oauthOidcLogin" ], "/velociraptor/auth/oidc/callback": [ "authenticators.IpFilter", " authenticators.(*OidcAuthenticator).oauthOidcCallback" ], - "/velociraptor/auth/oidc/cognito/callback": [ - "authenticators.IpFilter", - " authenticators.(*OidcAuthenticatorCognito).oauthOidcCallback" - ], - "/velociraptor/auth/oidc/cognito/login": [ - "authenticators.IpFilter", - " authenticators.(*OidcAuthenticator).oauthOidcLogin" - ], "/velociraptor/auth/oidc/login": [ "authenticators.IpFilter", " authenticators.(*OidcAuthenticator).oauthOidcLogin" diff --git a/api/proxy_test.go b/api/proxy_test.go index 758fb9d4253..3d74269603b 100644 --- a/api/proxy_test.go +++ b/api/proxy_test.go @@ -21,6 +21,8 @@ type APIProxyTestSuite struct { } func (self *APIProxyTestSuite) TestMultiAuthenticator() { + authenticators.ResetAuthCache() + mux := api_utils.NewServeMux() config_obj := proto.Clone(self.ConfigObj).(*config_proto.Config) @@ -41,12 +43,6 @@ func (self *APIProxyTestSuite) TestMultiAuthenticator() { Type: "GitHub", OauthClientId: "CCCCC", OauthClientSecret: "secret", - }, { - Type: "oidc-cognito", - OidcIssuer: "https://accounts.google.com", - OauthClientId: "CCCCC", - OauthClientSecret: "secret", - OidcName: "cognito", }, { Type: "azure", OauthClientId: "CCCCC", @@ -66,14 +62,14 @@ func (self *APIProxyTestSuite) TestMultiAuthenticator() { golden := ordereddict.NewDict() for _, delegate := range auther_multi.Delegates() { - auther_oidc, ok := delegate.(authenticators.OIDCConnector) + auther_oidc, ok := delegate.(*authenticators.OidcAuthenticator) if !ok { continue } oidc_config, err := auther_oidc.GetGenOauthConfig() assert.NoError(self.T(), err) - golden.Set(fmt.Sprintf("Redirect Provider %T", delegate), + golden.Set(fmt.Sprintf("Redirect Provider %T %v", delegate, auther_oidc.Name()), oidc_config.RedirectURL) } @@ -83,6 +79,8 @@ func (self *APIProxyTestSuite) TestMultiAuthenticator() { } func (self *APIProxyTestSuite) TestBasicAuthenticator() { + authenticators.ResetAuthCache() + mux := api_utils.NewServeMux() config_obj := proto.Clone(self.ConfigObj).(*config_proto.Config)