Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,732 changes: 1,601 additions & 1,131 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions api/client/proto/authservice_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 29 additions & 1 deletion api/client/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ import (
"context"
"errors"
"io"
"iter"

"github.com/gravitational/trace"
"google.golang.org/protobuf/types/known/emptypb"

"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/clientutils"
)

// GetWebSession returns the web session for the specified request.
Expand Down Expand Up @@ -129,7 +132,9 @@ func (c *Client) GetWebToken(ctx context.Context, req types.GetWebTokenRequest)
}

// GetWebTokens returns the list of all web tokens
// Deprecated: Prefer using [Client.ListWebTokens] or [Client.RangeWebTokens] instead.
func (c *Client) GetWebTokens(ctx context.Context) ([]types.WebToken, error) {
//nolint:staticcheck // TODO(okraport): deprecated, to be removed in v21
resp, err := c.grpc.GetWebTokens(ctx, &emptypb.Empty{})
if err != nil {
return nil, trace.Wrap(err)
Expand All @@ -141,6 +146,29 @@ func (c *Client) GetWebTokens(ctx context.Context) ([]types.WebToken, error) {
return out, nil
}

// ListWebTokens returns a page of web tokens
func (c *Client) ListWebTokens(ctx context.Context, limit int, start string) ([]types.WebToken, string, error) {
resp, err := c.grpc.ListWebTokens(ctx, &proto.ListWebTokensRequest{
PageToken: start,
PageSize: int32(limit),
})
if err != nil {
return nil, "", trace.Wrap(err)
}

tokens := make([]types.WebToken, 0, len(resp.Tokens))
for _, token := range resp.Tokens {
tokens = append(tokens, token)
}

return tokens, resp.NextPageToken, nil
}

// RangeWebTokens returns web tokens within the range [start, end).
func (c *Client) RangeWebTokens(ctx context.Context, start, end string) iter.Seq2[types.WebToken, error] {
return clientutils.RangeResources(ctx, start, end, c.ListWebTokens, types.WebToken.GetName)
}

// UpsertWebToken not implemented: can only be called locally.
func (c *Client) UpsertWebToken(ctx context.Context, token types.WebToken) error {
return trace.NotImplemented(notImplementedMessage)
Expand Down Expand Up @@ -188,7 +216,7 @@ func (r *webTokens) Get(ctx context.Context, req types.GetWebTokenRequest) (type
//
// Deprecated: Use [Client.GetWebTokens] instead.
func (r *webTokens) List(ctx context.Context) ([]types.WebToken, error) {
return r.c.GetWebTokens(ctx)
return clientutils.CollectWithFallback(ctx, r.c.ListWebTokens, r.c.GetWebTokens)
}

// Upsert not implemented: can only be called locally.
Expand Down
24 changes: 23 additions & 1 deletion api/proto/teleport/legacy/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,24 @@ message GetWebTokensResponse {
repeated types.WebTokenV3 Tokens = 1 [(gogoproto.jsontag) = "tokens"];
}

// ListWebTokensRequest contains all the requested web tokens.
message ListWebTokensRequest {
// The maximum number of items to return.
// The server may impose a different page size at its discretion.
int32 page_size = 1;
// The next_page_token value returned from a previous List request, if any.
string page_token = 2;
}

// ListWebTokensResponse contains all the requested web tokens.
message ListWebTokensResponse {
// Tokens is a list of web tokens.
repeated types.WebTokenV3 tokens = 1;
// Token to retrieve the next page of results, or empty if there are no
// more results in the list.
string next_page_token = 2;
}

// UpsertKubernetesServerRequest are the parameters used to add or update a
// kubernetes server.
message UpsertKubernetesServerRequest {
Expand Down Expand Up @@ -3083,7 +3101,11 @@ service AuthService {
// GetWebToken gets a web token.
rpc GetWebToken(types.GetWebTokenRequest) returns (GetWebTokenResponse);
// GetWebTokens gets all web tokens.
rpc GetWebTokens(google.protobuf.Empty) returns (GetWebTokensResponse);
rpc GetWebTokens(google.protobuf.Empty) returns (GetWebTokensResponse) {
option deprecated = true;
}
// ListWebTokens returns a page of web tokens.
rpc ListWebTokens(ListWebTokensRequest) returns (ListWebTokensResponse);
// DeleteWebToken deletes a web token.
rpc DeleteWebToken(types.DeleteWebTokenRequest) returns (google.protobuf.Empty);
// DeleteAllWebTokens deletes all web tokens.
Expand Down
1 change: 0 additions & 1 deletion build.assets/tooling/cmd/buf-plugin-linters/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ func newDefaultConfig() *Config {
"proto.AuthService.GetSSHTargets": {},
"proto.AuthService.GetSSODiagnosticInfo": {},
"proto.AuthService.GetTokens": {},
"proto.AuthService.GetWebTokens": {},
"proto.AuthService.GetWindowsDesktops": {},
"proto.AuthService.GetWindowsDesktopServices": {},
"proto.AuthService.ListAccessRequests": {},
Expand Down
15 changes: 15 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -2677,6 +2677,21 @@ func (a *ServerWithRoles) GetWebTokens(ctx context.Context) ([]types.WebToken, e
return tokens, nil
}

// ListWebTokens returns a page of web tokens
func (a *ServerWithRoles) ListWebTokens(ctx context.Context, limit int, start string) ([]types.WebToken, string, error) {
if err := a.authorizeAction(types.KindWebToken, types.VerbList); err != nil {
Copy link
Contributor Author

@okraport okraport Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches existing behaviour of GetWebTokens

return nil, "", trace.Wrap(err)
}

tokens, next, err := a.authServer.ListWebTokens(ctx, limit, start)
if err != nil {
return nil, "", trace.Wrap(err)
}

return tokens, next, nil

}

// DeleteWebToken removes the web token specified with req.
func (a *ServerWithRoles) DeleteWebToken(ctx context.Context, req types.DeleteWebTokenRequest) error {
if err := a.currentUserAction(req.User); err != nil {
Expand Down
28 changes: 28 additions & 0 deletions lib/auth/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1953,6 +1953,34 @@ func (g *GRPCServer) GetWebTokens(ctx context.Context, _ *emptypb.Empty) (*authp
}, nil
}

// ListWebTokens returns a page of web tokens
func (g *GRPCServer) ListWebTokens(ctx context.Context, req *authpb.ListWebTokensRequest) (*authpb.ListWebTokensResponse, error) {
auth, err := g.authenticate(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

tokens, next, err := auth.ListWebTokens(ctx, int(req.PageSize), req.PageToken)
if err != nil {
return nil, trace.Wrap(err)
}

resp := &authpb.ListWebTokensResponse{
Tokens: make([]*types.WebTokenV3, 0, len(tokens)),
NextPageToken: next,
}

for _, t := range tokens {
tokenV3, ok := t.(*types.WebTokenV3)
if !ok {
return nil, trace.BadParameter("unexpected type %T", t)
}
resp.Tokens = append(resp.Tokens, tokenV3)
}

return resp, nil
}

// DeleteWebToken removes the web token given with req.
func (g *GRPCServer) DeleteWebToken(ctx context.Context, req *types.DeleteWebTokenRequest) (*emptypb.Empty, error) {
auth, err := g.authenticate(ctx)
Expand Down
58 changes: 56 additions & 2 deletions lib/cache/web_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ package cache

import (
"context"
"iter"

"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/utils/clientutils"
"github.com/gravitational/teleport/lib/services"
)

Expand All @@ -42,8 +44,12 @@ func newWebTokenCollection(upstream services.WebToken, w types.WatchKind) (*coll
webTokenNameIndex: types.WebToken.GetName,
}),
fetcher: func(ctx context.Context, loadSecrets bool) ([]types.WebToken, error) {
installers, err := upstream.GetWebTokens(ctx)
return installers, trace.Wrap(err)
// TODO(lokraszewski): DELETE IN v21.0.0, replace with regular collect.
tokens, err := clientutils.CollectWithFallback(ctx, upstream.ListWebTokens, upstream.GetWebTokens)
if err != nil {
return nil, trace.Wrap(err)
}
return tokens, nil
},
headerTransform: func(hdr *types.ResourceHeader) types.WebToken {
return &types.WebTokenV3{
Expand Down Expand Up @@ -98,3 +104,51 @@ func (c *Cache) GetWebTokens(ctx context.Context) ([]types.WebToken, error) {

return tokens, nil
}

// ListWebTokens returns a page of web tokens
func (c *Cache) ListWebTokens(ctx context.Context, limit int, start string) ([]types.WebToken, string, error) {
ctx, span := c.Tracer.Start(ctx, "cache/ListWebTokens")
defer span.End()

lister := genericLister[types.WebToken, webTokenIndex]{
cache: c,
collection: c.collections.webTokens,
index: webTokenNameIndex,
upstreamList: c.Config.WebToken.ListWebTokens,
nextToken: types.WebToken.GetName,
}
out, next, err := lister.list(ctx, limit, start)
if err != nil {
return nil, "", trace.Wrap(err)
}

return out, next, nil
}

// RangeWebTokens returns web tokens within the range [start, end).
func (c *Cache) RangeWebTokens(ctx context.Context, start, end string) iter.Seq2[types.WebToken, error] {
lister := genericLister[types.WebToken, webTokenIndex]{
cache: c,
collection: c.collections.webTokens,
index: webTokenNameIndex,
upstreamList: c.Config.WebToken.ListWebTokens,
nextToken: types.WebToken.GetName,
// TODO(lokraszewski): DELETE IN v21.0.0
fallbackGetter: c.Config.WebToken.GetWebTokens,
}

return func(yield func(types.WebToken, error) bool) {
ctx, span := c.Tracer.Start(ctx, "cache/RangeWebTokens")
defer span.End()

for token, err := range lister.RangeWithFallback(ctx, start, end) {
if !yield(token, err) {
return
}

if err != nil {
return
}
}
}
}
Loading
Loading