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
3,110 changes: 1,790 additions & 1,320 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

40 changes: 40 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.

22 changes: 21 additions & 1 deletion api/client/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import (
"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 @@ -141,6 +143,24 @@ 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
}

// 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 @@ -176,7 +196,7 @@ func (r *webTokens) Get(ctx context.Context, req types.GetWebTokenRequest) (type

// List returns the list of all web tokens
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
20 changes: 20 additions & 0 deletions api/proto/teleport/legacy/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,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 @@ -3271,6 +3289,8 @@ service AuthService {
rpc GetWebToken(types.GetWebTokenRequest) returns (GetWebTokenResponse);
// GetWebTokens gets all web tokens.
rpc GetWebTokens(google.protobuf.Empty) returns (GetWebTokensResponse);
// 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
15 changes: 15 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -2719,6 +2719,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.action(apidefaults.Namespace, types.KindWebToken, types.VerbList); err != nil {
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 @@ -1979,6 +1979,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
28 changes: 28 additions & 0 deletions lib/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -2900,6 +2900,34 @@ func (c *Cache) GetWebToken(ctx context.Context, req types.GetWebTokenRequest) (
return rg.reader.GetWebToken(ctx, req)
}

func (c *Cache) GetWebTokens(ctx context.Context) ([]types.WebToken, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetWebTokens")
defer span.End()

rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.webTokens)
if err != nil {
return nil, trace.Wrap(err)
}

defer rg.Release()
return rg.reader.GetWebTokens(ctx)
}

// 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()

rg, err := readLegacyCollectionCache(c, c.legacyCacheCollections.webTokens)
if err != nil {
return nil, "", trace.Wrap(err)
}

defer rg.Release()
return rg.reader.ListWebTokens(ctx, limit, start)

}

// GetAuthPreference gets the cluster authentication config.
func (c *Cache) GetAuthPreference(ctx context.Context) (types.AuthPreference, error) {
ctx, span := c.Tracer.Start(ctx, "cache/GetAuthPreference")
Expand Down
62 changes: 62 additions & 0 deletions lib/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,68 @@ func TestTokens(t *testing.T) {
require.True(t, trace.IsNotFound(err))
}

func TestWebTokens(t *testing.T) {
t.Parallel()

p := newTestPack(t, ForProxy)
t.Cleanup(p.Close)

t.Run("GetWebTokens", func(t *testing.T) {
testResources(t, p, testFuncs[types.WebToken]{
newResource: func(name string) (types.WebToken, error) {
return types.NewWebToken(time.Now().Add(time.Hour), types.WebTokenSpecV3{
Token: name,
User: "llama",
})
},
create: p.webTokenS.UpsertWebToken,
update: p.webTokenS.UpsertWebToken,
cacheGet: func(ctx context.Context, token string) (types.WebToken, error) {
return p.cache.GetWebToken(ctx, types.GetWebTokenRequest{
Token: token,
User: "llama",
})
},
list: getAllAdapter(p.webTokenS.GetWebTokens),
cacheList: getAllAdapter(p.cache.GetWebTokens),
deleteAll: p.webTokenS.DeleteAllWebTokens,
delete: func(ctx context.Context, token string) error {
return p.webTokenS.DeleteWebToken(ctx, types.DeleteWebTokenRequest{
Token: token,
User: "llama",
})
},
}, withSkipPaginationTest())
})
t.Run("ListWebTokens", func(t *testing.T) {
testResources(t, p, testFuncs[types.WebToken]{
newResource: func(name string) (types.WebToken, error) {
return types.NewWebToken(time.Now().Add(time.Hour), types.WebTokenSpecV3{
Token: name,
User: "llama",
})
},
create: p.webTokenS.UpsertWebToken,
update: p.webTokenS.UpsertWebToken,
cacheGet: func(ctx context.Context, token string) (types.WebToken, error) {
return p.cache.GetWebToken(ctx, types.GetWebTokenRequest{
Token: token,
User: "llama",
})
},
list: p.webTokenS.ListWebTokens,
cacheList: p.cache.ListWebTokens,
deleteAll: p.webTokenS.DeleteAllWebTokens,
delete: func(ctx context.Context, token string) error {
return p.webTokenS.DeleteWebToken(ctx, types.DeleteWebTokenRequest{
Token: token,
User: "llama",
})
},
})
})
}

func TestAuthPreference(t *testing.T) {
t.Parallel()

Expand Down
4 changes: 3 additions & 1 deletion lib/cache/legacy_collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -1878,7 +1878,7 @@ var _ executor[types.WebSession, webSessionGetter] = webSessionExecutor{}
type webTokenExecutor struct{}

func (webTokenExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WebToken, error) {
return cache.WebToken.GetWebTokens(ctx)
return clientutils.CollectWithFallback(ctx, cache.WebToken.ListWebTokens, cache.WebToken.GetWebTokens)
}

func (webTokenExecutor) upsert(ctx context.Context, cache *Cache, resource types.WebToken) error {
Expand Down Expand Up @@ -1906,6 +1906,8 @@ func (webTokenExecutor) getReader(cache *Cache, cacheOK bool) webTokenGetter {

type webTokenGetter interface {
GetWebToken(ctx context.Context, req types.GetWebTokenRequest) (types.WebToken, error)
GetWebTokens(ctx context.Context) (out []types.WebToken, err error)
ListWebTokens(ctx context.Context, limit int, start string) ([]types.WebToken, string, error)
}

var _ executor[types.WebToken, webTokenGetter] = webTokenExecutor{}
Expand Down
35 changes: 35 additions & 0 deletions lib/services/local/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/sirupsen/logrus"

"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/services"
Expand Down Expand Up @@ -464,6 +465,40 @@ func (r *IdentityService) GetWebTokens(ctx context.Context) (out []types.WebToke
return out, nil
}

// ListWebTokens returns a page of web tokens
func (r *IdentityService) ListWebTokens(ctx context.Context, limit int, start string) ([]types.WebToken, string, error) {
// Adjust page size, so it can't be too large.
if limit <= 0 || limit > defaults.DefaultChunkSize {
limit = defaults.DefaultChunkSize
}

tokenKey := backend.NewKey(webPrefix, tokensPrefix)
startKey := tokenKey.AppendKey(backend.KeyFromString(start))
endKey := backend.RangeEnd(tokenKey)

var out []types.WebToken
result, err := r.Backend.GetRange(ctx, startKey, endKey, limit+1)
if err != nil {
return nil, "", trace.Wrap(err)
}

for _, item := range result.Items {
token, err := services.UnmarshalWebToken(item.Value, services.WithRevision(item.Revision))

if err != nil {
continue
}

if len(out) >= limit {
return out, token.GetToken(), nil
}

out = append(out, token)
}

return out, "", nil
}

// UpsertWebToken updates the existing or inserts a new web token.
func (r *IdentityService) UpsertWebToken(ctx context.Context, token types.WebToken) error {
rev := token.GetRevision()
Expand Down
Loading
Loading