diff --git a/.github/ISSUE_TEMPLATE/testplan.md b/.github/ISSUE_TEMPLATE/testplan.md index 2040c23e4915e..b5c7ae96e7885 100644 --- a/.github/ISSUE_TEMPLATE/testplan.md +++ b/.github/ISSUE_TEMPLATE/testplan.md @@ -1186,7 +1186,9 @@ With a default Postgres DB instance, a Teleport instance configured with DB acce (`auth_service.authentication` in the cluster config): - [ ] `type: local`, `second_factor: "off"` - [ ] `type: local`, `second_factor: "otp"` - - [ ] `type: local`, `second_factor: "webauthn"` + - [ ] `type: local`, `second_factor: "webauthn"`, + - [ ] `type: local`, `second_factor: "webauthn"`, log in passwordlessly with hardware key + - [ ] `type: local`, `second_factor: "webauthn"`, log in passwordlessly with touch ID - [ ] `type: local`, `second_factor: "optional"`, log in without MFA - [ ] `type: local`, `second_factor: "optional"`, log in with OTP - [ ] `type: local`, `second_factor: "optional"`, log in with hardware key diff --git a/lib/auth/webauthncli/api.go b/lib/auth/webauthncli/api.go index 3f6f25ea26c88..7bccb650d74df 100644 --- a/lib/auth/webauthncli/api.go +++ b/lib/auth/webauthncli/api.go @@ -51,13 +51,15 @@ type UserInfo struct { } // LoginPrompt is the user interface for FIDO2Login. +// +// Prompts can have remote implementations, thus all methods may error. type LoginPrompt interface { // PromptPIN prompts the user for their PIN. PromptPIN() (string, error) // PromptTouch prompts the user for a security key touch. // In certain situations multiple touches may be required (PIN-protected // devices, passwordless flows, etc). - PromptTouch() + PromptTouch() error // PromptCredential prompts the user to choose a credential, in case multiple // credentials are available. // Callers are free to modify the slice, such as by sorting the credentials, @@ -136,7 +138,9 @@ func crossPlatformLogin( return FIDO2Login(ctx, origin, assertion, prompt, opts) } - prompt.PromptTouch() + if err := prompt.PromptTouch(); err != nil { + return nil, "", trace.Wrap(err) + } resp, err := U2FLogin(ctx, origin, assertion) return resp, "" /* credentialUser */, err } @@ -154,13 +158,15 @@ func platformLogin(origin, user string, assertion *wanlib.CredentialAssertion, p } // RegisterPrompt is the user interface for FIDO2Register. +// +// Prompts can have remote implementations, thus all methods may error. type RegisterPrompt interface { // PromptPIN prompts the user for their PIN. PromptPIN() (string, error) // PromptTouch prompts the user for a security key touch. // In certain situations multiple touches may be required (eg, PIN-protected // devices) - PromptTouch() + PromptTouch() error } // Register performs client-side, U2F-compatible, Webauthn registration. @@ -178,6 +184,8 @@ func Register( return FIDO2Register(ctx, origin, cc, prompt) } - prompt.PromptTouch() + if err := prompt.PromptTouch(); err != nil { + return nil, trace.Wrap(err) + } return U2FRegister(ctx, origin, cc) } diff --git a/lib/auth/webauthncli/fido2.go b/lib/auth/webauthncli/fido2.go index 1d9f08d7a778a..9f2023b90d899 100644 --- a/lib/auth/webauthncli/fido2.go +++ b/lib/auth/webauthncli/fido2.go @@ -551,7 +551,9 @@ func runOnFIDO2Devices( if errors.Is(err, errNoSuitableDevices) { // No readily available devices means we need to prompt, otherwise the // user gets no feedback whatsoever. - prompt.PromptTouch() + if err := prompt.PromptTouch(); err != nil { + return trace.Wrap(err) + } prompted = true devices, err = findSuitableDevicesOrTimeout(ctx, filter, knownPaths) @@ -561,7 +563,10 @@ func runOnFIDO2Devices( } if !prompted { - prompt.PromptTouch() // about to select + // about to select + if err := prompt.PromptTouch(); err != nil { + return trace.Wrap(err) + } } dev, requiresPIN, err := selectDevice(ctx, "" /* pin */, devices, deviceCallback) switch { @@ -582,7 +587,9 @@ func runOnFIDO2Devices( } // Prompt a second touch after reading the PIN. - prompt.PromptTouch() + if err := prompt.PromptTouch(); err != nil { + return trace.Wrap(err) + } // Run the callback again with the informed PIN. // selectDevice is used since it correctly deals with cancellation. diff --git a/lib/auth/webauthncli/fido2_test.go b/lib/auth/webauthncli/fido2_test.go index 0a41dd6374fdd..1385cb973cd3f 100644 --- a/lib/auth/webauthncli/fido2_test.go +++ b/lib/auth/webauthncli/fido2_test.go @@ -120,7 +120,7 @@ func (p noopPrompt) PromptPIN() (string, error) { return "", nil } -func (p noopPrompt) PromptTouch() {} +func (p noopPrompt) PromptTouch() error { return nil } // pinCancelPrompt exercises cancellation after device selection. type pinCancelPrompt struct { @@ -135,8 +135,9 @@ func (p *pinCancelPrompt) PromptPIN() (string, error) { return p.pin, nil } -func (p pinCancelPrompt) PromptTouch() { +func (p pinCancelPrompt) PromptTouch() error { // 2nd touch never happens + return nil } func TestIsFIDO2Available(t *testing.T) { @@ -811,9 +812,9 @@ type countingPrompt struct { count int } -func (cp *countingPrompt) PromptTouch() { +func (cp *countingPrompt) PromptTouch() error { cp.count++ - cp.LoginPrompt.PromptTouch() + return cp.LoginPrompt.PromptTouch() } func TestFIDO2Login_PromptTouch(t *testing.T) { @@ -1706,8 +1707,9 @@ func (f *fakeFIDO2Device) PromptPIN() (string, error) { return f.pin, nil } -func (f *fakeFIDO2Device) PromptTouch() { +func (f *fakeFIDO2Device) PromptTouch() error { f.setUP() + return nil } func (f *fakeFIDO2Device) credentialID() []byte { diff --git a/lib/auth/webauthncli/prompt.go b/lib/auth/webauthncli/prompt.go index d5f40c30df330..2de926b2c0fa5 100644 --- a/lib/auth/webauthncli/prompt.go +++ b/lib/auth/webauthncli/prompt.go @@ -34,8 +34,9 @@ type DefaultPrompt struct { FirstTouchMessage, SecondTouchMessage string PromptCredentialMessage string - ctx context.Context - out io.Writer + ctx context.Context + out io.Writer + count int } @@ -59,18 +60,19 @@ func (p *DefaultPrompt) PromptPIN() (string, error) { } // PromptTouch prompts the user for a security key touch, using different -// messages for first and second prompts. -func (p *DefaultPrompt) PromptTouch() { +// messages for first and second prompts. Error is always nil. +func (p *DefaultPrompt) PromptTouch() error { if p.count == 0 { p.count++ if p.FirstTouchMessage != "" { fmt.Fprintln(p.out, p.FirstTouchMessage) } - return + return nil } if p.SecondTouchMessage != "" { fmt.Fprintln(p.out, p.SecondTouchMessage) } + return nil } // PromptCredential prompts the user to choose a credential, in case multiple diff --git a/lib/client/api.go b/lib/client/api.go index 59f23fc7ebd0b..169956fcc41f9 100644 --- a/lib/client/api.go +++ b/lib/client/api.go @@ -52,7 +52,6 @@ import ( apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/keypaths" "github.com/gravitational/teleport/lib/auth" - wanlib "github.com/gravitational/teleport/lib/auth/webauthn" wancli "github.com/gravitational/teleport/lib/auth/webauthncli" "github.com/gravitational/teleport/lib/client/terminal" "github.com/gravitational/teleport/lib/defaults" @@ -71,7 +70,6 @@ import ( "github.com/gravitational/teleport/lib/utils/prompt" "github.com/gravitational/teleport/lib/utils/proxy" - "github.com/duo-labs/webauthn/protocol" "github.com/gravitational/trace" "github.com/jonboulle/clockwork" "github.com/sirupsen/logrus" @@ -3289,31 +3287,6 @@ func (tc *TeleportClient) Login(ctx context.Context) (*Key, error) { } func (tc *TeleportClient) pwdlessLogin(ctx context.Context, pubKey []byte) (*auth.SSHLoginResponse, error) { - webClient, webURL, err := initClient(tc.WebProxyAddr, tc.InsecureSkipVerify, loopbackPool(tc.WebProxyAddr)) - if err != nil { - return nil, trace.Wrap(err) - } - - challengeJSON, err := webClient.PostJSON( - ctx, webClient.Endpoint("webapi", "mfa", "login", "begin"), - &MFAChallengeRequest{ - Passwordless: true, - }) - if err != nil { - return nil, trace.Wrap(err) - } - challenge := &MFAAuthenticateChallenge{} - if err := json.Unmarshal(challengeJSON.Bytes(), challenge); err != nil { - return nil, trace.Wrap(err) - } - // Sanity check WebAuthn challenge. - switch { - case challenge.WebauthnChallenge == nil: - return nil, trace.BadParameter("passwordless: webauthn challenge missing") - case challenge.WebauthnChallenge.Response.UserVerification == protocol.VerificationDiscouraged: - return nil, trace.BadParameter("passwordless: user verification requirement too lax (%v)", challenge.WebauthnChallenge.Response.UserVerification) - } - // Only pass on the user if explicitly set, otherwise let the credential // picker kick in. user := "" @@ -3321,35 +3294,23 @@ func (tc *TeleportClient) pwdlessLogin(ctx context.Context, pubKey []byte) (*aut user = tc.Username } - prompt := wancli.NewDefaultPrompt(ctx, tc.Stderr) - mfaResp, _, err := promptWebauthn(ctx, webURL.String(), challenge.WebauthnChallenge, prompt, &wancli.LoginOpts{ + response, err := SSHAgentPasswordlessLogin(ctx, SSHLoginPasswordless{ + SSHLogin: SSHLogin{ + ProxyAddr: tc.WebProxyAddr, + PubKey: pubKey, + TTL: tc.KeyTTL, + Insecure: tc.InsecureSkipVerify, + Pool: loopbackPool(tc.WebProxyAddr), + Compatibility: tc.CertificateFormat, + RouteToCluster: tc.SiteName, + KubernetesCluster: tc.KubernetesCluster, + }, User: user, AuthenticatorAttachment: tc.AuthenticatorAttachment, + StderrOverride: tc.Stderr, }) - if err != nil { - return nil, trace.Wrap(err) - } - loginRespJSON, err := webClient.PostJSON( - ctx, webClient.Endpoint("webapi", "mfa", "login", "finish"), - &AuthenticateSSHUserRequest{ - User: "", // User carried on WebAuthn assertion. - WebauthnChallengeResponse: wanlib.CredentialAssertionResponseFromProto(mfaResp.GetWebauthn()), - PubKey: pubKey, - TTL: tc.KeyTTL, - Compatibility: tc.CertificateFormat, - RouteToCluster: tc.SiteName, - KubernetesCluster: tc.KubernetesCluster, - }) - if err != nil { - return nil, trace.Wrap(err) - } - - loginResp := &auth.SSHLoginResponse{} - if err := json.Unmarshal(loginRespJSON.Bytes(), loginResp); err != nil { - return nil, trace.Wrap(err) - } - return loginResp, nil + return response, trace.Wrap(err) } func (tc *TeleportClient) localLogin(ctx context.Context, secondFactor constants.SecondFactorType, pub []byte) (*auth.SSHLoginResponse, error) { diff --git a/lib/client/api_login_test.go b/lib/client/api_login_test.go index 8977cadf48f44..9121e10944bbe 100644 --- a/lib/client/api_login_test.go +++ b/lib/client/api_login_test.go @@ -51,14 +51,7 @@ import ( ) func TestTeleportClient_Login_local(t *testing.T) { - // Silence logging during this test. - lvl := log.GetLevel() - t.Cleanup(func() { - log.SetOutput(os.Stderr) - log.SetLevel(lvl) - }) - log.SetOutput(io.Discard) - log.SetLevel(log.PanicLevel) + silenceLogger(t) clock := clockwork.NewFakeClockAt(time.Now()) sa := newStandaloneTeleport(t, clock) @@ -134,7 +127,12 @@ func TestTeleportClient_Login_local(t *testing.T) { case got != pin: return nil, errors.New("invalid PIN") } - prompt.PromptTouch() // Realistically, this would happen too. + + // Realistically, this would happen too. + if err := prompt.PromptTouch(); err != nil { + return nil, err + } + return solveWebauthn(ctx, origin, assertion, prompt) } @@ -491,3 +489,14 @@ func startAndWait(t *testing.T, cfg *service.Config, eventName string) *service. return instance } + +// silenceLogger silences logger during testing. +func silenceLogger(t *testing.T) { + lvl := log.GetLevel() + t.Cleanup(func() { + log.SetOutput(os.Stderr) + log.SetLevel(lvl) + }) + log.SetOutput(io.Discard) + log.SetLevel(log.PanicLevel) +} diff --git a/lib/client/weblogin.go b/lib/client/weblogin.go index 44b9916d89ae4..427ad109e5719 100644 --- a/lib/client/weblogin.go +++ b/lib/client/weblogin.go @@ -30,6 +30,7 @@ import ( "runtime" "time" + "github.com/duo-labs/webauthn/protocol" "github.com/gravitational/roundtrip" "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/client/proto" @@ -225,6 +226,24 @@ type SSHLoginMFA struct { PreferOTP bool } +// SSHLoginPasswordless contains SSH login parameters for passwordless login. +type SSHLoginPasswordless struct { + SSHLogin + + // StderrOverride will override the default os.Stderr if provided. + StderrOverride io.Writer + + // User is the login username. + User string + + // AuthenticatorAttachment is the authenticator attachment for passwordless prompts. + AuthenticatorAttachment wancli.AuthenticatorAttachment + + // CustomPrompt defines a custom webauthn login prompt. + // It's an optional field that when nil, it will use the wancli.DefaultPrompt. + CustomPrompt wancli.LoginPrompt +} + // initClient creates a new client to the HTTPS web proxy. func initClient(proxyAddr string, insecure bool, pool *x509.CertPool) (*WebClient, *url.URL, error) { log := logrus.WithFields(logrus.Fields{ @@ -364,6 +383,77 @@ func SSHAgentLogin(ctx context.Context, login SSHLoginDirect) (*auth.SSHLoginRes return out, nil } +// SSHAgentPasswordlessLogin requests a passwordless MFA challenge via the proxy. +// weblogin.CustomPrompt (or a default prompt) is used for interaction with the +// end user. +// +// Returns the SSH certificate if authn is successful or an error. +func SSHAgentPasswordlessLogin(ctx context.Context, login SSHLoginPasswordless) (*auth.SSHLoginResponse, error) { + webClient, webURL, err := initClient(login.ProxyAddr, login.Insecure, login.Pool) + if err != nil { + return nil, trace.Wrap(err) + } + + challengeJSON, err := webClient.PostJSON( + ctx, webClient.Endpoint("webapi", "mfa", "login", "begin"), + &MFAChallengeRequest{ + Passwordless: true, + }) + if err != nil { + return nil, trace.Wrap(err) + } + challenge := &MFAAuthenticateChallenge{} + if err := json.Unmarshal(challengeJSON.Bytes(), challenge); err != nil { + return nil, trace.Wrap(err) + } + // Sanity check WebAuthn challenge. + switch { + case challenge.WebauthnChallenge == nil: + return nil, trace.BadParameter("passwordless: webauthn challenge missing") + case challenge.WebauthnChallenge.Response.UserVerification == protocol.VerificationDiscouraged: + return nil, trace.BadParameter("passwordless: user verification requirement too lax (%v)", challenge.WebauthnChallenge.Response.UserVerification) + } + + stderr := login.StderrOverride + if stderr == nil { + stderr = os.Stderr + } + + prompt := login.CustomPrompt + if prompt == nil { + prompt = wancli.NewDefaultPrompt(ctx, stderr) + } + + mfaResp, _, err := promptWebauthn(ctx, webURL.String(), challenge.WebauthnChallenge, prompt, &wancli.LoginOpts{ + User: login.User, + AuthenticatorAttachment: login.AuthenticatorAttachment, + }) + if err != nil { + return nil, trace.Wrap(err) + } + + loginRespJSON, err := webClient.PostJSON( + ctx, webClient.Endpoint("webapi", "mfa", "login", "finish"), + &AuthenticateSSHUserRequest{ + User: "", // User carried on WebAuthn assertion. + WebauthnChallengeResponse: wanlib.CredentialAssertionResponseFromProto(mfaResp.GetWebauthn()), + PubKey: login.PubKey, + TTL: login.TTL, + Compatibility: login.Compatibility, + RouteToCluster: login.RouteToCluster, + KubernetesCluster: login.KubernetesCluster, + }) + if err != nil { + return nil, trace.Wrap(err) + } + + loginResp := &auth.SSHLoginResponse{} + if err := json.Unmarshal(loginRespJSON.Bytes(), loginResp); err != nil { + return nil, trace.Wrap(err) + } + return loginResp, nil +} + // SSHAgentMFALogin requests a MFA challenge via the proxy. // If the credentials are valid, the proxy will return a challenge. We then // prompt the user to provide 2nd factor and pass the response to the proxy. diff --git a/lib/client/weblogin_test.go b/lib/client/weblogin_test.go index 571e1014907ff..e4317f6288bd4 100644 --- a/lib/client/weblogin_test.go +++ b/lib/client/weblogin_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package client +package client_test import ( "context" @@ -22,10 +22,16 @@ import ( "net" "net/http" "net/http/httptest" + "strings" "testing" + "time" "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/types" + wanlib "github.com/gravitational/teleport/lib/auth/webauthn" + wancli "github.com/gravitational/teleport/lib/auth/webauthncli" + "github.com/gravitational/teleport/lib/client" + "github.com/jonboulle/clockwork" "github.com/stretchr/testify/require" ) @@ -50,7 +56,7 @@ func TestPlainHttpFallback(t *testing.T) { json.NewEncoder(w).Encode(proto.Certs{}) }, actionUnderTest: func(ctx context.Context, addr string, insecure bool) error { - _, err := HostCredentials(ctx, addr, insecure, types.RegisterUsingTokenRequest{}) + _, err := client.HostCredentials(ctx, addr, insecure, types.RegisterUsingTokenRequest{}) return err }, }, @@ -94,3 +100,133 @@ func TestPlainHttpFallback(t *testing.T) { }) } } + +func TestSSHAgentPasswordlessLogin(t *testing.T) { + silenceLogger(t) + + clock := clockwork.NewFakeClockAt(time.Now()) + sa := newStandaloneTeleport(t, clock) + webID := sa.WebAuthnID + device := sa.Device + + ctx := context.Background() + + // Prepare client config, it won't change throughout the test. + cfg := client.MakeDefaultConfig() + cfg.AddKeysToAgent = client.AddKeysToAgentNo + // Replace "127.0.0.1" with "localhost". The proxy address becomes the origin + // for Webauthn requests, and Webauthn doesn't take IP addresses. + cfg.WebProxyAddr = strings.Replace(sa.ProxyWebAddr, "127.0.0.1", "localhost", 1 /* n */) + cfg.KeysDir = t.TempDir() + cfg.InsecureSkipVerify = true + + // Reset functions after tests. + oldWebauthn := *client.PromptWebauthn + t.Cleanup(func() { + *client.PromptWebauthn = oldWebauthn + }) + + solvePwdless := func(ctx context.Context, origin string, assertion *wanlib.CredentialAssertion, prompt wancli.LoginPrompt) (*proto.MFAAuthenticateResponse, error) { + car, err := device.SignAssertion(origin, assertion) + if err != nil { + return nil, err + } + resp := &proto.MFAAuthenticateResponse{ + Response: &proto.MFAAuthenticateResponse_Webauthn{ + Webauthn: wanlib.CredentialAssertionResponseToProto(car), + }, + } + resp.GetWebauthn().Response.UserHandle = webID + + return resp, nil + } + + tc, err := client.NewClient(cfg) + require.NoError(t, err) + key, err := client.NewKey() + require.NoError(t, err) + + // customPromptCalled is a flag to ensure the custom prompt was indeed called + // for each test. + customPromptCalled := false + + tests := []struct { + name string + customPromptWebauthn func(ctx context.Context, origin string, assert *wanlib.CredentialAssertion, p wancli.LoginPrompt, _ *wancli.LoginOpts) (*proto.MFAAuthenticateResponse, string, error) + customPromptLogin wancli.LoginPrompt + }{ + { + name: "with custom prompt", + customPromptWebauthn: func(ctx context.Context, origin string, assert *wanlib.CredentialAssertion, p wancli.LoginPrompt, _ *wancli.LoginOpts) (*proto.MFAAuthenticateResponse, string, error) { + _, ok := p.(*customPromptLogin) + require.True(t, ok) + customPromptCalled = true + + // Test custom prompts can be called. + pin, err := p.PromptPIN() + require.NoError(t, err) + require.Empty(t, pin) + + creds, err := p.PromptCredential(nil) + require.NoError(t, err) + require.Empty(t, creds) + + require.NoError(t, p.PromptTouch()) + + resp, err := solvePwdless(ctx, origin, assert, p) + return resp, "", err + }, + customPromptLogin: &customPromptLogin{}, + }, + { + name: "without custom prompt", + customPromptWebauthn: func(ctx context.Context, origin string, assert *wanlib.CredentialAssertion, p wancli.LoginPrompt, _ *wancli.LoginOpts) (*proto.MFAAuthenticateResponse, string, error) { + _, ok := p.(*wancli.DefaultPrompt) + require.True(t, ok) + customPromptCalled = true + + resp, err := solvePwdless(ctx, origin, assert, p) + return resp, "", err + }, + }, + } + + for _, test := range tests { + customPromptCalled = false // reset flag on each test. + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + req := client.SSHLoginPasswordless{ + SSHLogin: client.SSHLogin{ + ProxyAddr: tc.WebProxyAddr, + PubKey: key.Pub, + TTL: tc.KeyTTL, + Insecure: tc.InsecureSkipVerify, + Compatibility: tc.CertificateFormat, + RouteToCluster: tc.SiteName, + KubernetesCluster: tc.KubernetesCluster, + }, + AuthenticatorAttachment: tc.AuthenticatorAttachment, + CustomPrompt: test.customPromptLogin, + } + + *client.PromptWebauthn = test.customPromptWebauthn + _, err = client.SSHAgentPasswordlessLogin(ctx, req) + require.NoError(t, err) + require.True(t, customPromptCalled, "Custom prompt present but not called") + } +} + +type customPromptLogin struct{} + +func (p *customPromptLogin) PromptPIN() (string, error) { + return "", nil +} + +func (p *customPromptLogin) PromptTouch() error { + return nil +} + +func (p *customPromptLogin) PromptCredential(deviceCreds []*wancli.CredentialInfo) (*wancli.CredentialInfo, error) { + return nil, nil +} diff --git a/lib/teleterm/api/proto/v1/auth_settings.proto b/lib/teleterm/api/proto/v1/auth_settings.proto index 1cb47f23d316d..f1bb9cfb21b43 100644 --- a/lib/teleterm/api/proto/v1/auth_settings.proto +++ b/lib/teleterm/api/proto/v1/auth_settings.proto @@ -32,6 +32,12 @@ message AuthSettings { // banner text that must be retrieved, displayed and acknowledged by // the user. bool has_message_of_the_day = 5; + // auth_type is the authentication type e.g. "local", "github", "saml", "oidc" + string auth_type = 6; + // allow_passwordless is true if passwordless logins are allowed. + bool allow_passwordless = 7; + // local_connector_name is the name of the local connector. + string local_connector_name = 8; } // AuthProvider describes a way of authentication that is supported by the server. Auth provider is diff --git a/lib/teleterm/api/proto/v1/service.proto b/lib/teleterm/api/proto/v1/service.proto index 9b4f1b2a466cd..a2157e70f3482 100644 --- a/lib/teleterm/api/proto/v1/service.proto +++ b/lib/teleterm/api/proto/v1/service.proto @@ -73,6 +73,24 @@ service TerminalService { rpc GetCluster(GetClusterRequest) returns (Cluster); // Login logs in a user to a cluster rpc Login(LoginRequest) returns (EmptyResponse); + // LoginPasswordless logs in a user to a cluster passwordlessly. + // + // The RPC is streaming both ways and the message sequence example for hardware keys are: + // (-> means client-to-server, <- means server-to-client) + // + // Hardware keys: + // -> Init + // <- Send PasswordlessPrompt enum TAP to choose a device + // -> Receive TAP device response + // <- Send PasswordlessPrompt enum PIN + // -> Receive PIN response + // <- Send PasswordlessPrompt enum RETAP to confirm + // -> Receive RETAP device response + // <- Send list of credentials (e.g. usernames) associated with device + // -> Receive the index number associated with the selected credential in list + // <- End + rpc LoginPasswordless(stream LoginPasswordlessRequest) + returns (stream LoginPasswordlessResponse); // ClusterLogin logs out a user from cluster rpc Logout(LogoutRequest) returns (EmptyResponse); } @@ -86,6 +104,61 @@ message GetClusterRequest { string cluster_uri = 1; } // LogoutRequest describes LogoutRequest message LogoutRequest { string cluster_uri = 1; } +// PasswordlessPrompt describes different prompts we need from users +// during the passwordless login flow. +enum PasswordlessPrompt { + PASSWORDLESS_PROMPT_UNSPECIFIED = 0; + + // PASSWORDLESS_PROMPT_PIN is used when we need a user's pin. + PASSWORDLESS_PROMPT_PIN = 1; + + // PASSWORDLESS_PROMPT_TAP is used when we require a user to tap their device. + PASSWORDLESS_PROMPT_TAP = 2; + + // PASSWORDLESS_PROMPT_CREDENTIAL is used when we require a user to select a username + // associated with their account. + PASSWORDLESS_PROMPT_CREDENTIAL = 3; +} + +// CredentialInfo holds fields related to a user's WebAuthn credential. +message CredentialInfo { string Username = 1; } + +// LoginPasswordlessResponse is a message sent by the server during the +// passwordless login flow. +message LoginPasswordlessResponse { + PasswordlessPrompt prompt = 1; + repeated CredentialInfo credentials = 2; +} + +// LoginPasswordlessRequest is a message sent by the client during the passwordless login flow. +message LoginPasswordlessRequest { + oneof request { + LoginPasswordlessRequestInit init = 1; + LoginPasswordlessPINResponse pin = 2; + LoginPasswordlessCredentialResponse credential = 3; + } + + // LoginPasswordlessRequestInit contains fields needed to init the stream request. + message LoginPasswordlessRequestInit { + // cluster_uri is needed to resolve cluster by its uri. + string cluster_uri = 1; + } + + // LoginPasswordlessPINResponse contains fields related to request from webauthncli.PromptPIN. + message LoginPasswordlessPINResponse { + // pin is the user's device's pin. + string pin = 1; + } + + // LoginPasswordlessPINResponse contains fields related to request from + // webauthncli.PromptCredential. + message LoginPasswordlessCredentialResponse { + // index is the associated number in the list of credentials that the user selected to log + // in as. + int64 index = 1; + } +} + // LoginRequest describes cluster login request message LoginRequest { // cluster_uri is the cluster uri diff --git a/lib/teleterm/api/protogen/golang/v1/auth_settings.pb.go b/lib/teleterm/api/protogen/golang/v1/auth_settings.pb.go index a8540e7c4d967..5896debbdfc2c 100644 --- a/lib/teleterm/api/protogen/golang/v1/auth_settings.pb.go +++ b/lib/teleterm/api/protogen/golang/v1/auth_settings.pb.go @@ -57,6 +57,12 @@ type AuthSettings struct { // banner text that must be retrieved, displayed and acknowledged by // the user. HasMessageOfTheDay bool `protobuf:"varint,5,opt,name=has_message_of_the_day,json=hasMessageOfTheDay,proto3" json:"has_message_of_the_day,omitempty"` + // auth_type is the authentication type e.g. "local", "github", "saml", "oidc" + AuthType string `protobuf:"bytes,6,opt,name=auth_type,json=authType,proto3" json:"auth_type,omitempty"` + // allow_passwordless is true if passwordless logins are allowed. + AllowPasswordless bool `protobuf:"varint,7,opt,name=allow_passwordless,json=allowPasswordless,proto3" json:"allow_passwordless,omitempty"` + // local_connector_name is the name of the local connector. + LocalConnectorName string `protobuf:"bytes,8,opt,name=local_connector_name,json=localConnectorName,proto3" json:"local_connector_name,omitempty"` } func (x *AuthSettings) Reset() { @@ -126,6 +132,27 @@ func (x *AuthSettings) GetHasMessageOfTheDay() bool { return false } +func (x *AuthSettings) GetAuthType() string { + if x != nil { + return x.AuthType + } + return "" +} + +func (x *AuthSettings) GetAllowPasswordless() bool { + if x != nil { + return x.AllowPasswordless + } + return false +} + +func (x *AuthSettings) GetLocalConnectorName() string { + if x != nil { + return x.LocalConnectorName + } + return "" +} + // AuthProvider describes a way of authentication that is supported by the server. Auth provider is // referred to as "auth connector" on the backend. type AuthProvider struct { @@ -199,8 +226,8 @@ var File_v1_auth_settings_proto protoreflect.FileDescriptor var file_v1_auth_settings_proto_rawDesc = []byte{ 0x0a, 0x16, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x22, 0x85, - 0x02, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x22, 0x83, + 0x03, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x23, 0x0a, @@ -216,16 +243,24 @@ var file_v1_auth_settings_proto_rawDesc = []byte{ 0x72, 0x73, 0x12, 0x32, 0x0a, 0x16, 0x68, 0x61, 0x73, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x68, 0x65, 0x5f, 0x64, 0x61, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x68, 0x61, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x66, - 0x54, 0x68, 0x65, 0x44, 0x61, 0x79, 0x22, 0x59, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, - 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x54, 0x68, 0x65, 0x44, 0x61, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, + 0x73, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x59, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x42, + 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, + 0x6d, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/lib/teleterm/api/protogen/golang/v1/service.pb.go b/lib/teleterm/api/protogen/golang/v1/service.pb.go index 25122cc2cea5b..fba4562d3d7f7 100644 --- a/lib/teleterm/api/protogen/golang/v1/service.pb.go +++ b/lib/teleterm/api/protogen/golang/v1/service.pb.go @@ -44,6 +44,64 @@ const ( // of the legacy proto package is being used. const _ = proto.ProtoPackageIsVersion4 +// PasswordlessPrompt describes different prompts we need from users +// during the passwordless login flow. +type PasswordlessPrompt int32 + +const ( + PasswordlessPrompt_PASSWORDLESS_PROMPT_UNSPECIFIED PasswordlessPrompt = 0 + // PASSWORDLESS_PROMPT_PIN is used when we need a user's pin. + PasswordlessPrompt_PASSWORDLESS_PROMPT_PIN PasswordlessPrompt = 1 + // PASSWORDLESS_PROMPT_TAP is used when we require a user to tap their device. + PasswordlessPrompt_PASSWORDLESS_PROMPT_TAP PasswordlessPrompt = 2 + // PASSWORDLESS_PROMPT_CREDENTIAL is used when we require a user to select a username + // associated with their account. + PasswordlessPrompt_PASSWORDLESS_PROMPT_CREDENTIAL PasswordlessPrompt = 3 +) + +// Enum value maps for PasswordlessPrompt. +var ( + PasswordlessPrompt_name = map[int32]string{ + 0: "PASSWORDLESS_PROMPT_UNSPECIFIED", + 1: "PASSWORDLESS_PROMPT_PIN", + 2: "PASSWORDLESS_PROMPT_TAP", + 3: "PASSWORDLESS_PROMPT_CREDENTIAL", + } + PasswordlessPrompt_value = map[string]int32{ + "PASSWORDLESS_PROMPT_UNSPECIFIED": 0, + "PASSWORDLESS_PROMPT_PIN": 1, + "PASSWORDLESS_PROMPT_TAP": 2, + "PASSWORDLESS_PROMPT_CREDENTIAL": 3, + } +) + +func (x PasswordlessPrompt) Enum() *PasswordlessPrompt { + p := new(PasswordlessPrompt) + *p = x + return p +} + +func (x PasswordlessPrompt) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PasswordlessPrompt) Descriptor() protoreflect.EnumDescriptor { + return file_v1_service_proto_enumTypes[0].Descriptor() +} + +func (PasswordlessPrompt) Type() protoreflect.EnumType { + return &file_v1_service_proto_enumTypes[0] +} + +func (x PasswordlessPrompt) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PasswordlessPrompt.Descriptor instead. +func (PasswordlessPrompt) EnumDescriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{0} +} + // RemoveClusterRequest describes RemoveClusterRequest type RemoveClusterRequest struct { state protoimpl.MessageState @@ -188,6 +246,206 @@ func (x *LogoutRequest) GetClusterUri() string { return "" } +// CredentialInfo holds fields related to a user's WebAuthn credential. +type CredentialInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=Username,proto3" json:"Username,omitempty"` +} + +func (x *CredentialInfo) Reset() { + *x = CredentialInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CredentialInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CredentialInfo) ProtoMessage() {} + +func (x *CredentialInfo) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CredentialInfo.ProtoReflect.Descriptor instead. +func (*CredentialInfo) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{3} +} + +func (x *CredentialInfo) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +// LoginPasswordlessResponse is a message sent by the server during the +// passwordless login flow. +type LoginPasswordlessResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prompt PasswordlessPrompt `protobuf:"varint,1,opt,name=prompt,proto3,enum=teleport.terminal.v1.PasswordlessPrompt" json:"prompt,omitempty"` + Credentials []*CredentialInfo `protobuf:"bytes,2,rep,name=credentials,proto3" json:"credentials,omitempty"` +} + +func (x *LoginPasswordlessResponse) Reset() { + *x = LoginPasswordlessResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginPasswordlessResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginPasswordlessResponse) ProtoMessage() {} + +func (x *LoginPasswordlessResponse) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginPasswordlessResponse.ProtoReflect.Descriptor instead. +func (*LoginPasswordlessResponse) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{4} +} + +func (x *LoginPasswordlessResponse) GetPrompt() PasswordlessPrompt { + if x != nil { + return x.Prompt + } + return PasswordlessPrompt_PASSWORDLESS_PROMPT_UNSPECIFIED +} + +func (x *LoginPasswordlessResponse) GetCredentials() []*CredentialInfo { + if x != nil { + return x.Credentials + } + return nil +} + +// LoginPasswordlessRequest is a message sent by the client during the passwordless login flow. +type LoginPasswordlessRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Request: + // *LoginPasswordlessRequest_Init + // *LoginPasswordlessRequest_Pin + // *LoginPasswordlessRequest_Credential + Request isLoginPasswordlessRequest_Request `protobuf_oneof:"request"` +} + +func (x *LoginPasswordlessRequest) Reset() { + *x = LoginPasswordlessRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginPasswordlessRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginPasswordlessRequest) ProtoMessage() {} + +func (x *LoginPasswordlessRequest) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginPasswordlessRequest.ProtoReflect.Descriptor instead. +func (*LoginPasswordlessRequest) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{5} +} + +func (m *LoginPasswordlessRequest) GetRequest() isLoginPasswordlessRequest_Request { + if m != nil { + return m.Request + } + return nil +} + +func (x *LoginPasswordlessRequest) GetInit() *LoginPasswordlessRequest_LoginPasswordlessRequestInit { + if x, ok := x.GetRequest().(*LoginPasswordlessRequest_Init); ok { + return x.Init + } + return nil +} + +func (x *LoginPasswordlessRequest) GetPin() *LoginPasswordlessRequest_LoginPasswordlessPINResponse { + if x, ok := x.GetRequest().(*LoginPasswordlessRequest_Pin); ok { + return x.Pin + } + return nil +} + +func (x *LoginPasswordlessRequest) GetCredential() *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse { + if x, ok := x.GetRequest().(*LoginPasswordlessRequest_Credential); ok { + return x.Credential + } + return nil +} + +type isLoginPasswordlessRequest_Request interface { + isLoginPasswordlessRequest_Request() +} + +type LoginPasswordlessRequest_Init struct { + Init *LoginPasswordlessRequest_LoginPasswordlessRequestInit `protobuf:"bytes,1,opt,name=init,proto3,oneof"` +} + +type LoginPasswordlessRequest_Pin struct { + Pin *LoginPasswordlessRequest_LoginPasswordlessPINResponse `protobuf:"bytes,2,opt,name=pin,proto3,oneof"` +} + +type LoginPasswordlessRequest_Credential struct { + Credential *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse `protobuf:"bytes,3,opt,name=credential,proto3,oneof"` +} + +func (*LoginPasswordlessRequest_Init) isLoginPasswordlessRequest_Request() {} + +func (*LoginPasswordlessRequest_Pin) isLoginPasswordlessRequest_Request() {} + +func (*LoginPasswordlessRequest_Credential) isLoginPasswordlessRequest_Request() {} + // LoginRequest describes cluster login request type LoginRequest struct { state protoimpl.MessageState @@ -205,7 +463,7 @@ type LoginRequest struct { func (x *LoginRequest) Reset() { *x = LoginRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[3] + mi := &file_v1_service_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -218,7 +476,7 @@ func (x *LoginRequest) String() string { func (*LoginRequest) ProtoMessage() {} func (x *LoginRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[3] + mi := &file_v1_service_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -231,7 +489,7 @@ func (x *LoginRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead. func (*LoginRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{3} + return file_v1_service_proto_rawDescGZIP(), []int{6} } func (x *LoginRequest) GetClusterUri() string { @@ -291,7 +549,7 @@ type AddClusterRequest struct { func (x *AddClusterRequest) Reset() { *x = AddClusterRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[4] + mi := &file_v1_service_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -304,7 +562,7 @@ func (x *AddClusterRequest) String() string { func (*AddClusterRequest) ProtoMessage() {} func (x *AddClusterRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[4] + mi := &file_v1_service_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -317,7 +575,7 @@ func (x *AddClusterRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddClusterRequest.ProtoReflect.Descriptor instead. func (*AddClusterRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{4} + return file_v1_service_proto_rawDescGZIP(), []int{7} } func (x *AddClusterRequest) GetName() string { @@ -338,7 +596,7 @@ type ListKubesRequest struct { func (x *ListKubesRequest) Reset() { *x = ListKubesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[5] + mi := &file_v1_service_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -351,7 +609,7 @@ func (x *ListKubesRequest) String() string { func (*ListKubesRequest) ProtoMessage() {} func (x *ListKubesRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[5] + mi := &file_v1_service_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -364,7 +622,7 @@ func (x *ListKubesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListKubesRequest.ProtoReflect.Descriptor instead. func (*ListKubesRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{5} + return file_v1_service_proto_rawDescGZIP(), []int{8} } func (x *ListKubesRequest) GetClusterUri() string { @@ -385,7 +643,7 @@ type ListAppsRequest struct { func (x *ListAppsRequest) Reset() { *x = ListAppsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[6] + mi := &file_v1_service_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -398,7 +656,7 @@ func (x *ListAppsRequest) String() string { func (*ListAppsRequest) ProtoMessage() {} func (x *ListAppsRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[6] + mi := &file_v1_service_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -411,7 +669,7 @@ func (x *ListAppsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAppsRequest.ProtoReflect.Descriptor instead. func (*ListAppsRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{6} + return file_v1_service_proto_rawDescGZIP(), []int{9} } func (x *ListAppsRequest) GetClusterUri() string { @@ -430,7 +688,7 @@ type ListClustersRequest struct { func (x *ListClustersRequest) Reset() { *x = ListClustersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[7] + mi := &file_v1_service_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -443,7 +701,7 @@ func (x *ListClustersRequest) String() string { func (*ListClustersRequest) ProtoMessage() {} func (x *ListClustersRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[7] + mi := &file_v1_service_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -456,7 +714,7 @@ func (x *ListClustersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListClustersRequest.ProtoReflect.Descriptor instead. func (*ListClustersRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{7} + return file_v1_service_proto_rawDescGZIP(), []int{10} } type ListClustersResponse struct { @@ -470,7 +728,7 @@ type ListClustersResponse struct { func (x *ListClustersResponse) Reset() { *x = ListClustersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[8] + mi := &file_v1_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -483,7 +741,7 @@ func (x *ListClustersResponse) String() string { func (*ListClustersResponse) ProtoMessage() {} func (x *ListClustersResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[8] + mi := &file_v1_service_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -496,7 +754,7 @@ func (x *ListClustersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListClustersResponse.ProtoReflect.Descriptor instead. func (*ListClustersResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{8} + return file_v1_service_proto_rawDescGZIP(), []int{11} } func (x *ListClustersResponse) GetClusters() []*Cluster { @@ -517,7 +775,7 @@ type ListDatabasesRequest struct { func (x *ListDatabasesRequest) Reset() { *x = ListDatabasesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[9] + mi := &file_v1_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -530,7 +788,7 @@ func (x *ListDatabasesRequest) String() string { func (*ListDatabasesRequest) ProtoMessage() {} func (x *ListDatabasesRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[9] + mi := &file_v1_service_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -543,7 +801,7 @@ func (x *ListDatabasesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDatabasesRequest.ProtoReflect.Descriptor instead. func (*ListDatabasesRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{9} + return file_v1_service_proto_rawDescGZIP(), []int{12} } func (x *ListDatabasesRequest) GetClusterUri() string { @@ -564,7 +822,7 @@ type ListLeafClustersRequest struct { func (x *ListLeafClustersRequest) Reset() { *x = ListLeafClustersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[10] + mi := &file_v1_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -577,7 +835,7 @@ func (x *ListLeafClustersRequest) String() string { func (*ListLeafClustersRequest) ProtoMessage() {} func (x *ListLeafClustersRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[10] + mi := &file_v1_service_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -590,7 +848,7 @@ func (x *ListLeafClustersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLeafClustersRequest.ProtoReflect.Descriptor instead. func (*ListLeafClustersRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{10} + return file_v1_service_proto_rawDescGZIP(), []int{13} } func (x *ListLeafClustersRequest) GetClusterUri() string { @@ -611,7 +869,7 @@ type ListDatabasesResponse struct { func (x *ListDatabasesResponse) Reset() { *x = ListDatabasesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[11] + mi := &file_v1_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -624,7 +882,7 @@ func (x *ListDatabasesResponse) String() string { func (*ListDatabasesResponse) ProtoMessage() {} func (x *ListDatabasesResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[11] + mi := &file_v1_service_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -637,7 +895,7 @@ func (x *ListDatabasesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDatabasesResponse.ProtoReflect.Descriptor instead. func (*ListDatabasesResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{11} + return file_v1_service_proto_rawDescGZIP(), []int{14} } func (x *ListDatabasesResponse) GetDatabases() []*Database { @@ -658,7 +916,7 @@ type ListDatabaseUsersRequest struct { func (x *ListDatabaseUsersRequest) Reset() { *x = ListDatabaseUsersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[12] + mi := &file_v1_service_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -671,7 +929,7 @@ func (x *ListDatabaseUsersRequest) String() string { func (*ListDatabaseUsersRequest) ProtoMessage() {} func (x *ListDatabaseUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[12] + mi := &file_v1_service_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -684,7 +942,7 @@ func (x *ListDatabaseUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDatabaseUsersRequest.ProtoReflect.Descriptor instead. func (*ListDatabaseUsersRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{12} + return file_v1_service_proto_rawDescGZIP(), []int{15} } func (x *ListDatabaseUsersRequest) GetDbUri() string { @@ -705,7 +963,7 @@ type ListDatabaseUsersResponse struct { func (x *ListDatabaseUsersResponse) Reset() { *x = ListDatabaseUsersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[13] + mi := &file_v1_service_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -718,7 +976,7 @@ func (x *ListDatabaseUsersResponse) String() string { func (*ListDatabaseUsersResponse) ProtoMessage() {} func (x *ListDatabaseUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[13] + mi := &file_v1_service_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -731,7 +989,7 @@ func (x *ListDatabaseUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDatabaseUsersResponse.ProtoReflect.Descriptor instead. func (*ListDatabaseUsersResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{13} + return file_v1_service_proto_rawDescGZIP(), []int{16} } func (x *ListDatabaseUsersResponse) GetUsers() []string { @@ -755,7 +1013,7 @@ type CreateGatewayRequest struct { func (x *CreateGatewayRequest) Reset() { *x = CreateGatewayRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[14] + mi := &file_v1_service_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -768,7 +1026,7 @@ func (x *CreateGatewayRequest) String() string { func (*CreateGatewayRequest) ProtoMessage() {} func (x *CreateGatewayRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[14] + mi := &file_v1_service_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -781,7 +1039,7 @@ func (x *CreateGatewayRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateGatewayRequest.ProtoReflect.Descriptor instead. func (*CreateGatewayRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{14} + return file_v1_service_proto_rawDescGZIP(), []int{17} } func (x *CreateGatewayRequest) GetTargetUri() string { @@ -823,7 +1081,7 @@ type ListGatewaysRequest struct { func (x *ListGatewaysRequest) Reset() { *x = ListGatewaysRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[15] + mi := &file_v1_service_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -836,7 +1094,7 @@ func (x *ListGatewaysRequest) String() string { func (*ListGatewaysRequest) ProtoMessage() {} func (x *ListGatewaysRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[15] + mi := &file_v1_service_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -849,7 +1107,7 @@ func (x *ListGatewaysRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGatewaysRequest.ProtoReflect.Descriptor instead. func (*ListGatewaysRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{15} + return file_v1_service_proto_rawDescGZIP(), []int{18} } func (x *ListGatewaysRequest) GetClusterIds() []string { @@ -870,7 +1128,7 @@ type ListGatewaysResponse struct { func (x *ListGatewaysResponse) Reset() { *x = ListGatewaysResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[16] + mi := &file_v1_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -883,7 +1141,7 @@ func (x *ListGatewaysResponse) String() string { func (*ListGatewaysResponse) ProtoMessage() {} func (x *ListGatewaysResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[16] + mi := &file_v1_service_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -896,7 +1154,7 @@ func (x *ListGatewaysResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGatewaysResponse.ProtoReflect.Descriptor instead. func (*ListGatewaysResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{16} + return file_v1_service_proto_rawDescGZIP(), []int{19} } func (x *ListGatewaysResponse) GetGateways() []*Gateway { @@ -917,7 +1175,7 @@ type RemoveGatewayRequest struct { func (x *RemoveGatewayRequest) Reset() { *x = RemoveGatewayRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[17] + mi := &file_v1_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -930,7 +1188,7 @@ func (x *RemoveGatewayRequest) String() string { func (*RemoveGatewayRequest) ProtoMessage() {} func (x *RemoveGatewayRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[17] + mi := &file_v1_service_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -943,7 +1201,7 @@ func (x *RemoveGatewayRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveGatewayRequest.ProtoReflect.Descriptor instead. func (*RemoveGatewayRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{17} + return file_v1_service_proto_rawDescGZIP(), []int{20} } func (x *RemoveGatewayRequest) GetGatewayUri() string { @@ -964,7 +1222,7 @@ type RestartGatewayRequest struct { func (x *RestartGatewayRequest) Reset() { *x = RestartGatewayRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[18] + mi := &file_v1_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -977,7 +1235,7 @@ func (x *RestartGatewayRequest) String() string { func (*RestartGatewayRequest) ProtoMessage() {} func (x *RestartGatewayRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[18] + mi := &file_v1_service_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -990,7 +1248,7 @@ func (x *RestartGatewayRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RestartGatewayRequest.ProtoReflect.Descriptor instead. func (*RestartGatewayRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{18} + return file_v1_service_proto_rawDescGZIP(), []int{21} } func (x *RestartGatewayRequest) GetGatewayUri() string { @@ -1012,7 +1270,7 @@ type SetGatewayTargetSubresourceNameRequest struct { func (x *SetGatewayTargetSubresourceNameRequest) Reset() { *x = SetGatewayTargetSubresourceNameRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[19] + mi := &file_v1_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1025,7 +1283,7 @@ func (x *SetGatewayTargetSubresourceNameRequest) String() string { func (*SetGatewayTargetSubresourceNameRequest) ProtoMessage() {} func (x *SetGatewayTargetSubresourceNameRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[19] + mi := &file_v1_service_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1038,7 +1296,7 @@ func (x *SetGatewayTargetSubresourceNameRequest) ProtoReflect() protoreflect.Mes // Deprecated: Use SetGatewayTargetSubresourceNameRequest.ProtoReflect.Descriptor instead. func (*SetGatewayTargetSubresourceNameRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{19} + return file_v1_service_proto_rawDescGZIP(), []int{22} } func (x *SetGatewayTargetSubresourceNameRequest) GetGatewayUri() string { @@ -1067,7 +1325,7 @@ type SetGatewayLocalPortRequest struct { func (x *SetGatewayLocalPortRequest) Reset() { *x = SetGatewayLocalPortRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[20] + mi := &file_v1_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1080,7 +1338,7 @@ func (x *SetGatewayLocalPortRequest) String() string { func (*SetGatewayLocalPortRequest) ProtoMessage() {} func (x *SetGatewayLocalPortRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[20] + mi := &file_v1_service_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1093,7 +1351,7 @@ func (x *SetGatewayLocalPortRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetGatewayLocalPortRequest.ProtoReflect.Descriptor instead. func (*SetGatewayLocalPortRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{20} + return file_v1_service_proto_rawDescGZIP(), []int{23} } func (x *SetGatewayLocalPortRequest) GetGatewayUri() string { @@ -1121,7 +1379,7 @@ type ListServersRequest struct { func (x *ListServersRequest) Reset() { *x = ListServersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[21] + mi := &file_v1_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1134,7 +1392,7 @@ func (x *ListServersRequest) String() string { func (*ListServersRequest) ProtoMessage() {} func (x *ListServersRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[21] + mi := &file_v1_service_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1147,7 +1405,7 @@ func (x *ListServersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListServersRequest.ProtoReflect.Descriptor instead. func (*ListServersRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{21} + return file_v1_service_proto_rawDescGZIP(), []int{24} } func (x *ListServersRequest) GetClusterUri() string { @@ -1168,7 +1426,7 @@ type ListServersResponse struct { func (x *ListServersResponse) Reset() { *x = ListServersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[22] + mi := &file_v1_service_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1181,7 +1439,7 @@ func (x *ListServersResponse) String() string { func (*ListServersResponse) ProtoMessage() {} func (x *ListServersResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[22] + mi := &file_v1_service_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1194,7 +1452,7 @@ func (x *ListServersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListServersResponse.ProtoReflect.Descriptor instead. func (*ListServersResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{22} + return file_v1_service_proto_rawDescGZIP(), []int{25} } func (x *ListServersResponse) GetServers() []*Server { @@ -1215,7 +1473,7 @@ type ListKubesResponse struct { func (x *ListKubesResponse) Reset() { *x = ListKubesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[23] + mi := &file_v1_service_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1228,7 +1486,7 @@ func (x *ListKubesResponse) String() string { func (*ListKubesResponse) ProtoMessage() {} func (x *ListKubesResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[23] + mi := &file_v1_service_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1241,41 +1499,175 @@ func (x *ListKubesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListKubesResponse.ProtoReflect.Descriptor instead. func (*ListKubesResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{23} + return file_v1_service_proto_rawDescGZIP(), []int{26} +} + +func (x *ListKubesResponse) GetKubes() []*Kube { + if x != nil { + return x.Kubes + } + return nil +} + +type ListAppsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Apps []*App `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"` +} + +func (x *ListAppsResponse) Reset() { + *x = ListAppsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListAppsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListAppsResponse) ProtoMessage() {} + +func (x *ListAppsResponse) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListAppsResponse.ProtoReflect.Descriptor instead. +func (*ListAppsResponse) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{27} +} + +func (x *ListAppsResponse) GetApps() []*App { + if x != nil { + return x.Apps + } + return nil +} + +type GetAuthSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterUri string `protobuf:"bytes,1,opt,name=cluster_uri,json=clusterUri,proto3" json:"cluster_uri,omitempty"` +} + +func (x *GetAuthSettingsRequest) Reset() { + *x = GetAuthSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetAuthSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAuthSettingsRequest) ProtoMessage() {} + +func (x *GetAuthSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetAuthSettingsRequest.ProtoReflect.Descriptor instead. +func (*GetAuthSettingsRequest) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{28} +} + +func (x *GetAuthSettingsRequest) GetClusterUri() string { + if x != nil { + return x.ClusterUri + } + return "" +} + +type EmptyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EmptyResponse) Reset() { + *x = EmptyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EmptyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmptyResponse) ProtoMessage() {} + +func (x *EmptyResponse) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (x *ListKubesResponse) GetKubes() []*Kube { - if x != nil { - return x.Kubes - } - return nil +// Deprecated: Use EmptyResponse.ProtoReflect.Descriptor instead. +func (*EmptyResponse) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{29} } -type ListAppsResponse struct { +// LoginPasswordlessRequestInit contains fields needed to init the stream request. +type LoginPasswordlessRequest_LoginPasswordlessRequestInit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Apps []*App `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"` + // cluster_uri is needed to resolve cluster by its uri. + ClusterUri string `protobuf:"bytes,1,opt,name=cluster_uri,json=clusterUri,proto3" json:"cluster_uri,omitempty"` } -func (x *ListAppsResponse) Reset() { - *x = ListAppsResponse{} +func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) Reset() { + *x = LoginPasswordlessRequest_LoginPasswordlessRequestInit{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[24] + mi := &file_v1_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *ListAppsResponse) String() string { +func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ListAppsResponse) ProtoMessage() {} +func (*LoginPasswordlessRequest_LoginPasswordlessRequestInit) ProtoMessage() {} -func (x *ListAppsResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[24] +func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1286,43 +1678,45 @@ func (x *ListAppsResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ListAppsResponse.ProtoReflect.Descriptor instead. -func (*ListAppsResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{24} +// Deprecated: Use LoginPasswordlessRequest_LoginPasswordlessRequestInit.ProtoReflect.Descriptor instead. +func (*LoginPasswordlessRequest_LoginPasswordlessRequestInit) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{5, 0} } -func (x *ListAppsResponse) GetApps() []*App { +func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) GetClusterUri() string { if x != nil { - return x.Apps + return x.ClusterUri } - return nil + return "" } -type GetAuthSettingsRequest struct { +// LoginPasswordlessPINResponse contains fields related to request from webauthncli.PromptPIN. +type LoginPasswordlessRequest_LoginPasswordlessPINResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ClusterUri string `protobuf:"bytes,1,opt,name=cluster_uri,json=clusterUri,proto3" json:"cluster_uri,omitempty"` + // pin is the user's device's pin. + Pin string `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` } -func (x *GetAuthSettingsRequest) Reset() { - *x = GetAuthSettingsRequest{} +func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) Reset() { + *x = LoginPasswordlessRequest_LoginPasswordlessPINResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[25] + mi := &file_v1_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *GetAuthSettingsRequest) String() string { +func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetAuthSettingsRequest) ProtoMessage() {} +func (*LoginPasswordlessRequest_LoginPasswordlessPINResponse) ProtoMessage() {} -func (x *GetAuthSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[25] +func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1333,41 +1727,47 @@ func (x *GetAuthSettingsRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetAuthSettingsRequest.ProtoReflect.Descriptor instead. -func (*GetAuthSettingsRequest) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{25} +// Deprecated: Use LoginPasswordlessRequest_LoginPasswordlessPINResponse.ProtoReflect.Descriptor instead. +func (*LoginPasswordlessRequest_LoginPasswordlessPINResponse) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{5, 1} } -func (x *GetAuthSettingsRequest) GetClusterUri() string { +func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) GetPin() string { if x != nil { - return x.ClusterUri + return x.Pin } return "" } -type EmptyResponse struct { +// LoginPasswordlessPINResponse contains fields related to request from +// webauthncli.PromptCredential. +type LoginPasswordlessRequest_LoginPasswordlessCredentialResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // index is the associated number in the list of credentials that the user selected to log + // in as. + Index int64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` } -func (x *EmptyResponse) Reset() { - *x = EmptyResponse{} +func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) Reset() { + *x = LoginPasswordlessRequest_LoginPasswordlessCredentialResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[26] + mi := &file_v1_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *EmptyResponse) String() string { +func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*EmptyResponse) ProtoMessage() {} +func (*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) ProtoMessage() {} -func (x *EmptyResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[26] +func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1378,9 +1778,16 @@ func (x *EmptyResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use EmptyResponse.ProtoReflect.Descriptor instead. -func (*EmptyResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{26} +// Deprecated: Use LoginPasswordlessRequest_LoginPasswordlessCredentialResponse.ProtoReflect.Descriptor instead. +func (*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{5, 2} +} + +func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) GetIndex() int64 { + if x != nil { + return x.Index + } + return 0 } // LocalParams describes parameters for local user logins @@ -1400,7 +1807,7 @@ type LoginRequest_LocalParams struct { func (x *LoginRequest_LocalParams) Reset() { *x = LoginRequest_LocalParams{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[27] + mi := &file_v1_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1413,7 +1820,7 @@ func (x *LoginRequest_LocalParams) String() string { func (*LoginRequest_LocalParams) ProtoMessage() {} func (x *LoginRequest_LocalParams) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[27] + mi := &file_v1_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1426,7 +1833,7 @@ func (x *LoginRequest_LocalParams) ProtoReflect() protoreflect.Message { // Deprecated: Use LoginRequest_LocalParams.ProtoReflect.Descriptor instead. func (*LoginRequest_LocalParams) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{3, 0} + return file_v1_service_proto_rawDescGZIP(), []int{6, 0} } func (x *LoginRequest_LocalParams) GetUser() string { @@ -1465,7 +1872,7 @@ type LoginRequest_SsoParams struct { func (x *LoginRequest_SsoParams) Reset() { *x = LoginRequest_SsoParams{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[28] + mi := &file_v1_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1478,7 +1885,7 @@ func (x *LoginRequest_SsoParams) String() string { func (*LoginRequest_SsoParams) ProtoMessage() {} func (x *LoginRequest_SsoParams) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[28] + mi := &file_v1_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1491,7 +1898,7 @@ func (x *LoginRequest_SsoParams) ProtoReflect() protoreflect.Message { // Deprecated: Use LoginRequest_SsoParams.ProtoReflect.Descriptor instead. func (*LoginRequest_SsoParams) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{3, 1} + return file_v1_service_proto_rawDescGZIP(), []int{6, 1} } func (x *LoginRequest_SsoParams) GetProviderType() string { @@ -1533,251 +1940,314 @@ var file_v1_service_proto_rawDesc = []byte{ 0x69, 0x22, 0x30, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x55, 0x72, 0x69, 0x22, 0xef, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, - 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x55, 0x72, 0x69, 0x12, 0x46, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x55, 0x72, 0x69, 0x22, 0x2c, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x22, 0xa5, 0x01, 0x0a, 0x19, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x40, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, + 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, + 0x74, 0x12, 0x46, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x8f, 0x04, 0x0a, 0x18, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x61, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x40, 0x0a, - 0x03, 0x73, 0x73, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, + 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x69, + 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x5f, 0x0a, 0x03, 0x70, 0x69, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x50, 0x49, 0x4e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x12, 0x74, 0x0a, 0x0a, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x52, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, + 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x1a, 0x3f, 0x0a, 0x1c, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x69, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, + 0x69, 0x1a, 0x30, 0x0a, 0x1c, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x50, 0x49, 0x4e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x70, 0x69, 0x6e, 0x1a, 0x3b, 0x0a, 0x23, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xef, 0x02, 0x0a, 0x0c, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x12, 0x46, 0x0a, + 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x05, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x40, 0x0a, 0x03, 0x73, 0x73, 0x6f, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x73, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x48, 0x00, 0x52, 0x03, 0x73, 0x73, 0x6f, 0x1a, 0x53, 0x0a, 0x0b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x55, 0x0a, 0x09, + 0x53, 0x73, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x27, 0x0a, + 0x11, 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x33, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, + 0x62, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x32, 0x0a, 0x0f, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, + 0x15, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x51, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, + 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, + 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x37, 0x0a, 0x14, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, + 0x72, 0x69, 0x22, 0x3a, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x55, + 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x62, + 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, - 0x73, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x03, 0x73, 0x73, 0x6f, 0x1a, - 0x53, 0x0a, 0x0b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x55, 0x0a, 0x09, 0x53, 0x73, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x27, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x33, - 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, - 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x55, 0x72, 0x69, 0x22, 0x32, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x51, - 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x73, 0x22, 0x37, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x3a, 0x0a, 0x17, 0x4c, 0x69, - 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x73, 0x22, 0x31, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x62, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x64, 0x62, 0x55, 0x72, 0x69, 0x22, 0x31, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x14, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, + 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x55, 0x72, 0x69, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, + 0x6f, 0x72, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x75, + 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x4c, + 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x49, 0x64, 0x73, 0x22, 0x51, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x08, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x22, 0x37, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, 0x69, 0x22, + 0x38, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, 0x69, 0x22, 0x81, 0x01, 0x0a, 0x26, 0x53, 0x65, + 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, + 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x55, 0x72, 0x69, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x73, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, + 0x1a, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, 0x69, 0x12, 0x1d, 0x0a, 0x0a, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x35, 0x0a, 0x12, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, + 0x72, 0x69, 0x22, 0x4d, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x22, 0x45, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x6b, 0x75, 0x62, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x75, 0x62, + 0x65, 0x52, 0x05, 0x6b, 0x75, 0x62, 0x65, 0x73, 0x22, 0x41, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x04, + 0x61, 0x70, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x04, 0x61, 0x70, 0x70, 0x73, 0x22, 0x39, 0x0a, 0x16, 0x47, + 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x55, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3c, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x22, 0x31, 0x0a, - 0x18, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x62, 0x5f, - 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x62, 0x55, 0x72, 0x69, - 0x22, 0x31, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x73, - 0x65, 0x72, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x72, 0x69, 0x12, 0x1f, 0x0a, 0x0b, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x51, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x52, 0x08, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x22, 0x37, - 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, 0x69, 0x22, 0x38, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, - 0x69, 0x22, 0x81, 0x01, 0x0a, 0x26, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, - 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, 0x69, 0x12, 0x36, 0x0a, - 0x17, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x75, - 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x55, 0x72, 0x69, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, - 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, - 0x6f, 0x72, 0x74, 0x22, 0x35, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x4d, 0x0a, 0x13, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x36, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, 0x45, 0x0a, 0x11, 0x4c, 0x69, 0x73, - 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, - 0x0a, 0x05, 0x6b, 0x75, 0x62, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x52, 0x05, 0x6b, 0x75, 0x62, 0x65, 0x73, - 0x22, 0x41, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x61, 0x70, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x04, 0x61, - 0x70, 0x70, 0x73, 0x22, 0x39, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x0f, - 0x0a, 0x0d, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, - 0xf2, 0x0e, 0x0a, 0x0f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, - 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, - 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, - 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x12, 0x2a, + 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x0f, 0x0a, 0x0d, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x97, 0x01, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x23, + 0x0a, 0x1f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, + 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, + 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x10, 0x01, + 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, + 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x54, 0x41, 0x50, 0x10, 0x02, 0x12, 0x22, 0x0a, + 0x1e, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, + 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x44, 0x45, 0x4e, 0x54, 0x49, 0x41, 0x4c, 0x10, + 0x03, 0x32, 0xec, 0x0f, 0x0a, 0x0f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, + 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x6d, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x68, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, + 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x11, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x2e, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, + 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x62, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x28, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, + 0x12, 0x26, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x59, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x12, 0x25, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0a, + 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x44, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, - 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x28, 0x2e, 0x74, + 0x31, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x73, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x12, 0x26, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x59, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x12, 0x25, 0x2e, 0x74, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, - 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0a, 0x41, 0x64, - 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, + 0x1f, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x66, 0x0a, + 0x13, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x6f, 0x72, 0x74, 0x12, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x63, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x0a, 0x47, 0x65, + 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x12, 0x50, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x73, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x1f, 0x53, - 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3c, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x66, 0x0a, 0x13, 0x53, - 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x12, 0x63, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x50, - 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x73, 0x65, 0x12, 0x78, 0x0a, 0x11, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, + 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x06, + 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, + 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x52, 0x0a, 0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x23, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, + 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1792,97 +2262,112 @@ func file_v1_service_proto_rawDescGZIP() []byte { return file_v1_service_proto_rawDescData } -var file_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 35) var file_v1_service_proto_goTypes = []interface{}{ - (*RemoveClusterRequest)(nil), // 0: teleport.terminal.v1.RemoveClusterRequest - (*GetClusterRequest)(nil), // 1: teleport.terminal.v1.GetClusterRequest - (*LogoutRequest)(nil), // 2: teleport.terminal.v1.LogoutRequest - (*LoginRequest)(nil), // 3: teleport.terminal.v1.LoginRequest - (*AddClusterRequest)(nil), // 4: teleport.terminal.v1.AddClusterRequest - (*ListKubesRequest)(nil), // 5: teleport.terminal.v1.ListKubesRequest - (*ListAppsRequest)(nil), // 6: teleport.terminal.v1.ListAppsRequest - (*ListClustersRequest)(nil), // 7: teleport.terminal.v1.ListClustersRequest - (*ListClustersResponse)(nil), // 8: teleport.terminal.v1.ListClustersResponse - (*ListDatabasesRequest)(nil), // 9: teleport.terminal.v1.ListDatabasesRequest - (*ListLeafClustersRequest)(nil), // 10: teleport.terminal.v1.ListLeafClustersRequest - (*ListDatabasesResponse)(nil), // 11: teleport.terminal.v1.ListDatabasesResponse - (*ListDatabaseUsersRequest)(nil), // 12: teleport.terminal.v1.ListDatabaseUsersRequest - (*ListDatabaseUsersResponse)(nil), // 13: teleport.terminal.v1.ListDatabaseUsersResponse - (*CreateGatewayRequest)(nil), // 14: teleport.terminal.v1.CreateGatewayRequest - (*ListGatewaysRequest)(nil), // 15: teleport.terminal.v1.ListGatewaysRequest - (*ListGatewaysResponse)(nil), // 16: teleport.terminal.v1.ListGatewaysResponse - (*RemoveGatewayRequest)(nil), // 17: teleport.terminal.v1.RemoveGatewayRequest - (*RestartGatewayRequest)(nil), // 18: teleport.terminal.v1.RestartGatewayRequest - (*SetGatewayTargetSubresourceNameRequest)(nil), // 19: teleport.terminal.v1.SetGatewayTargetSubresourceNameRequest - (*SetGatewayLocalPortRequest)(nil), // 20: teleport.terminal.v1.SetGatewayLocalPortRequest - (*ListServersRequest)(nil), // 21: teleport.terminal.v1.ListServersRequest - (*ListServersResponse)(nil), // 22: teleport.terminal.v1.ListServersResponse - (*ListKubesResponse)(nil), // 23: teleport.terminal.v1.ListKubesResponse - (*ListAppsResponse)(nil), // 24: teleport.terminal.v1.ListAppsResponse - (*GetAuthSettingsRequest)(nil), // 25: teleport.terminal.v1.GetAuthSettingsRequest - (*EmptyResponse)(nil), // 26: teleport.terminal.v1.EmptyResponse - (*LoginRequest_LocalParams)(nil), // 27: teleport.terminal.v1.LoginRequest.LocalParams - (*LoginRequest_SsoParams)(nil), // 28: teleport.terminal.v1.LoginRequest.SsoParams - (*Cluster)(nil), // 29: teleport.terminal.v1.Cluster - (*Database)(nil), // 30: teleport.terminal.v1.Database - (*Gateway)(nil), // 31: teleport.terminal.v1.Gateway - (*Server)(nil), // 32: teleport.terminal.v1.Server - (*Kube)(nil), // 33: teleport.terminal.v1.Kube - (*App)(nil), // 34: teleport.terminal.v1.App - (*AuthSettings)(nil), // 35: teleport.terminal.v1.AuthSettings + (PasswordlessPrompt)(0), // 0: teleport.terminal.v1.PasswordlessPrompt + (*RemoveClusterRequest)(nil), // 1: teleport.terminal.v1.RemoveClusterRequest + (*GetClusterRequest)(nil), // 2: teleport.terminal.v1.GetClusterRequest + (*LogoutRequest)(nil), // 3: teleport.terminal.v1.LogoutRequest + (*CredentialInfo)(nil), // 4: teleport.terminal.v1.CredentialInfo + (*LoginPasswordlessResponse)(nil), // 5: teleport.terminal.v1.LoginPasswordlessResponse + (*LoginPasswordlessRequest)(nil), // 6: teleport.terminal.v1.LoginPasswordlessRequest + (*LoginRequest)(nil), // 7: teleport.terminal.v1.LoginRequest + (*AddClusterRequest)(nil), // 8: teleport.terminal.v1.AddClusterRequest + (*ListKubesRequest)(nil), // 9: teleport.terminal.v1.ListKubesRequest + (*ListAppsRequest)(nil), // 10: teleport.terminal.v1.ListAppsRequest + (*ListClustersRequest)(nil), // 11: teleport.terminal.v1.ListClustersRequest + (*ListClustersResponse)(nil), // 12: teleport.terminal.v1.ListClustersResponse + (*ListDatabasesRequest)(nil), // 13: teleport.terminal.v1.ListDatabasesRequest + (*ListLeafClustersRequest)(nil), // 14: teleport.terminal.v1.ListLeafClustersRequest + (*ListDatabasesResponse)(nil), // 15: teleport.terminal.v1.ListDatabasesResponse + (*ListDatabaseUsersRequest)(nil), // 16: teleport.terminal.v1.ListDatabaseUsersRequest + (*ListDatabaseUsersResponse)(nil), // 17: teleport.terminal.v1.ListDatabaseUsersResponse + (*CreateGatewayRequest)(nil), // 18: teleport.terminal.v1.CreateGatewayRequest + (*ListGatewaysRequest)(nil), // 19: teleport.terminal.v1.ListGatewaysRequest + (*ListGatewaysResponse)(nil), // 20: teleport.terminal.v1.ListGatewaysResponse + (*RemoveGatewayRequest)(nil), // 21: teleport.terminal.v1.RemoveGatewayRequest + (*RestartGatewayRequest)(nil), // 22: teleport.terminal.v1.RestartGatewayRequest + (*SetGatewayTargetSubresourceNameRequest)(nil), // 23: teleport.terminal.v1.SetGatewayTargetSubresourceNameRequest + (*SetGatewayLocalPortRequest)(nil), // 24: teleport.terminal.v1.SetGatewayLocalPortRequest + (*ListServersRequest)(nil), // 25: teleport.terminal.v1.ListServersRequest + (*ListServersResponse)(nil), // 26: teleport.terminal.v1.ListServersResponse + (*ListKubesResponse)(nil), // 27: teleport.terminal.v1.ListKubesResponse + (*ListAppsResponse)(nil), // 28: teleport.terminal.v1.ListAppsResponse + (*GetAuthSettingsRequest)(nil), // 29: teleport.terminal.v1.GetAuthSettingsRequest + (*EmptyResponse)(nil), // 30: teleport.terminal.v1.EmptyResponse + (*LoginPasswordlessRequest_LoginPasswordlessRequestInit)(nil), // 31: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit + (*LoginPasswordlessRequest_LoginPasswordlessPINResponse)(nil), // 32: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse + (*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse)(nil), // 33: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse + (*LoginRequest_LocalParams)(nil), // 34: teleport.terminal.v1.LoginRequest.LocalParams + (*LoginRequest_SsoParams)(nil), // 35: teleport.terminal.v1.LoginRequest.SsoParams + (*Cluster)(nil), // 36: teleport.terminal.v1.Cluster + (*Database)(nil), // 37: teleport.terminal.v1.Database + (*Gateway)(nil), // 38: teleport.terminal.v1.Gateway + (*Server)(nil), // 39: teleport.terminal.v1.Server + (*Kube)(nil), // 40: teleport.terminal.v1.Kube + (*App)(nil), // 41: teleport.terminal.v1.App + (*AuthSettings)(nil), // 42: teleport.terminal.v1.AuthSettings } var file_v1_service_proto_depIdxs = []int32{ - 27, // 0: teleport.terminal.v1.LoginRequest.local:type_name -> teleport.terminal.v1.LoginRequest.LocalParams - 28, // 1: teleport.terminal.v1.LoginRequest.sso:type_name -> teleport.terminal.v1.LoginRequest.SsoParams - 29, // 2: teleport.terminal.v1.ListClustersResponse.clusters:type_name -> teleport.terminal.v1.Cluster - 30, // 3: teleport.terminal.v1.ListDatabasesResponse.databases:type_name -> teleport.terminal.v1.Database - 31, // 4: teleport.terminal.v1.ListGatewaysResponse.gateways:type_name -> teleport.terminal.v1.Gateway - 32, // 5: teleport.terminal.v1.ListServersResponse.servers:type_name -> teleport.terminal.v1.Server - 33, // 6: teleport.terminal.v1.ListKubesResponse.kubes:type_name -> teleport.terminal.v1.Kube - 34, // 7: teleport.terminal.v1.ListAppsResponse.apps:type_name -> teleport.terminal.v1.App - 7, // 8: teleport.terminal.v1.TerminalService.ListRootClusters:input_type -> teleport.terminal.v1.ListClustersRequest - 10, // 9: teleport.terminal.v1.TerminalService.ListLeafClusters:input_type -> teleport.terminal.v1.ListLeafClustersRequest - 9, // 10: teleport.terminal.v1.TerminalService.ListDatabases:input_type -> teleport.terminal.v1.ListDatabasesRequest - 12, // 11: teleport.terminal.v1.TerminalService.ListDatabaseUsers:input_type -> teleport.terminal.v1.ListDatabaseUsersRequest - 21, // 12: teleport.terminal.v1.TerminalService.ListServers:input_type -> teleport.terminal.v1.ListServersRequest - 5, // 13: teleport.terminal.v1.TerminalService.ListKubes:input_type -> teleport.terminal.v1.ListKubesRequest - 6, // 14: teleport.terminal.v1.TerminalService.ListApps:input_type -> teleport.terminal.v1.ListAppsRequest - 4, // 15: teleport.terminal.v1.TerminalService.AddCluster:input_type -> teleport.terminal.v1.AddClusterRequest - 0, // 16: teleport.terminal.v1.TerminalService.RemoveCluster:input_type -> teleport.terminal.v1.RemoveClusterRequest - 15, // 17: teleport.terminal.v1.TerminalService.ListGateways:input_type -> teleport.terminal.v1.ListGatewaysRequest - 14, // 18: teleport.terminal.v1.TerminalService.CreateGateway:input_type -> teleport.terminal.v1.CreateGatewayRequest - 17, // 19: teleport.terminal.v1.TerminalService.RemoveGateway:input_type -> teleport.terminal.v1.RemoveGatewayRequest - 18, // 20: teleport.terminal.v1.TerminalService.RestartGateway:input_type -> teleport.terminal.v1.RestartGatewayRequest - 19, // 21: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:input_type -> teleport.terminal.v1.SetGatewayTargetSubresourceNameRequest - 20, // 22: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:input_type -> teleport.terminal.v1.SetGatewayLocalPortRequest - 25, // 23: teleport.terminal.v1.TerminalService.GetAuthSettings:input_type -> teleport.terminal.v1.GetAuthSettingsRequest - 1, // 24: teleport.terminal.v1.TerminalService.GetCluster:input_type -> teleport.terminal.v1.GetClusterRequest - 3, // 25: teleport.terminal.v1.TerminalService.Login:input_type -> teleport.terminal.v1.LoginRequest - 2, // 26: teleport.terminal.v1.TerminalService.Logout:input_type -> teleport.terminal.v1.LogoutRequest - 8, // 27: teleport.terminal.v1.TerminalService.ListRootClusters:output_type -> teleport.terminal.v1.ListClustersResponse - 8, // 28: teleport.terminal.v1.TerminalService.ListLeafClusters:output_type -> teleport.terminal.v1.ListClustersResponse - 11, // 29: teleport.terminal.v1.TerminalService.ListDatabases:output_type -> teleport.terminal.v1.ListDatabasesResponse - 13, // 30: teleport.terminal.v1.TerminalService.ListDatabaseUsers:output_type -> teleport.terminal.v1.ListDatabaseUsersResponse - 22, // 31: teleport.terminal.v1.TerminalService.ListServers:output_type -> teleport.terminal.v1.ListServersResponse - 23, // 32: teleport.terminal.v1.TerminalService.ListKubes:output_type -> teleport.terminal.v1.ListKubesResponse - 24, // 33: teleport.terminal.v1.TerminalService.ListApps:output_type -> teleport.terminal.v1.ListAppsResponse - 29, // 34: teleport.terminal.v1.TerminalService.AddCluster:output_type -> teleport.terminal.v1.Cluster - 26, // 35: teleport.terminal.v1.TerminalService.RemoveCluster:output_type -> teleport.terminal.v1.EmptyResponse - 16, // 36: teleport.terminal.v1.TerminalService.ListGateways:output_type -> teleport.terminal.v1.ListGatewaysResponse - 31, // 37: teleport.terminal.v1.TerminalService.CreateGateway:output_type -> teleport.terminal.v1.Gateway - 26, // 38: teleport.terminal.v1.TerminalService.RemoveGateway:output_type -> teleport.terminal.v1.EmptyResponse - 26, // 39: teleport.terminal.v1.TerminalService.RestartGateway:output_type -> teleport.terminal.v1.EmptyResponse - 31, // 40: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:output_type -> teleport.terminal.v1.Gateway - 31, // 41: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:output_type -> teleport.terminal.v1.Gateway - 35, // 42: teleport.terminal.v1.TerminalService.GetAuthSettings:output_type -> teleport.terminal.v1.AuthSettings - 29, // 43: teleport.terminal.v1.TerminalService.GetCluster:output_type -> teleport.terminal.v1.Cluster - 26, // 44: teleport.terminal.v1.TerminalService.Login:output_type -> teleport.terminal.v1.EmptyResponse - 26, // 45: teleport.terminal.v1.TerminalService.Logout:output_type -> teleport.terminal.v1.EmptyResponse - 27, // [27:46] is the sub-list for method output_type - 8, // [8:27] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 0, // 0: teleport.terminal.v1.LoginPasswordlessResponse.prompt:type_name -> teleport.terminal.v1.PasswordlessPrompt + 4, // 1: teleport.terminal.v1.LoginPasswordlessResponse.credentials:type_name -> teleport.terminal.v1.CredentialInfo + 31, // 2: teleport.terminal.v1.LoginPasswordlessRequest.init:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit + 32, // 3: teleport.terminal.v1.LoginPasswordlessRequest.pin:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse + 33, // 4: teleport.terminal.v1.LoginPasswordlessRequest.credential:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse + 34, // 5: teleport.terminal.v1.LoginRequest.local:type_name -> teleport.terminal.v1.LoginRequest.LocalParams + 35, // 6: teleport.terminal.v1.LoginRequest.sso:type_name -> teleport.terminal.v1.LoginRequest.SsoParams + 36, // 7: teleport.terminal.v1.ListClustersResponse.clusters:type_name -> teleport.terminal.v1.Cluster + 37, // 8: teleport.terminal.v1.ListDatabasesResponse.databases:type_name -> teleport.terminal.v1.Database + 38, // 9: teleport.terminal.v1.ListGatewaysResponse.gateways:type_name -> teleport.terminal.v1.Gateway + 39, // 10: teleport.terminal.v1.ListServersResponse.servers:type_name -> teleport.terminal.v1.Server + 40, // 11: teleport.terminal.v1.ListKubesResponse.kubes:type_name -> teleport.terminal.v1.Kube + 41, // 12: teleport.terminal.v1.ListAppsResponse.apps:type_name -> teleport.terminal.v1.App + 11, // 13: teleport.terminal.v1.TerminalService.ListRootClusters:input_type -> teleport.terminal.v1.ListClustersRequest + 14, // 14: teleport.terminal.v1.TerminalService.ListLeafClusters:input_type -> teleport.terminal.v1.ListLeafClustersRequest + 13, // 15: teleport.terminal.v1.TerminalService.ListDatabases:input_type -> teleport.terminal.v1.ListDatabasesRequest + 16, // 16: teleport.terminal.v1.TerminalService.ListDatabaseUsers:input_type -> teleport.terminal.v1.ListDatabaseUsersRequest + 25, // 17: teleport.terminal.v1.TerminalService.ListServers:input_type -> teleport.terminal.v1.ListServersRequest + 9, // 18: teleport.terminal.v1.TerminalService.ListKubes:input_type -> teleport.terminal.v1.ListKubesRequest + 10, // 19: teleport.terminal.v1.TerminalService.ListApps:input_type -> teleport.terminal.v1.ListAppsRequest + 8, // 20: teleport.terminal.v1.TerminalService.AddCluster:input_type -> teleport.terminal.v1.AddClusterRequest + 1, // 21: teleport.terminal.v1.TerminalService.RemoveCluster:input_type -> teleport.terminal.v1.RemoveClusterRequest + 19, // 22: teleport.terminal.v1.TerminalService.ListGateways:input_type -> teleport.terminal.v1.ListGatewaysRequest + 18, // 23: teleport.terminal.v1.TerminalService.CreateGateway:input_type -> teleport.terminal.v1.CreateGatewayRequest + 21, // 24: teleport.terminal.v1.TerminalService.RemoveGateway:input_type -> teleport.terminal.v1.RemoveGatewayRequest + 22, // 25: teleport.terminal.v1.TerminalService.RestartGateway:input_type -> teleport.terminal.v1.RestartGatewayRequest + 23, // 26: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:input_type -> teleport.terminal.v1.SetGatewayTargetSubresourceNameRequest + 24, // 27: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:input_type -> teleport.terminal.v1.SetGatewayLocalPortRequest + 29, // 28: teleport.terminal.v1.TerminalService.GetAuthSettings:input_type -> teleport.terminal.v1.GetAuthSettingsRequest + 2, // 29: teleport.terminal.v1.TerminalService.GetCluster:input_type -> teleport.terminal.v1.GetClusterRequest + 7, // 30: teleport.terminal.v1.TerminalService.Login:input_type -> teleport.terminal.v1.LoginRequest + 6, // 31: teleport.terminal.v1.TerminalService.LoginPasswordless:input_type -> teleport.terminal.v1.LoginPasswordlessRequest + 3, // 32: teleport.terminal.v1.TerminalService.Logout:input_type -> teleport.terminal.v1.LogoutRequest + 12, // 33: teleport.terminal.v1.TerminalService.ListRootClusters:output_type -> teleport.terminal.v1.ListClustersResponse + 12, // 34: teleport.terminal.v1.TerminalService.ListLeafClusters:output_type -> teleport.terminal.v1.ListClustersResponse + 15, // 35: teleport.terminal.v1.TerminalService.ListDatabases:output_type -> teleport.terminal.v1.ListDatabasesResponse + 17, // 36: teleport.terminal.v1.TerminalService.ListDatabaseUsers:output_type -> teleport.terminal.v1.ListDatabaseUsersResponse + 26, // 37: teleport.terminal.v1.TerminalService.ListServers:output_type -> teleport.terminal.v1.ListServersResponse + 27, // 38: teleport.terminal.v1.TerminalService.ListKubes:output_type -> teleport.terminal.v1.ListKubesResponse + 28, // 39: teleport.terminal.v1.TerminalService.ListApps:output_type -> teleport.terminal.v1.ListAppsResponse + 36, // 40: teleport.terminal.v1.TerminalService.AddCluster:output_type -> teleport.terminal.v1.Cluster + 30, // 41: teleport.terminal.v1.TerminalService.RemoveCluster:output_type -> teleport.terminal.v1.EmptyResponse + 20, // 42: teleport.terminal.v1.TerminalService.ListGateways:output_type -> teleport.terminal.v1.ListGatewaysResponse + 38, // 43: teleport.terminal.v1.TerminalService.CreateGateway:output_type -> teleport.terminal.v1.Gateway + 30, // 44: teleport.terminal.v1.TerminalService.RemoveGateway:output_type -> teleport.terminal.v1.EmptyResponse + 30, // 45: teleport.terminal.v1.TerminalService.RestartGateway:output_type -> teleport.terminal.v1.EmptyResponse + 38, // 46: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:output_type -> teleport.terminal.v1.Gateway + 38, // 47: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:output_type -> teleport.terminal.v1.Gateway + 42, // 48: teleport.terminal.v1.TerminalService.GetAuthSettings:output_type -> teleport.terminal.v1.AuthSettings + 36, // 49: teleport.terminal.v1.TerminalService.GetCluster:output_type -> teleport.terminal.v1.Cluster + 30, // 50: teleport.terminal.v1.TerminalService.Login:output_type -> teleport.terminal.v1.EmptyResponse + 5, // 51: teleport.terminal.v1.TerminalService.LoginPasswordless:output_type -> teleport.terminal.v1.LoginPasswordlessResponse + 30, // 52: teleport.terminal.v1.TerminalService.Logout:output_type -> teleport.terminal.v1.EmptyResponse + 33, // [33:53] is the sub-list for method output_type + 13, // [13:33] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_v1_service_proto_init() } @@ -1935,7 +2420,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoginRequest); i { + switch v := v.(*CredentialInfo); i { case 0: return &v.state case 1: @@ -1947,7 +2432,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddClusterRequest); i { + switch v := v.(*LoginPasswordlessResponse); i { case 0: return &v.state case 1: @@ -1959,7 +2444,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListKubesRequest); i { + switch v := v.(*LoginPasswordlessRequest); i { case 0: return &v.state case 1: @@ -1971,7 +2456,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAppsRequest); i { + switch v := v.(*LoginRequest); i { case 0: return &v.state case 1: @@ -1983,7 +2468,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListClustersRequest); i { + switch v := v.(*AddClusterRequest); i { case 0: return &v.state case 1: @@ -1995,7 +2480,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListClustersResponse); i { + switch v := v.(*ListKubesRequest); i { case 0: return &v.state case 1: @@ -2007,7 +2492,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDatabasesRequest); i { + switch v := v.(*ListAppsRequest); i { case 0: return &v.state case 1: @@ -2019,7 +2504,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListLeafClustersRequest); i { + switch v := v.(*ListClustersRequest); i { case 0: return &v.state case 1: @@ -2031,7 +2516,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDatabasesResponse); i { + switch v := v.(*ListClustersResponse); i { case 0: return &v.state case 1: @@ -2043,7 +2528,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDatabaseUsersRequest); i { + switch v := v.(*ListDatabasesRequest); i { case 0: return &v.state case 1: @@ -2055,7 +2540,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDatabaseUsersResponse); i { + switch v := v.(*ListLeafClustersRequest); i { case 0: return &v.state case 1: @@ -2067,7 +2552,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateGatewayRequest); i { + switch v := v.(*ListDatabasesResponse); i { case 0: return &v.state case 1: @@ -2079,7 +2564,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListGatewaysRequest); i { + switch v := v.(*ListDatabaseUsersRequest); i { case 0: return &v.state case 1: @@ -2091,7 +2576,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListGatewaysResponse); i { + switch v := v.(*ListDatabaseUsersResponse); i { case 0: return &v.state case 1: @@ -2103,7 +2588,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveGatewayRequest); i { + switch v := v.(*CreateGatewayRequest); i { case 0: return &v.state case 1: @@ -2115,7 +2600,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RestartGatewayRequest); i { + switch v := v.(*ListGatewaysRequest); i { case 0: return &v.state case 1: @@ -2127,7 +2612,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetGatewayTargetSubresourceNameRequest); i { + switch v := v.(*ListGatewaysResponse); i { case 0: return &v.state case 1: @@ -2139,7 +2624,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetGatewayLocalPortRequest); i { + switch v := v.(*RemoveGatewayRequest); i { case 0: return &v.state case 1: @@ -2151,7 +2636,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListServersRequest); i { + switch v := v.(*RestartGatewayRequest); i { case 0: return &v.state case 1: @@ -2163,7 +2648,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListServersResponse); i { + switch v := v.(*SetGatewayTargetSubresourceNameRequest); i { case 0: return &v.state case 1: @@ -2175,7 +2660,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListKubesResponse); i { + switch v := v.(*SetGatewayLocalPortRequest); i { case 0: return &v.state case 1: @@ -2187,7 +2672,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAppsResponse); i { + switch v := v.(*ListServersRequest); i { case 0: return &v.state case 1: @@ -2199,7 +2684,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAuthSettingsRequest); i { + switch v := v.(*ListServersResponse); i { case 0: return &v.state case 1: @@ -2211,7 +2696,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmptyResponse); i { + switch v := v.(*ListKubesResponse); i { case 0: return &v.state case 1: @@ -2223,7 +2708,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoginRequest_LocalParams); i { + switch v := v.(*ListAppsResponse); i { case 0: return &v.state case 1: @@ -2235,6 +2720,78 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetAuthSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EmptyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessRequestInit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessPINResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginRequest_LocalParams); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LoginRequest_SsoParams); i { case 0: return &v.state @@ -2247,7 +2804,12 @@ func file_v1_service_proto_init() { } } } - file_v1_service_proto_msgTypes[3].OneofWrappers = []interface{}{ + file_v1_service_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*LoginPasswordlessRequest_Init)(nil), + (*LoginPasswordlessRequest_Pin)(nil), + (*LoginPasswordlessRequest_Credential)(nil), + } + file_v1_service_proto_msgTypes[6].OneofWrappers = []interface{}{ (*LoginRequest_Local)(nil), (*LoginRequest_Sso)(nil), } @@ -2256,13 +2818,14 @@ func file_v1_service_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_v1_service_proto_rawDesc, - NumEnums: 0, - NumMessages: 29, + NumEnums: 1, + NumMessages: 35, NumExtensions: 0, NumServices: 1, }, GoTypes: file_v1_service_proto_goTypes, DependencyIndexes: file_v1_service_proto_depIdxs, + EnumInfos: file_v1_service_proto_enumTypes, MessageInfos: file_v1_service_proto_msgTypes, }.Build() File_v1_service_proto = out.File @@ -2325,6 +2888,23 @@ type TerminalServiceClient interface { GetCluster(ctx context.Context, in *GetClusterRequest, opts ...grpc.CallOption) (*Cluster, error) // Login logs in a user to a cluster Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*EmptyResponse, error) + // LoginPasswordless logs in a user to a cluster passwordlessly. + // + // The RPC is streaming both ways and the message sequence example for hardware keys are: + // (-> means client-to-server, <- means server-to-client) + // + // Hardware keys: + // -> Init + // <- Send PasswordlessPrompt enum TAP to choose a device + // -> Receive TAP device response + // <- Send PasswordlessPrompt enum PIN + // -> Receive PIN response + // <- Send PasswordlessPrompt enum RETAP to confirm + // -> Receive RETAP device response + // <- Send list of credentials (e.g. usernames) associated with device + // -> Receive the index number associated with the selected credential in list + // <- End + LoginPasswordless(ctx context.Context, opts ...grpc.CallOption) (TerminalService_LoginPasswordlessClient, error) // ClusterLogin logs out a user from cluster Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*EmptyResponse, error) } @@ -2499,6 +3079,37 @@ func (c *terminalServiceClient) Login(ctx context.Context, in *LoginRequest, opt return out, nil } +func (c *terminalServiceClient) LoginPasswordless(ctx context.Context, opts ...grpc.CallOption) (TerminalService_LoginPasswordlessClient, error) { + stream, err := c.cc.NewStream(ctx, &_TerminalService_serviceDesc.Streams[0], "/teleport.terminal.v1.TerminalService/LoginPasswordless", opts...) + if err != nil { + return nil, err + } + x := &terminalServiceLoginPasswordlessClient{stream} + return x, nil +} + +type TerminalService_LoginPasswordlessClient interface { + Send(*LoginPasswordlessRequest) error + Recv() (*LoginPasswordlessResponse, error) + grpc.ClientStream +} + +type terminalServiceLoginPasswordlessClient struct { + grpc.ClientStream +} + +func (x *terminalServiceLoginPasswordlessClient) Send(m *LoginPasswordlessRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *terminalServiceLoginPasswordlessClient) Recv() (*LoginPasswordlessResponse, error) { + m := new(LoginPasswordlessResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *terminalServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*EmptyResponse, error) { out := new(EmptyResponse) err := c.cc.Invoke(ctx, "/teleport.terminal.v1.TerminalService/Logout", in, out, opts...) @@ -2552,6 +3163,23 @@ type TerminalServiceServer interface { GetCluster(context.Context, *GetClusterRequest) (*Cluster, error) // Login logs in a user to a cluster Login(context.Context, *LoginRequest) (*EmptyResponse, error) + // LoginPasswordless logs in a user to a cluster passwordlessly. + // + // The RPC is streaming both ways and the message sequence example for hardware keys are: + // (-> means client-to-server, <- means server-to-client) + // + // Hardware keys: + // -> Init + // <- Send PasswordlessPrompt enum TAP to choose a device + // -> Receive TAP device response + // <- Send PasswordlessPrompt enum PIN + // -> Receive PIN response + // <- Send PasswordlessPrompt enum RETAP to confirm + // -> Receive RETAP device response + // <- Send list of credentials (e.g. usernames) associated with device + // -> Receive the index number associated with the selected credential in list + // <- End + LoginPasswordless(TerminalService_LoginPasswordlessServer) error // ClusterLogin logs out a user from cluster Logout(context.Context, *LogoutRequest) (*EmptyResponse, error) } @@ -2614,6 +3242,9 @@ func (*UnimplementedTerminalServiceServer) GetCluster(context.Context, *GetClust func (*UnimplementedTerminalServiceServer) Login(context.Context, *LoginRequest) (*EmptyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") } +func (*UnimplementedTerminalServiceServer) LoginPasswordless(TerminalService_LoginPasswordlessServer) error { + return status.Errorf(codes.Unimplemented, "method LoginPasswordless not implemented") +} func (*UnimplementedTerminalServiceServer) Logout(context.Context, *LogoutRequest) (*EmptyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented") } @@ -2946,6 +3577,32 @@ func _TerminalService_Login_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _TerminalService_LoginPasswordless_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TerminalServiceServer).LoginPasswordless(&terminalServiceLoginPasswordlessServer{stream}) +} + +type TerminalService_LoginPasswordlessServer interface { + Send(*LoginPasswordlessResponse) error + Recv() (*LoginPasswordlessRequest, error) + grpc.ServerStream +} + +type terminalServiceLoginPasswordlessServer struct { + grpc.ServerStream +} + +func (x *terminalServiceLoginPasswordlessServer) Send(m *LoginPasswordlessResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *terminalServiceLoginPasswordlessServer) Recv() (*LoginPasswordlessRequest, error) { + m := new(LoginPasswordlessRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func _TerminalService_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(LogoutRequest) if err := dec(in); err != nil { @@ -3045,6 +3702,13 @@ var _TerminalService_serviceDesc = grpc.ServiceDesc{ Handler: _TerminalService_Logout_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "LoginPasswordless", + Handler: _TerminalService_LoginPasswordless_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, Metadata: "v1/service.proto", } diff --git a/lib/teleterm/api/protogen/js/v1/auth_settings_pb.d.ts b/lib/teleterm/api/protogen/js/v1/auth_settings_pb.d.ts index c31496ca3aae3..1ff6576a2acb6 100644 --- a/lib/teleterm/api/protogen/js/v1/auth_settings_pb.d.ts +++ b/lib/teleterm/api/protogen/js/v1/auth_settings_pb.d.ts @@ -24,6 +24,15 @@ export class AuthSettings extends jspb.Message { getHasMessageOfTheDay(): boolean; setHasMessageOfTheDay(value: boolean): AuthSettings; + getAuthType(): string; + setAuthType(value: string): AuthSettings; + + getAllowPasswordless(): boolean; + setAllowPasswordless(value: boolean): AuthSettings; + + getLocalConnectorName(): string; + setLocalConnectorName(value: string): AuthSettings; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): AuthSettings.AsObject; @@ -42,6 +51,9 @@ export namespace AuthSettings { preferredMfa: string, authProvidersList: Array, hasMessageOfTheDay: boolean, + authType: string, + allowPasswordless: boolean, + localConnectorName: string, } } diff --git a/lib/teleterm/api/protogen/js/v1/auth_settings_pb.js b/lib/teleterm/api/protogen/js/v1/auth_settings_pb.js index 1b5fd8ffe1558..2f9065ee7e3a9 100644 --- a/lib/teleterm/api/protogen/js/v1/auth_settings_pb.js +++ b/lib/teleterm/api/protogen/js/v1/auth_settings_pb.js @@ -103,7 +103,10 @@ proto.teleport.terminal.v1.AuthSettings.toObject = function(includeInstance, msg preferredMfa: jspb.Message.getFieldWithDefault(msg, 3, ""), authProvidersList: jspb.Message.toObjectList(msg.getAuthProvidersList(), proto.teleport.terminal.v1.AuthProvider.toObject, includeInstance), - hasMessageOfTheDay: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) + hasMessageOfTheDay: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), + authType: jspb.Message.getFieldWithDefault(msg, 6, ""), + allowPasswordless: jspb.Message.getBooleanFieldWithDefault(msg, 7, false), + localConnectorName: jspb.Message.getFieldWithDefault(msg, 8, "") }; if (includeInstance) { @@ -161,6 +164,18 @@ proto.teleport.terminal.v1.AuthSettings.deserializeBinaryFromReader = function(m var value = /** @type {boolean} */ (reader.readBool()); msg.setHasMessageOfTheDay(value); break; + case 6: + var value = /** @type {string} */ (reader.readString()); + msg.setAuthType(value); + break; + case 7: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setAllowPasswordless(value); + break; + case 8: + var value = /** @type {string} */ (reader.readString()); + msg.setLocalConnectorName(value); + break; default: reader.skipField(); break; @@ -226,6 +241,27 @@ proto.teleport.terminal.v1.AuthSettings.serializeBinaryToWriter = function(messa f ); } + f = message.getAuthType(); + if (f.length > 0) { + writer.writeString( + 6, + f + ); + } + f = message.getAllowPasswordless(); + if (f) { + writer.writeBool( + 7, + f + ); + } + f = message.getLocalConnectorName(); + if (f.length > 0) { + writer.writeString( + 8, + f + ); + } }; @@ -339,6 +375,60 @@ proto.teleport.terminal.v1.AuthSettings.prototype.setHasMessageOfTheDay = functi }; +/** + * optional string auth_type = 6; + * @return {string} + */ +proto.teleport.terminal.v1.AuthSettings.prototype.getAuthType = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.AuthSettings} returns this + */ +proto.teleport.terminal.v1.AuthSettings.prototype.setAuthType = function(value) { + return jspb.Message.setProto3StringField(this, 6, value); +}; + + +/** + * optional bool allow_passwordless = 7; + * @return {boolean} + */ +proto.teleport.terminal.v1.AuthSettings.prototype.getAllowPasswordless = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 7, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.teleport.terminal.v1.AuthSettings} returns this + */ +proto.teleport.terminal.v1.AuthSettings.prototype.setAllowPasswordless = function(value) { + return jspb.Message.setProto3BooleanField(this, 7, value); +}; + + +/** + * optional string local_connector_name = 8; + * @return {string} + */ +proto.teleport.terminal.v1.AuthSettings.prototype.getLocalConnectorName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.AuthSettings} returns this + */ +proto.teleport.terminal.v1.AuthSettings.prototype.setLocalConnectorName = function(value) { + return jspb.Message.setProto3StringField(this, 8, value); +}; + + diff --git a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts index 4722a24f5630c..727542d803267 100644 --- a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts +++ b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts @@ -34,6 +34,7 @@ interface ITerminalServiceService extends grpc.ServiceDefinition; responseDeserialize: grpc.deserialize; } +interface ITerminalServiceService_ILoginPasswordless extends grpc.MethodDefinition { + path: "/teleport.terminal.v1.TerminalService/LoginPasswordless"; + requestStream: true; + responseStream: true; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} interface ITerminalServiceService_ILogout extends grpc.MethodDefinition { path: "/teleport.terminal.v1.TerminalService/Logout"; requestStream: false; @@ -230,6 +240,7 @@ export interface ITerminalServiceServer { getAuthSettings: grpc.handleUnaryCall; getCluster: grpc.handleUnaryCall; login: grpc.handleUnaryCall; + loginPasswordless: grpc.handleBidiStreamingCall; logout: grpc.handleUnaryCall; } @@ -288,6 +299,9 @@ export interface ITerminalServiceClient { login(request: v1_service_pb.LoginRequest, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; login(request: v1_service_pb.LoginRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; login(request: v1_service_pb.LoginRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; + loginPasswordless(): grpc.ClientDuplexStream; + loginPasswordless(options: Partial): grpc.ClientDuplexStream; + loginPasswordless(metadata: grpc.Metadata, options?: Partial): grpc.ClientDuplexStream; logout(request: v1_service_pb.LogoutRequest, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; @@ -349,6 +363,8 @@ export class TerminalServiceClient extends grpc.Client implements ITerminalServi public login(request: v1_service_pb.LoginRequest, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; public login(request: v1_service_pb.LoginRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; public login(request: v1_service_pb.LoginRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; + public loginPasswordless(options?: Partial): grpc.ClientDuplexStream; + public loginPasswordless(metadata?: grpc.Metadata, options?: Partial): grpc.ClientDuplexStream; public logout(request: v1_service_pb.LogoutRequest, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; public logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; public logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; diff --git a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js index 6761c84dcbe40..b2a0d8b2dced4 100644 --- a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js +++ b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js @@ -280,6 +280,28 @@ function deserialize_teleport_terminal_v1_ListServersResponse(buffer_arg) { return v1_service_pb.ListServersResponse.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_teleport_terminal_v1_LoginPasswordlessRequest(arg) { + if (!(arg instanceof v1_service_pb.LoginPasswordlessRequest)) { + throw new Error('Expected argument of type teleport.terminal.v1.LoginPasswordlessRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_teleport_terminal_v1_LoginPasswordlessRequest(buffer_arg) { + return v1_service_pb.LoginPasswordlessRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_teleport_terminal_v1_LoginPasswordlessResponse(arg) { + if (!(arg instanceof v1_service_pb.LoginPasswordlessResponse)) { + throw new Error('Expected argument of type teleport.terminal.v1.LoginPasswordlessResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_teleport_terminal_v1_LoginPasswordlessResponse(buffer_arg) { + return v1_service_pb.LoginPasswordlessResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_teleport_terminal_v1_LoginRequest(arg) { if (!(arg instanceof v1_service_pb.LoginRequest)) { throw new Error('Expected argument of type teleport.terminal.v1.LoginRequest'); @@ -582,6 +604,33 @@ login: { responseSerialize: serialize_teleport_terminal_v1_EmptyResponse, responseDeserialize: deserialize_teleport_terminal_v1_EmptyResponse, }, + // LoginPasswordless logs in a user to a cluster passwordlessly. +// +// The RPC is streaming both ways and the message sequence example for hardware keys are: +// (-> means client-to-server, <- means server-to-client) +// +// Hardware keys: +// -> Init +// <- Send PasswordlessPrompt enum TAP to choose a device +// -> Receive TAP device response +// <- Send PasswordlessPrompt enum PIN +// -> Receive PIN response +// <- Send PasswordlessPrompt enum RETAP to confirm +// -> Receive RETAP device response +// <- Send list of credentials (e.g. usernames) associated with device +// -> Receive the index number associated with the selected credential in list +// <- End +loginPasswordless: { + path: '/teleport.terminal.v1.TerminalService/LoginPasswordless', + requestStream: true, + responseStream: true, + requestType: v1_service_pb.LoginPasswordlessRequest, + responseType: v1_service_pb.LoginPasswordlessResponse, + requestSerialize: serialize_teleport_terminal_v1_LoginPasswordlessRequest, + requestDeserialize: deserialize_teleport_terminal_v1_LoginPasswordlessRequest, + responseSerialize: serialize_teleport_terminal_v1_LoginPasswordlessResponse, + responseDeserialize: deserialize_teleport_terminal_v1_LoginPasswordlessResponse, + }, // ClusterLogin logs out a user from cluster logout: { path: '/teleport.terminal.v1.TerminalService/Logout', diff --git a/lib/teleterm/api/protogen/js/v1/service_pb.d.ts b/lib/teleterm/api/protogen/js/v1/service_pb.d.ts index 51762d2356451..2b5fa0c48f3df 100644 --- a/lib/teleterm/api/protogen/js/v1/service_pb.d.ts +++ b/lib/teleterm/api/protogen/js/v1/service_pb.d.ts @@ -77,6 +77,171 @@ export namespace LogoutRequest { } } +export class CredentialInfo extends jspb.Message { + getUsername(): string; + setUsername(value: string): CredentialInfo; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): CredentialInfo.AsObject; + static toObject(includeInstance: boolean, msg: CredentialInfo): CredentialInfo.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: CredentialInfo, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CredentialInfo; + static deserializeBinaryFromReader(message: CredentialInfo, reader: jspb.BinaryReader): CredentialInfo; +} + +export namespace CredentialInfo { + export type AsObject = { + username: string, + } +} + +export class LoginPasswordlessResponse extends jspb.Message { + getPrompt(): PasswordlessPrompt; + setPrompt(value: PasswordlessPrompt): LoginPasswordlessResponse; + + clearCredentialsList(): void; + getCredentialsList(): Array; + setCredentialsList(value: Array): LoginPasswordlessResponse; + addCredentials(value?: CredentialInfo, index?: number): CredentialInfo; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LoginPasswordlessResponse.AsObject; + static toObject(includeInstance: boolean, msg: LoginPasswordlessResponse): LoginPasswordlessResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LoginPasswordlessResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LoginPasswordlessResponse; + static deserializeBinaryFromReader(message: LoginPasswordlessResponse, reader: jspb.BinaryReader): LoginPasswordlessResponse; +} + +export namespace LoginPasswordlessResponse { + export type AsObject = { + prompt: PasswordlessPrompt, + credentialsList: Array, + } +} + +export class LoginPasswordlessRequest extends jspb.Message { + + hasInit(): boolean; + clearInit(): void; + getInit(): LoginPasswordlessRequest.LoginPasswordlessRequestInit | undefined; + setInit(value?: LoginPasswordlessRequest.LoginPasswordlessRequestInit): LoginPasswordlessRequest; + + + hasPin(): boolean; + clearPin(): void; + getPin(): LoginPasswordlessRequest.LoginPasswordlessPINResponse | undefined; + setPin(value?: LoginPasswordlessRequest.LoginPasswordlessPINResponse): LoginPasswordlessRequest; + + + hasCredential(): boolean; + clearCredential(): void; + getCredential(): LoginPasswordlessRequest.LoginPasswordlessCredentialResponse | undefined; + setCredential(value?: LoginPasswordlessRequest.LoginPasswordlessCredentialResponse): LoginPasswordlessRequest; + + + getRequestCase(): LoginPasswordlessRequest.RequestCase; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LoginPasswordlessRequest.AsObject; + static toObject(includeInstance: boolean, msg: LoginPasswordlessRequest): LoginPasswordlessRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LoginPasswordlessRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LoginPasswordlessRequest; + static deserializeBinaryFromReader(message: LoginPasswordlessRequest, reader: jspb.BinaryReader): LoginPasswordlessRequest; +} + +export namespace LoginPasswordlessRequest { + export type AsObject = { + init?: LoginPasswordlessRequest.LoginPasswordlessRequestInit.AsObject, + pin?: LoginPasswordlessRequest.LoginPasswordlessPINResponse.AsObject, + credential?: LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.AsObject, + } + + + export class LoginPasswordlessRequestInit extends jspb.Message { + getClusterUri(): string; + setClusterUri(value: string): LoginPasswordlessRequestInit; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LoginPasswordlessRequestInit.AsObject; + static toObject(includeInstance: boolean, msg: LoginPasswordlessRequestInit): LoginPasswordlessRequestInit.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LoginPasswordlessRequestInit, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LoginPasswordlessRequestInit; + static deserializeBinaryFromReader(message: LoginPasswordlessRequestInit, reader: jspb.BinaryReader): LoginPasswordlessRequestInit; + } + + export namespace LoginPasswordlessRequestInit { + export type AsObject = { + clusterUri: string, + } + } + + export class LoginPasswordlessPINResponse extends jspb.Message { + getPin(): string; + setPin(value: string): LoginPasswordlessPINResponse; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LoginPasswordlessPINResponse.AsObject; + static toObject(includeInstance: boolean, msg: LoginPasswordlessPINResponse): LoginPasswordlessPINResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LoginPasswordlessPINResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LoginPasswordlessPINResponse; + static deserializeBinaryFromReader(message: LoginPasswordlessPINResponse, reader: jspb.BinaryReader): LoginPasswordlessPINResponse; + } + + export namespace LoginPasswordlessPINResponse { + export type AsObject = { + pin: string, + } + } + + export class LoginPasswordlessCredentialResponse extends jspb.Message { + getIndex(): number; + setIndex(value: number): LoginPasswordlessCredentialResponse; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LoginPasswordlessCredentialResponse.AsObject; + static toObject(includeInstance: boolean, msg: LoginPasswordlessCredentialResponse): LoginPasswordlessCredentialResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LoginPasswordlessCredentialResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LoginPasswordlessCredentialResponse; + static deserializeBinaryFromReader(message: LoginPasswordlessCredentialResponse, reader: jspb.BinaryReader): LoginPasswordlessCredentialResponse; + } + + export namespace LoginPasswordlessCredentialResponse { + export type AsObject = { + index: number, + } + } + + + export enum RequestCase { + REQUEST_NOT_SET = 0, + + INIT = 1, + + PIN = 2, + + CREDENTIAL = 3, + + } + +} + export class LoginRequest extends jspb.Message { getClusterUri(): string; setClusterUri(value: string): LoginRequest; @@ -690,3 +855,10 @@ export namespace EmptyResponse { export type AsObject = { } } + +export enum PasswordlessPrompt { + PASSWORDLESS_PROMPT_UNSPECIFIED = 0, + PASSWORDLESS_PROMPT_PIN = 1, + PASSWORDLESS_PROMPT_TAP = 2, + PASSWORDLESS_PROMPT_CREDENTIAL = 3, +} diff --git a/lib/teleterm/api/protogen/js/v1/service_pb.js b/lib/teleterm/api/protogen/js/v1/service_pb.js index 648940b172419..194997a39bf44 100644 --- a/lib/teleterm/api/protogen/js/v1/service_pb.js +++ b/lib/teleterm/api/protogen/js/v1/service_pb.js @@ -33,6 +33,7 @@ var v1_auth_settings_pb = require('../v1/auth_settings_pb.js'); goog.object.extend(proto, v1_auth_settings_pb); goog.exportSymbol('proto.teleport.terminal.v1.AddClusterRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.CreateGatewayRequest', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.CredentialInfo', null, global); goog.exportSymbol('proto.teleport.terminal.v1.EmptyResponse', null, global); goog.exportSymbol('proto.teleport.terminal.v1.GetAuthSettingsRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.GetClusterRequest', null, global); @@ -51,11 +52,18 @@ goog.exportSymbol('proto.teleport.terminal.v1.ListKubesResponse', null, global); goog.exportSymbol('proto.teleport.terminal.v1.ListLeafClustersRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.ListServersRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.ListServersResponse', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.LoginPasswordlessRequest', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.LoginPasswordlessRequest.RequestCase', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.LoginPasswordlessResponse', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest.LocalParams', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest.ParamsCase', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest.SsoParams', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LogoutRequest', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.PasswordlessPrompt', null, global); goog.exportSymbol('proto.teleport.terminal.v1.RemoveClusterRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.RemoveGatewayRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.RestartGatewayRequest', null, global); @@ -124,6 +132,132 @@ if (goog.DEBUG && !COMPILED) { */ proto.teleport.terminal.v1.LogoutRequest.displayName = 'proto.teleport.terminal.v1.LogoutRequest'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.CredentialInfo = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.CredentialInfo, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.CredentialInfo.displayName = 'proto.teleport.terminal.v1.CredentialInfo'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.teleport.terminal.v1.LoginPasswordlessResponse.repeatedFields_, null); +}; +goog.inherits(proto.teleport.terminal.v1.LoginPasswordlessResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.LoginPasswordlessResponse.displayName = 'proto.teleport.terminal.v1.LoginPasswordlessResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.teleport.terminal.v1.LoginPasswordlessRequest.oneofGroups_); +}; +goog.inherits(proto.teleport.terminal.v1.LoginPasswordlessRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.LoginPasswordlessRequest.displayName = 'proto.teleport.terminal.v1.LoginPasswordlessRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.displayName = 'proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.displayName = 'proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.displayName = 'proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -608,68 +742,947 @@ if (goog.DEBUG && !COMPILED) { proto.teleport.terminal.v1.ListKubesResponse.displayName = 'proto.teleport.terminal.v1.ListKubesResponse'; } /** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.ListAppsResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.teleport.terminal.v1.ListAppsResponse.repeatedFields_, null); +}; +goog.inherits(proto.teleport.terminal.v1.ListAppsResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.ListAppsResponse.displayName = 'proto.teleport.terminal.v1.ListAppsResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.GetAuthSettingsRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.GetAuthSettingsRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.GetAuthSettingsRequest.displayName = 'proto.teleport.terminal.v1.GetAuthSettingsRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.EmptyResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.EmptyResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.EmptyResponse.displayName = 'proto.teleport.terminal.v1.EmptyResponse'; +} + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.RemoveClusterRequest.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.RemoveClusterRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.RemoveClusterRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.RemoveClusterRequest.toObject = function(includeInstance, msg) { + var f, obj = { + clusterUri: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.RemoveClusterRequest} + */ +proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.RemoveClusterRequest; + return proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.RemoveClusterRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.RemoveClusterRequest} + */ +proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setClusterUri(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.RemoveClusterRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.RemoveClusterRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.RemoveClusterRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.RemoveClusterRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getClusterUri(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string cluster_uri = 1; + * @return {string} + */ +proto.teleport.terminal.v1.RemoveClusterRequest.prototype.getClusterUri = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.RemoveClusterRequest} returns this + */ +proto.teleport.terminal.v1.RemoveClusterRequest.prototype.setClusterUri = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.GetClusterRequest.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.GetClusterRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.GetClusterRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.GetClusterRequest.toObject = function(includeInstance, msg) { + var f, obj = { + clusterUri: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.GetClusterRequest} + */ +proto.teleport.terminal.v1.GetClusterRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.GetClusterRequest; + return proto.teleport.terminal.v1.GetClusterRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.GetClusterRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.GetClusterRequest} + */ +proto.teleport.terminal.v1.GetClusterRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setClusterUri(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.GetClusterRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.GetClusterRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.GetClusterRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.GetClusterRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getClusterUri(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string cluster_uri = 1; + * @return {string} + */ +proto.teleport.terminal.v1.GetClusterRequest.prototype.getClusterUri = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.GetClusterRequest} returns this + */ +proto.teleport.terminal.v1.GetClusterRequest.prototype.setClusterUri = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.LogoutRequest.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.LogoutRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.LogoutRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.LogoutRequest.toObject = function(includeInstance, msg) { + var f, obj = { + clusterUri: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.LogoutRequest} + */ +proto.teleport.terminal.v1.LogoutRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.LogoutRequest; + return proto.teleport.terminal.v1.LogoutRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.LogoutRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.LogoutRequest} + */ +proto.teleport.terminal.v1.LogoutRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setClusterUri(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.LogoutRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.LogoutRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.LogoutRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.LogoutRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getClusterUri(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string cluster_uri = 1; + * @return {string} + */ +proto.teleport.terminal.v1.LogoutRequest.prototype.getClusterUri = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.LogoutRequest} returns this + */ +proto.teleport.terminal.v1.LogoutRequest.prototype.setClusterUri = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.CredentialInfo.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.CredentialInfo.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.CredentialInfo} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.CredentialInfo.toObject = function(includeInstance, msg) { + var f, obj = { + username: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.CredentialInfo} + */ +proto.teleport.terminal.v1.CredentialInfo.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.CredentialInfo; + return proto.teleport.terminal.v1.CredentialInfo.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.CredentialInfo} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.CredentialInfo} + */ +proto.teleport.terminal.v1.CredentialInfo.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setUsername(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.CredentialInfo.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.CredentialInfo.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.CredentialInfo} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.CredentialInfo.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getUsername(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string Username = 1; + * @return {string} + */ +proto.teleport.terminal.v1.CredentialInfo.prototype.getUsername = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.CredentialInfo} returns this + */ +proto.teleport.terminal.v1.CredentialInfo.prototype.setUsername = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.repeatedFields_ = [2]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.LoginPasswordlessResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.LoginPasswordlessResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.toObject = function(includeInstance, msg) { + var f, obj = { + prompt: jspb.Message.getFieldWithDefault(msg, 1, 0), + credentialsList: jspb.Message.toObjectList(msg.getCredentialsList(), + proto.teleport.terminal.v1.CredentialInfo.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessResponse} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.LoginPasswordlessResponse; + return proto.teleport.terminal.v1.LoginPasswordlessResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessResponse} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!proto.teleport.terminal.v1.PasswordlessPrompt} */ (reader.readEnum()); + msg.setPrompt(value); + break; + case 2: + var value = new proto.teleport.terminal.v1.CredentialInfo; + reader.readMessage(value,proto.teleport.terminal.v1.CredentialInfo.deserializeBinaryFromReader); + msg.addCredentials(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.LoginPasswordlessResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getPrompt(); + if (f !== 0.0) { + writer.writeEnum( + 1, + f + ); + } + f = message.getCredentialsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.teleport.terminal.v1.CredentialInfo.serializeBinaryToWriter + ); + } +}; + + +/** + * optional PasswordlessPrompt prompt = 1; + * @return {!proto.teleport.terminal.v1.PasswordlessPrompt} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.getPrompt = function() { + return /** @type {!proto.teleport.terminal.v1.PasswordlessPrompt} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {!proto.teleport.terminal.v1.PasswordlessPrompt} value + * @return {!proto.teleport.terminal.v1.LoginPasswordlessResponse} returns this + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.setPrompt = function(value) { + return jspb.Message.setProto3EnumField(this, 1, value); +}; + + +/** + * repeated CredentialInfo credentials = 2; + * @return {!Array} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.getCredentialsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.teleport.terminal.v1.CredentialInfo, 2)); +}; + + +/** + * @param {!Array} value + * @return {!proto.teleport.terminal.v1.LoginPasswordlessResponse} returns this +*/ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.setCredentialsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); +}; + + +/** + * @param {!proto.teleport.terminal.v1.CredentialInfo=} opt_value + * @param {number=} opt_index + * @return {!proto.teleport.terminal.v1.CredentialInfo} + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.addCredentials = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.teleport.terminal.v1.CredentialInfo, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessResponse} returns this + */ +proto.teleport.terminal.v1.LoginPasswordlessResponse.prototype.clearCredentialsList = function() { + return this.setCredentialsList([]); +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.oneofGroups_ = [[1,2,3]]; + +/** + * @enum {number} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.RequestCase = { + REQUEST_NOT_SET: 0, + INIT: 1, + PIN: 2, + CREDENTIAL: 3 +}; + +/** + * @return {proto.teleport.terminal.v1.LoginPasswordlessRequest.RequestCase} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.getRequestCase = function() { + return /** @type {proto.teleport.terminal.v1.LoginPasswordlessRequest.RequestCase} */(jspb.Message.computeOneofCase(this, proto.teleport.terminal.v1.LoginPasswordlessRequest.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.LoginPasswordlessRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.toObject = function(includeInstance, msg) { + var f, obj = { + init: (f = msg.getInit()) && proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.toObject(includeInstance, f), + pin: (f = msg.getPin()) && proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.toObject(includeInstance, f), + credential: (f = msg.getCredential()) && proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.LoginPasswordlessRequest; + return proto.teleport.terminal.v1.LoginPasswordlessRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} */ -proto.teleport.terminal.v1.ListAppsResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.teleport.terminal.v1.ListAppsResponse.repeatedFields_, null); +proto.teleport.terminal.v1.LoginPasswordlessRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit; + reader.readMessage(value,proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.deserializeBinaryFromReader); + msg.setInit(value); + break; + case 2: + var value = new proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse; + reader.readMessage(value,proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.deserializeBinaryFromReader); + msg.setPin(value); + break; + case 3: + var value = new proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse; + reader.readMessage(value,proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.deserializeBinaryFromReader); + msg.setCredential(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; }; -goog.inherits(proto.teleport.terminal.v1.ListAppsResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.teleport.terminal.v1.ListAppsResponse.displayName = 'proto.teleport.terminal.v1.ListAppsResponse'; -} + + /** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} */ -proto.teleport.terminal.v1.GetAuthSettingsRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.LoginPasswordlessRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); }; -goog.inherits(proto.teleport.terminal.v1.GetAuthSettingsRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.teleport.terminal.v1.GetAuthSettingsRequest.displayName = 'proto.teleport.terminal.v1.GetAuthSettingsRequest'; -} + + /** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.EmptyResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.teleport.terminal.v1.LoginPasswordlessRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getInit(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.serializeBinaryToWriter + ); + } + f = message.getPin(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.serializeBinaryToWriter + ); + } + f = message.getCredential(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.serializeBinaryToWriter + ); + } }; -goog.inherits(proto.teleport.terminal.v1.EmptyResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.teleport.terminal.v1.EmptyResponse.displayName = 'proto.teleport.terminal.v1.EmptyResponse'; -} + + @@ -686,8 +1699,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.teleport.terminal.v1.RemoveClusterRequest.prototype.toObject = function(opt_includeInstance) { - return proto.teleport.terminal.v1.RemoveClusterRequest.toObject(opt_includeInstance, this); +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.toObject(opt_includeInstance, this); }; @@ -696,11 +1709,11 @@ proto.teleport.terminal.v1.RemoveClusterRequest.prototype.toObject = function(op * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.teleport.terminal.v1.RemoveClusterRequest} msg The msg instance to transform. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.RemoveClusterRequest.toObject = function(includeInstance, msg) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.toObject = function(includeInstance, msg) { var f, obj = { clusterUri: jspb.Message.getFieldWithDefault(msg, 1, "") }; @@ -716,23 +1729,23 @@ proto.teleport.terminal.v1.RemoveClusterRequest.toObject = function(includeInsta /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.teleport.terminal.v1.RemoveClusterRequest} + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} */ -proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinary = function(bytes) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.teleport.terminal.v1.RemoveClusterRequest; - return proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit; + return proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.teleport.terminal.v1.RemoveClusterRequest} msg The message object to deserialize into. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.teleport.terminal.v1.RemoveClusterRequest} + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} */ -proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinaryFromReader = function(msg, reader) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -756,9 +1769,9 @@ proto.teleport.terminal.v1.RemoveClusterRequest.deserializeBinaryFromReader = fu * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.teleport.terminal.v1.RemoveClusterRequest.prototype.serializeBinary = function() { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.teleport.terminal.v1.RemoveClusterRequest.serializeBinaryToWriter(this, writer); + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -766,11 +1779,11 @@ proto.teleport.terminal.v1.RemoveClusterRequest.prototype.serializeBinary = func /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.teleport.terminal.v1.RemoveClusterRequest} message + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.RemoveClusterRequest.serializeBinaryToWriter = function(message, writer) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getClusterUri(); if (f.length > 0) { @@ -786,16 +1799,16 @@ proto.teleport.terminal.v1.RemoveClusterRequest.serializeBinaryToWriter = functi * optional string cluster_uri = 1; * @return {string} */ -proto.teleport.terminal.v1.RemoveClusterRequest.prototype.getClusterUri = function() { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.prototype.getClusterUri = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** * @param {string} value - * @return {!proto.teleport.terminal.v1.RemoveClusterRequest} returns this + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} returns this */ -proto.teleport.terminal.v1.RemoveClusterRequest.prototype.setClusterUri = function(value) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit.prototype.setClusterUri = function(value) { return jspb.Message.setProto3StringField(this, 1, value); }; @@ -816,8 +1829,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.teleport.terminal.v1.GetClusterRequest.prototype.toObject = function(opt_includeInstance) { - return proto.teleport.terminal.v1.GetClusterRequest.toObject(opt_includeInstance, this); +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.toObject(opt_includeInstance, this); }; @@ -826,13 +1839,13 @@ proto.teleport.terminal.v1.GetClusterRequest.prototype.toObject = function(opt_i * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.teleport.terminal.v1.GetClusterRequest} msg The msg instance to transform. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.GetClusterRequest.toObject = function(includeInstance, msg) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.toObject = function(includeInstance, msg) { var f, obj = { - clusterUri: jspb.Message.getFieldWithDefault(msg, 1, "") + pin: jspb.Message.getFieldWithDefault(msg, 1, "") }; if (includeInstance) { @@ -846,23 +1859,23 @@ proto.teleport.terminal.v1.GetClusterRequest.toObject = function(includeInstance /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.teleport.terminal.v1.GetClusterRequest} + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} */ -proto.teleport.terminal.v1.GetClusterRequest.deserializeBinary = function(bytes) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.teleport.terminal.v1.GetClusterRequest; - return proto.teleport.terminal.v1.GetClusterRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse; + return proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.teleport.terminal.v1.GetClusterRequest} msg The message object to deserialize into. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.teleport.terminal.v1.GetClusterRequest} + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} */ -proto.teleport.terminal.v1.GetClusterRequest.deserializeBinaryFromReader = function(msg, reader) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -871,7 +1884,7 @@ proto.teleport.terminal.v1.GetClusterRequest.deserializeBinaryFromReader = funct switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); - msg.setClusterUri(value); + msg.setPin(value); break; default: reader.skipField(); @@ -886,9 +1899,9 @@ proto.teleport.terminal.v1.GetClusterRequest.deserializeBinaryFromReader = funct * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.teleport.terminal.v1.GetClusterRequest.prototype.serializeBinary = function() { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.teleport.terminal.v1.GetClusterRequest.serializeBinaryToWriter(this, writer); + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -896,13 +1909,13 @@ proto.teleport.terminal.v1.GetClusterRequest.prototype.serializeBinary = functio /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.teleport.terminal.v1.GetClusterRequest} message + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.GetClusterRequest.serializeBinaryToWriter = function(message, writer) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getClusterUri(); + f = message.getPin(); if (f.length > 0) { writer.writeString( 1, @@ -913,19 +1926,19 @@ proto.teleport.terminal.v1.GetClusterRequest.serializeBinaryToWriter = function( /** - * optional string cluster_uri = 1; + * optional string pin = 1; * @return {string} */ -proto.teleport.terminal.v1.GetClusterRequest.prototype.getClusterUri = function() { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.prototype.getPin = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** * @param {string} value - * @return {!proto.teleport.terminal.v1.GetClusterRequest} returns this + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} returns this */ -proto.teleport.terminal.v1.GetClusterRequest.prototype.setClusterUri = function(value) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse.prototype.setPin = function(value) { return jspb.Message.setProto3StringField(this, 1, value); }; @@ -946,8 +1959,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.teleport.terminal.v1.LogoutRequest.prototype.toObject = function(opt_includeInstance) { - return proto.teleport.terminal.v1.LogoutRequest.toObject(opt_includeInstance, this); +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.toObject(opt_includeInstance, this); }; @@ -956,13 +1969,13 @@ proto.teleport.terminal.v1.LogoutRequest.prototype.toObject = function(opt_inclu * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.teleport.terminal.v1.LogoutRequest} msg The msg instance to transform. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.LogoutRequest.toObject = function(includeInstance, msg) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.toObject = function(includeInstance, msg) { var f, obj = { - clusterUri: jspb.Message.getFieldWithDefault(msg, 1, "") + index: jspb.Message.getFieldWithDefault(msg, 1, 0) }; if (includeInstance) { @@ -976,23 +1989,23 @@ proto.teleport.terminal.v1.LogoutRequest.toObject = function(includeInstance, ms /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.teleport.terminal.v1.LogoutRequest} + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} */ -proto.teleport.terminal.v1.LogoutRequest.deserializeBinary = function(bytes) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.teleport.terminal.v1.LogoutRequest; - return proto.teleport.terminal.v1.LogoutRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse; + return proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.teleport.terminal.v1.LogoutRequest} msg The message object to deserialize into. + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.teleport.terminal.v1.LogoutRequest} + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} */ -proto.teleport.terminal.v1.LogoutRequest.deserializeBinaryFromReader = function(msg, reader) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1000,8 +2013,8 @@ proto.teleport.terminal.v1.LogoutRequest.deserializeBinaryFromReader = function( var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setClusterUri(value); + var value = /** @type {number} */ (reader.readInt64()); + msg.setIndex(value); break; default: reader.skipField(); @@ -1016,9 +2029,9 @@ proto.teleport.terminal.v1.LogoutRequest.deserializeBinaryFromReader = function( * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.teleport.terminal.v1.LogoutRequest.prototype.serializeBinary = function() { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.teleport.terminal.v1.LogoutRequest.serializeBinaryToWriter(this, writer); + proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1026,15 +2039,15 @@ proto.teleport.terminal.v1.LogoutRequest.prototype.serializeBinary = function() /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.teleport.terminal.v1.LogoutRequest} message + * @param {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.teleport.terminal.v1.LogoutRequest.serializeBinaryToWriter = function(message, writer) { +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getClusterUri(); - if (f.length > 0) { - writer.writeString( + f = message.getIndex(); + if (f !== 0) { + writer.writeInt64( 1, f ); @@ -1043,20 +2056,131 @@ proto.teleport.terminal.v1.LogoutRequest.serializeBinaryToWriter = function(mess /** - * optional string cluster_uri = 1; - * @return {string} + * optional int64 index = 1; + * @return {number} */ -proto.teleport.terminal.v1.LogoutRequest.prototype.getClusterUri = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.prototype.getIndex = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); }; /** - * @param {string} value - * @return {!proto.teleport.terminal.v1.LogoutRequest} returns this + * @param {number} value + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} returns this */ -proto.teleport.terminal.v1.LogoutRequest.prototype.setClusterUri = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); +proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse.prototype.setIndex = function(value) { + return jspb.Message.setProto3IntField(this, 1, value); +}; + + +/** + * optional LoginPasswordlessRequestInit init = 1; + * @return {?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.getInit = function() { + return /** @type{?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit} */ ( + jspb.Message.getWrapperField(this, proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit, 1)); +}; + + +/** + * @param {?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit|undefined} value + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} returns this +*/ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.setInit = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.teleport.terminal.v1.LoginPasswordlessRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} returns this + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.clearInit = function() { + return this.setInit(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.hasInit = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional LoginPasswordlessPINResponse pin = 2; + * @return {?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.getPin = function() { + return /** @type{?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse} */ ( + jspb.Message.getWrapperField(this, proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse, 2)); +}; + + +/** + * @param {?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse|undefined} value + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} returns this +*/ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.setPin = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.teleport.terminal.v1.LoginPasswordlessRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} returns this + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.clearPin = function() { + return this.setPin(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.hasPin = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional LoginPasswordlessCredentialResponse credential = 3; + * @return {?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.getCredential = function() { + return /** @type{?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse} */ ( + jspb.Message.getWrapperField(this, proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse, 3)); +}; + + +/** + * @param {?proto.teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse|undefined} value + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} returns this +*/ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.setCredential = function(value) { + return jspb.Message.setOneofWrapperField(this, 3, proto.teleport.terminal.v1.LoginPasswordlessRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.teleport.terminal.v1.LoginPasswordlessRequest} returns this + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.clearCredential = function() { + return this.setCredential(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.teleport.terminal.v1.LoginPasswordlessRequest.prototype.hasCredential = function() { + return jspb.Message.getField(this, 3) != null; }; @@ -4982,4 +6106,14 @@ proto.teleport.terminal.v1.EmptyResponse.serializeBinaryToWriter = function(mess }; +/** + * @enum {number} + */ +proto.teleport.terminal.v1.PasswordlessPrompt = { + PASSWORDLESS_PROMPT_UNSPECIFIED: 0, + PASSWORDLESS_PROMPT_PIN: 1, + PASSWORDLESS_PROMPT_TAP: 2, + PASSWORDLESS_PROMPT_CREDENTIAL: 3 +}; + goog.object.extend(exports, proto.teleport.terminal.v1); diff --git a/lib/teleterm/apiserver/handler/handler_auth.go b/lib/teleterm/apiserver/handler/handler_auth.go index 17e2bdfd195d3..7047614fc6513 100644 --- a/lib/teleterm/apiserver/handler/handler_auth.go +++ b/lib/teleterm/apiserver/handler/handler_auth.go @@ -52,6 +52,32 @@ func (s *Handler) Login(ctx context.Context, req *api.LoginRequest) (*api.EmptyR } +// LoginPasswordless logs in a user to a cluster passwordlessly. +func (s *Handler) LoginPasswordless(stream api.TerminalService_LoginPasswordlessServer) error { + // Init stream request with cluster uri. + req, err := stream.Recv() + if err != nil { + return trace.Wrap(err) + } + + initReq := req.GetInit() + if initReq == nil || initReq.GetClusterUri() == "" { + return trace.BadParameter("cluster URI is required") + } + + cluster, err := s.DaemonService.ResolveCluster(initReq.GetClusterUri()) + if err != nil { + return trace.Wrap(err) + } + + // Start the prompt flow. + if err := cluster.PasswordlessLogin(stream.Context(), stream); err != nil { + return trace.Wrap(err) + } + + return nil +} + // Logout logs a user out from a cluster func (s *Handler) Logout(ctx context.Context, req *api.LogoutRequest) (*api.EmptyResponse, error) { if err := s.DaemonService.ClusterLogout(ctx, req.ClusterUri); err != nil { @@ -74,10 +100,12 @@ func (s *Handler) GetAuthSettings(ctx context.Context, req *api.GetAuthSettingsR } result := &api.AuthSettings{ - PreferredMfa: string(preferences.PreferredLocalMFA), - SecondFactor: string(preferences.SecondFactor), - LocalAuthEnabled: preferences.LocalAuthEnabled, - AuthProviders: []*api.AuthProvider{}, + PreferredMfa: string(preferences.PreferredLocalMFA), + SecondFactor: string(preferences.SecondFactor), + LocalAuthEnabled: preferences.LocalAuthEnabled, + AuthType: preferences.AuthType, + AllowPasswordless: preferences.AllowPasswordless, + LocalConnectorName: preferences.LocalConnectorName, } for _, provider := range preferences.Providers { diff --git a/lib/teleterm/clusters/cluster_auth.go b/lib/teleterm/clusters/cluster_auth.go index 0e57c74d1edeb..0bd66be84090e 100644 --- a/lib/teleterm/clusters/cluster_auth.go +++ b/lib/teleterm/clusters/cluster_auth.go @@ -18,14 +18,18 @@ package clusters import ( "context" + "errors" "fmt" + "sort" "github.com/gravitational/teleport/api/client/webclient" "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/lib/auth" + wancli "github.com/gravitational/teleport/lib/auth/webauthncli" "github.com/gravitational/teleport/lib/client" dbprofile "github.com/gravitational/teleport/lib/client/db" "github.com/gravitational/teleport/lib/kube/kubeconfig" + api "github.com/gravitational/teleport/lib/teleterm/api/protogen/golang/v1" "github.com/gravitational/trace" ) @@ -196,7 +200,7 @@ func (c *Cluster) localMFALogin(ctx context.Context, user, password string) erro return trace.Wrap(err) } - return err + return nil } func (c *Cluster) localLogin(ctx context.Context, user, password, otpToken string) error { @@ -277,3 +281,127 @@ func (c *Cluster) processAuthResponse(ctx context.Context, key *client.Key, resp return nil } + +// PasswordlessLogin processes passwordless logins for this cluster. +func (c *Cluster) PasswordlessLogin(ctx context.Context, stream api.TerminalService_LoginPasswordlessServer) error { + if _, err := c.clusterClient.Ping(ctx); err != nil { + return trace.Wrap(err) + } + + key, err := client.NewKey() + if err != nil { + return trace.Wrap(err) + } + + // TODO(alex-kovoy): SiteName needs to be reset if trying to login to a cluster with + // existing profile for the first time (investigate why) + c.clusterClient.SiteName = "" + + response, err := client.SSHAgentPasswordlessLogin(ctx, client.SSHLoginPasswordless{ + SSHLogin: client.SSHLogin{ + ProxyAddr: c.clusterClient.WebProxyAddr, + PubKey: key.Pub, + TTL: c.clusterClient.KeyTTL, + Insecure: c.clusterClient.InsecureSkipVerify, + Compatibility: c.clusterClient.CertificateFormat, + RouteToCluster: c.clusterClient.SiteName, + KubernetesCluster: c.clusterClient.KubernetesCluster, + }, + AuthenticatorAttachment: c.clusterClient.AuthenticatorAttachment, + CustomPrompt: newPwdlessLoginPrompt(ctx, stream), + }) + if err != nil { + return trace.Wrap(err) + } + + if err := c.processAuthResponse(ctx, key, response); err != nil { + return trace.Wrap(err) + } + + return nil +} + +// pwdlessLoginPrompt is a implementation for wancli.LoginPrompt for teleterm passwordless logins. +type pwdlessLoginPrompt struct { + Stream api.TerminalService_LoginPasswordlessServer +} + +func newPwdlessLoginPrompt(ctx context.Context, stream api.TerminalService_LoginPasswordlessServer) *pwdlessLoginPrompt { + return &pwdlessLoginPrompt{ + Stream: stream, + } +} + +// PromptPIN prompts the user for a PIN. +func (p *pwdlessLoginPrompt) PromptPIN() (string, error) { + if err := p.Stream.Send(&api.LoginPasswordlessResponse{ + Prompt: api.PasswordlessPrompt_PASSWORDLESS_PROMPT_PIN, + }); err != nil { + return "", trace.Wrap(err) + } + + req, err := p.Stream.Recv() + if err != nil { + return "", trace.Wrap(err) + } + + pinRes := req.GetPin() + if pinRes == nil || pinRes.GetPin() == "" { + return "", trace.BadParameter("pin is required") + } + + return pinRes.GetPin(), nil +} + +// PromptTouch prompts the user for a security key touch. +func (p *pwdlessLoginPrompt) PromptTouch() error { + return trace.Wrap(p.Stream.Send(&api.LoginPasswordlessResponse{Prompt: api.PasswordlessPrompt_PASSWORDLESS_PROMPT_TAP})) +} + +// PromptCredential prompts the user to select a login name in the list of logins. +func (p *pwdlessLoginPrompt) PromptCredential(deviceCreds []*wancli.CredentialInfo) (*wancli.CredentialInfo, error) { + // Shouldn't happen, but let's check just in case. + if len(deviceCreds) == 0 { + return nil, errors.New("attempted to prompt credential with empty credentials") + } + + // Sorts in place. + sort.Slice(deviceCreds, func(i, j int) bool { + c1 := deviceCreds[i] + c2 := deviceCreds[j] + return c1.User.Name < c2.User.Name + }) + + // Convert to grpc message. + creds := make([]*api.CredentialInfo, len(deviceCreds)) + for i, cred := range deviceCreds { + creds[i] = &api.CredentialInfo{ + Username: cred.User.Name, + } + } + + if err := p.Stream.Send(&api.LoginPasswordlessResponse{ + Prompt: api.PasswordlessPrompt_PASSWORDLESS_PROMPT_CREDENTIAL, + Credentials: creds, + }); err != nil { + return nil, trace.Wrap(err) + } + + req, err := p.Stream.Recv() + if err != nil { + return nil, trace.Wrap(err) + } + + credRes := req.GetCredential() + if credRes == nil { + return nil, trace.BadParameter("login name must be selected") + } + + // Test for out of range index values. + selectedIndex := credRes.GetIndex() + if selectedIndex < 0 || selectedIndex > int64(len(creds))-1 { + return nil, trace.BadParameter("invalid login name") + } + + return deviceCreds[selectedIndex], nil +} diff --git a/lib/teleterm/clusters/cluster_auth_test.go b/lib/teleterm/clusters/cluster_auth_test.go new file mode 100644 index 0000000000000..ba01ac1c7dec6 --- /dev/null +++ b/lib/teleterm/clusters/cluster_auth_test.go @@ -0,0 +1,140 @@ +/** + * Copyright 2022 Gravitational, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clusters + +import ( + "context" + "testing" + + wancli "github.com/gravitational/teleport/lib/auth/webauthncli" + api "github.com/gravitational/teleport/lib/teleterm/api/protogen/golang/v1" + "github.com/gravitational/trace" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +func TestPwdlessLoginPrompt_PromptPIN(t *testing.T) { + stream := &mockLoginPwdlessStream{} + + // Test valid pin. + stream.assertResp = func(res *api.LoginPasswordlessResponse) error { + require.Equal(t, api.PasswordlessPrompt_PASSWORDLESS_PROMPT_PIN, res.Prompt) + return nil + } + stream.serverReq = func() (*api.LoginPasswordlessRequest, error) { + return &api.LoginPasswordlessRequest{Request: &api.LoginPasswordlessRequest_Pin{ + Pin: &api.LoginPasswordlessRequest_LoginPasswordlessPINResponse{ + Pin: "1234"}, + }}, nil + } + + prompt := newPwdlessLoginPrompt(context.Background(), stream) + pin, err := prompt.PromptPIN() + require.NoError(t, err) + require.Equal(t, "1234", pin) + + // Test invalid pin. + stream.serverReq = func() (*api.LoginPasswordlessRequest, error) { + return &api.LoginPasswordlessRequest{Request: &api.LoginPasswordlessRequest_Pin{ + Pin: &api.LoginPasswordlessRequest_LoginPasswordlessPINResponse{ + Pin: ""}, + }}, nil + } + + _, err = prompt.PromptPIN() + require.True(t, trace.IsBadParameter(err)) +} + +func TestPwdlessLoginPrompt_PromptTouch(t *testing.T) { + stream := &mockLoginPwdlessStream{} + + stream.assertResp = func(res *api.LoginPasswordlessResponse) error { + require.Equal(t, api.PasswordlessPrompt_PASSWORDLESS_PROMPT_TAP, res.Prompt) + return nil + } + + prompt := newPwdlessLoginPrompt(context.Background(), stream) + err := prompt.PromptTouch() + require.NoError(t, err) +} + +func TestPwdlessLoginPrompt_PromptCredential(t *testing.T) { + stream := &mockLoginPwdlessStream{} + + unsortedCreds := []*wancli.CredentialInfo{ + {User: wancli.UserInfo{Name: "foo"}}, // will select + {User: wancli.UserInfo{Name: "bar"}}, + {User: wancli.UserInfo{Name: "ape"}}, + {User: wancli.UserInfo{Name: "llama"}}, + } + + expectedCredResponse := []*api.CredentialInfo{ + {Username: "ape"}, + {Username: "bar"}, + {Username: "foo"}, + {Username: "llama"}, + } + + // Test valid index. + stream.assertResp = func(res *api.LoginPasswordlessResponse) error { + require.Equal(t, api.PasswordlessPrompt_PASSWORDLESS_PROMPT_CREDENTIAL, res.Prompt) + require.Equal(t, expectedCredResponse, res.GetCredentials()) + return nil + } + stream.serverReq = func() (*api.LoginPasswordlessRequest, error) { + return &api.LoginPasswordlessRequest{Request: &api.LoginPasswordlessRequest_Credential{ + Credential: &api.LoginPasswordlessRequest_LoginPasswordlessCredentialResponse{ + Index: 2}, + }}, nil + } + + prompt := newPwdlessLoginPrompt(context.Background(), stream) + cred, err := prompt.PromptCredential(unsortedCreds) + require.NoError(t, err) + require.Equal(t, "foo", cred.User.Name) + + // Test invalid index. + stream.serverReq = func() (*api.LoginPasswordlessRequest, error) { + return &api.LoginPasswordlessRequest{Request: &api.LoginPasswordlessRequest_Credential{ + Credential: &api.LoginPasswordlessRequest_LoginPasswordlessCredentialResponse{ + Index: 4}, + }}, nil + } + _, err = prompt.PromptCredential(unsortedCreds) + require.True(t, trace.IsBadParameter(err)) +} + +type mockLoginPwdlessStream struct { + grpc.ServerStream + assertResp func(resp *api.LoginPasswordlessResponse) error + serverReq func() (*api.LoginPasswordlessRequest, error) +} + +func (m *mockLoginPwdlessStream) Send(resp *api.LoginPasswordlessResponse) error { + if m.assertResp != nil { + return m.assertResp(resp) + } + return trace.NotImplemented("assertResp not implemented") +} + +func (m *mockLoginPwdlessStream) Recv() (*api.LoginPasswordlessRequest, error) { + if m.serverReq != nil { + return m.serverReq() + } + return nil, trace.NotImplemented("serverReq not implemented") +}