Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove update verb requirement when creating Tokens #14506

Merged
merged 2 commits into from
Jul 19, 2022
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
10 changes: 10 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1870,6 +1870,16 @@ func (c *Client) UpsertToken(ctx context.Context, token types.ProvisionToken) er
return trail.FromGRPC(err)
}

// CreateToken creates a provision token.
func (c *Client) CreateToken(ctx context.Context, token types.ProvisionToken) error {
tokenV2, ok := token.(*types.ProvisionTokenV2)
if !ok {
return trace.BadParameter("invalid type %T", token)
}
_, err := c.grpc.CreateToken(ctx, tokenV2, c.callOpts...)
return trail.FromGRPC(err)
}

// GenerateToken generates a new auth token for the given service roles.
// This token can be used by corresponding services to authenticate with
// the Auth server and get a signed certificate and private key.
Expand Down
1,399 changes: 719 additions & 680 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2275,6 +2275,8 @@ service AuthService {
rpc GetTokens(google.protobuf.Empty) returns (types.ProvisionTokenV2List);
// UpsertToken upserts a token in a backend.
rpc UpsertToken(types.ProvisionTokenV2) returns (google.protobuf.Empty);
// CreateToken creates a token in a backend.
rpc CreateToken(types.ProvisionTokenV2) returns (google.protobuf.Empty);
// GenerateToken generates a new auth token.
rpc GenerateToken(GenerateTokenRequest) returns (GenerateTokenResponse);
// DeleteToken deletes an existing token in a backend described by the given request.
Expand Down
7 changes: 7 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,13 @@ func (a *ServerWithRoles) UpsertToken(ctx context.Context, token types.Provision
return a.authServer.UpsertToken(ctx, token)
}

func (a *ServerWithRoles) CreateToken(ctx context.Context, token types.ProvisionToken) error {
if err := a.action(apidefaults.Namespace, types.KindToken, types.VerbCreate); err != nil {
return trace.Wrap(err)
}
return a.authServer.CreateToken(ctx, token)
}

func (a *ServerWithRoles) UpsertPassword(user string, password []byte) error {
if err := a.currentUserAction(user); err != nil {
return trace.Wrap(err)
Expand Down
3 changes: 3 additions & 0 deletions lib/auth/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -1655,6 +1655,9 @@ type ProvisioningService interface {
// UpsertToken adds provisioning tokens for the auth server
UpsertToken(ctx context.Context, token types.ProvisionToken) error

// CreateToken creates a new provision token for the auth server
CreateToken(ctx context.Context, token types.ProvisionToken) error

// RegisterUsingToken calls the auth service API to register a new node via registration token
// which has been previously issued via GenerateToken
RegisterUsingToken(ctx context.Context, req *types.RegisterUsingTokenRequest) (*proto.Certs, error)
Expand Down
12 changes: 12 additions & 0 deletions lib/auth/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2887,6 +2887,18 @@ func (g *GRPCServer) UpsertToken(ctx context.Context, token *types.ProvisionToke
return &empty.Empty{}, nil
}

// CreateToken creates a token.
func (g *GRPCServer) CreateToken(ctx context.Context, token *types.ProvisionTokenV2) (*empty.Empty, error) {
auth, err := g.authenticate(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
if err = auth.ServerWithRoles.CreateToken(ctx, token); err != nil {
return nil, trace.Wrap(err)
}
return &empty.Empty{}, nil
}

// GenerateToken generates a new auth token.
func (g *GRPCServer) GenerateToken(ctx context.Context, req *proto.GenerateTokenRequest) (*proto.GenerateTokenResponse, error) {
auth, err := g.authenticate(ctx)
Expand Down
40 changes: 32 additions & 8 deletions lib/services/local/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,51 @@ func NewProvisioningService(backend backend.Backend) *ProvisioningService {

// UpsertToken adds provisioning tokens for the auth server
func (s *ProvisioningService) UpsertToken(ctx context.Context, p types.ProvisionToken) error {
if err := p.CheckAndSetDefaults(); err != nil {
item, err := s.tokenToItem(p)
if err != nil {
return trace.Wrap(err)
}

_, err = s.Put(ctx, *item)
if err != nil {
return trace.Wrap(err)
}
return nil
}

// CreateToken creates a new token for the auth server
func (s *ProvisioningService) CreateToken(ctx context.Context, p types.ProvisionToken) error {
item, err := s.tokenToItem(p)
if err != nil {
return trace.Wrap(err)
}

_, err = s.Create(ctx, *item)
if err != nil {
return trace.Wrap(err)
}

return nil
}

func (s *ProvisioningService) tokenToItem(p types.ProvisionToken) (*backend.Item, error) {
if err := p.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
if p.Expiry().IsZero() || p.Expiry().Sub(s.Clock().Now().UTC()) < time.Second {
p.SetExpiry(s.Clock().Now().UTC().Add(defaults.ProvisioningTokenTTL))
}
data, err := services.MarshalProvisionToken(p)
if err != nil {
return trace.Wrap(err)
return nil, trace.Wrap(err)
}
item := backend.Item{
item := &backend.Item{
Key: backend.Key(tokensPrefix, p.GetName()),
Value: data,
Expires: p.Expiry(),
ID: p.GetResourceID(),
}
_, err = s.Put(ctx, item)
if err != nil {
return trace.Wrap(err)
}
return nil
return item, nil
}

// DeleteAllTokens deletes all provisioning tokens
Expand Down
3 changes: 3 additions & 0 deletions lib/services/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ type Provisioner interface {
// UpsertToken adds provisioning tokens for the auth server
UpsertToken(ctx context.Context, token types.ProvisionToken) error

// CreateToken adds provisioning tokens for the auth server
CreateToken(ctx context.Context, token types.ProvisionToken) error

// GetToken finds and returns token by id
GetToken(ctx context.Context, token string) (types.ProvisionToken, error)

Expand Down
2 changes: 1 addition & 1 deletion lib/web/apiserver_login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func configureClusterForMFA(t *testing.T, env *webPack, spec *types.AuthPreferen
// Create user.
const user = "llama"
const password = "password"
env.proxies[0].createUser(ctx, t, user, "root", "password", "" /* otpSecret */)
env.proxies[0].createUser(ctx, t, user, "root", "password", "" /* otpSecret */, nil /* roles */)

// Register device.
clt, err := env.server.NewClient(auth.TestUser(user))
Expand Down
Loading