mirror of
https://github.com/juanfont/headscale.git
synced 2025-11-25 11:56:09 -05:00
types: make pre auth key use bcrypt (#2853)
This commit is contained in:
@@ -7,6 +7,13 @@ import (
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
const (
|
||||
// NewAPIKeyPrefixLength is the length of the prefix for new API keys.
|
||||
NewAPIKeyPrefixLength = 12
|
||||
// LegacyAPIKeyPrefixLength is the length of the prefix for legacy API keys.
|
||||
LegacyAPIKeyPrefixLength = 7
|
||||
)
|
||||
|
||||
// APIKey describes the datamodel for API keys used to remotely authenticate with
|
||||
// headscale.
|
||||
type APIKey struct {
|
||||
@@ -21,8 +28,16 @@ type APIKey struct {
|
||||
|
||||
func (key *APIKey) Proto() *v1.ApiKey {
|
||||
protoKey := v1.ApiKey{
|
||||
Id: key.ID,
|
||||
Prefix: key.Prefix,
|
||||
Id: key.ID,
|
||||
}
|
||||
|
||||
// Show prefix format: distinguish between new (12-char) and legacy (7-char) keys
|
||||
if len(key.Prefix) == NewAPIKeyPrefixLength {
|
||||
// New format key (12-char prefix)
|
||||
protoKey.Prefix = "hskey-api-" + key.Prefix + "-***"
|
||||
} else {
|
||||
// Legacy format key (7-char prefix) or fallback
|
||||
protoKey.Prefix = key.Prefix + "***"
|
||||
}
|
||||
|
||||
if key.Expiration != nil {
|
||||
|
||||
@@ -14,8 +14,15 @@ func (e PAKError) Error() string { return string(e) }
|
||||
|
||||
// PreAuthKey describes a pre-authorization key usable in a particular user.
|
||||
type PreAuthKey struct {
|
||||
ID uint64 `gorm:"primary_key"`
|
||||
Key string
|
||||
ID uint64 `gorm:"primary_key"`
|
||||
|
||||
// Legacy plaintext key (for backwards compatibility)
|
||||
Key string
|
||||
|
||||
// New bcrypt-based authentication
|
||||
Prefix string
|
||||
Hash []byte // bcrypt
|
||||
|
||||
UserID uint
|
||||
User User `gorm:"constraint:OnDelete:SET NULL;"`
|
||||
Reusable bool
|
||||
@@ -32,17 +39,59 @@ type PreAuthKey struct {
|
||||
Expiration *time.Time
|
||||
}
|
||||
|
||||
// PreAuthKeyNew is returned once when the key is created.
|
||||
type PreAuthKeyNew struct {
|
||||
ID uint64 `gorm:"primary_key"`
|
||||
Key string
|
||||
Reusable bool
|
||||
Ephemeral bool
|
||||
Tags []string
|
||||
Expiration *time.Time
|
||||
CreatedAt *time.Time
|
||||
User User
|
||||
}
|
||||
|
||||
func (key *PreAuthKeyNew) Proto() *v1.PreAuthKey {
|
||||
protoKey := v1.PreAuthKey{
|
||||
Id: key.ID,
|
||||
Key: key.Key,
|
||||
User: key.User.Proto(),
|
||||
Reusable: key.Reusable,
|
||||
Ephemeral: key.Ephemeral,
|
||||
AclTags: key.Tags,
|
||||
}
|
||||
|
||||
if key.Expiration != nil {
|
||||
protoKey.Expiration = timestamppb.New(*key.Expiration)
|
||||
}
|
||||
|
||||
if key.CreatedAt != nil {
|
||||
protoKey.CreatedAt = timestamppb.New(*key.CreatedAt)
|
||||
}
|
||||
|
||||
return &protoKey
|
||||
}
|
||||
|
||||
func (key *PreAuthKey) Proto() *v1.PreAuthKey {
|
||||
protoKey := v1.PreAuthKey{
|
||||
User: key.User.Proto(),
|
||||
Id: key.ID,
|
||||
Key: key.Key,
|
||||
Ephemeral: key.Ephemeral,
|
||||
Reusable: key.Reusable,
|
||||
Used: key.Used,
|
||||
AclTags: key.Tags,
|
||||
}
|
||||
|
||||
// For new keys (with prefix/hash), show the prefix so users can identify the key
|
||||
// For legacy keys (with plaintext key), show the full key for backwards compatibility
|
||||
if key.Prefix != "" {
|
||||
protoKey.Key = "hskey-auth-" + key.Prefix + "-***"
|
||||
} else if key.Key != "" {
|
||||
// Legacy key - show full key for backwards compatibility
|
||||
// TODO: Consider hiding this in a future major version
|
||||
protoKey.Key = key.Key
|
||||
}
|
||||
|
||||
if key.Expiration != nil {
|
||||
protoKey.Expiration = timestamppb.New(*key.Expiration)
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ func (src *PreAuthKey) Clone() *PreAuthKey {
|
||||
}
|
||||
dst := new(PreAuthKey)
|
||||
*dst = *src
|
||||
dst.Hash = append(src.Hash[:0:0], src.Hash...)
|
||||
dst.Tags = append(src.Tags[:0:0], src.Tags...)
|
||||
if dst.CreatedAt != nil {
|
||||
dst.CreatedAt = ptr.To(*src.CreatedAt)
|
||||
@@ -124,6 +125,8 @@ func (src *PreAuthKey) Clone() *PreAuthKey {
|
||||
var _PreAuthKeyCloneNeedsRegeneration = PreAuthKey(struct {
|
||||
ID uint64
|
||||
Key string
|
||||
Prefix string
|
||||
Hash []byte
|
||||
UserID uint
|
||||
User User
|
||||
Reusable bool
|
||||
|
||||
@@ -239,14 +239,16 @@ func (v *PreAuthKeyView) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v PreAuthKeyView) ID() uint64 { return v.ж.ID }
|
||||
func (v PreAuthKeyView) Key() string { return v.ж.Key }
|
||||
func (v PreAuthKeyView) UserID() uint { return v.ж.UserID }
|
||||
func (v PreAuthKeyView) User() User { return v.ж.User }
|
||||
func (v PreAuthKeyView) Reusable() bool { return v.ж.Reusable }
|
||||
func (v PreAuthKeyView) Ephemeral() bool { return v.ж.Ephemeral }
|
||||
func (v PreAuthKeyView) Used() bool { return v.ж.Used }
|
||||
func (v PreAuthKeyView) Tags() views.Slice[string] { return views.SliceOf(v.ж.Tags) }
|
||||
func (v PreAuthKeyView) ID() uint64 { return v.ж.ID }
|
||||
func (v PreAuthKeyView) Key() string { return v.ж.Key }
|
||||
func (v PreAuthKeyView) Prefix() string { return v.ж.Prefix }
|
||||
func (v PreAuthKeyView) Hash() views.ByteSlice[[]byte] { return views.ByteSliceOf(v.ж.Hash) }
|
||||
func (v PreAuthKeyView) UserID() uint { return v.ж.UserID }
|
||||
func (v PreAuthKeyView) User() User { return v.ж.User }
|
||||
func (v PreAuthKeyView) Reusable() bool { return v.ж.Reusable }
|
||||
func (v PreAuthKeyView) Ephemeral() bool { return v.ж.Ephemeral }
|
||||
func (v PreAuthKeyView) Used() bool { return v.ж.Used }
|
||||
func (v PreAuthKeyView) Tags() views.Slice[string] { return views.SliceOf(v.ж.Tags) }
|
||||
func (v PreAuthKeyView) CreatedAt() views.ValuePointer[time.Time] {
|
||||
return views.ValuePointerOf(v.ж.CreatedAt)
|
||||
}
|
||||
@@ -259,6 +261,8 @@ func (v PreAuthKeyView) Expiration() views.ValuePointer[time.Time] {
|
||||
var _PreAuthKeyViewNeedsRegeneration = PreAuthKey(struct {
|
||||
ID uint64
|
||||
Key string
|
||||
Prefix string
|
||||
Hash []byte
|
||||
UserID uint
|
||||
User User
|
||||
Reusable bool
|
||||
|
||||
Reference in New Issue
Block a user