Skip to content

Commit

Permalink
Remove use of legacy reset password token prefix (#19285)
Browse files Browse the repository at this point in the history
* Sneak in grammar fix
  • Loading branch information
kimlisa authored Dec 12, 2022
1 parent c70d200 commit f8e81e6
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 109 deletions.
3 changes: 1 addition & 2 deletions lib/auth/usertoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,7 @@ func (s *Server) getResetPasswordToken(ctx context.Context, tokenID string) (typ
return nil, trace.Wrap(err)
}

// DELETE IN 9.0.0: remove checking for empty string.
if token.GetSubKind() != "" && token.GetSubKind() != UserTokenTypeResetPassword && token.GetSubKind() != UserTokenTypeResetPasswordInvite {
if token.GetSubKind() != UserTokenTypeResetPassword && token.GetSubKind() != UserTokenTypeResetPasswordInvite {
return nil, trace.BadParameter("invalid token")
}

Expand Down
71 changes: 0 additions & 71 deletions lib/auth/usertoken_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@ import (
"github.com/gravitational/teleport/api/types"
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/api/types/webauthn"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/events/eventstest"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/services/local"
)

func TestCreateResetPasswordToken(t *testing.T) {
Expand Down Expand Up @@ -279,75 +277,6 @@ func TestUserTokenCreationSettings(t *testing.T) {
require.NotEmpty(t, token.GetMetadata().Expires)
}

// DELETE IN 9.0: remove legacy prefix and fallbacks.
func TestBackwardsCompForUserTokenWithLegacyPrefix(t *testing.T) {
t.Parallel()
srv := newTestTLSServer(t)

username := "joe@example.com"
_, _, err := CreateUserAndRole(srv.Auth(), username, []string{username})
require.NoError(t, err)

ctx := context.Background()

req := CreateUserTokenRequest{
Name: username,
TTL: time.Hour,
}

// Create a reset password user token.
legacyToken, err := srv.Auth().newUserToken(req)
require.NoError(t, err)

marshalledToken, err := services.MarshalUserToken(legacyToken)
require.NoError(t, err)

// Insert the token in backend using legacy prefix.
_, err = srv.AuthServer.Backend.Create(ctx, backend.Item{
Key: backend.Key(local.LegacyPasswordTokensPrefix, legacyToken.GetName(), "params"),
Value: marshalledToken,
})
require.NoError(t, err)

// Test fallback get token.
retrievedToken, err := srv.Auth().GetUserToken(ctx, legacyToken.GetName())
require.NoError(t, err)
require.Equal(t, legacyToken.GetName(), retrievedToken.GetName())

// Create a user token secrets.
legacySecrets, err := types.NewUserTokenSecrets(legacyToken.GetName())
legacySecrets.SetOTPKey("test")
require.NoError(t, err)

marshalledSecrets, err := services.MarshalUserTokenSecrets(legacySecrets)
require.NoError(t, err)

// Insert the secret in backend using legacy prefix.
_, err = srv.AuthServer.Backend.Create(ctx, backend.Item{
Key: backend.Key(local.LegacyPasswordTokensPrefix, legacySecrets.GetName(), "secrets"),
Value: marshalledSecrets,
})
require.NoError(t, err)

// Test fallback get secrets.
retrievedSecrets, err := srv.Auth().GetUserTokenSecrets(ctx, legacySecrets.GetName())
require.NoError(t, err)
require.Equal(t, legacyToken.GetName(), retrievedSecrets.GetName())
require.Equal(t, legacySecrets.GetOTPKey(), retrievedSecrets.GetOTPKey())

// Test deletion of token stored with legacy prefix.
// Helper method deleteUserTokens hits both GetUserTokens and DeleteUserToken path.
err = srv.Auth().deleteUserTokens(ctx, req.Name)
require.NoError(t, err)

// Test for deletion of token and secrets.
_, err = srv.Auth().GetUserToken(ctx, legacyToken.GetName())
require.True(t, trace.IsNotFound(err))

_, err = srv.Auth().GetUserTokenSecrets(ctx, legacySecrets.GetName())
require.True(t, trace.IsNotFound(err))
}

func TestCreatePrivilegeToken(t *testing.T) {
t.Parallel()
srv := newTestTLSServer(t)
Expand Down
35 changes: 4 additions & 31 deletions lib/services/local/usertoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,8 @@ func (s *IdentityService) GetUserTokens(ctx context.Context) ([]types.UserToken,
return nil, trace.Wrap(err)
}

// DELETE IN 9.0.0 retrieve tokens with old prefix.
startKey = backend.Key(LegacyPasswordTokensPrefix)
oldPrefixResult, err := s.GetRange(ctx, startKey, backend.RangeEnd(startKey), backend.NoLimit)
if err != nil {
return nil, trace.Wrap(err)
}

items := append(result.Items, oldPrefixResult.Items...)

var tokens []types.UserToken
for _, item := range items {
for _, item := range result.Items {
if !bytes.HasSuffix(item.Key, []byte(paramsPrefix)) {
continue
}
Expand Down Expand Up @@ -73,21 +64,12 @@ func (s *IdentityService) DeleteUserToken(ctx context.Context, tokenID string) e
return trace.Wrap(err)
}

// DELETE IN 9.0.0 also delete any tokens with old prefix.
startKey = backend.ExactKey(LegacyPasswordTokensPrefix, tokenID)
return trace.Wrap(s.DeleteRange(ctx, startKey, backend.RangeEnd(startKey)))
return nil
}

// GetUserToken returns a token by its ID.
func (s *IdentityService) GetUserToken(ctx context.Context, tokenID string) (types.UserToken, error) {
item, err := s.Get(ctx, backend.Key(userTokenPrefix, tokenID, paramsPrefix))

// DELETE IN 9.0.0: fallback for old prefix first.
if trace.IsNotFound(err) {
item, err = s.Get(ctx, backend.Key(LegacyPasswordTokensPrefix, tokenID, paramsPrefix))
}

// Handle errors from either Get.
switch {
case trace.IsNotFound(err):
return nil, trace.NotFound("user token(%s) not found", backend.MaskKeyName(tokenID))
Expand Down Expand Up @@ -130,13 +112,6 @@ func (s *IdentityService) CreateUserToken(ctx context.Context, token types.UserT
// GetUserTokenSecrets returns token secrets.
func (s *IdentityService) GetUserTokenSecrets(ctx context.Context, tokenID string) (types.UserTokenSecrets, error) {
item, err := s.Get(ctx, backend.Key(userTokenPrefix, tokenID, secretsPrefix))

// DELETE IN 9.0.0: fallback for old prefix first.
if trace.IsNotFound(err) {
item, err = s.Get(ctx, backend.Key(LegacyPasswordTokensPrefix, tokenID, secretsPrefix))
}

// Handle errors from either Get.
switch {
case trace.IsNotFound(err):
return nil, trace.NotFound("user token(%s) secrets not found", backend.MaskKeyName(tokenID))
Expand Down Expand Up @@ -173,8 +148,6 @@ func (s *IdentityService) UpsertUserTokenSecrets(ctx context.Context, secrets ty
}

const (
// DELETE IN 9.0.0 in favor of userTokenPrefix.
LegacyPasswordTokensPrefix = "resetpasswordtokens"
userTokenPrefix = "usertoken"
secretsPrefix = "secrets"
userTokenPrefix = "usertoken"
secretsPrefix = "secrets"
)
4 changes: 2 additions & 2 deletions lib/services/usertokensecrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"github.com/gravitational/teleport/lib/utils"
)

// UnmarshalUserTokenSecrets unmarshals the ResetPasswordTokenSecrets resource from JSON.
// UnmarshalUserTokenSecrets unmarshals the UserTokenSecrets resource from JSON.
func UnmarshalUserTokenSecrets(bytes []byte, opts ...MarshalOption) (types.UserTokenSecrets, error) {
if len(bytes) == 0 {
return nil, trace.BadParameter("missing resource data")
Expand All @@ -40,7 +40,7 @@ func UnmarshalUserTokenSecrets(bytes []byte, opts ...MarshalOption) (types.UserT
return &secrets, nil
}

// MarshalUserTokenSecrets marshals the ResetPasswordTokenSecrets resource to JSON.
// MarshalUserTokenSecrets marshals the UserTokenSecrets resource to JSON.
func MarshalUserTokenSecrets(secrets types.UserTokenSecrets, opts ...MarshalOption) ([]byte, error) {
if err := secrets.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
Expand Down
6 changes: 3 additions & 3 deletions lib/web/ui/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ func MakeDesktopServices(windowsDesktopServices []types.WindowsDesktopService) [
return desktopServices
}

// stripProtocolAndPort returns only the hostname of the uri.
// Handles uri's with no protocol eg: for some database connection
// endpoint the uri can be in the format "hostname:port".
// stripProtocolAndPort returns only the hostname of the URI.
// Handles URIs with no protocol eg: for some database connection
// endpoint the URI can be in the format "hostname:port".
func stripProtocolAndPort(uri string) string {
stripPort := func(uri string) string {
splitURI := strings.Split(uri, ":")
Expand Down

0 comments on commit f8e81e6

Please sign in to comment.