github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/client/client.go (about) 1 /* 2 Copyright 2020-2022 Gravitational, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package client 18 19 import ( 20 "cmp" 21 "compress/gzip" 22 "context" 23 "crypto/tls" 24 "errors" 25 "fmt" 26 "io" 27 "log/slog" 28 "net" 29 "slices" 30 "sync" 31 "sync/atomic" 32 "time" 33 34 "github.com/coreos/go-semver/semver" 35 "github.com/gravitational/trace" 36 "github.com/jonboulle/clockwork" 37 "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" 38 "golang.org/x/crypto/ssh" 39 "google.golang.org/grpc" 40 "google.golang.org/grpc/connectivity" 41 "google.golang.org/grpc/credentials" 42 ggzip "google.golang.org/grpc/encoding/gzip" 43 "google.golang.org/grpc/keepalive" 44 gmetadata "google.golang.org/grpc/metadata" 45 "google.golang.org/protobuf/types/known/durationpb" 46 "google.golang.org/protobuf/types/known/emptypb" 47 "google.golang.org/protobuf/types/known/timestamppb" 48 49 "github.com/gravitational/teleport/api/breaker" 50 "github.com/gravitational/teleport/api/client/accesslist" 51 "github.com/gravitational/teleport/api/client/accessmonitoringrules" 52 "github.com/gravitational/teleport/api/client/crownjewel" 53 crownjewelapi "github.com/gravitational/teleport/api/client/crownjewel" 54 "github.com/gravitational/teleport/api/client/discoveryconfig" 55 "github.com/gravitational/teleport/api/client/externalauditstorage" 56 kubewaitingcontainerclient "github.com/gravitational/teleport/api/client/kubewaitingcontainer" 57 "github.com/gravitational/teleport/api/client/okta" 58 "github.com/gravitational/teleport/api/client/proto" 59 "github.com/gravitational/teleport/api/client/scim" 60 "github.com/gravitational/teleport/api/client/secreport" 61 "github.com/gravitational/teleport/api/client/userloginstate" 62 "github.com/gravitational/teleport/api/constants" 63 "github.com/gravitational/teleport/api/defaults" 64 "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" 65 accesslistv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1" 66 accessmonitoringrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" 67 auditlogpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/auditlog/v1" 68 clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" 69 crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" 70 dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" 71 dbobjectimportrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1" 72 devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" 73 discoveryconfigv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1" 74 externalauditstoragev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/externalauditstorage/v1" 75 integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" 76 kubeproto "github.com/gravitational/teleport/api/gen/proto/go/teleport/kube/v1" 77 kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" 78 loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1" 79 machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" 80 oktapb "github.com/gravitational/teleport/api/gen/proto/go/teleport/okta/v1" 81 pluginspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/plugins/v1" 82 presencepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/presence/v1" 83 resourceusagepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/resourceusage/v1" 84 samlidppb "github.com/gravitational/teleport/api/gen/proto/go/teleport/samlidp/v1" 85 secreportsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/secreports/v1" 86 trustpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/trust/v1" 87 userloginstatev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userloginstate/v1" 88 userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" 89 userpreferencespb "github.com/gravitational/teleport/api/gen/proto/go/userpreferences/v1" 90 "github.com/gravitational/teleport/api/internalutils/stream" 91 "github.com/gravitational/teleport/api/metadata" 92 "github.com/gravitational/teleport/api/mfa" 93 "github.com/gravitational/teleport/api/observability/tracing" 94 "github.com/gravitational/teleport/api/types" 95 "github.com/gravitational/teleport/api/types/events" 96 "github.com/gravitational/teleport/api/types/wrappers" 97 "github.com/gravitational/teleport/api/utils" 98 "github.com/gravitational/teleport/api/utils/grpc/interceptors" 99 ) 100 101 func init() { 102 // gzip is used for gRPC auditStream compression. SetLevel changes the 103 // compression level, must be called in initialization, and is not thread safe. 104 if err := ggzip.SetLevel(gzip.BestSpeed); err != nil { 105 panic(err) 106 } 107 } 108 109 // AuthServiceClient keeps the interfaces implemented by the auth service. 110 type AuthServiceClient struct { 111 proto.AuthServiceClient 112 assist.AssistServiceClient 113 auditlogpb.AuditLogServiceClient 114 userpreferencespb.UserPreferencesServiceClient 115 } 116 117 // Client is a gRPC Client that connects to a Teleport Auth server either 118 // locally or over ssh through a Teleport web proxy or tunnel proxy. 119 // 120 // This client can be used to cover a variety of Teleport use cases, 121 // such as programmatically handling access requests, integrating 122 // with external tools, or dynamically configuring Teleport. 123 type Client struct { 124 // c contains configuration values for the client. 125 c Config 126 // tlsConfig is the *tls.Config for a successfully connected client. 127 tlsConfig *tls.Config 128 // dialer is the ContextDialer for a successfully connected client. 129 dialer ContextDialer 130 // conn is a grpc connection to the auth server. 131 conn *grpc.ClientConn 132 // grpc is the gRPC client specification for the auth server. 133 grpc AuthServiceClient 134 // JoinServiceClient is a client for the JoinService, which runs on both the 135 // auth and proxy. 136 *JoinServiceClient 137 // closedFlag is set to indicate that the connection is closed. 138 // It's a pointer to allow the Client struct to be copied. 139 closedFlag *int32 140 } 141 142 // New creates a new Client with an open connection to a Teleport server. 143 // 144 // New will try to open a connection with all combinations of addresses and credentials. 145 // The first successful connection to a server will be used, or an aggregated error will 146 // be returned if all combinations fail. 147 // 148 // cfg.Credentials must be non-empty. One of cfg.Addrs and cfg.Dialer must be non-empty, 149 // unless LoadProfile is used to fetch Credentials and load a web proxy dialer. 150 // 151 // See the example below for usage. 152 func New(ctx context.Context, cfg Config) (*Client, error) { 153 if err := cfg.CheckAndSetDefaults(); err != nil { 154 return nil, trace.Wrap(err) 155 } 156 157 // If cfg.DialInBackground is true, only a single connection is attempted. 158 // This option is primarily meant for internal use where the client has 159 // direct access to server values that guarantee a successful connection. 160 if cfg.DialInBackground { 161 return connectInBackground(ctx, cfg) 162 } 163 164 return connect(ctx, cfg) 165 } 166 167 // NewTracingClient creates a new tracing.Client that will forward spans to the 168 // connected Teleport server. See New for details on how the connection it 169 // established. 170 func NewTracingClient(ctx context.Context, cfg Config) (*tracing.Client, error) { 171 clt, err := New(ctx, cfg) 172 if err != nil { 173 return nil, trace.Wrap(err) 174 } 175 176 return tracing.NewClient(clt.GetConnection()), nil 177 } 178 179 // NewOktaClient creates a new Okta client for managing Okta resources. 180 func NewOktaClient(ctx context.Context, cfg Config) (*okta.Client, error) { 181 clt, err := New(ctx, cfg) 182 if err != nil { 183 return nil, trace.Wrap(err) 184 } 185 return okta.NewClient(oktapb.NewOktaServiceClient(clt.GetConnection())), nil 186 } 187 188 // newClient constructs a new client. 189 func newClient(cfg Config, dialer ContextDialer, tlsConfig *tls.Config) *Client { 190 return &Client{ 191 c: cfg, 192 dialer: dialer, 193 tlsConfig: ConfigureALPN(tlsConfig, cfg.ALPNSNIAuthDialClusterName), 194 closedFlag: new(int32), 195 } 196 } 197 198 // connectInBackground connects the client to the server in the background. 199 // 200 // The client will use the first credentials and the given dialer. 201 // 202 // If no dialer is given, the first address will be used. If no 203 // ALPNSNIAuthDialClusterName is given, this address must be an auth server 204 // address. 205 // 206 // If ALPNSNIAuthDialClusterName is given, the address is expected to be a web 207 // proxy address and the client will connect auth through the web proxy server 208 // using TLS Routing. 209 func connectInBackground(ctx context.Context, cfg Config) (*Client, error) { 210 tlsConfig, err := cfg.Credentials[0].TLSConfig() 211 if err != nil { 212 return nil, trace.Wrap(err) 213 } 214 if cfg.Dialer != nil { 215 return dialerConnect(ctx, connectParams{ 216 cfg: cfg, 217 tlsConfig: tlsConfig, 218 dialer: cfg.Dialer, 219 }) 220 } else if len(cfg.Addrs) != 0 { 221 return authConnect(ctx, connectParams{ 222 cfg: cfg, 223 tlsConfig: tlsConfig, 224 addr: cfg.Addrs[0], 225 }) 226 } 227 return nil, trace.BadParameter("must provide Dialer or Addrs in config") 228 } 229 230 // connect connects the client to the server using the Credentials and 231 // Dialer/Addresses provided in the client's config. Multiple goroutines are started 232 // to make dial attempts with different combinations of dialers and credentials. The 233 // first client to successfully connect is used to populate the client's connection 234 // attributes. If none successfully connect, an aggregated error is returned. 235 func connect(ctx context.Context, cfg Config) (*Client, error) { 236 ctx, cancel := context.WithCancel(ctx) 237 defer cancel() 238 var wg sync.WaitGroup 239 240 // sendError is used to send errors to errChan with context. 241 errChan := make(chan error) 242 sendError := func(err error) { 243 errChan <- trace.Wrap(err) 244 } 245 246 // syncConnect is used to concurrently create multiple clients 247 // with the different combination of connection parameters. 248 // The first successful client to be sent to cltChan will be returned. 249 cltChan := make(chan *Client) 250 syncConnect := func(ctx context.Context, connect connectFunc, params connectParams) { 251 wg.Add(1) 252 go func() { 253 defer wg.Done() 254 clt, err := connect(ctx, params) 255 if err != nil { 256 sendError(trace.Wrap(err)) 257 return 258 } 259 select { 260 case cltChan <- clt: 261 case <-ctx.Done(): 262 clt.Close() 263 } 264 }() 265 } 266 267 wg.Add(1) 268 go func() { 269 defer wg.Done() 270 271 // Connect with provided credentials. 272 for _, creds := range cfg.Credentials { 273 tlsConfig, err := creds.TLSConfig() 274 if err != nil { 275 sendError(trace.Wrap(err)) 276 continue 277 } 278 279 sshConfig, err := creds.SSHClientConfig() 280 if err != nil && !trace.IsNotImplemented(err) { 281 sendError(trace.Wrap(err)) 282 continue 283 } 284 285 // Connect with dialer provided in config. 286 if cfg.Dialer != nil { 287 syncConnect(ctx, dialerConnect, connectParams{ 288 cfg: cfg, 289 tlsConfig: tlsConfig, 290 }) 291 } 292 293 addrs := cfg.Addrs 294 if len(addrs) == 0 { 295 // If there's no explicitly specified address, fall back to 296 // an address provided by the credential, if it provides one. 297 credAddrSource, ok := creds.(CredentialsWithDefaultAddrs) 298 if ok { 299 addrs, err = credAddrSource.DefaultAddrs() 300 if err != nil { 301 sendError(trace.Wrap(err)) 302 continue 303 } 304 slog.DebugContext(ctx, "No addresses were configured explicitly, falling back to addresses specified by credential. Consider explicitly configuring an address.", "address", addrs) 305 } 306 } 307 308 // Attempt to connect to each address as Auth, Proxy, Tunnel and TLS Routing. 309 for _, addr := range addrs { 310 syncConnect(ctx, authConnect, connectParams{ 311 cfg: cfg, 312 tlsConfig: tlsConfig, 313 addr: addr, 314 }) 315 if sshConfig != nil { 316 for _, cf := range []connectFunc{proxyConnect, tunnelConnect, tlsRoutingConnect, tlsRoutingWithConnUpgradeConnect} { 317 syncConnect(ctx, cf, connectParams{ 318 cfg: cfg, 319 tlsConfig: tlsConfig, 320 sshConfig: sshConfig, 321 addr: addr, 322 }) 323 } 324 } 325 } 326 } 327 }() 328 329 // Start goroutine to wait for wait group. 330 go func() { 331 wg.Wait() 332 // Close errChan to return errors. 333 close(errChan) 334 }() 335 336 var errs []error 337 Outer: 338 for { 339 select { 340 // Use the first client to successfully connect in syncConnect. 341 case clt := <-cltChan: 342 go func() { 343 for range errChan { 344 } 345 }() 346 return clt, nil 347 case err, ok := <-errChan: 348 if !ok { 349 break Outer 350 } 351 // Add a new line to make errs human readable. 352 errs = append(errs, trace.Wrap(err, "")) 353 } 354 } 355 356 // errChan is closed, return errors. 357 if len(errs) == 0 { 358 if len(cfg.Addrs) == 0 && cfg.Dialer == nil { 359 // Some credentials don't require these fields. If no errors propagate, then they need to provide these fields. 360 return nil, trace.BadParameter("no connection methods found, try providing Dialer or Addrs in config") 361 } 362 // This case should never be reached with config validation and above case. 363 return nil, trace.Errorf("no connection methods found") 364 } 365 if ctx.Err() != nil { 366 errs = append(errs, trace.Wrap(ctx.Err())) 367 } 368 return nil, trace.Wrap(trace.NewAggregate(errs...), "all connection methods failed") 369 } 370 371 type ( 372 connectFunc func(ctx context.Context, params connectParams) (*Client, error) 373 connectParams struct { 374 cfg Config 375 addr string 376 tlsConfig *tls.Config 377 dialer ContextDialer 378 sshConfig *ssh.ClientConfig 379 } 380 ) 381 382 // authConnect connects to the Teleport Auth Server directly or through Proxy. 383 func authConnect(ctx context.Context, params connectParams) (*Client, error) { 384 dialer := NewDialer(ctx, params.cfg.KeepAlivePeriod, params.cfg.DialTimeout, 385 WithInsecureSkipVerify(params.cfg.InsecureAddressDiscovery), 386 WithALPNConnUpgrade(params.cfg.ALPNConnUpgradeRequired), 387 WithALPNConnUpgradePing(true), // Use Ping protocol for long-lived connections. 388 WithPROXYHeaderGetter(params.cfg.PROXYHeaderGetter), 389 ) 390 391 clt := newClient(params.cfg, dialer, params.tlsConfig) 392 if err := clt.dialGRPC(ctx, params.addr); err != nil { 393 return nil, trace.Wrap(err, "failed to connect to addr %v as an auth server", params.addr) 394 } 395 return clt, nil 396 } 397 398 // tunnelConnect connects to the Teleport Auth Server through the proxy's reverse tunnel. 399 func tunnelConnect(ctx context.Context, params connectParams) (*Client, error) { 400 if params.sshConfig == nil { 401 return nil, trace.BadParameter("must provide ssh client config") 402 } 403 dialer := newTunnelDialer(*params.sshConfig, params.cfg.KeepAlivePeriod, params.cfg.DialTimeout, WithInsecureSkipVerify(params.cfg.InsecureAddressDiscovery)) 404 clt := newClient(params.cfg, dialer, params.tlsConfig) 405 if err := clt.dialGRPC(ctx, params.addr); err != nil { 406 return nil, trace.Wrap(err, "failed to connect to addr %v as a reverse tunnel proxy", params.addr) 407 } 408 return clt, nil 409 } 410 411 // proxyConnect connects to the Teleport Auth Server through the proxy. 412 // takes a specific addr parameter to allow the proxy address to be modified 413 // when using special credentials. 414 func proxyConnect(ctx context.Context, params connectParams) (*Client, error) { 415 if params.sshConfig == nil { 416 return nil, trace.BadParameter("must provide ssh client config") 417 } 418 419 dialer := NewProxyDialer( 420 *params.sshConfig, 421 params.cfg.KeepAlivePeriod, 422 params.cfg.DialTimeout, 423 params.addr, 424 params.cfg.InsecureAddressDiscovery, 425 WithInsecureSkipVerify(params.cfg.InsecureAddressDiscovery), 426 ) 427 clt := newClient(params.cfg, dialer, params.tlsConfig) 428 if err := clt.dialGRPC(ctx, params.addr); err != nil { 429 return nil, trace.Wrap(err, "failed to connect to addr %v as a web proxy", params.addr) 430 } 431 return clt, nil 432 } 433 434 // tlsRoutingConnect connects to the Teleport Auth Server through the proxy using TLS Routing. 435 func tlsRoutingConnect(ctx context.Context, params connectParams) (*Client, error) { 436 if params.sshConfig == nil { 437 return nil, trace.BadParameter("must provide ssh client config") 438 } 439 dialer := newTLSRoutingTunnelDialer(*params.sshConfig, params.cfg.KeepAlivePeriod, params.cfg.DialTimeout, params.addr, params.cfg.InsecureAddressDiscovery) 440 clt := newClient(params.cfg, dialer, params.tlsConfig) 441 if err := clt.dialGRPC(ctx, params.addr); err != nil { 442 return nil, trace.Wrap(err, "failed to connect to addr %v with TLS Routing dialer", params.addr) 443 } 444 return clt, nil 445 } 446 447 // tlsRoutingWithConnUpgradeConnect connects to the Teleport Auth Server 448 // through the proxy using TLS Routing with ALPN connection upgrade. 449 func tlsRoutingWithConnUpgradeConnect(ctx context.Context, params connectParams) (*Client, error) { 450 if params.sshConfig == nil { 451 return nil, trace.BadParameter("must provide ssh client config") 452 } 453 dialer := newTLSRoutingWithConnUpgradeDialer(*params.sshConfig, params) 454 clt := newClient(params.cfg, dialer, params.tlsConfig) 455 if err := clt.dialGRPC(ctx, params.addr); err != nil { 456 return nil, trace.Wrap(err, "failed to connect to addr %v with TLS Routing with ALPN connection upgrade dialer", params.addr) 457 } 458 return clt, nil 459 } 460 461 // dialerConnect connects to the Teleport Auth Server through a custom dialer. 462 // The dialer must provide the address in a custom ContextDialerFunc function. 463 func dialerConnect(ctx context.Context, params connectParams) (*Client, error) { 464 if params.dialer == nil { 465 if params.cfg.Dialer == nil { 466 return nil, trace.BadParameter("must provide dialer to connectParams.dialer or params.cfg.Dialer") 467 } 468 params.dialer = params.cfg.Dialer 469 } 470 clt := newClient(params.cfg, params.dialer, params.tlsConfig) 471 // Since the client uses a custom dialer to connect to the server and SNI 472 // is used for the TLS handshake, the address dialed here is arbitrary. 473 if err := clt.dialGRPC(ctx, constants.APIDomain); err != nil { 474 return nil, trace.Wrap(err, "failed to connect using pre-defined dialer") 475 } 476 return clt, nil 477 } 478 479 // dialGRPC dials a connection between server and client. 480 func (c *Client) dialGRPC(ctx context.Context, addr string) error { 481 dialContext, cancel := context.WithTimeout(ctx, c.c.DialTimeout) 482 defer cancel() 483 484 cb, err := breaker.New(c.c.CircuitBreakerConfig) 485 if err != nil { 486 return trace.Wrap(err) 487 } 488 489 var dialOpts []grpc.DialOption 490 dialOpts = append(dialOpts, grpc.WithContextDialer(c.grpcDialer())) 491 dialOpts = append(dialOpts, 492 grpc.WithChainUnaryInterceptor( 493 otelUnaryClientInterceptor(), 494 metadata.UnaryClientInterceptor, 495 interceptors.GRPCClientUnaryErrorInterceptor, 496 interceptors.WithMFAUnaryInterceptor(c.PerformMFACeremony), 497 breaker.UnaryClientInterceptor(cb), 498 ), 499 grpc.WithChainStreamInterceptor( 500 otelStreamClientInterceptor(), 501 metadata.StreamClientInterceptor, 502 interceptors.GRPCClientStreamErrorInterceptor, 503 breaker.StreamClientInterceptor(cb), 504 ), 505 ) 506 // Only set transportCredentials if tlsConfig is set. This makes it possible 507 // to explicitly provide grpc.WithTransportCredentials(insecure.NewCredentials()) 508 // in the client's dial options. 509 if c.tlsConfig != nil { 510 dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(c.tlsConfig))) 511 } 512 // must come last, otherwise provided opts may get clobbered by defaults above 513 dialOpts = append(dialOpts, c.c.DialOpts...) 514 515 conn, err := grpc.DialContext(dialContext, addr, dialOpts...) 516 if err != nil { 517 return trace.Wrap(err) 518 } 519 520 c.conn = conn 521 c.grpc = AuthServiceClient{ 522 AuthServiceClient: proto.NewAuthServiceClient(c.conn), 523 AssistServiceClient: assist.NewAssistServiceClient(c.conn), 524 AuditLogServiceClient: auditlogpb.NewAuditLogServiceClient(c.conn), 525 UserPreferencesServiceClient: userpreferencespb.NewUserPreferencesServiceClient(c.conn), 526 } 527 c.JoinServiceClient = NewJoinServiceClient(proto.NewJoinServiceClient(c.conn)) 528 529 return nil 530 } 531 532 // We wrap the creation of the otelgrpc interceptors in a sync.Once - this is 533 // because each time this is called, they create a new underlying metric. If 534 // something (e.g tbot) is repeatedly creating new clients and closing them, 535 // then this leads to a memory leak since the underlying metric is not cleaned 536 // up. 537 // See https://github.com/gravitational/teleport/issues/30759 538 // See https://github.com/open-telemetry/opentelemetry-go-contrib/issues/4226 539 var otelStreamClientInterceptor = sync.OnceValue(func() grpc.StreamClientInterceptor { 540 //nolint:staticcheck // SA1019. There is a data race in the stats.Handler that is replacing 541 // the interceptor. See https://github.com/open-telemetry/opentelemetry-go-contrib/issues/4576. 542 return otelgrpc.StreamClientInterceptor() 543 }) 544 545 var otelUnaryClientInterceptor = sync.OnceValue(func() grpc.UnaryClientInterceptor { 546 //nolint:staticcheck // SA1019. There is a data race in the stats.Handler that is replacing 547 // the interceptor. See https://github.com/open-telemetry/opentelemetry-go-contrib/issues/4576. 548 return otelgrpc.UnaryClientInterceptor() 549 }) 550 551 // ConfigureALPN configures ALPN SNI cluster routing information in TLS settings allowing for 552 // allowing to dial auth service through Teleport Proxy directly without using SSH Tunnels. 553 func ConfigureALPN(tlsConfig *tls.Config, clusterName string) *tls.Config { 554 if tlsConfig == nil { 555 return nil 556 } 557 if clusterName == "" { 558 return tlsConfig 559 } 560 out := tlsConfig.Clone() 561 routeInfo := fmt.Sprintf("%s%s", constants.ALPNSNIAuthProtocol, utils.EncodeClusterName(clusterName)) 562 out.NextProtos = append([]string{routeInfo}, out.NextProtos...) 563 return out 564 } 565 566 // grpcDialer wraps the client's dialer with a grpcDialer. 567 func (c *Client) grpcDialer() func(ctx context.Context, addr string) (net.Conn, error) { 568 return func(ctx context.Context, addr string) (net.Conn, error) { 569 if c.isClosed() { 570 return nil, trace.ConnectionProblem(nil, "client is closed") 571 } 572 conn, err := c.dialer.DialContext(ctx, "tcp", addr) 573 if err != nil { 574 return nil, trace.ConnectionProblem(err, "failed to dial: %v", err) 575 } 576 return conn, nil 577 } 578 } 579 580 // waitForConnectionReady waits for the client's grpc connection finish dialing, returning an error 581 // if the ctx is canceled or the client's gRPC connection enters an unexpected state. This can be used 582 // alongside the DialInBackground client config option to wait until background dialing has completed. 583 func (c *Client) waitForConnectionReady(ctx context.Context) error { 584 for { 585 if c.conn == nil { 586 return errors.New("conn was closed") 587 } 588 switch state := c.conn.GetState(); state { 589 case connectivity.Ready: 590 return nil 591 case connectivity.TransientFailure, connectivity.Connecting, connectivity.Idle: 592 // Wait for expected state transitions. For details about grpc.ClientConn state changes 593 // see https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md 594 if !c.conn.WaitForStateChange(ctx, state) { 595 // ctx canceled 596 return trace.Wrap(ctx.Err()) 597 } 598 case connectivity.Shutdown: 599 return trace.Errorf("client gRPC connection entered an unexpected state: %v", state) 600 } 601 } 602 } 603 604 // Config contains configuration of the client 605 type Config struct { 606 // Addrs is a list of teleport auth/proxy server addresses to dial. 607 Addrs []string 608 // Credentials are a list of credentials to use when attempting 609 // to connect to the server. 610 Credentials []Credentials 611 // Dialer is a custom dialer used to dial a server. The Dialer should 612 // have custom logic to provide an address to the dialer. If set, Dialer 613 // takes precedence over all other connection options. 614 Dialer ContextDialer 615 // DialOpts define options for dialing the client connection. 616 DialOpts []grpc.DialOption 617 // DialInBackground specifies to dial the connection in the background 618 // rather than blocking until the connection is up. A predefined Dialer 619 // or an auth server address must be provided. 620 DialInBackground bool 621 // DialTimeout defines how long to attempt dialing before timing out. 622 DialTimeout time.Duration 623 // KeepAlivePeriod defines period between keep alives. 624 KeepAlivePeriod time.Duration 625 // KeepAliveCount specifies the amount of missed keep alives 626 // to wait for before declaring the connection as broken. 627 KeepAliveCount int 628 // The web proxy uses a self-signed TLS certificate by default, which 629 // requires this field to be set. If the web proxy was provided with 630 // signed TLS certificates, this field should not be set. 631 InsecureAddressDiscovery bool 632 // ALPNSNIAuthDialClusterName if present the client will include ALPN SNI routing information in TLS Hello message 633 // allowing to dial auth service through Teleport Proxy directly without using SSH Tunnels. 634 ALPNSNIAuthDialClusterName string 635 // CircuitBreakerConfig defines how the circuit breaker should behave. 636 CircuitBreakerConfig breaker.Config 637 // Context is the base context to use for dialing. If not provided context.Background is used 638 Context context.Context 639 // ALPNConnUpgradeRequired indicates that ALPN connection upgrades are 640 // required for making TLS Routing requests. 641 // 642 // In DialInBackground mode without a Dialer, a valid value must be 643 // provided as it's assumed that the caller knows the context if connection 644 // upgrades are required for TLS Routing. 645 // 646 // In default mode, this value is optional as some of the connect methods 647 // will perform necessary tests to decide if connection upgrade is 648 // required. 649 ALPNConnUpgradeRequired bool 650 // PROXYHeaderGetter returns signed PROXY header that is sent to allow Proxy to propagate client's real IP to the 651 // auth server from the Proxy's web server, when we create user's client for the web session. 652 PROXYHeaderGetter PROXYHeaderGetter 653 // MFAPromptConstructor is used to create MFA prompts when needed. 654 // If nil, the client will not prompt for MFA. 655 MFAPromptConstructor mfa.PromptConstructor 656 } 657 658 // CheckAndSetDefaults checks and sets default config values. 659 func (c *Config) CheckAndSetDefaults() error { 660 if len(c.Credentials) == 0 { 661 return trace.BadParameter("missing connection credentials") 662 } 663 664 if c.KeepAlivePeriod == 0 { 665 c.KeepAlivePeriod = defaults.ServerKeepAliveTTL() 666 } 667 if c.KeepAliveCount == 0 { 668 c.KeepAliveCount = defaults.KeepAliveCountMax 669 } 670 if c.DialTimeout == 0 { 671 c.DialTimeout = defaults.DefaultIOTimeout 672 } 673 if c.CircuitBreakerConfig.Trip == nil || c.CircuitBreakerConfig.IsSuccessful == nil { 674 c.CircuitBreakerConfig = breaker.DefaultBreakerConfig(clockwork.NewRealClock()) 675 } 676 677 if c.Context == nil { 678 c.Context = context.Background() 679 } 680 681 c.DialOpts = append(c.DialOpts, grpc.WithKeepaliveParams(keepalive.ClientParameters{ 682 Time: c.KeepAlivePeriod, 683 Timeout: c.KeepAlivePeriod * time.Duration(c.KeepAliveCount), 684 PermitWithoutStream: true, 685 })) 686 if !c.DialInBackground { 687 c.DialOpts = append( 688 c.DialOpts, 689 // Provides additional feedback on connection failure, otherwise, 690 // users will only receive a `context deadline exceeded` error when 691 // c.DialInBackground == false. 692 // 693 // grpc.WithReturnConnectionError implies grpc.WithBlock which is 694 // necessary for connection route selection to work properly. 695 grpc.WithReturnConnectionError(), 696 ) 697 } 698 699 return nil 700 } 701 702 // Config returns the tls.Config the client connected with. 703 func (c *Client) Config() *tls.Config { 704 return c.tlsConfig 705 } 706 707 // Dialer returns the ContextDialer the client connected with. 708 func (c *Client) Dialer() ContextDialer { 709 return c.dialer 710 } 711 712 // GetConnection returns gRPC connection. 713 func (c *Client) GetConnection() *grpc.ClientConn { 714 return c.conn 715 } 716 717 // SetMFAPromptConstructor sets the MFA prompt constructor for this client. 718 func (c *Client) SetMFAPromptConstructor(pc mfa.PromptConstructor) { 719 c.c.MFAPromptConstructor = pc 720 } 721 722 // Close closes the Client connection to the auth server. 723 func (c *Client) Close() error { 724 if c.setClosed() && c.conn != nil { 725 return trace.Wrap(c.conn.Close()) 726 } 727 return nil 728 } 729 730 // isClosed returns whether the client is marked as closed. 731 func (c *Client) isClosed() bool { 732 return atomic.LoadInt32(c.closedFlag) == 1 733 } 734 735 // setClosed marks the client as closed and returns true if it was open. 736 func (c *Client) setClosed() bool { 737 return atomic.CompareAndSwapInt32(c.closedFlag, 0, 1) 738 } 739 740 // DevicesClient returns an unadorned Device Trust client, using the underlying 741 // Auth gRPC connection. 742 // Clients connecting to non-Enterprise clusters, or older Teleport versions, 743 // still get a devices client when calling this method, but all RPCs will return 744 // "not implemented" errors (as per the default gRPC behavior). 745 func (c *Client) DevicesClient() devicepb.DeviceTrustServiceClient { 746 return devicepb.NewDeviceTrustServiceClient(c.conn) 747 } 748 749 // CreateDeviceResource creates a device using its resource representation. 750 // Prefer using [DevicesClient] directly if you can. 751 func (c *Client) CreateDeviceResource(ctx context.Context, res *types.DeviceV1) (*types.DeviceV1, error) { 752 dev, err := types.DeviceFromResource(res) 753 if err != nil { 754 return nil, trace.Wrap(err) 755 } 756 757 created, err := c.DevicesClient().CreateDevice(ctx, &devicepb.CreateDeviceRequest{ 758 Device: dev, 759 CreateAsResource: true, 760 }) 761 if err != nil { 762 return nil, trace.Wrap(err) 763 } 764 return types.DeviceToResource(created), nil 765 } 766 767 // DeleteDeviceResource deletes a device using its ID (either devicepb.Device.Id 768 // or its Metadata.Name). 769 // Prefer using [DevicesClient] directly if you can. 770 func (c *Client) DeleteDeviceResource(ctx context.Context, id string) error { 771 _, err := c.DevicesClient().DeleteDevice(ctx, &devicepb.DeleteDeviceRequest{ 772 DeviceId: id, 773 }) 774 return trace.Wrap(err) 775 } 776 777 // GetDeviceResource reads a device using its ID (either devicepb.Device.Id 778 // or its Metadata.Name). 779 // Prefer using [DevicesClient] directly if you can. 780 func (c *Client) GetDeviceResource(ctx context.Context, id string) (*types.DeviceV1, error) { 781 dev, err := c.DevicesClient().GetDevice(ctx, &devicepb.GetDeviceRequest{ 782 DeviceId: id, 783 }) 784 if err != nil { 785 return nil, trace.Wrap(err) 786 } 787 return types.DeviceToResource(dev), nil 788 } 789 790 // UpsertDeviceResource creates or updates a device using its resource 791 // representation. 792 // Prefer using [DevicesClient] directly if you can. 793 func (c *Client) UpsertDeviceResource(ctx context.Context, res *types.DeviceV1) (*types.DeviceV1, error) { 794 dev, err := types.DeviceFromResource(res) 795 if err != nil { 796 return nil, trace.Wrap(err) 797 } 798 799 upserted, err := c.DevicesClient().UpsertDevice(ctx, &devicepb.UpsertDeviceRequest{ 800 Device: dev, 801 CreateAsResource: true, 802 }) 803 if err != nil { 804 return nil, trace.Wrap(err) 805 } 806 return types.DeviceToResource(upserted), nil 807 } 808 809 // LoginRuleClient returns an unadorned Login Rule client, using the underlying 810 // Auth gRPC connection. 811 // Clients connecting to non-Enterprise clusters, or older Teleport versions, 812 // still get a login rule client when calling this method, but all RPCs will 813 // return "not implemented" errors (as per the default gRPC behavior). 814 func (c *Client) LoginRuleClient() loginrulepb.LoginRuleServiceClient { 815 return loginrulepb.NewLoginRuleServiceClient(c.conn) 816 } 817 818 // SecReportsClient returns Security client that can be used to fetch security reports. 819 func (c *Client) SecReportsClient() *secreport.Client { 820 return secreport.NewClient(secreportsv1.NewSecReportsServiceClient(c.conn)) 821 } 822 823 // SAMLIdPClient returns an unadorned SAML IdP client, using the underlying 824 // Auth gRPC connection. 825 // Clients connecting to non-Enterprise clusters, or older Teleport versions, 826 // still get a SAML IdP client when calling this method, but all RPCs will 827 // return "not implemented" errors (as per the default gRPC behavior). 828 func (c *Client) SAMLIdPClient() samlidppb.SAMLIdPServiceClient { 829 return samlidppb.NewSAMLIdPServiceClient(c.conn) 830 } 831 832 // ExternalAuditStorageClient returns an unadorned External Audit Storage 833 // client, using the underlying Auth gRPC connection. 834 // Clients connecting to non-Enterprise clusters, or older Teleport versions, 835 // still get a external audit client when calling this method, but all RPCs will 836 // return "not implemented" errors (as per the default gRPC behavior). 837 func (c *Client) ExternalAuditStorageClient() *externalauditstorage.Client { 838 return externalauditstorage.NewClient(externalauditstoragev1.NewExternalAuditStorageServiceClient(c.conn)) 839 } 840 841 // TrustClient returns an unadorned Trust client, using the underlying 842 // Auth gRPC connection. 843 func (c *Client) TrustClient() trustpb.TrustServiceClient { 844 return trustpb.NewTrustServiceClient(c.conn) 845 } 846 847 // EmbeddingClient returns an unadorned Embedding client, using the underlying 848 // Auth gRPC connection. 849 func (c *Client) EmbeddingClient() assist.AssistEmbeddingServiceClient { 850 return assist.NewAssistEmbeddingServiceClient(c.conn) 851 } 852 853 // BotServiceClient returns an unadorned client for the bot service. 854 func (c *Client) BotServiceClient() machineidv1pb.BotServiceClient { 855 return machineidv1pb.NewBotServiceClient(c.conn) 856 } 857 858 // PresenceServiceClient returns an unadorned client for the presence service. 859 func (c *Client) PresenceServiceClient() presencepb.PresenceServiceClient { 860 return presencepb.NewPresenceServiceClient(c.conn) 861 } 862 863 // WorkloadIdentityServiceClient returns an unadorned client for the workload 864 // identity service. 865 func (c *Client) WorkloadIdentityServiceClient() machineidv1pb.WorkloadIdentityServiceClient { 866 return machineidv1pb.NewWorkloadIdentityServiceClient(c.conn) 867 } 868 869 // Ping gets basic info about the auth server. 870 func (c *Client) Ping(ctx context.Context) (proto.PingResponse, error) { 871 rsp, err := c.grpc.Ping(ctx, &proto.PingRequest{}) 872 if err != nil { 873 return proto.PingResponse{}, trace.Wrap(err) 874 } 875 876 return *rsp, nil 877 } 878 879 // CreateUser creates a new user from the specified descriptor. 880 func (c *Client) CreateUser(ctx context.Context, user types.User) (types.User, error) { 881 userV2, ok := user.(*types.UserV2) 882 if !ok { 883 return nil, trace.BadParameter("unsupported user type %T", user) 884 } 885 886 resp, err := userspb.NewUsersServiceClient(c.conn).CreateUser(ctx, &userspb.CreateUserRequest{User: userV2}) 887 if err != nil { 888 // TODO(tross): DELETE IN 16.0.0 889 if trace.IsNotImplemented(err) { 890 //nolint:staticcheck // SA1019. Kept for backward compatibility. 891 if _, err := c.grpc.CreateUser(ctx, userV2); err != nil { 892 return nil, trace.Wrap(err) 893 } 894 895 //nolint:staticcheck // SA1019. Kept for backward compatibility. 896 created, err := c.grpc.GetUser(ctx, &proto.GetUserRequest{Name: user.GetName()}) 897 return created, trace.Wrap(err) 898 } 899 900 return nil, trace.Wrap(err) 901 } 902 903 return resp.User, trace.Wrap(err) 904 } 905 906 // UpsertUser creates a new user or updates an existing user. 907 func (c *Client) UpsertUser(ctx context.Context, user types.User) (types.User, error) { 908 userV2, ok := user.(*types.UserV2) 909 if !ok { 910 return nil, trace.BadParameter("unsupported user type %T", user) 911 } 912 913 resp, err := userspb.NewUsersServiceClient(c.conn).UpsertUser(ctx, &userspb.UpsertUserRequest{User: userV2}) 914 if err != nil { 915 return nil, trace.Wrap(err) 916 } 917 918 return resp.User, trace.Wrap(err) 919 } 920 921 // UpdateUser updates an existing user in a backend. 922 func (c *Client) UpdateUser(ctx context.Context, user types.User) (types.User, error) { 923 userV2, ok := user.(*types.UserV2) 924 if !ok { 925 return nil, trace.BadParameter("unsupported user type %T", user) 926 } 927 928 resp, err := userspb.NewUsersServiceClient(c.conn).UpdateUser(ctx, &userspb.UpdateUserRequest{User: userV2}) 929 if err != nil { 930 // TODO(tross): DELETE IN 16.0.0 931 if trace.IsNotImplemented(err) { 932 //nolint:staticcheck // SA1019. Kept for backward compatibility. 933 if _, err := c.grpc.UpdateUser(ctx, userV2); err != nil { 934 return nil, trace.Wrap(err) 935 } 936 937 //nolint:staticcheck // SA1019. Kept for backward compatibility. 938 updated, err := c.grpc.GetUser(ctx, &proto.GetUserRequest{Name: user.GetName()}) 939 return updated, trace.Wrap(err) 940 } 941 942 return nil, trace.Wrap(err) 943 } 944 945 return resp.User, trace.Wrap(err) 946 } 947 948 // GetUser returns a list of usernames registered in the system. 949 // withSecrets controls whether authentication details are returned. 950 func (c *Client) GetUser(ctx context.Context, name string, withSecrets bool) (types.User, error) { 951 if name == "" { 952 return nil, trace.BadParameter("missing username") 953 } 954 resp, err := userspb.NewUsersServiceClient(c.conn).GetUser(ctx, &userspb.GetUserRequest{Name: name, WithSecrets: withSecrets}) 955 if err != nil { 956 // TODO(tross): DELETE IN 16.0.0 957 if trace.IsNotImplemented(err) { 958 //nolint:staticcheck // SA1019. Kept for backward compatibility. 959 user, err := c.grpc.GetUser(ctx, &proto.GetUserRequest{ 960 Name: name, 961 WithSecrets: withSecrets, 962 }) 963 return user, trace.Wrap(err) 964 } 965 966 return nil, trace.Wrap(err) 967 } 968 return resp.User, nil 969 } 970 971 // GetCurrentUser returns current user as seen by the server. 972 // Useful especially in the context of remote clusters which perform role and trait mapping. 973 func (c *Client) GetCurrentUser(ctx context.Context) (types.User, error) { 974 resp, err := userspb.NewUsersServiceClient(c.conn).GetUser(ctx, &userspb.GetUserRequest{CurrentUser: true}) 975 if err != nil { 976 // TODO(tross): DELETE IN 16.0.0 977 if trace.IsNotImplemented(err) { 978 //nolint:staticcheck // SA1019. Kept for backward compatibility. 979 currentUser, err := c.grpc.GetCurrentUser(ctx, &emptypb.Empty{}) 980 return currentUser, trace.Wrap(err) 981 } 982 return nil, trace.Wrap(err) 983 } 984 return resp.User, nil 985 } 986 987 // GetCurrentUserRoles returns current user's roles. 988 func (c *Client) GetCurrentUserRoles(ctx context.Context) ([]types.Role, error) { 989 stream, err := c.grpc.GetCurrentUserRoles(ctx, &emptypb.Empty{}) 990 if err != nil { 991 return nil, trace.Wrap(err) 992 } 993 var roles []types.Role 994 for role, err := stream.Recv(); !errors.Is(err, io.EOF); role, err = stream.Recv() { 995 if err != nil { 996 return nil, trace.Wrap(err) 997 } 998 roles = append(roles, role) 999 } 1000 return roles, nil 1001 } 1002 1003 // GetUsers returns all currently registered users. 1004 // withSecrets controls whether authentication details are returned. 1005 func (c *Client) GetUsers(ctx context.Context, withSecrets bool) ([]types.User, error) { 1006 req := userspb.ListUsersRequest{ 1007 WithSecrets: withSecrets, 1008 } 1009 1010 var out []types.User 1011 for { 1012 rsp, err := c.ListUsers(ctx, &req) 1013 if err != nil { 1014 // TODO(tross): DELETE IN 16.0.0 1015 if trace.IsNotImplemented(err) { 1016 return c.getUsersCompat(ctx, withSecrets) 1017 } 1018 1019 return nil, trace.Wrap(err) 1020 } 1021 1022 for _, user := range rsp.Users { 1023 out = append(out, user) 1024 } 1025 1026 req.PageToken = rsp.NextPageToken 1027 if req.PageToken == "" { 1028 break 1029 } 1030 } 1031 1032 return out, nil 1033 } 1034 1035 // getUsersCompat is a fallback used to load users when talking to older auth servers that 1036 // don't implement the newer ListUsers method. 1037 func (c *Client) getUsersCompat(ctx context.Context, withSecrets bool) ([]types.User, error) { 1038 //nolint:staticcheck // SA1019. Kept for backward compatibility. 1039 stream, err := c.grpc.GetUsers(ctx, &proto.GetUsersRequest{ 1040 WithSecrets: withSecrets, 1041 }) 1042 if err != nil { 1043 return nil, trace.Wrap(err) 1044 } 1045 var users []types.User 1046 for user, err := stream.Recv(); !errors.Is(err, io.EOF); user, err = stream.Recv() { 1047 if err != nil { 1048 return nil, trace.Wrap(err) 1049 } 1050 users = append(users, user) 1051 } 1052 return users, nil 1053 } 1054 1055 // ListUsers returns a page of users. 1056 func (c *Client) ListUsers(ctx context.Context, req *userspb.ListUsersRequest) (*userspb.ListUsersResponse, error) { 1057 var header gmetadata.MD 1058 1059 rsp, err := userspb.NewUsersServiceClient(c.conn).ListUsers(ctx, req, grpc.Header(&header)) 1060 if err != nil { 1061 return nil, trace.Wrap(err) 1062 } 1063 1064 if req.Filter == nil { 1065 // remaining logic is all filter compat that we can skip 1066 return rsp, nil 1067 } 1068 1069 vs, _ := metadata.VersionFromMetadata(header) 1070 ver, _ := semver.NewVersion(vs) 1071 if ver != nil && ver.Major >= 16 { 1072 // auth implements all expected filtering features 1073 return rsp, nil 1074 } 1075 1076 filtered := rsp.Users[:0] 1077 for _, user := range rsp.Users { 1078 if req.Filter.Match(user) { 1079 filtered = append(filtered, user) 1080 } 1081 } 1082 rsp.Users = filtered 1083 return rsp, nil 1084 } 1085 1086 // DeleteUser deletes a user by name. 1087 func (c *Client) DeleteUser(ctx context.Context, user string) error { 1088 _, err := userspb.NewUsersServiceClient(c.conn).DeleteUser(ctx, &userspb.DeleteUserRequest{Name: user}) 1089 // TODO(tross): DELETE IN 16.0.0 1090 if trace.IsNotImplemented(err) { 1091 //nolint:staticcheck // SA1019. Kept for backward compatibility. 1092 _, err := c.grpc.DeleteUser(ctx, &proto.DeleteUserRequest{Name: user}) 1093 return trace.Wrap(err) 1094 } 1095 1096 return trace.Wrap(err) 1097 } 1098 1099 // GenerateUserCerts takes the public key in the OpenSSH `authorized_keys` plain 1100 // text format, signs it using User Certificate Authority signing key and 1101 // returns the resulting certificates. 1102 func (c *Client) GenerateUserCerts(ctx context.Context, req proto.UserCertsRequest) (*proto.Certs, error) { 1103 certs, err := c.grpc.GenerateUserCerts(ctx, &req) 1104 if err != nil { 1105 return nil, trace.Wrap(err) 1106 } 1107 return certs, nil 1108 } 1109 1110 // GenerateHostCerts generates host certificates. 1111 func (c *Client) GenerateHostCerts(ctx context.Context, req *proto.HostCertsRequest) (*proto.Certs, error) { 1112 if err := req.CheckAndSetDefaults(); err != nil { 1113 return nil, trace.Wrap(err) 1114 } 1115 certs, err := c.grpc.GenerateHostCerts(ctx, req) 1116 if err != nil { 1117 return nil, trace.Wrap(err) 1118 } 1119 return certs, nil 1120 } 1121 1122 // GenerateOpenSSHCert signs a SSH certificate that can be used 1123 // to connect to Agentless nodes. 1124 func (c *Client) GenerateOpenSSHCert(ctx context.Context, req *proto.OpenSSHCertRequest) (*proto.OpenSSHCert, error) { 1125 cert, err := c.grpc.GenerateOpenSSHCert(ctx, req) 1126 if err != nil { 1127 return nil, trace.Wrap(err) 1128 } 1129 return cert, nil 1130 } 1131 1132 // EmitAuditEvent sends an auditable event to the auth server. 1133 func (c *Client) EmitAuditEvent(ctx context.Context, event events.AuditEvent) error { 1134 grpcEvent, err := events.ToOneOf(event) 1135 if err != nil { 1136 return trace.Wrap(err) 1137 } 1138 _, err = c.grpc.EmitAuditEvent(context.WithoutCancel(ctx), grpcEvent) 1139 if err != nil { 1140 return trace.Wrap(err) 1141 } 1142 return nil 1143 } 1144 1145 // GetResetPasswordToken returns a reset password token for the specified tokenID. 1146 func (c *Client) GetResetPasswordToken(ctx context.Context, tokenID string) (types.UserToken, error) { 1147 token, err := c.grpc.GetResetPasswordToken(ctx, &proto.GetResetPasswordTokenRequest{ 1148 TokenID: tokenID, 1149 }) 1150 if err != nil { 1151 return nil, trace.Wrap(err) 1152 } 1153 1154 return token, nil 1155 } 1156 1157 // CreateResetPasswordToken creates reset password token. 1158 func (c *Client) CreateResetPasswordToken(ctx context.Context, req *proto.CreateResetPasswordTokenRequest) (types.UserToken, error) { 1159 token, err := c.grpc.CreateResetPasswordToken(ctx, req) 1160 if err != nil { 1161 return nil, trace.Wrap(err) 1162 } 1163 1164 return token, nil 1165 } 1166 1167 // GetAccessRequests retrieves a list of all access requests matching the provided filter. 1168 func (c *Client) GetAccessRequests(ctx context.Context, filter types.AccessRequestFilter) ([]types.AccessRequest, error) { 1169 requests, err := c.ListAllAccessRequests(ctx, &proto.ListAccessRequestsRequest{ 1170 Filter: &filter, 1171 }) 1172 if err != nil { 1173 return nil, trace.Wrap(err) 1174 } 1175 1176 ireqs := make([]types.AccessRequest, 0, len(requests)) 1177 for _, r := range requests { 1178 ireqs = append(ireqs, r) 1179 } 1180 1181 return ireqs, nil 1182 } 1183 1184 // ListAccessRequests is an access request getter with pagination and sorting options. 1185 func (c *Client) ListAccessRequests(ctx context.Context, req *proto.ListAccessRequestsRequest) (*proto.ListAccessRequestsResponse, error) { 1186 rsp, err := c.grpc.ListAccessRequests(ctx, req) 1187 return rsp, trace.Wrap(err) 1188 } 1189 1190 // ListAllAccessRequests aggregates all access requests via the ListAccessRequests api. This is equivalent to calling GetAccessRequests 1191 // except that it supports custom sort order/indexes. Calling this method rather than ListAccessRequests also provides the advantage 1192 // that it can fallback to calling the old GetAccessRequests grpc method if it encounters and outdated control plane. For that reason, 1193 // implementations that don't actually *need* pagination are better served by calling this method. 1194 func (c *Client) ListAllAccessRequests(ctx context.Context, req *proto.ListAccessRequestsRequest) ([]*types.AccessRequestV3, error) { 1195 var requests []*types.AccessRequestV3 1196 for { 1197 rsp, err := c.ListAccessRequests(ctx, req) 1198 if err != nil { 1199 if trace.IsNotImplemented(err) { 1200 return c.listAllAccessRequestsCompat(ctx, req) 1201 } 1202 1203 return nil, trace.Wrap(err) 1204 } 1205 1206 requests = append(requests, rsp.AccessRequests...) 1207 1208 req.StartKey = rsp.NextKey 1209 if req.StartKey == "" { 1210 break 1211 } 1212 } 1213 1214 return requests, nil 1215 } 1216 1217 // listAllAccessRequestsCompat is a helper that simulates ListAllAccessRequests behavior via the old GetAccessRequests method. 1218 func (c *Client) listAllAccessRequestsCompat(ctx context.Context, req *proto.ListAccessRequestsRequest) ([]*types.AccessRequestV3, error) { 1219 var filter types.AccessRequestFilter 1220 if req.Filter != nil { 1221 filter = *req.Filter 1222 } 1223 requests, err := c.getAccessRequests(ctx, filter) 1224 if err != nil { 1225 return nil, trace.Wrap(err) 1226 } 1227 1228 switch req.Sort { 1229 case proto.AccessRequestSort_DEFAULT: 1230 // no custom sort order needed 1231 case proto.AccessRequestSort_CREATED: 1232 slices.SortFunc(requests, func(a, b *types.AccessRequestV3) int { 1233 return a.GetCreationTime().Compare(b.GetCreationTime()) 1234 }) 1235 case proto.AccessRequestSort_STATE: 1236 slices.SortFunc(requests, func(a, b *types.AccessRequestV3) int { 1237 return cmp.Compare(a.GetState().String(), b.GetState().String()) 1238 }) 1239 default: 1240 return nil, trace.BadParameter("list access request compat fallback does not support sort order %q", req.Sort) 1241 } 1242 1243 if req.Descending { 1244 slices.Reverse(requests) 1245 } 1246 1247 return requests, nil 1248 } 1249 1250 // getAccessRequests calls the old GetAccessRequests method. used by back-compat logic when interacting with 1251 // an outdated control-plane that doesn't support ListAccessRequests. 1252 func (c *Client) getAccessRequests(ctx context.Context, filter types.AccessRequestFilter) ([]*types.AccessRequestV3, error) { 1253 stream, err := c.grpc.GetAccessRequestsV2(ctx, &filter) 1254 if err != nil { 1255 return nil, trace.Wrap(err) 1256 } 1257 1258 var reqs []*types.AccessRequestV3 1259 for { 1260 req, err := stream.Recv() 1261 if errors.Is(err, io.EOF) { 1262 break 1263 } 1264 1265 if err != nil { 1266 return nil, trace.Wrap(err) 1267 } 1268 reqs = append(reqs, req) 1269 } 1270 1271 return reqs, nil 1272 } 1273 1274 // CreateAccessRequestV2 registers a new access request with the auth server. 1275 func (c *Client) CreateAccessRequestV2(ctx context.Context, req types.AccessRequest) (types.AccessRequest, error) { 1276 r, ok := req.(*types.AccessRequestV3) 1277 if !ok { 1278 return nil, trace.BadParameter("unexpected access request type %T", req) 1279 } 1280 resp, err := c.grpc.CreateAccessRequestV2(ctx, r) 1281 return resp, trace.Wrap(err) 1282 } 1283 1284 // DeleteAccessRequest deletes an access request. 1285 func (c *Client) DeleteAccessRequest(ctx context.Context, reqID string) error { 1286 _, err := c.grpc.DeleteAccessRequest(ctx, &proto.RequestID{ID: reqID}) 1287 return trace.Wrap(err) 1288 } 1289 1290 // GetAccessRequestAllowedPromotions returns the list of promotions allowed for the given access request. 1291 func (c *Client) GetAccessRequestAllowedPromotions(ctx context.Context, req types.AccessRequest) (*types.AccessRequestAllowedPromotions, error) { 1292 resp, err := c.grpc.GetAccessRequestAllowedPromotions(ctx, &proto.AccessRequestAllowedPromotionRequest{ 1293 AccessRequestID: req.GetName(), 1294 }) 1295 if err != nil { 1296 return nil, trace.Wrap(err) 1297 } 1298 return resp.AllowedPromotions, nil 1299 } 1300 1301 // SetAccessRequestState updates the state of an existing access request. 1302 func (c *Client) SetAccessRequestState(ctx context.Context, params types.AccessRequestUpdate) error { 1303 setter := proto.RequestStateSetter{ 1304 ID: params.RequestID, 1305 State: params.State, 1306 Reason: params.Reason, 1307 Annotations: params.Annotations, 1308 Roles: params.Roles, 1309 AssumeStartTime: params.AssumeStartTime, 1310 } 1311 if d := utils.GetDelegator(ctx); d != "" { 1312 setter.Delegator = d 1313 } 1314 _, err := c.grpc.SetAccessRequestState(ctx, &setter) 1315 return trace.Wrap(err) 1316 } 1317 1318 // SubmitAccessReview applies a review to a request and returns the post-application state. 1319 func (c *Client) SubmitAccessReview(ctx context.Context, params types.AccessReviewSubmission) (types.AccessRequest, error) { 1320 req, err := c.grpc.SubmitAccessReview(ctx, ¶ms) 1321 if err != nil { 1322 return nil, trace.Wrap(err) 1323 } 1324 return req, nil 1325 } 1326 1327 // GetAccessCapabilities requests the access capabilities of a user. 1328 func (c *Client) GetAccessCapabilities(ctx context.Context, req types.AccessCapabilitiesRequest) (*types.AccessCapabilities, error) { 1329 caps, err := c.grpc.GetAccessCapabilities(ctx, &req) 1330 if err != nil { 1331 return nil, trace.Wrap(err) 1332 } 1333 return caps, nil 1334 } 1335 1336 // GetPluginData loads all plugin data matching the supplied filter. 1337 func (c *Client) GetPluginData(ctx context.Context, filter types.PluginDataFilter) ([]types.PluginData, error) { 1338 seq, err := c.grpc.GetPluginData(ctx, &filter) 1339 if err != nil { 1340 return nil, trace.Wrap(err) 1341 } 1342 data := make([]types.PluginData, 0, len(seq.PluginData)) 1343 for _, d := range seq.PluginData { 1344 data = append(data, d) 1345 } 1346 return data, nil 1347 } 1348 1349 // UpdatePluginData updates a per-resource PluginData entry. 1350 func (c *Client) UpdatePluginData(ctx context.Context, params types.PluginDataUpdateParams) error { 1351 _, err := c.grpc.UpdatePluginData(ctx, ¶ms) 1352 return trace.Wrap(err) 1353 } 1354 1355 // AcquireSemaphore acquires lease with requested resources from semaphore. 1356 func (c *Client) AcquireSemaphore(ctx context.Context, params types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) { 1357 lease, err := c.grpc.AcquireSemaphore(ctx, ¶ms) 1358 if err != nil { 1359 return nil, trace.Wrap(err) 1360 } 1361 return lease, nil 1362 } 1363 1364 // KeepAliveSemaphoreLease updates semaphore lease. 1365 func (c *Client) KeepAliveSemaphoreLease(ctx context.Context, lease types.SemaphoreLease) error { 1366 _, err := c.grpc.KeepAliveSemaphoreLease(ctx, &lease) 1367 return trace.Wrap(err) 1368 } 1369 1370 // CancelSemaphoreLease cancels semaphore lease early. 1371 func (c *Client) CancelSemaphoreLease(ctx context.Context, lease types.SemaphoreLease) error { 1372 _, err := c.grpc.CancelSemaphoreLease(ctx, &lease) 1373 return trace.Wrap(err) 1374 } 1375 1376 // GetSemaphores returns a list of all semaphores matching the supplied filter. 1377 func (c *Client) GetSemaphores(ctx context.Context, filter types.SemaphoreFilter) ([]types.Semaphore, error) { 1378 rsp, err := c.grpc.GetSemaphores(ctx, &filter) 1379 if err != nil { 1380 return nil, trace.Wrap(err) 1381 } 1382 sems := make([]types.Semaphore, 0, len(rsp.Semaphores)) 1383 for _, s := range rsp.Semaphores { 1384 sems = append(sems, s) 1385 } 1386 return sems, nil 1387 } 1388 1389 // DeleteSemaphore deletes a semaphore matching the supplied filter. 1390 func (c *Client) DeleteSemaphore(ctx context.Context, filter types.SemaphoreFilter) error { 1391 _, err := c.grpc.DeleteSemaphore(ctx, &filter) 1392 return trace.Wrap(err) 1393 } 1394 1395 // GetKubernetesServers returns the list of kubernetes servers registered in the 1396 // cluster. 1397 func (c *Client) GetKubernetesServers(ctx context.Context) ([]types.KubeServer, error) { 1398 servers, err := GetAllResources[types.KubeServer](ctx, c, &proto.ListResourcesRequest{ 1399 Namespace: defaults.Namespace, 1400 ResourceType: types.KindKubeServer, 1401 }) 1402 return servers, trace.Wrap(err) 1403 } 1404 1405 // DeleteKubernetesServer deletes a named kubernetes server. 1406 func (c *Client) DeleteKubernetesServer(ctx context.Context, hostID, name string) error { 1407 _, err := c.grpc.DeleteKubernetesServer(ctx, &proto.DeleteKubernetesServerRequest{ 1408 HostID: hostID, 1409 Name: name, 1410 }) 1411 return trace.Wrap(err) 1412 } 1413 1414 // DeleteAllKubernetesServers deletes all registered kubernetes servers. 1415 func (c *Client) DeleteAllKubernetesServers(ctx context.Context) error { 1416 _, err := c.grpc.DeleteAllKubernetesServers(ctx, &proto.DeleteAllKubernetesServersRequest{}) 1417 return trace.Wrap(err) 1418 } 1419 1420 // UpsertKubernetesServer is used by kubernetes services to report their presence 1421 // to other auth servers in form of heartbeat expiring after ttl period. 1422 func (c *Client) UpsertKubernetesServer(ctx context.Context, s types.KubeServer) (*types.KeepAlive, error) { 1423 server, ok := s.(*types.KubernetesServerV3) 1424 if !ok { 1425 return nil, trace.BadParameter("invalid type %T, expected *types.KubernetesServerV3", server) 1426 } 1427 keepAlive, err := c.grpc.UpsertKubernetesServer(ctx, &proto.UpsertKubernetesServerRequest{Server: server}) 1428 if err != nil { 1429 return nil, trace.Wrap(err) 1430 } 1431 return keepAlive, nil 1432 } 1433 1434 // GetApplicationServers returns all registered application servers. 1435 func (c *Client) GetApplicationServers(ctx context.Context, namespace string) ([]types.AppServer, error) { 1436 servers, err := GetAllResources[types.AppServer](ctx, c, &proto.ListResourcesRequest{ 1437 Namespace: namespace, 1438 ResourceType: types.KindAppServer, 1439 }) 1440 return servers, trace.Wrap(err) 1441 } 1442 1443 // UpsertApplicationServer registers an application server. 1444 func (c *Client) UpsertApplicationServer(ctx context.Context, server types.AppServer) (*types.KeepAlive, error) { 1445 s, ok := server.(*types.AppServerV3) 1446 if !ok { 1447 return nil, trace.BadParameter("invalid type %T", server) 1448 } 1449 keepAlive, err := c.grpc.UpsertApplicationServer(ctx, &proto.UpsertApplicationServerRequest{ 1450 Server: s, 1451 }) 1452 if err != nil { 1453 return nil, trace.Wrap(err) 1454 } 1455 return keepAlive, nil 1456 } 1457 1458 // DeleteApplicationServer removes specified application server. 1459 func (c *Client) DeleteApplicationServer(ctx context.Context, namespace, hostID, name string) error { 1460 _, err := c.grpc.DeleteApplicationServer(ctx, &proto.DeleteApplicationServerRequest{ 1461 Namespace: namespace, 1462 HostID: hostID, 1463 Name: name, 1464 }) 1465 return trace.Wrap(err) 1466 } 1467 1468 // DeleteAllApplicationServers removes all registered application servers. 1469 func (c *Client) DeleteAllApplicationServers(ctx context.Context, namespace string) error { 1470 _, err := c.grpc.DeleteAllApplicationServers(ctx, &proto.DeleteAllApplicationServersRequest{ 1471 Namespace: namespace, 1472 }) 1473 return trace.Wrap(err) 1474 } 1475 1476 // GetAppSession gets an application web session. 1477 func (c *Client) GetAppSession(ctx context.Context, req types.GetAppSessionRequest) (types.WebSession, error) { 1478 resp, err := c.grpc.GetAppSession(ctx, &proto.GetAppSessionRequest{ 1479 SessionID: req.SessionID, 1480 }) 1481 if err != nil { 1482 return nil, trace.Wrap(err) 1483 } 1484 1485 return resp.GetSession(), nil 1486 } 1487 1488 // ListAppSessions gets a paginated list of application web sessions. 1489 func (c *Client) ListAppSessions(ctx context.Context, pageSize int, pageToken, user string) ([]types.WebSession, string, error) { 1490 resp, err := c.grpc.ListAppSessions( 1491 ctx, 1492 &proto.ListAppSessionsRequest{ 1493 PageSize: int32(pageSize), 1494 PageToken: pageToken, 1495 User: user, 1496 }) 1497 if err != nil { 1498 return nil, "", trace.Wrap(err) 1499 } 1500 1501 out := make([]types.WebSession, 0, len(resp.GetSessions())) 1502 for _, v := range resp.GetSessions() { 1503 out = append(out, v) 1504 } 1505 return out, resp.NextPageToken, nil 1506 } 1507 1508 // GetSnowflakeSessions gets all Snowflake web sessions. 1509 func (c *Client) GetSnowflakeSessions(ctx context.Context) ([]types.WebSession, error) { 1510 resp, err := c.grpc.GetSnowflakeSessions(ctx, &emptypb.Empty{}) 1511 if err != nil { 1512 return nil, trace.Wrap(err) 1513 } 1514 1515 out := make([]types.WebSession, 0, len(resp.GetSessions())) 1516 for _, v := range resp.GetSessions() { 1517 out = append(out, v) 1518 } 1519 return out, nil 1520 } 1521 1522 // ListSAMLIdPSessions gets a paginated list of SAML IdP sessions. 1523 func (c *Client) ListSAMLIdPSessions(ctx context.Context, pageSize int, pageToken, user string) ([]types.WebSession, string, error) { 1524 resp, err := c.grpc.ListSAMLIdPSessions( 1525 ctx, 1526 &proto.ListSAMLIdPSessionsRequest{ 1527 PageSize: int32(pageSize), 1528 PageToken: pageToken, 1529 User: user, 1530 }) 1531 if err != nil { 1532 return nil, "", trace.Wrap(err) 1533 } 1534 1535 out := make([]types.WebSession, 0, len(resp.GetSessions())) 1536 for _, v := range resp.GetSessions() { 1537 out = append(out, v) 1538 } 1539 return out, resp.NextPageToken, nil 1540 } 1541 1542 // CreateAppSession creates an application web session. Application web 1543 // sessions represent a browser session the client holds. 1544 func (c *Client) CreateAppSession(ctx context.Context, req *proto.CreateAppSessionRequest) (types.WebSession, error) { 1545 resp, err := c.grpc.CreateAppSession(ctx, req) 1546 if err != nil { 1547 return nil, trace.Wrap(err) 1548 } 1549 1550 return resp.GetSession(), nil 1551 } 1552 1553 // CreateSnowflakeSession creates a Snowflake web session. 1554 func (c *Client) CreateSnowflakeSession(ctx context.Context, req types.CreateSnowflakeSessionRequest) (types.WebSession, error) { 1555 resp, err := c.grpc.CreateSnowflakeSession(ctx, &proto.CreateSnowflakeSessionRequest{ 1556 Username: req.Username, 1557 SessionToken: req.SessionToken, 1558 TokenTTL: proto.Duration(req.TokenTTL), 1559 }) 1560 if err != nil { 1561 return nil, trace.Wrap(err) 1562 } 1563 1564 return resp.GetSession(), nil 1565 } 1566 1567 // CreateSAMLIdPSession creates a SAML IdP session. 1568 func (c *Client) CreateSAMLIdPSession(ctx context.Context, req types.CreateSAMLIdPSessionRequest) (types.WebSession, error) { 1569 resp, err := c.grpc.CreateSAMLIdPSession(ctx, &proto.CreateSAMLIdPSessionRequest{ 1570 SessionID: req.SessionID, 1571 Username: req.Username, 1572 SAMLSession: req.SAMLSession, 1573 }) 1574 if err != nil { 1575 return nil, trace.Wrap(err) 1576 } 1577 1578 return resp.GetSession(), nil 1579 } 1580 1581 // GetSnowflakeSession gets a Snowflake web session. 1582 func (c *Client) GetSnowflakeSession(ctx context.Context, req types.GetSnowflakeSessionRequest) (types.WebSession, error) { 1583 resp, err := c.grpc.GetSnowflakeSession(ctx, &proto.GetSnowflakeSessionRequest{ 1584 SessionID: req.SessionID, 1585 }) 1586 if err != nil { 1587 return nil, trace.Wrap(err) 1588 } 1589 1590 return resp.GetSession(), nil 1591 } 1592 1593 // GetSAMLIdPSession gets a SAML IdP session. 1594 func (c *Client) GetSAMLIdPSession(ctx context.Context, req types.GetSAMLIdPSessionRequest) (types.WebSession, error) { 1595 resp, err := c.grpc.GetSAMLIdPSession(ctx, &proto.GetSAMLIdPSessionRequest{ 1596 SessionID: req.SessionID, 1597 }) 1598 if err != nil { 1599 return nil, trace.Wrap(err) 1600 } 1601 1602 return resp.GetSession(), nil 1603 } 1604 1605 // DeleteAppSession removes an application web session. 1606 func (c *Client) DeleteAppSession(ctx context.Context, req types.DeleteAppSessionRequest) error { 1607 _, err := c.grpc.DeleteAppSession(ctx, &proto.DeleteAppSessionRequest{ 1608 SessionID: req.SessionID, 1609 }) 1610 return trace.Wrap(err) 1611 } 1612 1613 // DeleteSnowflakeSession removes a Snowflake web session. 1614 func (c *Client) DeleteSnowflakeSession(ctx context.Context, req types.DeleteSnowflakeSessionRequest) error { 1615 _, err := c.grpc.DeleteSnowflakeSession(ctx, &proto.DeleteSnowflakeSessionRequest{ 1616 SessionID: req.SessionID, 1617 }) 1618 return trace.Wrap(err) 1619 } 1620 1621 // DeleteSAMLIdPSession removes a SAML IdP session. 1622 func (c *Client) DeleteSAMLIdPSession(ctx context.Context, req types.DeleteSAMLIdPSessionRequest) error { 1623 _, err := c.grpc.DeleteSAMLIdPSession(ctx, &proto.DeleteSAMLIdPSessionRequest{ 1624 SessionID: req.SessionID, 1625 }) 1626 return trace.Wrap(err) 1627 } 1628 1629 // DeleteAllAppSessions removes all application web sessions. 1630 func (c *Client) DeleteAllAppSessions(ctx context.Context) error { 1631 _, err := c.grpc.DeleteAllAppSessions(ctx, &emptypb.Empty{}) 1632 return trace.Wrap(err) 1633 } 1634 1635 // DeleteAllSnowflakeSessions removes all Snowflake web sessions. 1636 func (c *Client) DeleteAllSnowflakeSessions(ctx context.Context) error { 1637 _, err := c.grpc.DeleteAllSnowflakeSessions(ctx, &emptypb.Empty{}) 1638 return trace.Wrap(err) 1639 } 1640 1641 // DeleteAllSAMLIdPSessions removes all SAML IdP sessions. 1642 func (c *Client) DeleteAllSAMLIdPSessions(ctx context.Context) error { 1643 _, err := c.grpc.DeleteAllSAMLIdPSessions(ctx, &emptypb.Empty{}) 1644 return trace.Wrap(err) 1645 } 1646 1647 // DeleteUserAppSessions deletes all user’s application sessions. 1648 func (c *Client) DeleteUserAppSessions(ctx context.Context, req *proto.DeleteUserAppSessionsRequest) error { 1649 _, err := c.grpc.DeleteUserAppSessions(ctx, req) 1650 return trace.Wrap(err) 1651 } 1652 1653 // DeleteUserSAMLIdPSessions deletes all user’s SAML IdP sessions. 1654 func (c *Client) DeleteUserSAMLIdPSessions(ctx context.Context, username string) error { 1655 req := &proto.DeleteUserSAMLIdPSessionsRequest{ 1656 Username: username, 1657 } 1658 _, err := c.grpc.DeleteUserSAMLIdPSessions(ctx, req) 1659 return trace.Wrap(err) 1660 } 1661 1662 // GenerateAppToken creates a JWT token with application access. 1663 func (c *Client) GenerateAppToken(ctx context.Context, req types.GenerateAppTokenRequest) (string, error) { 1664 traits := map[string]*wrappers.StringValues{} 1665 for traitName, traitValues := range req.Traits { 1666 traits[traitName] = &wrappers.StringValues{ 1667 Values: traitValues, 1668 } 1669 } 1670 resp, err := c.grpc.GenerateAppToken(ctx, &proto.GenerateAppTokenRequest{ 1671 Username: req.Username, 1672 Roles: req.Roles, 1673 Traits: traits, 1674 URI: req.URI, 1675 Expires: req.Expires, 1676 }) 1677 if err != nil { 1678 return "", trace.Wrap(err) 1679 } 1680 1681 return resp.GetToken(), nil 1682 } 1683 1684 // GenerateSnowflakeJWT generates JWT in the Snowflake required format. 1685 func (c *Client) GenerateSnowflakeJWT(ctx context.Context, req types.GenerateSnowflakeJWT) (string, error) { 1686 resp, err := c.grpc.GenerateSnowflakeJWT(ctx, &proto.SnowflakeJWTRequest{ 1687 UserName: req.Username, 1688 AccountName: req.Account, 1689 }) 1690 if err != nil { 1691 return "", trace.Wrap(err) 1692 } 1693 1694 return resp.GetToken(), nil 1695 } 1696 1697 // GetDatabaseServers returns all registered database proxy servers. 1698 // 1699 // Note that in HA setups, a registered database may have multiple 1700 // DatabaseServer entries. Web UI and `tsh db ls` extract databases from this 1701 // list and remove duplicates by name. 1702 func (c *Client) GetDatabaseServers(ctx context.Context, namespace string) ([]types.DatabaseServer, error) { 1703 servers, err := GetAllResources[types.DatabaseServer](ctx, c, &proto.ListResourcesRequest{ 1704 Namespace: namespace, 1705 ResourceType: types.KindDatabaseServer, 1706 }) 1707 return servers, trace.Wrap(err) 1708 } 1709 1710 // UpsertDatabaseServer registers a new database proxy server. 1711 func (c *Client) UpsertDatabaseServer(ctx context.Context, server types.DatabaseServer) (*types.KeepAlive, error) { 1712 s, ok := server.(*types.DatabaseServerV3) 1713 if !ok { 1714 return nil, trace.BadParameter("invalid type %T", server) 1715 } 1716 keepAlive, err := c.grpc.UpsertDatabaseServer(ctx, &proto.UpsertDatabaseServerRequest{ 1717 Server: s, 1718 }) 1719 if err != nil { 1720 return nil, trace.Wrap(err) 1721 } 1722 return keepAlive, nil 1723 } 1724 1725 // DeleteDatabaseServer removes the specified database proxy server. 1726 func (c *Client) DeleteDatabaseServer(ctx context.Context, namespace, hostID, name string) error { 1727 _, err := c.grpc.DeleteDatabaseServer(ctx, &proto.DeleteDatabaseServerRequest{ 1728 Namespace: namespace, 1729 HostID: hostID, 1730 Name: name, 1731 }) 1732 if err != nil { 1733 return trace.Wrap(err) 1734 } 1735 return nil 1736 } 1737 1738 // DeleteAllDatabaseServers removes all registered database proxy servers. 1739 func (c *Client) DeleteAllDatabaseServers(ctx context.Context, namespace string) error { 1740 _, err := c.grpc.DeleteAllDatabaseServers(ctx, &proto.DeleteAllDatabaseServersRequest{ 1741 Namespace: namespace, 1742 }) 1743 if err != nil { 1744 return trace.Wrap(err) 1745 } 1746 return nil 1747 } 1748 1749 // SignDatabaseCSR generates a client certificate used by proxy when talking 1750 // to a remote database service. 1751 func (c *Client) SignDatabaseCSR(ctx context.Context, req *proto.DatabaseCSRRequest) (*proto.DatabaseCSRResponse, error) { 1752 resp, err := c.grpc.SignDatabaseCSR(ctx, req) 1753 if err != nil { 1754 return nil, trace.Wrap(err) 1755 } 1756 return resp, nil 1757 } 1758 1759 // GenerateDatabaseCert generates a client certificate used by a database 1760 // service to authenticate with the database instance, or a server certificate 1761 // for configuring a self-hosted database, depending on the requester_name. 1762 func (c *Client) GenerateDatabaseCert(ctx context.Context, req *proto.DatabaseCertRequest) (*proto.DatabaseCertResponse, error) { 1763 resp, err := c.grpc.GenerateDatabaseCert(ctx, req) 1764 if err != nil { 1765 return nil, trace.Wrap(err) 1766 } 1767 return resp, nil 1768 } 1769 1770 // GetRole returns role by name 1771 func (c *Client) GetRole(ctx context.Context, name string) (types.Role, error) { 1772 if name == "" { 1773 return nil, trace.BadParameter("missing name") 1774 } 1775 role, err := c.grpc.GetRole(ctx, &proto.GetRoleRequest{Name: name}) 1776 if err != nil { 1777 return nil, trace.Wrap(err) 1778 } 1779 return role, nil 1780 } 1781 1782 // GetRoles returns a list of roles 1783 func (c *Client) GetRoles(ctx context.Context) ([]types.Role, error) { 1784 var roles []types.Role 1785 var req proto.ListRolesRequest 1786 for { 1787 rsp, err := c.ListRoles(ctx, &req) 1788 if err != nil { 1789 if trace.IsNotImplemented(err) { 1790 // fallback to calling the old non-paginated role API. 1791 roles, err = c.getRoles(ctx) 1792 return roles, trace.Wrap(err) 1793 } 1794 return nil, trace.Wrap(err) 1795 } 1796 1797 for _, r := range rsp.Roles { 1798 roles = append(roles, r) 1799 } 1800 req.StartKey = rsp.NextKey 1801 if req.StartKey == "" { 1802 break 1803 } 1804 } 1805 1806 return roles, nil 1807 } 1808 1809 // getRoles calls the old non-paginated GetRoles method. 1810 // 1811 // DELETE IN 17.0 1812 func (c *Client) getRoles(ctx context.Context) ([]types.Role, error) { 1813 resp, err := c.grpc.GetRoles(ctx, &emptypb.Empty{}) 1814 if err != nil { 1815 return nil, trace.Wrap(err) 1816 } 1817 roles := make([]types.Role, 0, len(resp.GetRoles())) 1818 for _, role := range resp.GetRoles() { 1819 roles = append(roles, role) 1820 } 1821 return roles, nil 1822 } 1823 1824 // ListRoles is a paginated role getter. 1825 func (c *Client) ListRoles(ctx context.Context, req *proto.ListRolesRequest) (*proto.ListRolesResponse, error) { 1826 var header gmetadata.MD 1827 rsp, err := c.grpc.ListRoles(ctx, req, grpc.Header(&header)) 1828 if err != nil { 1829 return nil, trace.Wrap(err) 1830 } 1831 1832 if req.Filter == nil { 1833 // remaining logic is all filter compat that we can skip 1834 return rsp, nil 1835 } 1836 1837 vs, _ := metadata.VersionFromMetadata(header) 1838 ver, _ := semver.NewVersion(vs) 1839 if ver != nil && ver.Major >= 16 { 1840 // auth implements all expected filtering features 1841 return rsp, nil 1842 } 1843 1844 filtered := rsp.Roles[:0] 1845 for _, role := range rsp.Roles { 1846 if req.Filter.Match(role) { 1847 filtered = append(filtered, role) 1848 } 1849 } 1850 rsp.Roles = filtered 1851 1852 return rsp, nil 1853 } 1854 1855 // CreateRole creates a new role. 1856 func (c *Client) CreateRole(ctx context.Context, role types.Role) (types.Role, error) { 1857 r, ok := role.(*types.RoleV6) 1858 if !ok { 1859 return nil, trace.BadParameter("invalid type %T", role) 1860 } 1861 1862 created, err := c.grpc.CreateRole(ctx, &proto.CreateRoleRequest{Role: r}) 1863 return created, trace.Wrap(err) 1864 } 1865 1866 // UpdateRole updates an already existing role. 1867 func (c *Client) UpdateRole(ctx context.Context, role types.Role) (types.Role, error) { 1868 r, ok := role.(*types.RoleV6) 1869 if !ok { 1870 return nil, trace.BadParameter("invalid type %T", role) 1871 } 1872 1873 updated, err := c.grpc.UpdateRole(ctx, &proto.UpdateRoleRequest{Role: r}) 1874 return updated, trace.Wrap(err) 1875 } 1876 1877 // UpsertRole creates or updates a role. 1878 func (c *Client) UpsertRole(ctx context.Context, role types.Role) (types.Role, error) { 1879 r, ok := role.(*types.RoleV6) 1880 if !ok { 1881 return nil, trace.BadParameter("invalid type %T", role) 1882 } 1883 1884 upserted, err := c.grpc.UpsertRoleV2(ctx, &proto.UpsertRoleRequest{Role: r}) 1885 if err != nil && trace.IsNotImplemented(err) { 1886 //nolint:staticcheck // SA1019. Kept for backward compatibility. 1887 _, err := c.grpc.UpsertRole(ctx, r) 1888 if err != nil { 1889 return nil, trace.Wrap(err) 1890 } 1891 1892 r, err := c.grpc.GetRole(ctx, &proto.GetRoleRequest{Name: role.GetName()}) 1893 return r, trace.Wrap(err) 1894 } 1895 1896 return upserted, trace.Wrap(err) 1897 } 1898 1899 // DeleteRole deletes role by name 1900 func (c *Client) DeleteRole(ctx context.Context, name string) error { 1901 if name == "" { 1902 return trace.BadParameter("missing name") 1903 } 1904 _, err := c.grpc.DeleteRole(ctx, &proto.DeleteRoleRequest{Name: name}) 1905 return trace.Wrap(err) 1906 } 1907 1908 // AddMFADeviceSync adds a new MFA device. 1909 func (c *Client) AddMFADeviceSync(ctx context.Context, in *proto.AddMFADeviceSyncRequest) (*proto.AddMFADeviceSyncResponse, error) { 1910 res, err := c.grpc.AddMFADeviceSync(ctx, in) 1911 return res, trace.Wrap(err) 1912 } 1913 1914 // DeleteMFADeviceSync deletes a users MFA device. 1915 func (c *Client) DeleteMFADeviceSync(ctx context.Context, in *proto.DeleteMFADeviceSyncRequest) error { 1916 _, err := c.grpc.DeleteMFADeviceSync(ctx, in) 1917 return trace.Wrap(err) 1918 } 1919 1920 func (c *Client) GetMFADevices(ctx context.Context, in *proto.GetMFADevicesRequest) (*proto.GetMFADevicesResponse, error) { 1921 resp, err := c.grpc.GetMFADevices(ctx, in) 1922 if err != nil { 1923 return nil, trace.Wrap(err) 1924 } 1925 return resp, nil 1926 } 1927 1928 func (c *Client) IsMFARequired(ctx context.Context, req *proto.IsMFARequiredRequest) (*proto.IsMFARequiredResponse, error) { 1929 resp, err := c.grpc.IsMFARequired(ctx, req) 1930 if err != nil { 1931 return nil, trace.Wrap(err) 1932 } 1933 return resp, nil 1934 } 1935 1936 // GetOIDCConnector returns an OIDC connector by name. 1937 func (c *Client) GetOIDCConnector(ctx context.Context, name string, withSecrets bool) (types.OIDCConnector, error) { 1938 if name == "" { 1939 return nil, trace.BadParameter("cannot get OIDC Connector, missing name") 1940 } 1941 req := &types.ResourceWithSecretsRequest{Name: name, WithSecrets: withSecrets} 1942 resp, err := c.grpc.GetOIDCConnector(ctx, req) 1943 if err != nil { 1944 return nil, trace.Wrap(err) 1945 } 1946 return resp, nil 1947 } 1948 1949 // GetOIDCConnectors returns a list of OIDC connectors. 1950 func (c *Client) GetOIDCConnectors(ctx context.Context, withSecrets bool) ([]types.OIDCConnector, error) { 1951 req := &types.ResourcesWithSecretsRequest{WithSecrets: withSecrets} 1952 resp, err := c.grpc.GetOIDCConnectors(ctx, req) 1953 if err != nil { 1954 return nil, trace.Wrap(err) 1955 } 1956 oidcConnectors := make([]types.OIDCConnector, len(resp.OIDCConnectors)) 1957 for i, oidcConnector := range resp.OIDCConnectors { 1958 oidcConnectors[i] = oidcConnector 1959 } 1960 return oidcConnectors, nil 1961 } 1962 1963 // CreateOIDCConnector creates an OIDC connector. 1964 func (c *Client) CreateOIDCConnector(ctx context.Context, connector types.OIDCConnector) (types.OIDCConnector, error) { 1965 oidcConnector, ok := connector.(*types.OIDCConnectorV3) 1966 if !ok { 1967 return nil, trace.BadParameter("invalid type %T", connector) 1968 } 1969 conn, err := c.grpc.CreateOIDCConnector(ctx, &proto.CreateOIDCConnectorRequest{Connector: oidcConnector}) 1970 return conn, trace.Wrap(err) 1971 } 1972 1973 // UpdateOIDCConnector updates an OIDC connector. 1974 func (c *Client) UpdateOIDCConnector(ctx context.Context, connector types.OIDCConnector) (types.OIDCConnector, error) { 1975 oidcConnector, ok := connector.(*types.OIDCConnectorV3) 1976 if !ok { 1977 return nil, trace.BadParameter("invalid type %T", oidcConnector) 1978 } 1979 conn, err := c.grpc.UpdateOIDCConnector(ctx, &proto.UpdateOIDCConnectorRequest{Connector: oidcConnector}) 1980 return conn, trace.Wrap(err) 1981 } 1982 1983 // UpsertOIDCConnector creates or updates an OIDC connector. 1984 func (c *Client) UpsertOIDCConnector(ctx context.Context, oidcConnector types.OIDCConnector) (types.OIDCConnector, error) { 1985 connector, ok := oidcConnector.(*types.OIDCConnectorV3) 1986 if !ok { 1987 return nil, trace.BadParameter("invalid type %T", oidcConnector) 1988 } 1989 1990 upserted, err := c.grpc.UpsertOIDCConnectorV2(ctx, &proto.UpsertOIDCConnectorRequest{Connector: connector}) 1991 // TODO(tross) DELETE IN 16.0.0 1992 if err != nil && trace.IsNotImplemented(err) { 1993 //nolint:staticcheck // SA1019. Kept for backward compatibility. 1994 if _, err := c.grpc.UpsertOIDCConnector(ctx, connector); err != nil { 1995 return nil, trace.Wrap(err) 1996 } 1997 1998 conn, err := c.GetOIDCConnector(ctx, oidcConnector.GetName(), false) 1999 if err != nil { 2000 return nil, trace.Wrap(err) 2001 } 2002 2003 // Override the secrets with the values from the passed in connector since 2004 // the call to GetOIDCConnector above did not request secrets. 2005 conn.SetClientSecret(connector.GetClientSecret()) 2006 conn.SetGoogleServiceAccount(connector.GetGoogleServiceAccount()) 2007 2008 return conn, nil 2009 } 2010 return upserted, trace.Wrap(err) 2011 } 2012 2013 // DeleteOIDCConnector deletes an OIDC connector by name. 2014 func (c *Client) DeleteOIDCConnector(ctx context.Context, name string) error { 2015 if name == "" { 2016 return trace.BadParameter("cannot delete OIDC Connector, missing name") 2017 } 2018 _, err := c.grpc.DeleteOIDCConnector(ctx, &types.ResourceRequest{Name: name}) 2019 return trace.Wrap(err) 2020 } 2021 2022 // CreateOIDCAuthRequest creates OIDCAuthRequest. 2023 func (c *Client) CreateOIDCAuthRequest(ctx context.Context, req types.OIDCAuthRequest) (*types.OIDCAuthRequest, error) { 2024 resp, err := c.grpc.CreateOIDCAuthRequest(ctx, &req) 2025 if err != nil { 2026 return nil, trace.Wrap(err) 2027 } 2028 return resp, nil 2029 } 2030 2031 // GetOIDCAuthRequest gets an OIDCAuthRequest by state token. 2032 func (c *Client) GetOIDCAuthRequest(ctx context.Context, stateToken string) (*types.OIDCAuthRequest, error) { 2033 req := &proto.GetOIDCAuthRequestRequest{StateToken: stateToken} 2034 resp, err := c.grpc.GetOIDCAuthRequest(ctx, req) 2035 if err != nil { 2036 return nil, trace.Wrap(err) 2037 } 2038 return resp, nil 2039 } 2040 2041 // GetSAMLConnector returns a SAML connector by name. 2042 func (c *Client) GetSAMLConnector(ctx context.Context, name string, withSecrets bool) (types.SAMLConnector, error) { 2043 if name == "" { 2044 return nil, trace.BadParameter("cannot get SAML Connector, missing name") 2045 } 2046 req := &types.ResourceWithSecretsRequest{Name: name, WithSecrets: withSecrets} 2047 resp, err := c.grpc.GetSAMLConnector(ctx, req) 2048 if err != nil { 2049 return nil, trace.Wrap(err) 2050 } 2051 return resp, nil 2052 } 2053 2054 // GetSAMLConnectors returns a list of SAML connectors. 2055 func (c *Client) GetSAMLConnectors(ctx context.Context, withSecrets bool) ([]types.SAMLConnector, error) { 2056 req := &types.ResourcesWithSecretsRequest{WithSecrets: withSecrets} 2057 resp, err := c.grpc.GetSAMLConnectors(ctx, req) 2058 if err != nil { 2059 return nil, trace.Wrap(err) 2060 } 2061 samlConnectors := make([]types.SAMLConnector, len(resp.SAMLConnectors)) 2062 for i, samlConnector := range resp.SAMLConnectors { 2063 samlConnectors[i] = samlConnector 2064 } 2065 return samlConnectors, nil 2066 } 2067 2068 // CreateSAMLConnector creates a SAML connector. 2069 func (c *Client) CreateSAMLConnector(ctx context.Context, connector types.SAMLConnector) (types.SAMLConnector, error) { 2070 samlConnectorV2, ok := connector.(*types.SAMLConnectorV2) 2071 if !ok { 2072 return nil, trace.BadParameter("invalid type %T", connector) 2073 } 2074 conn, err := c.grpc.CreateSAMLConnector(ctx, &proto.CreateSAMLConnectorRequest{Connector: samlConnectorV2}) 2075 return conn, trace.Wrap(err) 2076 } 2077 2078 // UpdateSAMLConnector updates a SAML connector. 2079 func (c *Client) UpdateSAMLConnector(ctx context.Context, connector types.SAMLConnector) (types.SAMLConnector, error) { 2080 samlConnectorV2, ok := connector.(*types.SAMLConnectorV2) 2081 if !ok { 2082 return nil, trace.BadParameter("invalid type %T", connector) 2083 } 2084 conn, err := c.grpc.UpdateSAMLConnector(ctx, &proto.UpdateSAMLConnectorRequest{Connector: samlConnectorV2}) 2085 return conn, trace.Wrap(err) 2086 } 2087 2088 // UpsertSAMLConnector creates or updates a SAML connector. 2089 func (c *Client) UpsertSAMLConnector(ctx context.Context, connector types.SAMLConnector) (types.SAMLConnector, error) { 2090 samlConnector, ok := connector.(*types.SAMLConnectorV2) 2091 if !ok { 2092 return nil, trace.BadParameter("invalid type %T", connector) 2093 } 2094 2095 upserted, err := c.grpc.UpsertSAMLConnectorV2(ctx, &proto.UpsertSAMLConnectorRequest{Connector: samlConnector}) 2096 // TODO(tross) DELETE IN 16.0.0 2097 if err != nil && trace.IsNotImplemented(err) { 2098 //nolint:staticcheck // SA1019. Kept for backward compatibility. 2099 if _, err := c.grpc.UpsertSAMLConnector(ctx, samlConnector); err != nil { 2100 return nil, trace.Wrap(err) 2101 } 2102 conn, err := c.GetSAMLConnector(ctx, samlConnector.GetName(), false) 2103 if err != nil { 2104 return nil, trace.Wrap(err) 2105 } 2106 2107 // Override the secrets with the values from the passed in connector since 2108 // the call to GetSAMLConnector above did not request secrets. 2109 conn.SetSigningKeyPair(connector.GetSigningKeyPair()) 2110 2111 return conn, nil 2112 } 2113 return upserted, trace.Wrap(err) 2114 } 2115 2116 // DeleteSAMLConnector deletes a SAML connector by name. 2117 func (c *Client) DeleteSAMLConnector(ctx context.Context, name string) error { 2118 if name == "" { 2119 return trace.BadParameter("cannot delete SAML Connector, missing name") 2120 } 2121 _, err := c.grpc.DeleteSAMLConnector(ctx, &types.ResourceRequest{Name: name}) 2122 return trace.Wrap(err) 2123 } 2124 2125 // CreateSAMLAuthRequest creates SAMLAuthRequest. 2126 func (c *Client) CreateSAMLAuthRequest(ctx context.Context, req types.SAMLAuthRequest) (*types.SAMLAuthRequest, error) { 2127 resp, err := c.grpc.CreateSAMLAuthRequest(ctx, &req) 2128 if err != nil { 2129 return nil, trace.Wrap(err) 2130 } 2131 return resp, nil 2132 } 2133 2134 // GetSAMLAuthRequest gets a SAMLAuthRequest by id. 2135 func (c *Client) GetSAMLAuthRequest(ctx context.Context, id string) (*types.SAMLAuthRequest, error) { 2136 req := &proto.GetSAMLAuthRequestRequest{ID: id} 2137 resp, err := c.grpc.GetSAMLAuthRequest(ctx, req) 2138 if err != nil { 2139 return nil, trace.Wrap(err) 2140 } 2141 return resp, nil 2142 } 2143 2144 // GetGithubConnector returns a Github connector by name. 2145 func (c *Client) GetGithubConnector(ctx context.Context, name string, withSecrets bool) (types.GithubConnector, error) { 2146 if name == "" { 2147 return nil, trace.BadParameter("cannot get GitHub Connector, missing name") 2148 } 2149 req := &types.ResourceWithSecretsRequest{Name: name, WithSecrets: withSecrets} 2150 resp, err := c.grpc.GetGithubConnector(ctx, req) 2151 if err != nil { 2152 return nil, trace.Wrap(err) 2153 } 2154 return resp, nil 2155 } 2156 2157 // GetGithubConnectors returns a list of Github connectors. 2158 func (c *Client) GetGithubConnectors(ctx context.Context, withSecrets bool) ([]types.GithubConnector, error) { 2159 req := &types.ResourcesWithSecretsRequest{WithSecrets: withSecrets} 2160 resp, err := c.grpc.GetGithubConnectors(ctx, req) 2161 if err != nil { 2162 return nil, trace.Wrap(err) 2163 } 2164 githubConnectors := make([]types.GithubConnector, len(resp.GithubConnectors)) 2165 for i, githubConnector := range resp.GithubConnectors { 2166 githubConnectors[i] = githubConnector 2167 } 2168 return githubConnectors, nil 2169 } 2170 2171 // CreateGithubConnector creates a Github connector. 2172 func (c *Client) CreateGithubConnector(ctx context.Context, connector types.GithubConnector) (types.GithubConnector, error) { 2173 githubConnector, ok := connector.(*types.GithubConnectorV3) 2174 if !ok { 2175 return nil, trace.BadParameter("invalid type %T", connector) 2176 } 2177 conn, err := c.grpc.CreateGithubConnector(ctx, &proto.CreateGithubConnectorRequest{Connector: githubConnector}) 2178 return conn, trace.Wrap(err) 2179 } 2180 2181 // UpdateGithubConnector updates a Github connector. 2182 func (c *Client) UpdateGithubConnector(ctx context.Context, connector types.GithubConnector) (types.GithubConnector, error) { 2183 githubConnector, ok := connector.(*types.GithubConnectorV3) 2184 if !ok { 2185 return nil, trace.BadParameter("invalid type %T", connector) 2186 } 2187 conn, err := c.grpc.UpdateGithubConnector(ctx, &proto.UpdateGithubConnectorRequest{Connector: githubConnector}) 2188 return conn, trace.Wrap(err) 2189 } 2190 2191 // UpsertGithubConnector creates or updates a Github connector. 2192 func (c *Client) UpsertGithubConnector(ctx context.Context, connector types.GithubConnector) (types.GithubConnector, error) { 2193 githubConnector, ok := connector.(*types.GithubConnectorV3) 2194 if !ok { 2195 return nil, trace.BadParameter("invalid type %T", connector) 2196 } 2197 conn, err := c.grpc.UpsertGithubConnectorV2(ctx, &proto.UpsertGithubConnectorRequest{Connector: githubConnector}) 2198 // TODO(tross) DELETE IN 16.0.0 2199 if err != nil && trace.IsNotImplemented(err) { 2200 //nolint:staticcheck // SA1019. Kept for backward compatibility testing. 2201 if _, err := c.grpc.UpsertGithubConnector(ctx, githubConnector); err != nil { 2202 return nil, trace.Wrap(err) 2203 } 2204 2205 resp, err := c.grpc.GetGithubConnector(ctx, &types.ResourceWithSecretsRequest{Name: connector.GetName(), WithSecrets: false}) 2206 if err != nil { 2207 return nil, trace.Wrap(err) 2208 } 2209 2210 // Override the client secret with the value from the passed in connector since 2211 // the call to GetGithubConnector above did not request secrets. 2212 resp.SetClientSecret(connector.GetClientSecret()) 2213 2214 return resp, nil 2215 } 2216 return conn, trace.Wrap(err) 2217 } 2218 2219 // DeleteGithubConnector deletes a Github connector by name. 2220 func (c *Client) DeleteGithubConnector(ctx context.Context, name string) error { 2221 if name == "" { 2222 return trace.BadParameter("cannot delete GitHub Connector, missing name") 2223 } 2224 _, err := c.grpc.DeleteGithubConnector(ctx, &types.ResourceRequest{Name: name}) 2225 return trace.Wrap(err) 2226 } 2227 2228 // CreateGithubAuthRequest creates GithubAuthRequest. 2229 func (c *Client) CreateGithubAuthRequest(ctx context.Context, req types.GithubAuthRequest) (*types.GithubAuthRequest, error) { 2230 resp, err := c.grpc.CreateGithubAuthRequest(ctx, &req) 2231 if err != nil { 2232 return nil, trace.Wrap(err) 2233 } 2234 return resp, nil 2235 } 2236 2237 // GetGithubAuthRequest gets a GithubAuthRequest by state token. 2238 func (c *Client) GetGithubAuthRequest(ctx context.Context, stateToken string) (*types.GithubAuthRequest, error) { 2239 req := &proto.GetGithubAuthRequestRequest{StateToken: stateToken} 2240 resp, err := c.grpc.GetGithubAuthRequest(ctx, req) 2241 if err != nil { 2242 return nil, trace.Wrap(err) 2243 } 2244 return resp, nil 2245 } 2246 2247 // GetSSODiagnosticInfo returns SSO diagnostic info records for a specific SSO Auth request. 2248 func (c *Client) GetSSODiagnosticInfo(ctx context.Context, authRequestKind string, authRequestID string) (*types.SSODiagnosticInfo, error) { 2249 req := &proto.GetSSODiagnosticInfoRequest{AuthRequestKind: authRequestKind, AuthRequestID: authRequestID} 2250 resp, err := c.grpc.GetSSODiagnosticInfo(ctx, req) 2251 if err != nil { 2252 return nil, trace.Wrap(err) 2253 } 2254 return resp, nil 2255 } 2256 2257 // GetServerInfos returns a stream of ServerInfos. 2258 func (c *Client) GetServerInfos(ctx context.Context) stream.Stream[types.ServerInfo] { 2259 // set up cancelable context so that Stream.Done can close the stream if the caller 2260 // halts early. 2261 ctx, cancel := context.WithCancel(ctx) 2262 2263 serverInfos, err := c.grpc.GetServerInfos(ctx, &emptypb.Empty{}) 2264 if err != nil { 2265 cancel() 2266 return stream.Fail[types.ServerInfo](trace.Wrap(err)) 2267 } 2268 return stream.Func(func() (types.ServerInfo, error) { 2269 si, err := serverInfos.Recv() 2270 if err != nil { 2271 if errors.Is(err, io.EOF) { 2272 // io.EOF signals that stream has completed successfully 2273 return nil, io.EOF 2274 } 2275 return nil, trace.Wrap(err) 2276 } 2277 return si, nil 2278 }, cancel) 2279 } 2280 2281 // GetServerInfo returns a ServerInfo by name. 2282 func (c *Client) GetServerInfo(ctx context.Context, name string) (types.ServerInfo, error) { 2283 if name == "" { 2284 return nil, trace.BadParameter("cannot get server info, missing name") 2285 } 2286 req := &types.ResourceRequest{Name: name} 2287 resp, err := c.grpc.GetServerInfo(ctx, req) 2288 if err != nil { 2289 return nil, trace.Wrap(err) 2290 } 2291 return resp, nil 2292 } 2293 2294 // UpsertServerInfo upserts a ServerInfo. 2295 func (c *Client) UpsertServerInfo(ctx context.Context, serverInfo types.ServerInfo) error { 2296 si, ok := serverInfo.(*types.ServerInfoV1) 2297 if !ok { 2298 return trace.BadParameter("invalid type %T", serverInfo) 2299 } 2300 _, err := c.grpc.UpsertServerInfo(ctx, si) 2301 return trace.Wrap(err) 2302 } 2303 2304 // DeleteServerInfo deletes a ServerInfo by name. 2305 func (c *Client) DeleteServerInfo(ctx context.Context, name string) error { 2306 if name == "" { 2307 return trace.BadParameter("cannot delete server info, missing name") 2308 } 2309 req := &types.ResourceRequest{Name: name} 2310 _, err := c.grpc.DeleteServerInfo(ctx, req) 2311 return trace.Wrap(err) 2312 } 2313 2314 // DeleteAllServerInfos deletes all ServerInfos. 2315 func (c *Client) DeleteAllServerInfos(ctx context.Context) error { 2316 _, err := c.grpc.DeleteAllServerInfos(ctx, &emptypb.Empty{}) 2317 return trace.Wrap(err) 2318 } 2319 2320 // GetTrustedCluster returns a Trusted Cluster by name. 2321 func (c *Client) GetTrustedCluster(ctx context.Context, name string) (types.TrustedCluster, error) { 2322 if name == "" { 2323 return nil, trace.BadParameter("cannot get trusted cluster, missing name") 2324 } 2325 req := &types.ResourceRequest{Name: name} 2326 resp, err := c.grpc.GetTrustedCluster(ctx, req) 2327 if err != nil { 2328 return nil, trace.Wrap(err) 2329 } 2330 return resp, nil 2331 } 2332 2333 // GetTrustedClusters returns a list of Trusted Clusters. 2334 func (c *Client) GetTrustedClusters(ctx context.Context) ([]types.TrustedCluster, error) { 2335 resp, err := c.grpc.GetTrustedClusters(ctx, &emptypb.Empty{}) 2336 if err != nil { 2337 return nil, trace.Wrap(err) 2338 } 2339 trustedClusters := make([]types.TrustedCluster, len(resp.TrustedClusters)) 2340 for i, trustedCluster := range resp.TrustedClusters { 2341 trustedClusters[i] = trustedCluster 2342 } 2343 return trustedClusters, nil 2344 } 2345 2346 // UpsertTrustedCluster creates or updates a Trusted Cluster. 2347 func (c *Client) UpsertTrustedCluster(ctx context.Context, trusedCluster types.TrustedCluster) (types.TrustedCluster, error) { 2348 trustedCluster, ok := trusedCluster.(*types.TrustedClusterV2) 2349 if !ok { 2350 return nil, trace.BadParameter("invalid type %T", trusedCluster) 2351 } 2352 resp, err := c.grpc.UpsertTrustedCluster(ctx, trustedCluster) 2353 if err != nil { 2354 return nil, trace.Wrap(err) 2355 } 2356 return resp, nil 2357 } 2358 2359 // DeleteTrustedCluster deletes a Trusted Cluster by name. 2360 func (c *Client) DeleteTrustedCluster(ctx context.Context, name string) error { 2361 if name == "" { 2362 return trace.BadParameter("cannot delete trusted cluster, missing name") 2363 } 2364 _, err := c.grpc.DeleteTrustedCluster(ctx, &types.ResourceRequest{Name: name}) 2365 return trace.Wrap(err) 2366 } 2367 2368 // GetToken returns a provision token by name. 2369 func (c *Client) GetToken(ctx context.Context, name string) (types.ProvisionToken, error) { 2370 if name == "" { 2371 return nil, trace.BadParameter("cannot get token, missing name") 2372 } 2373 resp, err := c.grpc.GetToken(ctx, &types.ResourceRequest{Name: name}) 2374 if err != nil { 2375 return nil, trace.Wrap(err) 2376 } 2377 return resp, nil 2378 } 2379 2380 // GetTokens returns a list of active provision tokens for nodes and users. 2381 func (c *Client) GetTokens(ctx context.Context) ([]types.ProvisionToken, error) { 2382 resp, err := c.grpc.GetTokens(ctx, &emptypb.Empty{}) 2383 if err != nil { 2384 return nil, trace.Wrap(err) 2385 } 2386 2387 tokens := make([]types.ProvisionToken, len(resp.ProvisionTokens)) 2388 for i, token := range resp.ProvisionTokens { 2389 tokens[i] = token 2390 } 2391 return tokens, nil 2392 } 2393 2394 // UpsertToken creates or updates a provision token. 2395 func (c *Client) UpsertToken(ctx context.Context, token types.ProvisionToken) error { 2396 tokenV2, ok := token.(*types.ProvisionTokenV2) 2397 if !ok { 2398 return trace.BadParameter("invalid type %T", token) 2399 } 2400 2401 _, err := c.grpc.UpsertTokenV2(ctx, &proto.UpsertTokenV2Request{ 2402 Token: &proto.UpsertTokenV2Request_V2{ 2403 V2: tokenV2, 2404 }, 2405 }) 2406 return trace.Wrap(err) 2407 } 2408 2409 // CreateToken creates a provision token. 2410 func (c *Client) CreateToken(ctx context.Context, token types.ProvisionToken) error { 2411 tokenV2, ok := token.(*types.ProvisionTokenV2) 2412 if !ok { 2413 return trace.BadParameter("invalid type %T", token) 2414 } 2415 2416 _, err := c.grpc.CreateTokenV2(ctx, &proto.CreateTokenV2Request{ 2417 Token: &proto.CreateTokenV2Request_V2{ 2418 V2: tokenV2, 2419 }, 2420 }) 2421 return trace.Wrap(err) 2422 } 2423 2424 // DeleteToken deletes a provision token by name. 2425 func (c *Client) DeleteToken(ctx context.Context, name string) error { 2426 if name == "" { 2427 return trace.BadParameter("cannot delete token, missing name") 2428 } 2429 _, err := c.grpc.DeleteToken(ctx, &types.ResourceRequest{Name: name}) 2430 return trace.Wrap(err) 2431 } 2432 2433 // GetNode returns a node by name and namespace. 2434 func (c *Client) GetNode(ctx context.Context, namespace, name string) (types.Server, error) { 2435 resp, err := c.grpc.GetNode(ctx, &types.ResourceInNamespaceRequest{ 2436 Name: name, 2437 Namespace: namespace, 2438 }) 2439 if err != nil { 2440 return nil, trace.Wrap(err) 2441 } 2442 return resp, nil 2443 } 2444 2445 // GetNodes returns a complete list of nodes that the user has access to in the given namespace. 2446 func (c *Client) GetNodes(ctx context.Context, namespace string) ([]types.Server, error) { 2447 servers, err := GetAllResources[types.Server](ctx, c, &proto.ListResourcesRequest{ 2448 ResourceType: types.KindNode, 2449 Namespace: namespace, 2450 }) 2451 2452 return servers, trace.Wrap(err) 2453 } 2454 2455 // UpsertNode is used by SSH servers to report their presence 2456 // to the auth servers in form of heartbeat expiring after ttl period. 2457 func (c *Client) UpsertNode(ctx context.Context, node types.Server) (*types.KeepAlive, error) { 2458 if node.GetNamespace() == "" { 2459 return nil, trace.BadParameter("missing node namespace") 2460 } 2461 serverV2, ok := node.(*types.ServerV2) 2462 if !ok { 2463 return nil, trace.BadParameter("invalid type %T", node) 2464 } 2465 keepAlive, err := c.grpc.UpsertNode(ctx, serverV2) 2466 if err != nil { 2467 return nil, trace.Wrap(err) 2468 } 2469 return keepAlive, nil 2470 } 2471 2472 // DeleteNode deletes a node by name and namespace. 2473 func (c *Client) DeleteNode(ctx context.Context, namespace, name string) error { 2474 if namespace == "" { 2475 return trace.BadParameter("missing parameter namespace") 2476 } 2477 if name == "" { 2478 return trace.BadParameter("missing parameter name") 2479 } 2480 _, err := c.grpc.DeleteNode(ctx, &types.ResourceInNamespaceRequest{ 2481 Name: name, 2482 Namespace: namespace, 2483 }) 2484 return trace.Wrap(err) 2485 } 2486 2487 // DeleteAllNodes deletes all nodes in a given namespace. 2488 func (c *Client) DeleteAllNodes(ctx context.Context, namespace string) error { 2489 if namespace == "" { 2490 return trace.BadParameter("missing parameter namespace") 2491 } 2492 _, err := c.grpc.DeleteAllNodes(ctx, &types.ResourcesInNamespaceRequest{Namespace: namespace}) 2493 return trace.Wrap(err) 2494 } 2495 2496 // StreamSessionEvents streams audit events from a given session recording. 2497 func (c *Client) StreamSessionEvents(ctx context.Context, sessionID string, startIndex int64) (chan events.AuditEvent, chan error) { 2498 request := &proto.StreamSessionEventsRequest{ 2499 SessionID: sessionID, 2500 StartIndex: int32(startIndex), 2501 } 2502 2503 ch := make(chan events.AuditEvent) 2504 e := make(chan error, 1) 2505 2506 stream, err := c.grpc.StreamSessionEvents(ctx, request) 2507 if err != nil { 2508 e <- trace.Wrap(err) 2509 return ch, e 2510 } 2511 2512 go func() { 2513 outer: 2514 for { 2515 oneOf, err := stream.Recv() 2516 if err != nil { 2517 if !errors.Is(err, io.EOF) { 2518 e <- trace.Wrap(err) 2519 } else { 2520 close(ch) 2521 } 2522 2523 break outer 2524 } 2525 2526 event, err := events.FromOneOf(*oneOf) 2527 if err != nil { 2528 e <- trace.Wrap(err) 2529 break outer 2530 } 2531 2532 select { 2533 case ch <- event: 2534 case <-ctx.Done(): 2535 e <- trace.Wrap(ctx.Err()) 2536 break outer 2537 } 2538 } 2539 }() 2540 2541 return ch, e 2542 } 2543 2544 // SearchEvents allows searching for events with a full pagination support. 2545 func (c *Client) SearchEvents(ctx context.Context, fromUTC, toUTC time.Time, namespace string, eventTypes []string, limit int, order types.EventOrder, startKey string) ([]events.AuditEvent, string, error) { 2546 request := &proto.GetEventsRequest{ 2547 Namespace: namespace, 2548 StartDate: fromUTC, 2549 EndDate: toUTC, 2550 EventTypes: eventTypes, 2551 Limit: int32(limit), 2552 StartKey: startKey, 2553 Order: proto.Order(order), 2554 } 2555 2556 response, err := c.grpc.GetEvents(ctx, request) 2557 if err != nil { 2558 return nil, "", trace.Wrap(err) 2559 } 2560 2561 decodedEvents := make([]events.AuditEvent, 0, len(response.Items)) 2562 for _, rawEvent := range response.Items { 2563 event, err := events.FromOneOf(*rawEvent) 2564 if err != nil { 2565 if trace.IsBadParameter(err) { 2566 slog.WarnContext(ctx, "skipping unknown event", "error", err) 2567 continue 2568 } 2569 return nil, "", trace.Wrap(err) 2570 } 2571 decodedEvents = append(decodedEvents, event) 2572 } 2573 2574 return decodedEvents, response.LastKey, nil 2575 } 2576 2577 // SearchUnstructuredEvents allows searching for events with a full pagination support 2578 // and returns events in an unstructured format (json like). 2579 // This method is used by the Teleport event-handler plugin to receive events 2580 // from the auth server wihout having to support the Protobuf event schema. 2581 func (c *Client) SearchUnstructuredEvents(ctx context.Context, fromUTC, toUTC time.Time, namespace string, eventTypes []string, limit int, order types.EventOrder, startKey string) ([]*auditlogpb.EventUnstructured, string, error) { 2582 request := &auditlogpb.GetUnstructuredEventsRequest{ 2583 Namespace: namespace, 2584 StartDate: timestamppb.New(fromUTC), 2585 EndDate: timestamppb.New(toUTC), 2586 EventTypes: eventTypes, 2587 Limit: int32(limit), 2588 StartKey: startKey, 2589 Order: auditlogpb.Order(order), 2590 } 2591 2592 response, err := c.grpc.GetUnstructuredEvents(ctx, request) 2593 if err != nil { 2594 return nil, "", trace.Wrap(err) 2595 } 2596 2597 return response.Items, response.LastKey, nil 2598 } 2599 2600 // StreamUnstructuredSessionEvents streams audit events from a given session recording in an unstructured format. 2601 // This method is used by the Teleport event-handler plugin to receive events 2602 // from the auth server wihout having to support the Protobuf event schema. 2603 func (c *Client) StreamUnstructuredSessionEvents(ctx context.Context, sessionID string, startIndex int64) (chan *auditlogpb.EventUnstructured, chan error) { 2604 request := &auditlogpb.StreamUnstructuredSessionEventsRequest{ 2605 SessionId: sessionID, 2606 StartIndex: int32(startIndex), 2607 } 2608 2609 ch := make(chan *auditlogpb.EventUnstructured) 2610 e := make(chan error, 1) 2611 2612 stream, err := c.grpc.StreamUnstructuredSessionEvents(ctx, request) 2613 if err != nil { 2614 if trace.IsNotImplemented(trace.Wrap(err)) { 2615 // If the server does not support the unstructured events API, 2616 // fallback to the legacy API. 2617 // This code patch shouldn't be triggered because the server 2618 // returns the error only if the client calls Recv() on the stream. 2619 // However, we keep this code patch here just in case there is a bug 2620 // on the client grpc side. 2621 c.streamUnstructuredSessionEventsFallback(ctx, sessionID, startIndex, ch, e) 2622 } else { 2623 e <- trace.Wrap(err) 2624 } 2625 return ch, e 2626 } 2627 go func() { 2628 for { 2629 event, err := stream.Recv() 2630 if err != nil { 2631 if !errors.Is(err, io.EOF) { 2632 // If the server does not support the unstructured events API, it will 2633 // return an error with code Unimplemented. This error is received 2634 // the first time the client calls Recv() on the stream. 2635 // If the client receives this error, it should fallback to the legacy 2636 // API that spins another goroutine to convert the events to the 2637 // unstructured format and sends them to the channel ch. 2638 // Once we decide to spin the goroutine, we can leave this loop without 2639 // reporting any error to the caller. 2640 if trace.IsNotImplemented(trace.Wrap(err)) { 2641 // If the server does not support the unstructured events API, 2642 // fallback to the legacy API. 2643 go c.streamUnstructuredSessionEventsFallback(ctx, sessionID, startIndex, ch, e) 2644 return 2645 } 2646 e <- trace.Wrap(err) 2647 } else { 2648 close(ch) 2649 } 2650 return 2651 } 2652 2653 select { 2654 case ch <- event: 2655 case <-ctx.Done(): 2656 e <- trace.Wrap(ctx.Err()) 2657 return 2658 } 2659 } 2660 }() 2661 2662 return ch, e 2663 } 2664 2665 // streamUnstructuredSessionEventsFallback is a fallback implementation of the 2666 // StreamUnstructuredSessionEvents method that is used when the server does not 2667 // support the unstructured events API. This method uses the old API to stream 2668 // events from the server and converts them to the unstructured format. This 2669 // method converts the events at event handler plugin side, which can cause 2670 // the plugin to miss some events if the plugin is not updated to the latest 2671 // version. 2672 // NOTE(tigrato): This code was reintroduced in 15.0.0 because the gRPC method was renamed 2673 // incorrectly in 13.1-14.3 which caused the server to return Unimplemented 2674 // error to the client and the client to fallback to the legacy API. 2675 // TODO(tigrato): DELETE IN 16.0.0 2676 func (c *Client) streamUnstructuredSessionEventsFallback(ctx context.Context, sessionID string, startIndex int64, ch chan *auditlogpb.EventUnstructured, e chan error) { 2677 request := &proto.StreamSessionEventsRequest{ 2678 SessionID: sessionID, 2679 StartIndex: int32(startIndex), 2680 } 2681 2682 stream, err := c.grpc.StreamSessionEvents(ctx, request) 2683 if err != nil { 2684 e <- trace.Wrap(err) 2685 return 2686 } 2687 2688 go func() { 2689 for { 2690 oneOf, err := stream.Recv() 2691 if err != nil { 2692 if !errors.Is(err, io.EOF) { 2693 e <- trace.Wrap(err) 2694 } else { 2695 close(ch) 2696 } 2697 2698 return 2699 } 2700 2701 event, err := events.FromOneOf(*oneOf) 2702 if err != nil { 2703 e <- trace.Wrap(err) 2704 return 2705 } 2706 2707 unstructedEvent, err := events.ToUnstructured(event) 2708 if err != nil { 2709 e <- trace.Wrap(err) 2710 return 2711 } 2712 2713 select { 2714 case ch <- unstructedEvent: 2715 case <-ctx.Done(): 2716 e <- trace.Wrap(ctx.Err()) 2717 return 2718 } 2719 } 2720 }() 2721 } 2722 2723 // SearchSessionEvents allows searching for session events with a full pagination support. 2724 func (c *Client) SearchSessionEvents(ctx context.Context, fromUTC time.Time, toUTC time.Time, limit int, order types.EventOrder, startKey string) ([]events.AuditEvent, string, error) { 2725 request := &proto.GetSessionEventsRequest{ 2726 StartDate: fromUTC, 2727 EndDate: toUTC, 2728 Limit: int32(limit), 2729 StartKey: startKey, 2730 Order: proto.Order(order), 2731 } 2732 2733 response, err := c.grpc.GetSessionEvents(ctx, request) 2734 if err != nil { 2735 return nil, "", trace.Wrap(err) 2736 } 2737 2738 decodedEvents := make([]events.AuditEvent, 0, len(response.Items)) 2739 for _, rawEvent := range response.Items { 2740 event, err := events.FromOneOf(*rawEvent) 2741 if err != nil { 2742 return nil, "", trace.Wrap(err) 2743 } 2744 decodedEvents = append(decodedEvents, event) 2745 } 2746 2747 return decodedEvents, response.LastKey, nil 2748 } 2749 2750 // ClusterConfigClient returns an unadorned Cluster Configuration client, using the underlying 2751 // Auth gRPC connection. 2752 func (c *Client) ClusterConfigClient() clusterconfigpb.ClusterConfigServiceClient { 2753 return clusterconfigpb.NewClusterConfigServiceClient(c.conn) 2754 } 2755 2756 // GetClusterNetworkingConfig gets cluster networking configuration. 2757 func (c *Client) GetClusterNetworkingConfig(ctx context.Context) (types.ClusterNetworkingConfig, error) { 2758 resp, err := c.ClusterConfigClient().GetClusterNetworkingConfig(ctx, &clusterconfigpb.GetClusterNetworkingConfigRequest{}) 2759 if err != nil && trace.IsNotImplemented(err) { 2760 resp, err = c.grpc.GetClusterNetworkingConfig(ctx, &emptypb.Empty{}) 2761 } 2762 return resp, trace.Wrap(err) 2763 } 2764 2765 // SetClusterNetworkingConfig sets cluster networking configuration. 2766 // Deprecated: Use UpdateClusterNetworkingConfig or UpsertClusterNetworkingConfig instead. 2767 func (c *Client) SetClusterNetworkingConfig(ctx context.Context, netConfig *types.ClusterNetworkingConfigV2) error { 2768 _, err := c.grpc.SetClusterNetworkingConfig(ctx, netConfig) 2769 return trace.Wrap(err) 2770 } 2771 2772 // setClusterNetworkingConfig sets cluster networking configuration. 2773 func (c *Client) setClusterNetworkingConfig(ctx context.Context, netConfig *types.ClusterNetworkingConfigV2) (types.ClusterNetworkingConfig, error) { 2774 _, err := c.grpc.SetClusterNetworkingConfig(ctx, netConfig) 2775 if err != nil { 2776 return nil, trace.Wrap(err) 2777 } 2778 2779 cfg, err := c.grpc.GetClusterNetworkingConfig(ctx, &emptypb.Empty{}) 2780 return cfg, trace.Wrap(err) 2781 } 2782 2783 // UpdateClusterNetworkingConfig updates an existing cluster networking configuration. 2784 func (c *Client) UpdateClusterNetworkingConfig(ctx context.Context, cfg types.ClusterNetworkingConfig) (types.ClusterNetworkingConfig, error) { 2785 v2, ok := cfg.(*types.ClusterNetworkingConfigV2) 2786 if !ok { 2787 return nil, trace.BadParameter("unsupported cluster networking config type %T", cfg) 2788 } 2789 2790 updated, err := c.ClusterConfigClient().UpdateClusterNetworkingConfig(ctx, &clusterconfigpb.UpdateClusterNetworkingConfigRequest{ClusterNetworkConfig: v2}) 2791 // TODO(tross) DELETE IN v18.0.0 2792 if trace.IsNotImplemented(err) { 2793 cnc, err := c.setClusterNetworkingConfig(ctx, v2) 2794 return cnc, trace.Wrap(err) 2795 } 2796 2797 return updated, trace.Wrap(err) 2798 } 2799 2800 // UpsertClusterNetworkingConfig creates a new configuration or overwrites the existing cluster networking configuration. 2801 func (c *Client) UpsertClusterNetworkingConfig(ctx context.Context, cfg types.ClusterNetworkingConfig) (types.ClusterNetworkingConfig, error) { 2802 v2, ok := cfg.(*types.ClusterNetworkingConfigV2) 2803 if !ok { 2804 return nil, trace.BadParameter("unsupported cluster networking config type %T", cfg) 2805 } 2806 2807 updated, err := c.ClusterConfigClient().UpsertClusterNetworkingConfig(ctx, &clusterconfigpb.UpsertClusterNetworkingConfigRequest{ClusterNetworkConfig: v2}) 2808 // TODO(tross) DELETE IN v18.0.0 2809 if trace.IsNotImplemented(err) { 2810 cnc, err := c.setClusterNetworkingConfig(ctx, v2) 2811 return cnc, trace.Wrap(err) 2812 } 2813 2814 return updated, trace.Wrap(err) 2815 } 2816 2817 // ResetClusterNetworkingConfig resets cluster networking configuration to defaults. 2818 func (c *Client) ResetClusterNetworkingConfig(ctx context.Context) error { 2819 _, err := c.ClusterConfigClient().ResetClusterNetworkingConfig(ctx, &clusterconfigpb.ResetClusterNetworkingConfigRequest{}) 2820 if err != nil && trace.IsNotImplemented(err) { 2821 _, err := c.grpc.ResetClusterNetworkingConfig(ctx, &emptypb.Empty{}) 2822 return trace.Wrap(err) 2823 } 2824 2825 return trace.Wrap(err) 2826 } 2827 2828 // GetSessionRecordingConfig gets session recording configuration. 2829 func (c *Client) GetSessionRecordingConfig(ctx context.Context) (types.SessionRecordingConfig, error) { 2830 resp, err := c.ClusterConfigClient().GetSessionRecordingConfig(ctx, &clusterconfigpb.GetSessionRecordingConfigRequest{}) 2831 if err != nil && trace.IsNotImplemented(err) { 2832 resp, err = c.grpc.GetSessionRecordingConfig(ctx, &emptypb.Empty{}) 2833 } 2834 2835 return resp, trace.Wrap(err) 2836 } 2837 2838 // SetSessionRecordingConfig sets session recording configuration. 2839 // Deprecated: Use UpdateSessionRecordingConfig or UpsertSessionRecordingConfig instead. 2840 func (c *Client) SetSessionRecordingConfig(ctx context.Context, recConfig types.SessionRecordingConfig) error { 2841 recConfigV2, ok := recConfig.(*types.SessionRecordingConfigV2) 2842 if !ok { 2843 return trace.BadParameter("invalid type %T", recConfig) 2844 } 2845 2846 _, err := c.grpc.SetSessionRecordingConfig(ctx, recConfigV2) 2847 return trace.Wrap(err) 2848 } 2849 2850 // setSessionRecordingConfig sets session recording configuration. 2851 func (c *Client) setSessionRecordingConfig(ctx context.Context, recConfig types.SessionRecordingConfig) (types.SessionRecordingConfig, error) { 2852 recConfigV2, ok := recConfig.(*types.SessionRecordingConfigV2) 2853 if !ok { 2854 return nil, trace.BadParameter("invalid type %T", recConfig) 2855 } 2856 2857 if _, err := c.grpc.SetSessionRecordingConfig(ctx, recConfigV2); err != nil { 2858 return nil, trace.Wrap(err) 2859 } 2860 2861 cfg, err := c.grpc.GetSessionRecordingConfig(ctx, &emptypb.Empty{}) 2862 return cfg, trace.Wrap(err) 2863 } 2864 2865 // ResetSessionRecordingConfig resets session recording configuration to defaults. 2866 func (c *Client) ResetSessionRecordingConfig(ctx context.Context) error { 2867 _, err := c.ClusterConfigClient().ResetSessionRecordingConfig(ctx, &clusterconfigpb.ResetSessionRecordingConfigRequest{}) 2868 if err != nil && trace.IsNotImplemented(err) { 2869 _, err := c.grpc.ResetSessionRecordingConfig(ctx, &emptypb.Empty{}) 2870 return trace.Wrap(err) 2871 } 2872 2873 return trace.Wrap(err) 2874 } 2875 2876 // UpdateSessionRecordingConfig updates an existing session recording configuration. 2877 func (c *Client) UpdateSessionRecordingConfig(ctx context.Context, cfg types.SessionRecordingConfig) (types.SessionRecordingConfig, error) { 2878 v2, ok := cfg.(*types.SessionRecordingConfigV2) 2879 if !ok { 2880 return nil, trace.BadParameter("unsupported session recording config type %T", cfg) 2881 } 2882 2883 updated, err := c.ClusterConfigClient().UpdateSessionRecordingConfig(ctx, &clusterconfigpb.UpdateSessionRecordingConfigRequest{SessionRecordingConfig: v2}) 2884 // TODO(tross) DELETE IN v18.0.0 2885 if trace.IsNotImplemented(err) { 2886 cfg, err = c.setSessionRecordingConfig(ctx, v2) 2887 return cfg, trace.Wrap(err) 2888 } 2889 return updated, trace.Wrap(err) 2890 } 2891 2892 // UpsertSessionRecordingConfig creates a new configuration or overwrites the existing session recording configuration. 2893 func (c *Client) UpsertSessionRecordingConfig(ctx context.Context, cfg types.SessionRecordingConfig) (types.SessionRecordingConfig, error) { 2894 v2, ok := cfg.(*types.SessionRecordingConfigV2) 2895 if !ok { 2896 return nil, trace.BadParameter("unsupported session recording config type %T", cfg) 2897 } 2898 2899 updated, err := c.ClusterConfigClient().UpsertSessionRecordingConfig(ctx, &clusterconfigpb.UpsertSessionRecordingConfigRequest{SessionRecordingConfig: v2}) 2900 // TODO(tross) DELETE IN v18.0.0 2901 if trace.IsNotImplemented(err) { 2902 cfg, err = c.setSessionRecordingConfig(ctx, v2) 2903 return cfg, trace.Wrap(err) 2904 } 2905 return updated, trace.Wrap(err) 2906 } 2907 2908 // GetAuthPreference gets the active cluster auth preference. 2909 func (c *Client) GetAuthPreference(ctx context.Context) (types.AuthPreference, error) { 2910 pref, err := c.ClusterConfigClient().GetAuthPreference(ctx, &clusterconfigpb.GetAuthPreferenceRequest{}) 2911 // TODO(tross) DELETE IN v18.0.0 2912 if err != nil && trace.IsNotImplemented(err) { 2913 pref, err = c.grpc.GetAuthPreference(ctx, &emptypb.Empty{}) 2914 if err != nil { 2915 return nil, trace.Wrap(err) 2916 } 2917 2918 // An old server would send PIVSlot instead of HardwareKey.PIVSlot 2919 // TODO(Joerger): DELETE IN 17.0.0 2920 pref.CheckSetPIVSlot() 2921 } 2922 2923 return pref, trace.Wrap(err) 2924 } 2925 2926 // SetAuthPreference sets cluster auth preference via the legacy mechanism. 2927 // Deprecated: Use UpdateAuthPreference or UpsertAuthPreference instead. 2928 // TODO(tross) DELETE IN v18.0.0 2929 func (c *Client) SetAuthPreference(ctx context.Context, authPref types.AuthPreference) error { 2930 authPrefV2, ok := authPref.(*types.AuthPreferenceV2) 2931 if !ok { 2932 return trace.BadParameter("invalid type %T", authPref) 2933 } 2934 2935 // An old server would expect PIVSlot instead of HardwareKey.PIVSlot 2936 // TODO(Joerger): DELETE IN 17.0.0 2937 authPrefV2.CheckSetPIVSlot() 2938 2939 _, err := c.grpc.SetAuthPreference(ctx, authPrefV2) 2940 return trace.Wrap(err) 2941 } 2942 2943 // setAuthPreference sets cluster auth preference via the legacy mechanism. 2944 // TODO(tross) DELETE IN v18.0.0 2945 func (c *Client) setAuthPreference(ctx context.Context, authPref *types.AuthPreferenceV2) (types.AuthPreference, error) { 2946 // An old server would expect PIVSlot instead of HardwareKey.PIVSlot 2947 // TODO(Joerger): DELETE IN 17.0.0 2948 authPref.CheckSetPIVSlot() 2949 2950 _, err := c.grpc.SetAuthPreference(ctx, authPref) 2951 if err != nil { 2952 return nil, trace.Wrap(err) 2953 } 2954 2955 pref, err := c.grpc.GetAuthPreference(ctx, &emptypb.Empty{}) 2956 return pref, trace.Wrap(err) 2957 } 2958 2959 // ResetAuthPreference resets cluster auth preference to defaults. 2960 func (c *Client) ResetAuthPreference(ctx context.Context) error { 2961 _, err := c.ClusterConfigClient().ResetAuthPreference(ctx, &clusterconfigpb.ResetAuthPreferenceRequest{}) 2962 // TODO(tross) DELETE IN v18.0.0 2963 if err != nil && trace.IsNotImplemented(err) { 2964 _, err := c.grpc.ResetAuthPreference(ctx, &emptypb.Empty{}) 2965 return trace.Wrap(err) 2966 } 2967 return trace.Wrap(err) 2968 } 2969 2970 // UpdateAuthPreference updates an existing auth preference. 2971 func (c *Client) UpdateAuthPreference(ctx context.Context, p types.AuthPreference) (types.AuthPreference, error) { 2972 v2, ok := p.(*types.AuthPreferenceV2) 2973 if !ok { 2974 return nil, trace.BadParameter("unsupported auth preference type %T", p) 2975 } 2976 2977 updated, err := c.ClusterConfigClient().UpdateAuthPreference(ctx, &clusterconfigpb.UpdateAuthPreferenceRequest{AuthPreference: v2}) 2978 // TODO(tross) DELETE IN v18.0.0 2979 if trace.IsNotImplemented(err) { 2980 pref, err := c.setAuthPreference(ctx, v2) 2981 return pref, trace.Wrap(err) 2982 } 2983 return updated, trace.Wrap(err) 2984 } 2985 2986 // UpsertAuthPreference creates a new preference or overwrites the existing auth preference. 2987 func (c *Client) UpsertAuthPreference(ctx context.Context, p types.AuthPreference) (types.AuthPreference, error) { 2988 v2, ok := p.(*types.AuthPreferenceV2) 2989 if !ok { 2990 return nil, trace.BadParameter("unsupported auth preference type %T", p) 2991 } 2992 2993 updated, err := c.ClusterConfigClient().UpsertAuthPreference(ctx, &clusterconfigpb.UpsertAuthPreferenceRequest{AuthPreference: v2}) 2994 // TODO(tross) DELETE IN v18.0.0 2995 if trace.IsNotImplemented(err) { 2996 pref, err := c.setAuthPreference(ctx, v2) 2997 return pref, trace.Wrap(err) 2998 } 2999 return updated, trace.Wrap(err) 3000 } 3001 3002 // GetClusterAuditConfig gets cluster audit configuration. 3003 func (c *Client) GetClusterAuditConfig(ctx context.Context) (types.ClusterAuditConfig, error) { 3004 resp, err := c.grpc.GetClusterAuditConfig(ctx, &emptypb.Empty{}) 3005 if err != nil { 3006 return nil, trace.Wrap(err) 3007 } 3008 return resp, nil 3009 } 3010 3011 // GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server. 3012 func (c *Client) GetClusterAccessGraphConfig(ctx context.Context) (*clusterconfigpb.AccessGraphConfig, error) { 3013 rsp, err := c.ClusterConfigClient().GetClusterAccessGraphConfig(ctx, &clusterconfigpb.GetClusterAccessGraphConfigRequest{}) 3014 if err != nil { 3015 return nil, trace.Wrap(err) 3016 } 3017 return rsp.AccessGraph, nil 3018 } 3019 3020 // GetInstaller gets all installer script resources 3021 func (c *Client) GetInstallers(ctx context.Context) ([]types.Installer, error) { 3022 resp, err := c.grpc.GetInstallers(ctx, &emptypb.Empty{}) 3023 if err != nil { 3024 return nil, trace.Wrap(err) 3025 } 3026 installers := make([]types.Installer, len(resp.Installers)) 3027 for i, inst := range resp.Installers { 3028 installers[i] = inst 3029 } 3030 return installers, nil 3031 } 3032 3033 // GetUIConfig gets the configuration for the UI served by the proxy service 3034 func (c *Client) GetUIConfig(ctx context.Context) (types.UIConfig, error) { 3035 resp, err := c.grpc.GetUIConfig(ctx, &emptypb.Empty{}) 3036 return resp, trace.Wrap(err) 3037 } 3038 3039 // SetUIConfig sets the configuration for the UI served by the proxy service 3040 func (c *Client) SetUIConfig(ctx context.Context, uic types.UIConfig) error { 3041 uicV1, ok := uic.(*types.UIConfigV1) 3042 if !ok { 3043 return trace.BadParameter("invalid type %T", uic) 3044 } 3045 _, err := c.grpc.SetUIConfig(ctx, uicV1) 3046 return trace.Wrap(err) 3047 } 3048 3049 func (c *Client) DeleteUIConfig(ctx context.Context) error { 3050 _, err := c.grpc.DeleteUIConfig(ctx, &emptypb.Empty{}) 3051 return trace.Wrap(err) 3052 } 3053 3054 // GetInstaller gets the cluster installer resource 3055 func (c *Client) GetInstaller(ctx context.Context, name string) (types.Installer, error) { 3056 resp, err := c.grpc.GetInstaller(ctx, &types.ResourceRequest{Name: name}) 3057 if err != nil { 3058 return nil, trace.Wrap(err) 3059 } 3060 return resp, nil 3061 } 3062 3063 // SetInstaller sets the cluster installer resource 3064 func (c *Client) SetInstaller(ctx context.Context, inst types.Installer) error { 3065 instV1, ok := inst.(*types.InstallerV1) 3066 if !ok { 3067 return trace.BadParameter("invalid type %T", inst) 3068 } 3069 _, err := c.grpc.SetInstaller(ctx, instV1) 3070 return trace.Wrap(err) 3071 } 3072 3073 // DeleteInstaller deletes the cluster installer resource 3074 func (c *Client) DeleteInstaller(ctx context.Context, name string) error { 3075 _, err := c.grpc.DeleteInstaller(ctx, &types.ResourceRequest{Name: name}) 3076 return trace.Wrap(err) 3077 } 3078 3079 // DeleteAllInstallers deletes all the installer resources. 3080 func (c *Client) DeleteAllInstallers(ctx context.Context) error { 3081 _, err := c.grpc.DeleteAllInstallers(ctx, &emptypb.Empty{}) 3082 return trace.Wrap(err) 3083 } 3084 3085 // GetLock gets a lock by name. 3086 func (c *Client) GetLock(ctx context.Context, name string) (types.Lock, error) { 3087 if name == "" { 3088 return nil, trace.BadParameter("missing lock name") 3089 } 3090 resp, err := c.grpc.GetLock(ctx, &proto.GetLockRequest{Name: name}) 3091 if err != nil { 3092 return nil, trace.Wrap(err) 3093 } 3094 return resp, nil 3095 } 3096 3097 // GetLocks gets all/in-force locks that match at least one of the targets when specified. 3098 func (c *Client) GetLocks(ctx context.Context, inForceOnly bool, targets ...types.LockTarget) ([]types.Lock, error) { 3099 targetPtrs := make([]*types.LockTarget, len(targets)) 3100 for i := range targets { 3101 targetPtrs[i] = &targets[i] 3102 } 3103 resp, err := c.grpc.GetLocks(ctx, &proto.GetLocksRequest{ 3104 InForceOnly: inForceOnly, 3105 Targets: targetPtrs, 3106 }) 3107 if err != nil { 3108 return nil, trace.Wrap(err) 3109 } 3110 locks := make([]types.Lock, 0, len(resp.Locks)) 3111 for _, lock := range resp.Locks { 3112 locks = append(locks, lock) 3113 } 3114 return locks, nil 3115 } 3116 3117 // UpsertLock upserts a lock. 3118 func (c *Client) UpsertLock(ctx context.Context, lock types.Lock) error { 3119 lockV2, ok := lock.(*types.LockV2) 3120 if !ok { 3121 return trace.BadParameter("invalid type %T", lock) 3122 } 3123 _, err := c.grpc.UpsertLock(ctx, lockV2) 3124 return trace.Wrap(err) 3125 } 3126 3127 // DeleteLock deletes a lock. 3128 func (c *Client) DeleteLock(ctx context.Context, name string) error { 3129 if name == "" { 3130 return trace.BadParameter("missing lock name") 3131 } 3132 _, err := c.grpc.DeleteLock(ctx, &proto.DeleteLockRequest{Name: name}) 3133 return trace.Wrap(err) 3134 } 3135 3136 // ReplaceRemoteLocks replaces the set of locks associated with a remote cluster. 3137 func (c *Client) ReplaceRemoteLocks(ctx context.Context, clusterName string, locks []types.Lock) error { 3138 if clusterName == "" { 3139 return trace.BadParameter("missing cluster name") 3140 } 3141 lockV2s := make([]*types.LockV2, 0, len(locks)) 3142 for _, lock := range locks { 3143 lockV2, ok := lock.(*types.LockV2) 3144 if !ok { 3145 return trace.BadParameter("unexpected lock type %T", lock) 3146 } 3147 lockV2s = append(lockV2s, lockV2) 3148 } 3149 _, err := c.grpc.ReplaceRemoteLocks(ctx, &proto.ReplaceRemoteLocksRequest{ 3150 ClusterName: clusterName, 3151 Locks: lockV2s, 3152 }) 3153 return trace.Wrap(err) 3154 } 3155 3156 // GetNetworkRestrictions retrieves the network restrictions 3157 func (c *Client) GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) { 3158 nr, err := c.grpc.GetNetworkRestrictions(ctx, &emptypb.Empty{}) 3159 if err != nil { 3160 return nil, trace.Wrap(err) 3161 } 3162 return nr, nil 3163 } 3164 3165 // SetNetworkRestrictions updates the network restrictions 3166 func (c *Client) SetNetworkRestrictions(ctx context.Context, nr types.NetworkRestrictions) error { 3167 restrictionsV4, ok := nr.(*types.NetworkRestrictionsV4) 3168 if !ok { 3169 return trace.BadParameter("invalid type %T", nr) 3170 } 3171 _, err := c.grpc.SetNetworkRestrictions(ctx, restrictionsV4) 3172 if err != nil { 3173 return trace.Wrap(err) 3174 } 3175 return nil 3176 } 3177 3178 // DeleteNetworkRestrictions deletes the network restrictions 3179 func (c *Client) DeleteNetworkRestrictions(ctx context.Context) error { 3180 _, err := c.grpc.DeleteNetworkRestrictions(ctx, &emptypb.Empty{}) 3181 if err != nil { 3182 return trace.Wrap(err) 3183 } 3184 return nil 3185 } 3186 3187 // CreateApp creates a new application resource. 3188 func (c *Client) CreateApp(ctx context.Context, app types.Application) error { 3189 appV3, ok := app.(*types.AppV3) 3190 if !ok { 3191 return trace.BadParameter("unsupported application type %T", app) 3192 } 3193 _, err := c.grpc.CreateApp(ctx, appV3) 3194 return trace.Wrap(err) 3195 } 3196 3197 // UpdateApp updates existing application resource. 3198 func (c *Client) UpdateApp(ctx context.Context, app types.Application) error { 3199 appV3, ok := app.(*types.AppV3) 3200 if !ok { 3201 return trace.BadParameter("unsupported application type %T", app) 3202 } 3203 _, err := c.grpc.UpdateApp(ctx, appV3) 3204 return trace.Wrap(err) 3205 } 3206 3207 // GetApp returns the specified application resource. 3208 // 3209 // Note that application resources here refers to "dynamically-added" 3210 // applications such as applications created by `tctl create`, or the CreateApp 3211 // API. Applications defined in the `app_service.apps` section of the service 3212 // YAML configuration are not collected in this API. 3213 // 3214 // For a full list of registered applications that are served by an application 3215 // service, use GetApplicationServers instead. 3216 func (c *Client) GetApp(ctx context.Context, name string) (types.Application, error) { 3217 if name == "" { 3218 return nil, trace.BadParameter("missing application name") 3219 } 3220 app, err := c.grpc.GetApp(ctx, &types.ResourceRequest{Name: name}) 3221 if err != nil { 3222 return nil, trace.Wrap(err) 3223 } 3224 return app, nil 3225 } 3226 3227 // GetApps returns all application resources. 3228 // 3229 // Note that application resources here refers to "dynamically-added" 3230 // applications such as applications created by `tctl create`, or the CreateApp 3231 // API. Applications defined in the `app_service.apps` section of the service 3232 // YAML configuration are not collected in this API. 3233 // 3234 // For a full list of registered applications that are served by an application 3235 // service, use GetApplicationServers instead. 3236 func (c *Client) GetApps(ctx context.Context) ([]types.Application, error) { 3237 items, err := c.grpc.GetApps(ctx, &emptypb.Empty{}) 3238 if err != nil { 3239 return nil, trace.Wrap(err) 3240 } 3241 apps := make([]types.Application, len(items.Apps)) 3242 for i := range items.Apps { 3243 apps[i] = items.Apps[i] 3244 } 3245 return apps, nil 3246 } 3247 3248 // DeleteApp deletes specified application resource. 3249 func (c *Client) DeleteApp(ctx context.Context, name string) error { 3250 _, err := c.grpc.DeleteApp(ctx, &types.ResourceRequest{Name: name}) 3251 return trace.Wrap(err) 3252 } 3253 3254 // DeleteAllApps deletes all application resources. 3255 func (c *Client) DeleteAllApps(ctx context.Context) error { 3256 _, err := c.grpc.DeleteAllApps(ctx, &emptypb.Empty{}) 3257 return trace.Wrap(err) 3258 } 3259 3260 // CreateKubernetesCluster creates a new kubernetes cluster resource. 3261 func (c *Client) CreateKubernetesCluster(ctx context.Context, cluster types.KubeCluster) error { 3262 kubeClusterV3, ok := cluster.(*types.KubernetesClusterV3) 3263 if !ok { 3264 return trace.BadParameter("unsupported kubernetes cluster type %T", cluster) 3265 } 3266 _, err := c.grpc.CreateKubernetesCluster(ctx, kubeClusterV3) 3267 return trace.Wrap(err) 3268 } 3269 3270 // UpdateKubernetesCluster updates existing kubernetes cluster resource. 3271 func (c *Client) UpdateKubernetesCluster(ctx context.Context, cluster types.KubeCluster) error { 3272 kubeClusterV3, ok := cluster.(*types.KubernetesClusterV3) 3273 if !ok { 3274 return trace.BadParameter("unsupported kubernetes cluster type %T", cluster) 3275 } 3276 _, err := c.grpc.UpdateKubernetesCluster(ctx, kubeClusterV3) 3277 return trace.Wrap(err) 3278 } 3279 3280 // GetKubernetesCluster returns the specified kubernetes resource. 3281 func (c *Client) GetKubernetesCluster(ctx context.Context, name string) (types.KubeCluster, error) { 3282 if name == "" { 3283 return nil, trace.BadParameter("missing kubernetes cluster name") 3284 } 3285 cluster, err := c.grpc.GetKubernetesCluster(ctx, &types.ResourceRequest{Name: name}) 3286 if err != nil { 3287 return nil, trace.Wrap(err) 3288 } 3289 return cluster, nil 3290 } 3291 3292 // GetKubernetesClusters returns all kubernetes cluster resources. 3293 func (c *Client) GetKubernetesClusters(ctx context.Context) ([]types.KubeCluster, error) { 3294 items, err := c.grpc.GetKubernetesClusters(ctx, &emptypb.Empty{}) 3295 if err != nil { 3296 return nil, trace.Wrap(err) 3297 } 3298 clusters := make([]types.KubeCluster, len(items.KubernetesClusters)) 3299 for i := range items.KubernetesClusters { 3300 clusters[i] = items.KubernetesClusters[i] 3301 } 3302 return clusters, nil 3303 } 3304 3305 // DeleteKubernetesCluster deletes specified kubernetes cluster resource. 3306 func (c *Client) DeleteKubernetesCluster(ctx context.Context, name string) error { 3307 _, err := c.grpc.DeleteKubernetesCluster(ctx, &types.ResourceRequest{Name: name}) 3308 return trace.Wrap(err) 3309 } 3310 3311 // DeleteAllKubernetesClusters deletes all kubernetes cluster resources. 3312 func (c *Client) DeleteAllKubernetesClusters(ctx context.Context) error { 3313 _, err := c.grpc.DeleteAllKubernetesClusters(ctx, &emptypb.Empty{}) 3314 return trace.Wrap(err) 3315 } 3316 3317 // GetKubernetesWaitingContainerClient an unadorned KubeWaitingContainers 3318 // client, using the underlying Auth gRPC connection. 3319 func (c *Client) GetKubernetesWaitingContainerClient() *kubewaitingcontainerclient.Client { 3320 return kubewaitingcontainerclient.NewClient(kubewaitingcontainerpb.NewKubeWaitingContainersServiceClient(c.conn)) 3321 } 3322 3323 // ListKubernetesWaitingContainers lists Kubernetes ephemeral 3324 // containers that are waiting to be created until moderated 3325 // session conditions are met. 3326 func (c *Client) ListKubernetesWaitingContainers(ctx context.Context, pageSize int, pageToken string) ([]*kubewaitingcontainerpb.KubernetesWaitingContainer, string, error) { 3327 return c.GetKubernetesWaitingContainerClient().ListKubernetesWaitingContainers(ctx, pageSize, pageToken) 3328 } 3329 3330 // GetKubernetesWaitingContainer returns a Kubernetes ephemeral 3331 // container that are waiting to be created until moderated 3332 // session conditions are met. 3333 func (c *Client) GetKubernetesWaitingContainer(ctx context.Context, req *kubewaitingcontainerpb.GetKubernetesWaitingContainerRequest) (*kubewaitingcontainerpb.KubernetesWaitingContainer, error) { 3334 return c.GetKubernetesWaitingContainerClient().GetKubernetesWaitingContainer(ctx, req) 3335 } 3336 3337 // CreateKubernetesWaitingContainer creates a Kubernetes ephemeral 3338 // container that are waiting to be created until moderated 3339 // session conditions are met. 3340 func (c *Client) CreateKubernetesWaitingContainer(ctx context.Context, waitingPod *kubewaitingcontainerpb.KubernetesWaitingContainer) (*kubewaitingcontainerpb.KubernetesWaitingContainer, error) { 3341 return c.GetKubernetesWaitingContainerClient().CreateKubernetesWaitingContainer(ctx, waitingPod) 3342 } 3343 3344 // DeleteKubernetesWaitingContainer deletes a Kubernetes ephemeral 3345 // container that are waiting to be created until moderated 3346 // session conditions are met. 3347 func (c *Client) DeleteKubernetesWaitingContainer(ctx context.Context, req *kubewaitingcontainerpb.DeleteKubernetesWaitingContainerRequest) error { 3348 return c.GetKubernetesWaitingContainerClient().DeleteKubernetesWaitingContainer(ctx, req) 3349 } 3350 3351 // CreateDatabase creates a new database resource. 3352 func (c *Client) CreateDatabase(ctx context.Context, database types.Database) error { 3353 databaseV3, ok := database.(*types.DatabaseV3) 3354 if !ok { 3355 return trace.BadParameter("unsupported database type %T", database) 3356 } 3357 _, err := c.grpc.CreateDatabase(ctx, databaseV3) 3358 return trace.Wrap(err) 3359 } 3360 3361 // UpdateDatabase updates existing database resource. 3362 func (c *Client) UpdateDatabase(ctx context.Context, database types.Database) error { 3363 databaseV3, ok := database.(*types.DatabaseV3) 3364 if !ok { 3365 return trace.BadParameter("unsupported database type %T", database) 3366 } 3367 _, err := c.grpc.UpdateDatabase(ctx, databaseV3) 3368 return trace.Wrap(err) 3369 } 3370 3371 // GetDatabase returns the specified database resource. 3372 // 3373 // Note that database resources here refers to "dynamically-added" databases 3374 // such as databases created by `tctl create`, the discovery service, or the 3375 // CreateDatabase API. Databases discovered by the database agent (legacy 3376 // discovery flow using `database_service.aws/database_service.azure`) and 3377 // static databases defined in the `database_service.databases` section of the 3378 // service YAML configuration are not collected in this API. 3379 // 3380 // For a full list of registered databases that are served by a database 3381 // service, use GetDatabaseServers instead. 3382 func (c *Client) GetDatabase(ctx context.Context, name string) (types.Database, error) { 3383 if name == "" { 3384 return nil, trace.BadParameter("missing database name") 3385 } 3386 database, err := c.grpc.GetDatabase(ctx, &types.ResourceRequest{Name: name}) 3387 if err != nil { 3388 return nil, trace.Wrap(err) 3389 } 3390 return database, nil 3391 } 3392 3393 // GetDatabases returns all database resources. 3394 // 3395 // Note that database resources here refers to "dynamically-added" databases 3396 // such as databases created by `tctl create`, the discovery service, or the 3397 // CreateDatabase API. Databases discovered by the database agent (legacy 3398 // discovery flow using `database_service.aws/database_service.azure`) and 3399 // static databases defined in the `database_service.databases` section of the 3400 // service YAML configuration are not collected in this API. 3401 // 3402 // For a full list of registered databases that are served by a database 3403 // service, use GetDatabaseServers instead. 3404 func (c *Client) GetDatabases(ctx context.Context) ([]types.Database, error) { 3405 items, err := c.grpc.GetDatabases(ctx, &emptypb.Empty{}) 3406 if err != nil { 3407 return nil, trace.Wrap(err) 3408 } 3409 databases := make([]types.Database, len(items.Databases)) 3410 for i := range items.Databases { 3411 databases[i] = items.Databases[i] 3412 } 3413 return databases, nil 3414 } 3415 3416 // DeleteDatabase deletes specified database resource. 3417 func (c *Client) DeleteDatabase(ctx context.Context, name string) error { 3418 _, err := c.grpc.DeleteDatabase(ctx, &types.ResourceRequest{Name: name}) 3419 return trace.Wrap(err) 3420 } 3421 3422 // DeleteAllDatabases deletes all database resources. 3423 func (c *Client) DeleteAllDatabases(ctx context.Context) error { 3424 _, err := c.grpc.DeleteAllDatabases(ctx, &emptypb.Empty{}) 3425 return trace.Wrap(err) 3426 } 3427 3428 // UpsertDatabaseService creates or updates existing DatabaseService resource. 3429 func (c *Client) UpsertDatabaseService(ctx context.Context, service types.DatabaseService) (*types.KeepAlive, error) { 3430 serviceV1, ok := service.(*types.DatabaseServiceV1) 3431 if !ok { 3432 return nil, trace.BadParameter("unsupported DatabaseService type %T", serviceV1) 3433 } 3434 keepAlive, err := c.grpc.UpsertDatabaseService(ctx, &proto.UpsertDatabaseServiceRequest{ 3435 Service: serviceV1, 3436 }) 3437 3438 return keepAlive, trace.Wrap(err) 3439 } 3440 3441 // DeleteDatabaseService deletes a specific DatabaseService resource. 3442 func (c *Client) DeleteDatabaseService(ctx context.Context, name string) error { 3443 _, err := c.grpc.DeleteDatabaseService(ctx, &types.ResourceRequest{Name: name}) 3444 return trace.Wrap(err) 3445 } 3446 3447 // DeleteAllDatabaseServices deletes all DatabaseService resources. 3448 // If an error occurs, a partial delete may happen. 3449 func (c *Client) DeleteAllDatabaseServices(ctx context.Context) error { 3450 _, err := c.grpc.DeleteAllDatabaseServices(ctx, &proto.DeleteAllDatabaseServicesRequest{}) 3451 return trace.Wrap(err) 3452 } 3453 3454 // GetDatabaseObjectImportRules retrieves all database object import rules. 3455 func (c *Client) GetDatabaseObjectImportRules(ctx context.Context) ([]*dbobjectimportrulev1.DatabaseObjectImportRule, error) { 3456 var out []*dbobjectimportrulev1.DatabaseObjectImportRule 3457 req := &dbobjectimportrulev1.ListDatabaseObjectImportRulesRequest{} 3458 client := c.DatabaseObjectImportRuleClient() 3459 for { 3460 resp, err := client.ListDatabaseObjectImportRules(ctx, req) 3461 if err != nil { 3462 return nil, trace.Wrap(err) 3463 } 3464 out = append(out, resp.Rules...) 3465 3466 if resp.NextPageToken == "" { 3467 break 3468 } 3469 req.PageToken = resp.NextPageToken 3470 } 3471 3472 return out, nil 3473 } 3474 3475 // GetDatabaseObjects retrieves all database objects. 3476 func (c *Client) GetDatabaseObjects(ctx context.Context) ([]*dbobjectv1.DatabaseObject, error) { 3477 var out []*dbobjectv1.DatabaseObject 3478 req := &dbobjectv1.ListDatabaseObjectsRequest{} 3479 client := c.DatabaseObjectClient() 3480 for { 3481 resp, err := client.ListDatabaseObjects(ctx, req) 3482 if err != nil { 3483 return nil, trace.Wrap(err) 3484 } 3485 out = append(out, resp.Objects...) 3486 3487 if resp.NextPageToken == "" { 3488 break 3489 } 3490 req.PageToken = resp.NextPageToken 3491 } 3492 3493 return out, nil 3494 } 3495 3496 // GetWindowsDesktopServices returns all registered windows desktop services. 3497 func (c *Client) GetWindowsDesktopServices(ctx context.Context) ([]types.WindowsDesktopService, error) { 3498 resp, err := c.grpc.GetWindowsDesktopServices(ctx, &emptypb.Empty{}) 3499 if err != nil { 3500 return nil, trace.Wrap(err) 3501 } 3502 services := make([]types.WindowsDesktopService, 0, len(resp.GetServices())) 3503 for _, service := range resp.GetServices() { 3504 services = append(services, service) 3505 } 3506 return services, nil 3507 } 3508 3509 // GetWindowsDesktopService returns a registered windows desktop service by name. 3510 func (c *Client) GetWindowsDesktopService(ctx context.Context, name string) (types.WindowsDesktopService, error) { 3511 resp, err := c.grpc.GetWindowsDesktopService(ctx, &proto.GetWindowsDesktopServiceRequest{Name: name}) 3512 if err != nil { 3513 return nil, trace.Wrap(err) 3514 } 3515 return resp.GetService(), nil 3516 } 3517 3518 // UpsertWindowsDesktopService registers a new windows desktop service. 3519 func (c *Client) UpsertWindowsDesktopService(ctx context.Context, service types.WindowsDesktopService) (*types.KeepAlive, error) { 3520 s, ok := service.(*types.WindowsDesktopServiceV3) 3521 if !ok { 3522 return nil, trace.BadParameter("invalid type %T", service) 3523 } 3524 keepAlive, err := c.grpc.UpsertWindowsDesktopService(ctx, s) 3525 if err != nil { 3526 return nil, trace.Wrap(err) 3527 } 3528 return keepAlive, nil 3529 } 3530 3531 // DeleteWindowsDesktopService removes the specified windows desktop service. 3532 func (c *Client) DeleteWindowsDesktopService(ctx context.Context, name string) error { 3533 _, err := c.grpc.DeleteWindowsDesktopService(ctx, &proto.DeleteWindowsDesktopServiceRequest{ 3534 Name: name, 3535 }) 3536 if err != nil { 3537 return trace.Wrap(err) 3538 } 3539 return nil 3540 } 3541 3542 // DeleteAllWindowsDesktopServices removes all registered windows desktop services. 3543 func (c *Client) DeleteAllWindowsDesktopServices(ctx context.Context) error { 3544 _, err := c.grpc.DeleteAllWindowsDesktopServices(ctx, &emptypb.Empty{}) 3545 if err != nil { 3546 return trace.Wrap(err) 3547 } 3548 return nil 3549 } 3550 3551 // GetWindowsDesktops returns all registered windows desktop hosts. 3552 func (c *Client) GetWindowsDesktops(ctx context.Context, filter types.WindowsDesktopFilter) ([]types.WindowsDesktop, error) { 3553 resp, err := c.grpc.GetWindowsDesktops(ctx, &filter) 3554 if err != nil { 3555 return nil, trace.Wrap(err) 3556 } 3557 desktops := make([]types.WindowsDesktop, 0, len(resp.GetDesktops())) 3558 for _, desktop := range resp.GetDesktops() { 3559 desktops = append(desktops, desktop) 3560 } 3561 return desktops, nil 3562 } 3563 3564 // CreateWindowsDesktop registers a new windows desktop host. 3565 func (c *Client) CreateWindowsDesktop(ctx context.Context, desktop types.WindowsDesktop) error { 3566 d, ok := desktop.(*types.WindowsDesktopV3) 3567 if !ok { 3568 return trace.BadParameter("invalid type %T", desktop) 3569 } 3570 _, err := c.grpc.CreateWindowsDesktop(ctx, d) 3571 return trace.Wrap(err) 3572 } 3573 3574 // UpdateWindowsDesktop updates an existing windows desktop host. 3575 func (c *Client) UpdateWindowsDesktop(ctx context.Context, desktop types.WindowsDesktop) error { 3576 d, ok := desktop.(*types.WindowsDesktopV3) 3577 if !ok { 3578 return trace.BadParameter("invalid type %T", desktop) 3579 } 3580 _, err := c.grpc.UpdateWindowsDesktop(ctx, d) 3581 return trace.Wrap(err) 3582 } 3583 3584 // UpsertWindowsDesktop updates a windows desktop resource, creating it if it doesn't exist. 3585 func (c *Client) UpsertWindowsDesktop(ctx context.Context, desktop types.WindowsDesktop) error { 3586 d, ok := desktop.(*types.WindowsDesktopV3) 3587 if !ok { 3588 return trace.BadParameter("invalid type %T", desktop) 3589 } 3590 _, err := c.grpc.UpsertWindowsDesktop(ctx, d) 3591 return trace.Wrap(err) 3592 } 3593 3594 // DeleteWindowsDesktop removes the specified windows desktop host. 3595 // Note: unlike GetWindowsDesktops, this will delete at-most one desktop. 3596 // Passing an empty host ID will not trigger "delete all" behavior. To delete 3597 // all desktops, use DeleteAllWindowsDesktops. 3598 func (c *Client) DeleteWindowsDesktop(ctx context.Context, hostID, name string) error { 3599 _, err := c.grpc.DeleteWindowsDesktop(ctx, &proto.DeleteWindowsDesktopRequest{ 3600 Name: name, 3601 HostID: hostID, 3602 }) 3603 if err != nil { 3604 return trace.Wrap(err) 3605 } 3606 return nil 3607 } 3608 3609 // DeleteAllWindowsDesktops removes all registered windows desktop hosts. 3610 func (c *Client) DeleteAllWindowsDesktops(ctx context.Context) error { 3611 _, err := c.grpc.DeleteAllWindowsDesktops(ctx, &emptypb.Empty{}) 3612 if err != nil { 3613 return trace.Wrap(err) 3614 } 3615 return nil 3616 } 3617 3618 // GenerateWindowsDesktopCert generates client certificate for Windows RDP authentication. 3619 func (c *Client) GenerateWindowsDesktopCert(ctx context.Context, req *proto.WindowsDesktopCertRequest) (*proto.WindowsDesktopCertResponse, error) { 3620 resp, err := c.grpc.GenerateWindowsDesktopCert(ctx, req) 3621 if err != nil { 3622 return nil, trace.Wrap(err) 3623 } 3624 return resp, nil 3625 } 3626 3627 // ChangeUserAuthentication allows a user with a reset or invite token to change their password and if enabled also adds a new mfa device. 3628 // Upon success, creates new web session and creates new set of recovery codes (if user meets requirements). 3629 func (c *Client) ChangeUserAuthentication(ctx context.Context, req *proto.ChangeUserAuthenticationRequest) (*proto.ChangeUserAuthenticationResponse, error) { 3630 res, err := c.grpc.ChangeUserAuthentication(ctx, req) 3631 return res, trace.Wrap(err) 3632 } 3633 3634 // StartAccountRecovery creates a recovery start token for a user who successfully verified their username and their recovery code. 3635 // This token is used as part of a URL that will be emailed to the user (not done in this request). 3636 // Represents step 1 of the account recovery process. 3637 func (c *Client) StartAccountRecovery(ctx context.Context, req *proto.StartAccountRecoveryRequest) (types.UserToken, error) { 3638 res, err := c.grpc.StartAccountRecovery(ctx, req) 3639 return res, trace.Wrap(err) 3640 } 3641 3642 // VerifyAccountRecovery creates a recovery approved token after successful verification of users password or second factor 3643 // (authn depending on what user needed to recover). This token will allow users to perform protected actions while not logged in. 3644 // Represents step 2 of the account recovery process after RPC StartAccountRecovery. 3645 func (c *Client) VerifyAccountRecovery(ctx context.Context, req *proto.VerifyAccountRecoveryRequest) (types.UserToken, error) { 3646 res, err := c.grpc.VerifyAccountRecovery(ctx, req) 3647 return res, trace.Wrap(err) 3648 } 3649 3650 // CompleteAccountRecovery sets a new password or adds a new mfa device, 3651 // allowing user to regain access to their account using the new credentials. 3652 // Represents the last step in the account recovery process after RPC's StartAccountRecovery and VerifyAccountRecovery. 3653 func (c *Client) CompleteAccountRecovery(ctx context.Context, req *proto.CompleteAccountRecoveryRequest) error { 3654 _, err := c.grpc.CompleteAccountRecovery(ctx, req) 3655 return trace.Wrap(err) 3656 } 3657 3658 // CreateAccountRecoveryCodes creates new set of recovery codes for a user, replacing and invalidating any previously owned codes. 3659 func (c *Client) CreateAccountRecoveryCodes(ctx context.Context, req *proto.CreateAccountRecoveryCodesRequest) (*proto.RecoveryCodes, error) { 3660 res, err := c.grpc.CreateAccountRecoveryCodes(ctx, req) 3661 return res, trace.Wrap(err) 3662 } 3663 3664 // GetAccountRecoveryToken returns a user token resource after verifying the token in 3665 // request is not expired and is of the correct recovery type. 3666 func (c *Client) GetAccountRecoveryToken(ctx context.Context, req *proto.GetAccountRecoveryTokenRequest) (types.UserToken, error) { 3667 res, err := c.grpc.GetAccountRecoveryToken(ctx, req) 3668 return res, trace.Wrap(err) 3669 } 3670 3671 // GetAccountRecoveryCodes returns the user in context their recovery codes resource without any secrets. 3672 func (c *Client) GetAccountRecoveryCodes(ctx context.Context, req *proto.GetAccountRecoveryCodesRequest) (*proto.RecoveryCodes, error) { 3673 res, err := c.grpc.GetAccountRecoveryCodes(ctx, req) 3674 return res, trace.Wrap(err) 3675 } 3676 3677 // CreateAuthenticateChallenge creates and returns MFA challenges for a users registered MFA devices. 3678 func (c *Client) CreateAuthenticateChallenge(ctx context.Context, in *proto.CreateAuthenticateChallengeRequest) (*proto.MFAAuthenticateChallenge, error) { 3679 resp, err := c.grpc.CreateAuthenticateChallenge(ctx, in) 3680 return resp, trace.Wrap(err) 3681 } 3682 3683 // CreatePrivilegeToken is implemented by AuthService.CreatePrivilegeToken. 3684 func (c *Client) CreatePrivilegeToken(ctx context.Context, req *proto.CreatePrivilegeTokenRequest) (*types.UserTokenV3, error) { 3685 resp, err := c.grpc.CreatePrivilegeToken(ctx, req) 3686 return resp, trace.Wrap(err) 3687 } 3688 3689 // CreateRegisterChallenge creates and returns MFA register challenge for a new MFA device. 3690 func (c *Client) CreateRegisterChallenge(ctx context.Context, in *proto.CreateRegisterChallengeRequest) (*proto.MFARegisterChallenge, error) { 3691 resp, err := c.grpc.CreateRegisterChallenge(ctx, in) 3692 return resp, trace.Wrap(err) 3693 } 3694 3695 // GenerateCertAuthorityCRL generates an empty CRL for a CA. 3696 func (c *Client) GenerateCertAuthorityCRL(ctx context.Context, req *proto.CertAuthorityRequest) (*proto.CRL, error) { 3697 resp, err := c.grpc.GenerateCertAuthorityCRL(ctx, req) 3698 return resp, trace.Wrap(err) 3699 } 3700 3701 // ListResources returns a paginated list of nodes that the user has access to. 3702 // `nextKey` is used as `startKey` in another call to ListResources to retrieve 3703 // the next page. If you want to list all resources pages, check the 3704 // `GetResourcesWithFilters` function. 3705 // It will return a `trace.LimitExceeded` error if the page exceeds gRPC max 3706 // message size. 3707 func (c *Client) ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error) { 3708 if err := req.CheckAndSetDefaults(); err != nil { 3709 return nil, trace.Wrap(err) 3710 } 3711 3712 resp, err := c.grpc.ListResources(ctx, &req) 3713 if err != nil { 3714 return nil, trace.Wrap(err) 3715 } 3716 3717 resources := make([]types.ResourceWithLabels, len(resp.GetResources())) 3718 for i, respResource := range resp.GetResources() { 3719 switch req.ResourceType { 3720 case types.KindDatabaseServer: 3721 resources[i] = respResource.GetDatabaseServer() 3722 case types.KindDatabaseService: 3723 resources[i] = respResource.GetDatabaseService() 3724 case types.KindAppServer: 3725 resources[i] = respResource.GetAppServer() 3726 case types.KindNode: 3727 resources[i] = respResource.GetNode() 3728 case types.KindWindowsDesktop: 3729 resources[i] = respResource.GetWindowsDesktop() 3730 case types.KindWindowsDesktopService: 3731 resources[i] = respResource.GetWindowsDesktopService() 3732 case types.KindKubernetesCluster: 3733 resources[i] = respResource.GetKubeCluster() 3734 case types.KindKubeServer: 3735 resources[i] = respResource.GetKubernetesServer() 3736 case types.KindUserGroup: 3737 resources[i] = respResource.GetUserGroup() 3738 case types.KindAppOrSAMLIdPServiceProvider: 3739 //nolint:staticcheck // SA1019. TODO(sshah) DELETE IN 17.0 3740 resources[i] = respResource.GetAppServerOrSAMLIdPServiceProvider() 3741 case types.KindSAMLIdPServiceProvider: 3742 resources[i] = respResource.GetSAMLIdPServiceProvider() 3743 default: 3744 return nil, trace.NotImplemented("resource type %s does not support pagination", req.ResourceType) 3745 } 3746 } 3747 3748 return &types.ListResourcesResponse{ 3749 Resources: resources, 3750 NextKey: resp.NextKey, 3751 TotalCount: int(resp.TotalCount), 3752 }, nil 3753 } 3754 3755 // GetResources returns a paginated list of resources that the user has access to. 3756 // `nextKey` is used as `startKey` in another call to GetResources to retrieve 3757 // the next page. 3758 // It will return a `trace.LimitExceeded` error if the page exceeds gRPC max 3759 // message size. 3760 func (c *Client) GetResources(ctx context.Context, req *proto.ListResourcesRequest) (*proto.ListResourcesResponse, error) { 3761 if err := req.CheckAndSetDefaults(); err != nil { 3762 return nil, trace.Wrap(err) 3763 } 3764 3765 resp, err := c.grpc.ListResources(ctx, req) 3766 return resp, trace.Wrap(err) 3767 } 3768 3769 // ListUnifiedResources returns a paginated list of unified resources that the user has access to. 3770 // `nextKey` is used as `startKey` in another call to ListUnifiedResources to retrieve 3771 // the next page. 3772 // It will return a `trace.LimitExceeded` error if the page exceeds gRPC max 3773 // message size. 3774 func (c *Client) ListUnifiedResources(ctx context.Context, req *proto.ListUnifiedResourcesRequest) (*proto.ListUnifiedResourcesResponse, error) { 3775 if err := req.CheckAndSetDefaults(); err != nil { 3776 return nil, trace.Wrap(err) 3777 } 3778 3779 resp, err := c.grpc.ListUnifiedResources(ctx, req) 3780 return resp, trace.Wrap(err) 3781 } 3782 3783 // GetResourcesClient is an interface used by GetResources to abstract over implementations of 3784 // the ListResources method. 3785 type GetResourcesClient interface { 3786 GetResources(ctx context.Context, req *proto.ListResourcesRequest) (*proto.ListResourcesResponse, error) 3787 } 3788 3789 // ListUnifiedResourcesClient is an interface used by ListUnifiedResources to abstract over implementations of 3790 // the ListUnifiedResources method. 3791 type ListUnifiedResourcesClient interface { 3792 ListUnifiedResources(ctx context.Context, req *proto.ListUnifiedResourcesRequest) (*proto.ListUnifiedResourcesResponse, error) 3793 } 3794 3795 // ResourcePage holds a page of results from [GetResourcePage]. 3796 type ResourcePage[T types.ResourceWithLabels] struct { 3797 // Resources retrieved for a single [proto.ListResourcesRequest]. The length of 3798 // the slice will be at most [proto.ListResourcesRequest.Limit]. 3799 Resources []T 3800 // Total number of all resources matching the request. It will be greater than 3801 // the length of [Resources] if the number of matches exceeds the request limit. 3802 Total int 3803 // NextKey is the start of the next page 3804 NextKey string 3805 } 3806 3807 // convertEnrichedResource extracts the resource and any enriched information from the 3808 // PaginatedResource returned from the rpc ListUnifiedResources. 3809 func convertEnrichedResource(resource *proto.PaginatedResource) (*types.EnrichedResource, error) { 3810 if r := resource.GetNode(); r != nil { 3811 return &types.EnrichedResource{ResourceWithLabels: r, Logins: resource.Logins, RequiresRequest: resource.RequiresRequest}, nil 3812 } else if r := resource.GetDatabaseServer(); r != nil { 3813 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3814 } else if r := resource.GetDatabaseService(); r != nil { 3815 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3816 } else if r := resource.GetAppServerOrSAMLIdPServiceProvider(); r != nil { //nolint:staticcheck // SA1019. TODO(sshah) DELETE IN 17.0 3817 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3818 } else if r := resource.GetWindowsDesktop(); r != nil { 3819 return &types.EnrichedResource{ResourceWithLabels: r, Logins: resource.Logins, RequiresRequest: resource.RequiresRequest}, nil 3820 } else if r := resource.GetWindowsDesktopService(); r != nil { 3821 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3822 } else if r := resource.GetKubeCluster(); r != nil { 3823 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3824 } else if r := resource.GetKubernetesServer(); r != nil { 3825 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3826 } else if r := resource.GetUserGroup(); r != nil { 3827 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3828 } else if r := resource.GetAppServer(); r != nil { 3829 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3830 } else if r := resource.GetSAMLIdPServiceProvider(); r != nil { 3831 return &types.EnrichedResource{ResourceWithLabels: r, RequiresRequest: resource.RequiresRequest}, nil 3832 } else { 3833 return nil, trace.BadParameter("received unsupported resource %T", resource.Resource) 3834 } 3835 } 3836 3837 // GetUnifiedResourcePage is a helper for getting a single page of unified resources that match the provided request. 3838 func GetUnifiedResourcePage(ctx context.Context, clt ListUnifiedResourcesClient, req *proto.ListUnifiedResourcesRequest) ([]*types.EnrichedResource, string, error) { 3839 var out []*types.EnrichedResource 3840 3841 // Set the limit to the default size if one was not provided within 3842 // an acceptable range. 3843 if req.Limit <= 0 || req.Limit > int32(defaults.DefaultChunkSize) { 3844 req.Limit = int32(defaults.DefaultChunkSize) 3845 } 3846 3847 for { 3848 resp, err := clt.ListUnifiedResources(ctx, req) 3849 if err != nil { 3850 if trace.IsLimitExceeded(err) { 3851 // Cut chunkSize in half if gRPC max message size is exceeded. 3852 req.Limit /= 2 3853 // This is an extremely unlikely scenario, but better to cover it anyways. 3854 if req.Limit == 0 { 3855 return nil, "", trace.Wrap(err, "resource is too large to retrieve") 3856 } 3857 3858 continue 3859 } 3860 3861 return nil, "", trace.Wrap(err) 3862 } 3863 3864 for _, respResource := range resp.Resources { 3865 resource, err := convertEnrichedResource(respResource) 3866 if err != nil { 3867 return nil, "", trace.Wrap(err) 3868 } 3869 out = append(out, resource) 3870 } 3871 3872 return out, resp.NextKey, nil 3873 } 3874 } 3875 3876 // GetEnrichedResourcePage is a helper for getting a single page of enriched resources. 3877 func GetEnrichedResourcePage(ctx context.Context, clt GetResourcesClient, req *proto.ListResourcesRequest) (ResourcePage[*types.EnrichedResource], error) { 3878 var out ResourcePage[*types.EnrichedResource] 3879 3880 // Set the limit to the default size if one was not provided within 3881 // an acceptable range. 3882 if req.Limit <= 0 || req.Limit > int32(defaults.DefaultChunkSize) { 3883 req.Limit = int32(defaults.DefaultChunkSize) 3884 } 3885 3886 for { 3887 resp, err := clt.GetResources(ctx, req) 3888 if err != nil { 3889 if trace.IsLimitExceeded(err) { 3890 // Cut chunkSize in half if gRPC max message size is exceeded. 3891 req.Limit /= 2 3892 // This is an extremely unlikely scenario, but better to cover it anyways. 3893 if req.Limit == 0 { 3894 return out, trace.Wrap(err, "resource is too large to retrieve") 3895 } 3896 3897 continue 3898 } 3899 3900 return out, trace.Wrap(err) 3901 } 3902 3903 for _, respResource := range resp.Resources { 3904 var resource types.ResourceWithLabels 3905 switch req.ResourceType { 3906 case types.KindDatabaseServer: 3907 resource = respResource.GetDatabaseServer() 3908 case types.KindDatabaseService: 3909 resource = respResource.GetDatabaseService() 3910 case types.KindAppServer: 3911 resource = respResource.GetAppServer() 3912 case types.KindNode: 3913 resource = respResource.GetNode() 3914 case types.KindWindowsDesktop: 3915 resource = respResource.GetWindowsDesktop() 3916 case types.KindWindowsDesktopService: 3917 resource = respResource.GetWindowsDesktopService() 3918 case types.KindKubernetesCluster: 3919 resource = respResource.GetKubeCluster() 3920 case types.KindKubeServer: 3921 resource = respResource.GetKubernetesServer() 3922 case types.KindUserGroup: 3923 resource = respResource.GetUserGroup() 3924 case types.KindAppOrSAMLIdPServiceProvider: 3925 //nolint:staticcheck // SA1019. TODO(sshah) DELETE IN 17.0 3926 resource = respResource.GetAppServerOrSAMLIdPServiceProvider() 3927 case types.KindSAMLIdPServiceProvider: 3928 resource = respResource.GetSAMLIdPServiceProvider() 3929 default: 3930 out.Resources = nil 3931 return out, trace.NotImplemented("resource type %s does not support pagination", req.ResourceType) 3932 } 3933 3934 out.Resources = append(out.Resources, &types.EnrichedResource{ResourceWithLabels: resource, Logins: respResource.Logins}) 3935 } 3936 3937 out.NextKey = resp.NextKey 3938 out.Total = int(resp.TotalCount) 3939 3940 return out, nil 3941 } 3942 } 3943 3944 // GetResourcePage is a helper for getting a single page of resources that match the provide request. 3945 func GetResourcePage[T types.ResourceWithLabels](ctx context.Context, clt GetResourcesClient, req *proto.ListResourcesRequest) (ResourcePage[T], error) { 3946 var out ResourcePage[T] 3947 3948 // Set the limit to the default size if one was not provided within 3949 // an acceptable range. 3950 if req.Limit <= 0 || req.Limit > int32(defaults.DefaultChunkSize) { 3951 req.Limit = int32(defaults.DefaultChunkSize) 3952 } 3953 3954 for { 3955 resp, err := clt.GetResources(ctx, req) 3956 if err != nil { 3957 if trace.IsLimitExceeded(err) { 3958 // Cut chunkSize in half if gRPC max message size is exceeded. 3959 req.Limit /= 2 3960 // This is an extremely unlikely scenario, but better to cover it anyways. 3961 if req.Limit == 0 { 3962 return out, trace.Wrap(err, "resource is too large to retrieve") 3963 } 3964 3965 continue 3966 } 3967 3968 return out, trace.Wrap(err) 3969 } 3970 3971 for _, respResource := range resp.Resources { 3972 var resource types.ResourceWithLabels 3973 switch req.ResourceType { 3974 case types.KindDatabaseServer: 3975 resource = respResource.GetDatabaseServer() 3976 case types.KindDatabaseService: 3977 resource = respResource.GetDatabaseService() 3978 case types.KindAppServer: 3979 resource = respResource.GetAppServer() 3980 case types.KindNode: 3981 resource = respResource.GetNode() 3982 case types.KindWindowsDesktop: 3983 resource = respResource.GetWindowsDesktop() 3984 case types.KindWindowsDesktopService: 3985 resource = respResource.GetWindowsDesktopService() 3986 case types.KindKubernetesCluster: 3987 resource = respResource.GetKubeCluster() 3988 case types.KindKubeServer: 3989 resource = respResource.GetKubernetesServer() 3990 case types.KindUserGroup: 3991 resource = respResource.GetUserGroup() 3992 case types.KindAppOrSAMLIdPServiceProvider: 3993 //nolint:staticcheck // SA1019. TODO(sshah) DELETE IN 17.0 3994 resource = respResource.GetAppServerOrSAMLIdPServiceProvider() 3995 case types.KindSAMLIdPServiceProvider: 3996 resource = respResource.GetSAMLIdPServiceProvider() 3997 default: 3998 out.Resources = nil 3999 return out, trace.NotImplemented("resource type %s does not support pagination", req.ResourceType) 4000 } 4001 4002 t, ok := resource.(T) 4003 if !ok { 4004 out.Resources = nil 4005 return out, trace.BadParameter("received unexpected resource type %T", resource) 4006 } 4007 out.Resources = append(out.Resources, t) 4008 } 4009 4010 out.NextKey = resp.NextKey 4011 out.Total = int(resp.TotalCount) 4012 4013 return out, nil 4014 } 4015 } 4016 4017 // GetAllResources is a helper for getting all existing resources that match the provided request. In addition to 4018 // iterating pages, it also correctly handles downsizing pages when LimitExceeded errors are encountered. 4019 func GetAllResources[T types.ResourceWithLabels](ctx context.Context, clt GetResourcesClient, req *proto.ListResourcesRequest) ([]T, error) { 4020 var out []T 4021 4022 // Set the limit to the default size. 4023 req.Limit = int32(defaults.DefaultChunkSize) 4024 for { 4025 page, err := GetResourcePage[T](ctx, clt, req) 4026 if err != nil { 4027 return nil, trace.Wrap(err) 4028 } 4029 4030 out = append(out, page.Resources...) 4031 4032 if page.NextKey == "" || len(page.Resources) == 0 { 4033 break 4034 } 4035 4036 req.StartKey = page.NextKey 4037 } 4038 4039 return out, nil 4040 } 4041 4042 // ListResourcesClient is an interface used by GetResourcesWithFilters to abstract over implementations of 4043 // the ListResources method. 4044 type ListResourcesClient interface { 4045 ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error) 4046 } 4047 4048 // GetResourcesWithFilters is a helper for getting a list of resources with optional filtering. In addition to 4049 // iterating pages, it also correctly handles downsizing pages when LimitExceeded errors are encountered. 4050 // 4051 // GetAllResources or GetResourcePage should be preferred for client side operations to avoid converting 4052 // from []types.ResourceWithLabels to concrete types. 4053 func GetResourcesWithFilters(ctx context.Context, clt ListResourcesClient, req proto.ListResourcesRequest) ([]types.ResourceWithLabels, error) { 4054 // Retrieve the complete list of resources in chunks. 4055 var ( 4056 resources []types.ResourceWithLabels 4057 startKey string 4058 chunkSize = int32(defaults.DefaultChunkSize) 4059 ) 4060 4061 for { 4062 resp, err := clt.ListResources(ctx, proto.ListResourcesRequest{ 4063 Namespace: req.Namespace, 4064 ResourceType: req.ResourceType, 4065 StartKey: startKey, 4066 Limit: chunkSize, 4067 Labels: req.Labels, 4068 SearchKeywords: req.SearchKeywords, 4069 PredicateExpression: req.PredicateExpression, 4070 UseSearchAsRoles: req.UseSearchAsRoles, 4071 }) 4072 if err != nil { 4073 if trace.IsLimitExceeded(err) { 4074 // Cut chunkSize in half if gRPC max message size is exceeded. 4075 chunkSize = chunkSize / 2 4076 // This is an extremely unlikely scenario, but better to cover it anyways. 4077 if chunkSize == 0 { 4078 return nil, trace.Wrap(err, "resource is too large to retrieve") 4079 } 4080 4081 continue 4082 } 4083 4084 return nil, trace.Wrap(err) 4085 } 4086 4087 startKey = resp.NextKey 4088 resources = append(resources, resp.Resources...) 4089 if startKey == "" || len(resp.Resources) == 0 { 4090 break 4091 } 4092 4093 } 4094 4095 return resources, nil 4096 } 4097 4098 // GetKubernetesResourcesWithFilters is a helper for getting a list of kubernetes resources with optional filtering. In addition to 4099 // iterating pages, it also correctly handles downsizing pages when LimitExceeded errors are encountered. 4100 func GetKubernetesResourcesWithFilters(ctx context.Context, clt kubeproto.KubeServiceClient, req *kubeproto.ListKubernetesResourcesRequest) ([]types.ResourceWithLabels, error) { 4101 var ( 4102 resources []types.ResourceWithLabels 4103 startKey = req.StartKey 4104 // Retrieve the complete list of resources in chunks. 4105 chunkSize = req.Limit 4106 ) 4107 4108 // Set the chunk size to the default if it is not set. 4109 if chunkSize == 0 { 4110 chunkSize = int32(defaults.DefaultChunkSize) 4111 } 4112 4113 for { 4114 // Reset startKey to the previous page's nextKey. 4115 req.StartKey = startKey 4116 // Set the chunk size based on the previous chunk size error. 4117 req.Limit = chunkSize 4118 4119 resp, err := clt.ListKubernetesResources( 4120 ctx, 4121 req, 4122 ) 4123 if err != nil { 4124 if trace.IsLimitExceeded(err) { 4125 // Cut chunkSize in half if gRPC max message size is exceeded. 4126 chunkSize = chunkSize / 2 4127 // This is an extremely unlikely scenario, but better to cover it anyways. 4128 if chunkSize == 0 { 4129 return nil, trace.Wrap(err, "resource is too large to retrieve") 4130 } 4131 continue 4132 } 4133 return nil, trace.Wrap(err) 4134 } 4135 4136 startKey = resp.NextKey 4137 4138 resources = append(resources, types.KubeResources(resp.Resources).AsResources()...) 4139 if startKey == "" || len(resp.Resources) == 0 { 4140 break 4141 } 4142 } 4143 return resources, nil 4144 } 4145 4146 // GetSSHTargets gets all servers that would match an equivalent ssh dial request. Note that this method 4147 // returns all resources directly accessible to the user *and* all resources available via 'SearchAsRoles', 4148 // which is what we want when handling things like ambiguous host errors and resource-based access requests, 4149 // but may result in confusing behavior if it is used outside of those contexts. 4150 func (c *Client) GetSSHTargets(ctx context.Context, req *proto.GetSSHTargetsRequest) (*proto.GetSSHTargetsResponse, error) { 4151 rsp, err := c.grpc.GetSSHTargets(ctx, req) 4152 if err := trace.Wrap(err); !trace.IsNotImplemented(err) { 4153 return rsp, err 4154 } 4155 4156 // if we got a not implemented error, fallback to client-side filtering 4157 servers, err := GetAllResources[*types.ServerV2](ctx, c, &proto.ListResourcesRequest{ 4158 ResourceType: types.KindNode, 4159 UseSearchAsRoles: true, 4160 }) 4161 if err != nil { 4162 return nil, trace.Wrap(err) 4163 } 4164 4165 // we only get here if we hit a NotImplementedError from GetSSHTargets, which means 4166 // we should be performing client-side filtering with default parameters instead. 4167 routeMatcher := utils.NewSSHRouteMatcher(req.Host, req.Port, false) 4168 4169 // do client-side filtering 4170 filtered := servers[:0] 4171 for _, srv := range servers { 4172 if !routeMatcher.RouteToServer(srv) { 4173 continue 4174 } 4175 4176 filtered = append(filtered, srv) 4177 } 4178 4179 return &proto.GetSSHTargetsResponse{ 4180 Servers: filtered, 4181 }, nil 4182 } 4183 4184 // CreateSessionTracker creates a tracker resource for an active session. 4185 func (c *Client) CreateSessionTracker(ctx context.Context, st types.SessionTracker) (types.SessionTracker, error) { 4186 v1, ok := st.(*types.SessionTrackerV1) 4187 if !ok { 4188 return nil, trace.BadParameter("invalid type %T, expected *types.SessionTrackerV1", st) 4189 } 4190 4191 req := &proto.CreateSessionTrackerRequest{SessionTracker: v1} 4192 tracker, err := c.grpc.CreateSessionTracker(ctx, req) 4193 if err != nil { 4194 return nil, trace.Wrap(err) 4195 } 4196 return tracker, nil 4197 } 4198 4199 // GetSessionTracker returns the current state of a session tracker for an active session. 4200 func (c *Client) GetSessionTracker(ctx context.Context, sessionID string) (types.SessionTracker, error) { 4201 req := &proto.GetSessionTrackerRequest{SessionID: sessionID} 4202 resp, err := c.grpc.GetSessionTracker(ctx, req) 4203 if err != nil { 4204 return nil, trace.Wrap(err) 4205 } 4206 return resp, nil 4207 } 4208 4209 // GetActiveSessionTrackers returns a list of active session trackers. 4210 func (c *Client) GetActiveSessionTrackers(ctx context.Context) ([]types.SessionTracker, error) { 4211 stream, err := c.grpc.GetActiveSessionTrackers(ctx, &emptypb.Empty{}) 4212 if err != nil { 4213 return nil, trace.Wrap(err) 4214 } 4215 4216 var sessions []types.SessionTracker 4217 for { 4218 session, err := stream.Recv() 4219 if err != nil { 4220 if errors.Is(err, io.EOF) { 4221 break 4222 } 4223 4224 return nil, trace.Wrap(err) 4225 } 4226 4227 sessions = append(sessions, session) 4228 } 4229 4230 return sessions, nil 4231 } 4232 4233 // GetActiveSessionTrackersWithFilter returns a list of active sessions filtered by a filter. 4234 func (c *Client) GetActiveSessionTrackersWithFilter(ctx context.Context, filter *types.SessionTrackerFilter) ([]types.SessionTracker, error) { 4235 stream, err := c.grpc.GetActiveSessionTrackersWithFilter(ctx, filter) 4236 if err != nil { 4237 return nil, trace.Wrap(err) 4238 } 4239 4240 var sessions []types.SessionTracker 4241 for { 4242 session, err := stream.Recv() 4243 if err != nil { 4244 if errors.Is(err, io.EOF) { 4245 break 4246 } 4247 4248 return nil, trace.Wrap(err) 4249 } 4250 4251 sessions = append(sessions, session) 4252 } 4253 4254 return sessions, nil 4255 } 4256 4257 // RemoveSessionTracker removes a tracker resource for an active session. 4258 func (c *Client) RemoveSessionTracker(ctx context.Context, sessionID string) error { 4259 _, err := c.grpc.RemoveSessionTracker(ctx, &proto.RemoveSessionTrackerRequest{SessionID: sessionID}) 4260 return trace.Wrap(err) 4261 } 4262 4263 // UpdateSessionTracker updates a tracker resource for an active session. 4264 func (c *Client) UpdateSessionTracker(ctx context.Context, req *proto.UpdateSessionTrackerRequest) error { 4265 _, err := c.grpc.UpdateSessionTracker(ctx, req) 4266 return trace.Wrap(err) 4267 } 4268 4269 // MaintainSessionPresence establishes a channel used to continuously verify the presence for a session. 4270 func (c *Client) MaintainSessionPresence(ctx context.Context) (proto.AuthService_MaintainSessionPresenceClient, error) { 4271 stream, err := c.grpc.MaintainSessionPresence(ctx) 4272 return stream, trace.Wrap(err) 4273 } 4274 4275 // GetDomainName returns local auth domain of the current auth server 4276 func (c *Client) GetDomainName(ctx context.Context) (string, error) { 4277 resp, err := c.grpc.GetDomainName(ctx, &emptypb.Empty{}) 4278 if err != nil { 4279 return "", trace.Wrap(err) 4280 } 4281 return resp.DomainName, nil 4282 } 4283 4284 // GetClusterCACert returns the PEM-encoded TLS certs for the local cluster. If 4285 // the cluster has multiple TLS certs, they will all be concatenated. 4286 func (c *Client) GetClusterCACert(ctx context.Context) (*proto.GetClusterCACertResponse, error) { 4287 resp, err := c.grpc.GetClusterCACert(ctx, &emptypb.Empty{}) 4288 if err != nil { 4289 return nil, trace.Wrap(err) 4290 } 4291 return resp, nil 4292 } 4293 4294 // GetConnectionDiagnostic reads a connection diagnostic 4295 func (c *Client) GetConnectionDiagnostic(ctx context.Context, name string) (types.ConnectionDiagnostic, error) { 4296 req := &proto.GetConnectionDiagnosticRequest{ 4297 Name: name, 4298 } 4299 res, err := c.grpc.GetConnectionDiagnostic(ctx, req) 4300 return res, trace.Wrap(err) 4301 } 4302 4303 // CreateConnectionDiagnostic creates a new connection diagnostic. 4304 func (c *Client) CreateConnectionDiagnostic(ctx context.Context, connectionDiagnostic types.ConnectionDiagnostic) error { 4305 connectionDiagnosticV1, ok := connectionDiagnostic.(*types.ConnectionDiagnosticV1) 4306 if !ok { 4307 return trace.BadParameter("invalid type %T", connectionDiagnostic) 4308 } 4309 _, err := c.grpc.CreateConnectionDiagnostic(ctx, connectionDiagnosticV1) 4310 return trace.Wrap(err) 4311 } 4312 4313 // UpdateConnectionDiagnostic updates a connection diagnostic. 4314 func (c *Client) UpdateConnectionDiagnostic(ctx context.Context, connectionDiagnostic types.ConnectionDiagnostic) error { 4315 connectionDiagnosticV1, ok := connectionDiagnostic.(*types.ConnectionDiagnosticV1) 4316 if !ok { 4317 return trace.BadParameter("invalid type %T", connectionDiagnostic) 4318 } 4319 _, err := c.grpc.UpdateConnectionDiagnostic(ctx, connectionDiagnosticV1) 4320 return trace.Wrap(err) 4321 } 4322 4323 // AppendDiagnosticTrace adds a new trace for the given ConnectionDiagnostic. 4324 func (c *Client) AppendDiagnosticTrace(ctx context.Context, name string, t *types.ConnectionDiagnosticTrace) (types.ConnectionDiagnostic, error) { 4325 req := &proto.AppendDiagnosticTraceRequest{ 4326 Name: name, 4327 Trace: t, 4328 } 4329 connectionDiagnostic, err := c.grpc.AppendDiagnosticTrace(ctx, req) 4330 if err != nil { 4331 return nil, trace.Wrap(err) 4332 } 4333 4334 return connectionDiagnostic, nil 4335 } 4336 4337 // GetClusterAlerts loads matching cluster alerts. 4338 func (c *Client) GetClusterAlerts(ctx context.Context, query types.GetClusterAlertsRequest) ([]types.ClusterAlert, error) { 4339 rsp, err := c.grpc.GetClusterAlerts(ctx, &query) 4340 if err != nil { 4341 return nil, trace.Wrap(err) 4342 } 4343 return rsp.Alerts, nil 4344 } 4345 4346 // UpsertClusterAlert creates a cluster alert. 4347 func (c *Client) UpsertClusterAlert(ctx context.Context, alert types.ClusterAlert) error { 4348 _, err := c.grpc.UpsertClusterAlert(ctx, &proto.UpsertClusterAlertRequest{ 4349 Alert: alert, 4350 }) 4351 return trace.Wrap(err) 4352 } 4353 4354 func (c *Client) ChangePassword(ctx context.Context, req *proto.ChangePasswordRequest) error { 4355 _, err := c.grpc.ChangePassword(ctx, req) 4356 return trace.Wrap(err) 4357 } 4358 4359 // SubmitUsageEvent submits an external usage event. 4360 func (c *Client) SubmitUsageEvent(ctx context.Context, req *proto.SubmitUsageEventRequest) error { 4361 _, err := c.grpc.SubmitUsageEvent(ctx, req) 4362 4363 return trace.Wrap(err) 4364 } 4365 4366 // GetLicense returns the license used to start the teleport enterprise auth server 4367 func (c *Client) GetLicense(ctx context.Context) (string, error) { 4368 resp, err := c.grpc.GetLicense(ctx, &proto.GetLicenseRequest{}) 4369 if err != nil { 4370 return "", trace.Wrap(err) 4371 } 4372 return string(resp.License), nil 4373 } 4374 4375 // ListReleases returns a list of teleport enterprise releases 4376 func (c *Client) ListReleases(ctx context.Context, req *proto.ListReleasesRequest) ([]*types.Release, error) { 4377 resp, err := c.grpc.ListReleases(ctx, req) 4378 if err != nil { 4379 return nil, trace.Wrap(err) 4380 } 4381 4382 return resp.Releases, nil 4383 } 4384 4385 // CreateAlertAck marks a cluster alert as acknowledged. 4386 func (c *Client) CreateAlertAck(ctx context.Context, ack types.AlertAcknowledgement) error { 4387 _, err := c.grpc.CreateAlertAck(ctx, &ack) 4388 return trace.Wrap(err) 4389 } 4390 4391 // GetAlertAcks gets active alert acknowledgements. 4392 func (c *Client) GetAlertAcks(ctx context.Context) ([]types.AlertAcknowledgement, error) { 4393 rsp, err := c.grpc.GetAlertAcks(ctx, &proto.GetAlertAcksRequest{}) 4394 if err != nil { 4395 return nil, trace.Wrap(err) 4396 } 4397 return rsp.Acks, nil 4398 } 4399 4400 // ClearAlertAcks clears alert acknowledgments. 4401 func (c *Client) ClearAlertAcks(ctx context.Context, req proto.ClearAlertAcksRequest) error { 4402 _, err := c.grpc.ClearAlertAcks(ctx, &req) 4403 return trace.Wrap(err) 4404 } 4405 4406 // ListSAMLIdPServiceProviders returns a paginated list of SAML IdP service provider resources. 4407 func (c *Client) ListSAMLIdPServiceProviders(ctx context.Context, pageSize int, nextKey string) ([]types.SAMLIdPServiceProvider, string, error) { 4408 resp, err := c.grpc.ListSAMLIdPServiceProviders(ctx, &proto.ListSAMLIdPServiceProvidersRequest{ 4409 Limit: int32(pageSize), 4410 NextKey: nextKey, 4411 }) 4412 if err != nil { 4413 return nil, "", trace.Wrap(err) 4414 } 4415 serviceProviders := make([]types.SAMLIdPServiceProvider, 0, len(resp.GetServiceProviders())) 4416 for _, sp := range resp.GetServiceProviders() { 4417 serviceProviders = append(serviceProviders, sp) 4418 } 4419 return serviceProviders, resp.GetNextKey(), nil 4420 } 4421 4422 // GetSAMLIdPServiceProvider returns the specified SAML IdP service provider resources. 4423 func (c *Client) GetSAMLIdPServiceProvider(ctx context.Context, name string) (types.SAMLIdPServiceProvider, error) { 4424 sp, err := c.grpc.GetSAMLIdPServiceProvider(ctx, &proto.GetSAMLIdPServiceProviderRequest{ 4425 Name: name, 4426 }) 4427 if err != nil { 4428 return nil, trace.Wrap(err) 4429 } 4430 return sp, nil 4431 } 4432 4433 // CreateSAMLIdPServiceProvider creates a new SAML IdP service provider resource. 4434 func (c *Client) CreateSAMLIdPServiceProvider(ctx context.Context, sp types.SAMLIdPServiceProvider) error { 4435 spV1, ok := sp.(*types.SAMLIdPServiceProviderV1) 4436 if !ok { 4437 return trace.BadParameter("unsupported SAML IdP service provider type %T", sp) 4438 } 4439 4440 _, err := c.grpc.CreateSAMLIdPServiceProvider(ctx, spV1) 4441 if err != nil { 4442 return trace.Wrap(err) 4443 } 4444 return nil 4445 } 4446 4447 // UpdateSAMLIdPServiceProvider updates an existing SAML IdP service provider resource. 4448 func (c *Client) UpdateSAMLIdPServiceProvider(ctx context.Context, sp types.SAMLIdPServiceProvider) error { 4449 spV1, ok := sp.(*types.SAMLIdPServiceProviderV1) 4450 if !ok { 4451 return trace.BadParameter("unsupported SAML IdP service provider type %T", sp) 4452 } 4453 4454 _, err := c.grpc.UpdateSAMLIdPServiceProvider(ctx, spV1) 4455 if err != nil { 4456 return trace.Wrap(err) 4457 } 4458 return nil 4459 } 4460 4461 // DeleteSAMLIdPServiceProvider removes the specified SAML IdP service provider resource. 4462 func (c *Client) DeleteSAMLIdPServiceProvider(ctx context.Context, name string) error { 4463 _, err := c.grpc.DeleteSAMLIdPServiceProvider(ctx, &proto.DeleteSAMLIdPServiceProviderRequest{ 4464 Name: name, 4465 }) 4466 if err != nil { 4467 return trace.Wrap(err) 4468 } 4469 return nil 4470 } 4471 4472 // DeleteAllSAMLIdPServiceProviders removes all SAML IdP service providers. 4473 func (c *Client) DeleteAllSAMLIdPServiceProviders(ctx context.Context) error { 4474 _, err := c.grpc.DeleteAllSAMLIdPServiceProviders(ctx, &emptypb.Empty{}) 4475 if err != nil { 4476 return trace.Wrap(err) 4477 } 4478 return nil 4479 } 4480 4481 // ListUserGroups returns a paginated list of SAML IdP service provider resources. 4482 func (c *Client) ListUserGroups(ctx context.Context, pageSize int, nextKey string) ([]types.UserGroup, string, error) { 4483 resp, err := c.grpc.ListUserGroups(ctx, &proto.ListUserGroupsRequest{ 4484 Limit: int32(pageSize), 4485 NextKey: nextKey, 4486 }) 4487 if err != nil { 4488 return nil, "", trace.Wrap(err) 4489 } 4490 userGroups := make([]types.UserGroup, 0, len(resp.GetUserGroups())) 4491 for _, ug := range resp.GetUserGroups() { 4492 userGroups = append(userGroups, ug) 4493 } 4494 return userGroups, resp.GetNextKey(), nil 4495 } 4496 4497 // GetUserGroup returns the specified SAML IdP service provider resources. 4498 func (c *Client) GetUserGroup(ctx context.Context, name string) (types.UserGroup, error) { 4499 ug, err := c.grpc.GetUserGroup(ctx, &proto.GetUserGroupRequest{ 4500 Name: name, 4501 }) 4502 if err != nil { 4503 return nil, trace.Wrap(err) 4504 } 4505 return ug, nil 4506 } 4507 4508 // CreateUserGroup creates a new user group resource. 4509 func (c *Client) CreateUserGroup(ctx context.Context, ug types.UserGroup) error { 4510 ugV1, ok := ug.(*types.UserGroupV1) 4511 if !ok { 4512 return trace.BadParameter("unsupported user group type %T", ug) 4513 } 4514 4515 _, err := c.grpc.CreateUserGroup(ctx, ugV1) 4516 if err != nil { 4517 return trace.Wrap(err) 4518 } 4519 return nil 4520 } 4521 4522 // UpdateUserGroup updates an existing user group resource. 4523 func (c *Client) UpdateUserGroup(ctx context.Context, ug types.UserGroup) error { 4524 ugV1, ok := ug.(*types.UserGroupV1) 4525 if !ok { 4526 return trace.BadParameter("unsupported user group type %T", ug) 4527 } 4528 4529 _, err := c.grpc.UpdateUserGroup(ctx, ugV1) 4530 if err != nil { 4531 return trace.Wrap(err) 4532 } 4533 return nil 4534 } 4535 4536 // DeleteUserGroup removes the specified user group resource. 4537 func (c *Client) DeleteUserGroup(ctx context.Context, name string) error { 4538 _, err := c.grpc.DeleteUserGroup(ctx, &proto.DeleteUserGroupRequest{ 4539 Name: name, 4540 }) 4541 if err != nil { 4542 return trace.Wrap(err) 4543 } 4544 return nil 4545 } 4546 4547 // DeleteAllUserGroups removes all user groups. 4548 func (c *Client) DeleteAllUserGroups(ctx context.Context) error { 4549 _, err := c.grpc.DeleteAllUserGroups(ctx, &emptypb.Empty{}) 4550 if err != nil { 4551 return trace.Wrap(err) 4552 } 4553 return nil 4554 } 4555 4556 // ExportUpgradeWindows is used to load derived upgrade window values for agents that 4557 // need to export schedules to external upgraders. 4558 func (c *Client) ExportUpgradeWindows(ctx context.Context, req proto.ExportUpgradeWindowsRequest) (proto.ExportUpgradeWindowsResponse, error) { 4559 rsp, err := c.grpc.ExportUpgradeWindows(ctx, &req) 4560 if err != nil { 4561 return proto.ExportUpgradeWindowsResponse{}, trace.Wrap(err) 4562 } 4563 return *rsp, nil 4564 } 4565 4566 // GetClusterMaintenanceConfig gets the current maintenance window config singleton. 4567 func (c *Client) GetClusterMaintenanceConfig(ctx context.Context) (types.ClusterMaintenanceConfig, error) { 4568 rsp, err := c.grpc.GetClusterMaintenanceConfig(ctx, &emptypb.Empty{}) 4569 if err != nil { 4570 return nil, trace.Wrap(err) 4571 } 4572 return rsp, nil 4573 } 4574 4575 // UpdateClusterMaintenanceConfig updates the current maintenance window config singleton. 4576 func (c *Client) UpdateClusterMaintenanceConfig(ctx context.Context, cmc types.ClusterMaintenanceConfig) error { 4577 req, ok := cmc.(*types.ClusterMaintenanceConfigV1) 4578 if !ok { 4579 return trace.BadParameter("unexpected maintenance config type: %T", cmc) 4580 } 4581 4582 _, err := c.grpc.UpdateClusterMaintenanceConfig(ctx, req) 4583 return trace.Wrap(err) 4584 } 4585 4586 // DeleteClusterMaintenanceConfig deletes the current maintenance window config singleton. 4587 func (c *Client) DeleteClusterMaintenanceConfig(ctx context.Context) error { 4588 _, err := c.grpc.DeleteClusterMaintenanceConfig(ctx, &emptypb.Empty{}) 4589 return trace.Wrap(err) 4590 } 4591 4592 // integrationsClient returns an unadorned Integration client, using the underlying 4593 // Auth gRPC connection. 4594 func (c *Client) integrationsClient() integrationpb.IntegrationServiceClient { 4595 return integrationpb.NewIntegrationServiceClient(c.conn) 4596 } 4597 4598 // ListIntegrations returns a paginated list of Integrations. 4599 // The response includes a nextKey which must be used to fetch the next page. 4600 func (c *Client) ListIntegrations(ctx context.Context, pageSize int, nextKey string) ([]types.Integration, string, error) { 4601 resp, err := c.integrationsClient().ListIntegrations(ctx, &integrationpb.ListIntegrationsRequest{ 4602 Limit: int32(pageSize), 4603 NextKey: nextKey, 4604 }) 4605 if err != nil { 4606 return nil, "", trace.Wrap(err) 4607 } 4608 4609 integrations := make([]types.Integration, 0, len(resp.GetIntegrations())) 4610 for _, ig := range resp.GetIntegrations() { 4611 integrations = append(integrations, ig) 4612 } 4613 4614 return integrations, resp.GetNextKey(), nil 4615 } 4616 4617 // ListAllIntegrations returns the list of all Integrations. 4618 func (c *Client) ListAllIntegrations(ctx context.Context) ([]types.Integration, error) { 4619 var result []types.Integration 4620 var nextKey string 4621 for { 4622 integrations, nextKey, err := c.ListIntegrations(ctx, 0, nextKey) 4623 if err != nil { 4624 return nil, trace.Wrap(err) 4625 } 4626 result = append(result, integrations...) 4627 if nextKey == "" { 4628 return result, nil 4629 } 4630 } 4631 } 4632 4633 // GetIntegration returns an Integration by its name. 4634 func (c *Client) GetIntegration(ctx context.Context, name string) (types.Integration, error) { 4635 ig, err := c.integrationsClient().GetIntegration(ctx, &integrationpb.GetIntegrationRequest{ 4636 Name: name, 4637 }) 4638 if err != nil { 4639 return nil, trace.Wrap(err) 4640 } 4641 4642 return ig, nil 4643 } 4644 4645 // CreateIntegration creates a new Integration. 4646 func (c *Client) CreateIntegration(ctx context.Context, ig types.Integration) (types.Integration, error) { 4647 igV1, ok := ig.(*types.IntegrationV1) 4648 if !ok { 4649 return nil, trace.BadParameter("unsupported integration type %T", ig) 4650 } 4651 4652 ig, err := c.integrationsClient().CreateIntegration(ctx, &integrationpb.CreateIntegrationRequest{Integration: igV1}) 4653 if err != nil { 4654 return nil, trace.Wrap(err) 4655 } 4656 4657 return ig, nil 4658 } 4659 4660 // UpdateIntegration updates an existing Integration. 4661 func (c *Client) UpdateIntegration(ctx context.Context, ig types.Integration) (types.Integration, error) { 4662 igV1, ok := ig.(*types.IntegrationV1) 4663 if !ok { 4664 return nil, trace.BadParameter("unsupported integration type %T", ig) 4665 } 4666 4667 ig, err := c.integrationsClient().UpdateIntegration(ctx, &integrationpb.UpdateIntegrationRequest{Integration: igV1}) 4668 if err != nil { 4669 return nil, trace.Wrap(err) 4670 } 4671 4672 return ig, nil 4673 } 4674 4675 // DeleteIntegration removes an Integration by its name. 4676 func (c *Client) DeleteIntegration(ctx context.Context, name string) error { 4677 _, err := c.integrationsClient().DeleteIntegration(ctx, &integrationpb.DeleteIntegrationRequest{ 4678 Name: name, 4679 }) 4680 return trace.Wrap(err) 4681 } 4682 4683 // DeleteAllIntegrations removes all Integrations. 4684 func (c *Client) DeleteAllIntegrations(ctx context.Context) error { 4685 _, err := c.integrationsClient().DeleteAllIntegrations(ctx, &integrationpb.DeleteAllIntegrationsRequest{}) 4686 return trace.Wrap(err) 4687 } 4688 4689 // GenerateAWSOIDCToken generates a token to be used when executing an AWS OIDC Integration action. 4690 func (c *Client) GenerateAWSOIDCToken(ctx context.Context, integration string) (string, error) { 4691 resp, err := c.integrationsClient().GenerateAWSOIDCToken(ctx, &integrationpb.GenerateAWSOIDCTokenRequest{ 4692 Integration: integration, 4693 }) 4694 if err != nil { 4695 return "", trace.Wrap(err) 4696 } 4697 4698 return resp.GetToken(), nil 4699 } 4700 4701 // PluginsClient returns an unadorned Plugins client, using the underlying 4702 // Auth gRPC connection. 4703 // Clients connecting to non-Enterprise clusters, or older Teleport versions, 4704 // still get a plugins client when calling this method, but all RPCs will return 4705 // "not implemented" errors (as per the default gRPC behavior). 4706 func (c *Client) PluginsClient() pluginspb.PluginServiceClient { 4707 return pluginspb.NewPluginServiceClient(c.conn) 4708 } 4709 4710 // GetLoginRule retrieves a login rule described by name. 4711 func (c *Client) GetLoginRule(ctx context.Context, name string) (*loginrulepb.LoginRule, error) { 4712 rule, err := c.LoginRuleClient().GetLoginRule(ctx, &loginrulepb.GetLoginRuleRequest{ 4713 Name: name, 4714 }) 4715 return rule, trace.Wrap(err) 4716 } 4717 4718 // CreateLoginRule creates a login rule if one with the same name does not 4719 // already exist, else it returns an error. 4720 func (c *Client) CreateLoginRule(ctx context.Context, rule *loginrulepb.LoginRule) (*loginrulepb.LoginRule, error) { 4721 rule, err := c.LoginRuleClient().CreateLoginRule(ctx, &loginrulepb.CreateLoginRuleRequest{ 4722 LoginRule: rule, 4723 }) 4724 return rule, trace.Wrap(err) 4725 } 4726 4727 // UpsertLoginRule creates a login rule if one with the same name does not 4728 // already exist, else it replaces the existing login rule. 4729 func (c *Client) UpsertLoginRule(ctx context.Context, rule *loginrulepb.LoginRule) (*loginrulepb.LoginRule, error) { 4730 rule, err := c.LoginRuleClient().UpsertLoginRule(ctx, &loginrulepb.UpsertLoginRuleRequest{ 4731 LoginRule: rule, 4732 }) 4733 return rule, trace.Wrap(err) 4734 } 4735 4736 // DeleteLoginRule deletes an existing login rule by name. 4737 func (c *Client) DeleteLoginRule(ctx context.Context, name string) error { 4738 _, err := c.LoginRuleClient().DeleteLoginRule(ctx, &loginrulepb.DeleteLoginRuleRequest{ 4739 Name: name, 4740 }) 4741 return trace.Wrap(err) 4742 } 4743 4744 // OktaClient returns an Okta client. 4745 // Clients connecting older Teleport versions still get an okta client when 4746 // calling this method, but all RPCs will return "not implemented" errors (as per 4747 // the default gRPC behavior). 4748 func (c *Client) OktaClient() *okta.Client { 4749 return okta.NewClient(oktapb.NewOktaServiceClient(c.conn)) 4750 } 4751 4752 func (c *Client) SCIMClient() *scim.Client { 4753 return scim.NewClientFromConn(c.conn) 4754 } 4755 4756 // AccessListClient returns an access list client. 4757 // Clients connecting to older Teleport versions, still get an access list client 4758 // when calling this method, but all RPCs will return "not implemented" errors 4759 // (as per the default gRPC behavior). 4760 func (c *Client) AccessListClient() *accesslist.Client { 4761 return accesslist.NewClient(accesslistv1.NewAccessListServiceClient(c.conn)) 4762 } 4763 4764 // AccessMonitoringRulesClient returns an Access Monitoring Rules client. 4765 // Clients connecting to older Teleport versions, still get an access list client 4766 // when calling this method, but all RPCs will return "not implemented" errors 4767 // (as per the default gRPC behavior). 4768 func (c *Client) AccessMonitoringRulesClient() *accessmonitoringrules.Client { 4769 return accessmonitoringrules.NewClient(accessmonitoringrulev1.NewAccessMonitoringRulesServiceClient(c.conn)) 4770 } 4771 4772 // DatabaseObjectImportRuleClient returns a client for managing database object import rules. 4773 func (c *Client) DatabaseObjectImportRuleClient() dbobjectimportrulev1.DatabaseObjectImportRuleServiceClient { 4774 return dbobjectimportrulev1.NewDatabaseObjectImportRuleServiceClient(c.conn) 4775 } 4776 4777 // DatabaseObjectClient returns a client for managing database objects. 4778 func (c *Client) DatabaseObjectClient() dbobjectv1.DatabaseObjectServiceClient { 4779 return dbobjectv1.NewDatabaseObjectServiceClient(c.conn) 4780 } 4781 4782 // DiscoveryConfigClient returns a DiscoveryConfig client. 4783 // Clients connecting to older Teleport versions, still get an DiscoveryConfig client 4784 // when calling this method, but all RPCs will return "not implemented" errors 4785 // (as per the default gRPC behavior). 4786 func (c *Client) DiscoveryConfigClient() *discoveryconfig.Client { 4787 return discoveryconfig.NewClient(discoveryconfigv1.NewDiscoveryConfigServiceClient(c.conn)) 4788 } 4789 4790 // CrownJewelServiceClient returns a CrownJewel client. 4791 // Clients connecting to older Teleport versions, still get a CrownJewel client 4792 // when calling this method, but all RPCs will return "not implemented" errors 4793 // (as per the default gRPC behavior). 4794 func (c *Client) CrownJewelServiceClient() *crownjewelapi.Client { 4795 return crownjewel.NewClient(crownjewelv1.NewCrownJewelServiceClient(c.conn)) 4796 } 4797 4798 // UserLoginStateClient returns a user login state client. 4799 // Clients connecting to older Teleport versions, still get a user login state client 4800 // when calling this method, but all RPCs will return "not implemented" errors 4801 // (as per the default gRPC behavior). 4802 func (c *Client) UserLoginStateClient() *userloginstate.Client { 4803 return userloginstate.NewClient(userloginstatev1.NewUserLoginStateServiceClient(c.conn)) 4804 } 4805 4806 // GetCertAuthority retrieves a CA by type and domain. 4807 func (c *Client) GetCertAuthority(ctx context.Context, id types.CertAuthID, loadKeys bool) (types.CertAuthority, error) { 4808 ca, err := c.TrustClient().GetCertAuthority(ctx, &trustpb.GetCertAuthorityRequest{ 4809 Type: string(id.Type), 4810 Domain: id.DomainName, 4811 IncludeKey: loadKeys, 4812 }) 4813 4814 return ca, trace.Wrap(err) 4815 } 4816 4817 // GetCertAuthorities retrieves CAs by type. 4818 func (c *Client) GetCertAuthorities(ctx context.Context, caType types.CertAuthType, loadKeys bool) ([]types.CertAuthority, error) { 4819 resp, err := c.TrustClient().GetCertAuthorities(ctx, &trustpb.GetCertAuthoritiesRequest{ 4820 Type: string(caType), 4821 IncludeKey: loadKeys, 4822 }) 4823 if err != nil { 4824 return nil, trace.Wrap(err) 4825 } 4826 4827 cas := make([]types.CertAuthority, 0, len(resp.CertAuthoritiesV2)) 4828 for _, ca := range resp.CertAuthoritiesV2 { 4829 cas = append(cas, ca) 4830 } 4831 4832 return cas, nil 4833 } 4834 4835 // DeleteCertAuthority removes a CA matching the type and domain. 4836 func (c *Client) DeleteCertAuthority(ctx context.Context, id types.CertAuthID) error { 4837 _, err := c.TrustClient().DeleteCertAuthority(ctx, &trustpb.DeleteCertAuthorityRequest{ 4838 Type: string(id.Type), 4839 Domain: id.DomainName, 4840 }) 4841 4842 return trace.Wrap(err) 4843 } 4844 4845 // UpsertCertAuthority creates or updates the provided cert authority. 4846 func (c *Client) UpsertCertAuthority(ctx context.Context, ca types.CertAuthority) (types.CertAuthority, error) { 4847 cav2, ok := ca.(*types.CertAuthorityV2) 4848 if !ok { 4849 return nil, trace.BadParameter("unexpected ca type %T", ca) 4850 } 4851 4852 out, err := c.TrustClient().UpsertCertAuthority(ctx, &trustpb.UpsertCertAuthorityRequest{ 4853 CertAuthority: cav2, 4854 }) 4855 4856 return out, trace.Wrap(err) 4857 } 4858 4859 // RotateCertAuthority updates or inserts new cert authority 4860 func (c *Client) RotateCertAuthority(ctx context.Context, rr types.RotateRequest) error { 4861 req := &trustpb.RotateCertAuthorityRequest{ 4862 Type: string(rr.Type), 4863 TargetPhase: rr.TargetPhase, 4864 Mode: rr.Mode, 4865 } 4866 4867 if rr.GracePeriod != nil { 4868 req.GracePeriod = durationpb.New(*rr.GracePeriod) 4869 } 4870 4871 if rr.Schedule != nil { 4872 req.Schedule = &trustpb.RotationSchedule{ 4873 UpdateClients: timestamppb.New(rr.Schedule.UpdateClients), 4874 UpdateServers: timestamppb.New(rr.Schedule.UpdateServers), 4875 Standby: timestamppb.New(rr.Schedule.Standby), 4876 } 4877 } 4878 4879 _, err := c.TrustClient().RotateCertAuthority(ctx, req) 4880 return trace.Wrap(err) 4881 } 4882 4883 // RotateExternalCertAuthority rotates the provided cert authority. 4884 func (c *Client) RotateExternalCertAuthority(ctx context.Context, ca types.CertAuthority) error { 4885 cav2, ok := ca.(*types.CertAuthorityV2) 4886 if !ok { 4887 return trace.BadParameter("unexpected ca type %T", ca) 4888 } 4889 4890 _, err := c.TrustClient().RotateExternalCertAuthority(ctx, &trustpb.RotateExternalCertAuthorityRequest{ 4891 CertAuthority: cav2, 4892 }) 4893 4894 return trace.Wrap(err) 4895 } 4896 4897 // UpdateHeadlessAuthenticationState updates a headless authentication state. 4898 func (c *Client) UpdateHeadlessAuthenticationState(ctx context.Context, id string, state types.HeadlessAuthenticationState, mfaResponse *proto.MFAAuthenticateResponse) error { 4899 _, err := c.grpc.UpdateHeadlessAuthenticationState(ctx, &proto.UpdateHeadlessAuthenticationStateRequest{ 4900 Id: id, 4901 State: state, 4902 MfaResponse: mfaResponse, 4903 }) 4904 if err != nil { 4905 return trace.Wrap(err) 4906 } 4907 return nil 4908 } 4909 4910 // GetHeadlessAuthentication retrieves a headless authentication by id. 4911 func (c *Client) GetHeadlessAuthentication(ctx context.Context, id string) (*types.HeadlessAuthentication, error) { 4912 headlessAuthn, err := c.grpc.GetHeadlessAuthentication(ctx, &proto.GetHeadlessAuthenticationRequest{ 4913 Id: id, 4914 }) 4915 if err != nil { 4916 return nil, trace.Wrap(err) 4917 } 4918 return headlessAuthn, nil 4919 } 4920 4921 // WatchPendingHeadlessAuthentications creates a watcher for pending headless authentication for the current user. 4922 func (c *Client) WatchPendingHeadlessAuthentications(ctx context.Context) (types.Watcher, error) { 4923 cancelCtx, cancel := context.WithCancel(ctx) 4924 stream, err := c.grpc.WatchPendingHeadlessAuthentications(cancelCtx, &emptypb.Empty{}) 4925 if err != nil { 4926 cancel() 4927 return nil, trace.Wrap(err) 4928 } 4929 w := &streamWatcher{ 4930 stream: stream, 4931 ctx: cancelCtx, 4932 cancel: cancel, 4933 eventsC: make(chan types.Event), 4934 } 4935 go w.receiveEvents() 4936 return w, nil 4937 } 4938 4939 // CreateAssistantConversation creates a new conversation entry in the backend. 4940 func (c *Client) CreateAssistantConversation(ctx context.Context, req *assist.CreateAssistantConversationRequest) (*assist.CreateAssistantConversationResponse, error) { 4941 resp, err := c.grpc.CreateAssistantConversation(ctx, req) 4942 if err != nil { 4943 return nil, trace.Wrap(err) 4944 } 4945 4946 return resp, nil 4947 } 4948 4949 // GetAssistantMessages retrieves assistant messages with given conversation ID. 4950 func (c *Client) GetAssistantMessages(ctx context.Context, req *assist.GetAssistantMessagesRequest) (*assist.GetAssistantMessagesResponse, error) { 4951 messages, err := c.grpc.GetAssistantMessages(ctx, req) 4952 if err != nil { 4953 return nil, trace.Wrap(err) 4954 } 4955 return messages, nil 4956 } 4957 4958 // DeleteAssistantConversation deletes a conversation entry in the backend. 4959 func (c *Client) DeleteAssistantConversation(ctx context.Context, req *assist.DeleteAssistantConversationRequest) error { 4960 _, err := c.grpc.DeleteAssistantConversation(ctx, req) 4961 if err != nil { 4962 return trace.Wrap(err) 4963 } 4964 return nil 4965 } 4966 4967 // IsAssistEnabled returns true if the assist is enabled or not on the auth level. 4968 func (c *Client) IsAssistEnabled(ctx context.Context) (*assist.IsAssistEnabledResponse, error) { 4969 resp, err := c.grpc.IsAssistEnabled(ctx, &assist.IsAssistEnabledRequest{}) 4970 if err != nil { 4971 return nil, trace.Wrap(err) 4972 } 4973 return resp, nil 4974 } 4975 4976 // GetAssistantConversations returns all conversations started by a user. 4977 func (c *Client) GetAssistantConversations(ctx context.Context, request *assist.GetAssistantConversationsRequest) (*assist.GetAssistantConversationsResponse, error) { 4978 messages, err := c.grpc.GetAssistantConversations(ctx, request) 4979 if err != nil { 4980 return nil, trace.Wrap(err) 4981 } 4982 return messages, nil 4983 } 4984 4985 // CreateAssistantMessage saves a new conversation message. 4986 func (c *Client) CreateAssistantMessage(ctx context.Context, in *assist.CreateAssistantMessageRequest) error { 4987 _, err := c.grpc.CreateAssistantMessage(ctx, in) 4988 if err != nil { 4989 return trace.Wrap(err) 4990 } 4991 return nil 4992 } 4993 4994 // UpdateAssistantConversationInfo updates conversation info. 4995 func (c *Client) UpdateAssistantConversationInfo(ctx context.Context, in *assist.UpdateAssistantConversationInfoRequest) error { 4996 _, err := c.grpc.UpdateAssistantConversationInfo(ctx, in) 4997 if err != nil { 4998 return trace.Wrap(err) 4999 } 5000 return nil 5001 } 5002 5003 func (c *Client) GetAssistantEmbeddings(ctx context.Context, in *assist.GetAssistantEmbeddingsRequest) (*assist.GetAssistantEmbeddingsResponse, error) { 5004 result, err := c.EmbeddingClient().GetAssistantEmbeddings(ctx, in) 5005 if err != nil { 5006 return nil, trace.Wrap(err) 5007 } 5008 return result, nil 5009 } 5010 5011 // GetUserPreferences returns the user preferences for a given user. 5012 func (c *Client) GetUserPreferences(ctx context.Context, in *userpreferencespb.GetUserPreferencesRequest) (*userpreferencespb.GetUserPreferencesResponse, error) { 5013 resp, err := c.grpc.GetUserPreferences(ctx, in) 5014 if err != nil { 5015 return nil, trace.Wrap(err) 5016 } 5017 return resp, nil 5018 } 5019 5020 // UpsertUserPreferences creates or updates user preferences for a given username. 5021 func (c *Client) UpsertUserPreferences(ctx context.Context, in *userpreferencespb.UpsertUserPreferencesRequest) error { 5022 _, err := c.grpc.UpsertUserPreferences(ctx, in) 5023 if err != nil { 5024 return trace.Wrap(err) 5025 } 5026 return nil 5027 } 5028 5029 // ResourceUsageClient returns an unadorned Resource Usage service client, 5030 // using the underlying Auth gRPC connection. 5031 // Clients connecting to non-Enterprise clusters, or older Teleport versions, 5032 // still get a plugins client when calling this method, but all RPCs will return 5033 // "not implemented" errors (as per the default gRPC behavior). 5034 func (c *Client) ResourceUsageClient() resourceusagepb.ResourceUsageServiceClient { 5035 return resourceusagepb.NewResourceUsageServiceClient(c.conn) 5036 } 5037 5038 // UpdateRemoteCluster updates remote cluster from the specified value. 5039 // TODO(noah): In v17.0.0 this method should switch to call UpdateRemoteCluster 5040 // on the presence service client. 5041 func (c *Client) UpdateRemoteCluster(ctx context.Context, rc types.RemoteCluster) error { 5042 rcV3, ok := rc.(*types.RemoteClusterV3) 5043 if !ok { 5044 return trace.BadParameter("unsupported remote cluster type %T", rcV3) 5045 } 5046 5047 _, err := c.grpc.UpdateRemoteCluster(ctx, rcV3) 5048 return trace.Wrap(err) 5049 } 5050 5051 // ListRemoteClusters returns a page of remote clusters. 5052 func (c *Client) ListRemoteClusters(ctx context.Context, pageSize int, nextToken string) ([]types.RemoteCluster, string, error) { 5053 res, err := c.PresenceServiceClient().ListRemoteClusters(ctx, &presencepb.ListRemoteClustersRequest{ 5054 PageSize: int32(pageSize), 5055 PageToken: nextToken, 5056 }) 5057 if err != nil { 5058 return nil, "", trace.Wrap(err) 5059 } 5060 rcs := make([]types.RemoteCluster, 0, len(res.RemoteClusters)) 5061 for _, rc := range res.RemoteClusters { 5062 rcs = append(rcs, rc) 5063 } 5064 return rcs, res.NextPageToken, nil 5065 } 5066 5067 // DeleteRemoteCluster creates remote cluster resource 5068 func (c *Client) DeleteRemoteCluster(ctx context.Context, name string) error { 5069 _, err := c.PresenceServiceClient().DeleteRemoteCluster(ctx, &presencepb.DeleteRemoteClusterRequest{ 5070 Name: name, 5071 }) 5072 return trace.Wrap(err) 5073 } 5074 5075 // GetRemoteCluster returns remote cluster by name 5076 func (c *Client) GetRemoteCluster(ctx context.Context, name string) (types.RemoteCluster, error) { 5077 rc, err := c.PresenceServiceClient().GetRemoteCluster(ctx, &presencepb.GetRemoteClusterRequest{ 5078 Name: name, 5079 }) 5080 return rc, trace.Wrap(err) 5081 }