2021-08-19 21:12:21 +02:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/google/uuid"
|
2021-08-20 22:33:43 +02:00
|
|
|
"hash/fnv"
|
|
|
|
"strconv"
|
2021-08-19 21:12:21 +02:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// SetupKeyReusable is a multi-use key (can be used for multiple machines)
|
|
|
|
SetupKeyReusable SetupKeyType = "reusable"
|
|
|
|
// SetupKeyOneOff is a single use key (can be used only once)
|
|
|
|
SetupKeyOneOff SetupKeyType = "one-off"
|
|
|
|
|
|
|
|
// DefaultSetupKeyDuration = 1 month
|
|
|
|
DefaultSetupKeyDuration = 24 * 30 * time.Hour
|
|
|
|
// DefaultSetupKeyName is a default name of the default setup key
|
|
|
|
DefaultSetupKeyName = "Default key"
|
|
|
|
)
|
|
|
|
|
|
|
|
// SetupKeyType is the type of setup key
|
|
|
|
type SetupKeyType string
|
|
|
|
|
|
|
|
// SetupKey represents a pre-authorized key used to register machines (peers)
|
|
|
|
type SetupKey struct {
|
2021-08-20 22:33:43 +02:00
|
|
|
Id string
|
2021-08-19 21:12:21 +02:00
|
|
|
Key string
|
|
|
|
Name string
|
|
|
|
Type SetupKeyType
|
|
|
|
CreatedAt time.Time
|
|
|
|
ExpiresAt time.Time
|
|
|
|
// Revoked indicates whether the key was revoked or not (we don't remove them for tracking purposes)
|
|
|
|
Revoked bool
|
|
|
|
// UsedTimes indicates how many times the key was used
|
|
|
|
UsedTimes int
|
2021-08-22 11:29:25 +02:00
|
|
|
// LastUsed last time the key was used for peer registration
|
|
|
|
LastUsed time.Time
|
2021-08-19 21:12:21 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 22:33:43 +02:00
|
|
|
//Copy copies SetupKey to a new object
|
|
|
|
func (key *SetupKey) Copy() *SetupKey {
|
|
|
|
return &SetupKey{
|
|
|
|
Id: key.Id,
|
|
|
|
Key: key.Key,
|
|
|
|
Name: key.Name,
|
|
|
|
Type: key.Type,
|
|
|
|
CreatedAt: key.CreatedAt,
|
|
|
|
ExpiresAt: key.ExpiresAt,
|
|
|
|
Revoked: key.Revoked,
|
|
|
|
UsedTimes: key.UsedTimes,
|
2021-08-25 14:16:17 +02:00
|
|
|
LastUsed: key.LastUsed,
|
2021-08-20 22:33:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-22 11:29:25 +02:00
|
|
|
//IncrementUsage makes a copy of a key, increments the UsedTimes by 1 and sets LastUsed to now
|
|
|
|
func (key *SetupKey) IncrementUsage() *SetupKey {
|
|
|
|
c := key.Copy()
|
|
|
|
c.UsedTimes = c.UsedTimes + 1
|
|
|
|
c.LastUsed = time.Now()
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2021-08-19 21:12:21 +02:00
|
|
|
// IsValid is true if the key was not revoked, is not expired and used not more than it was supposed to
|
|
|
|
func (key *SetupKey) IsValid() bool {
|
2021-08-25 14:16:17 +02:00
|
|
|
return !key.IsRevoked() && !key.IsExpired() && !key.IsOverUsed()
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsRevoked if key was revoked
|
|
|
|
func (key *SetupKey) IsRevoked() bool {
|
|
|
|
return key.Revoked
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsExpired if key was expired
|
|
|
|
func (key *SetupKey) IsExpired() bool {
|
|
|
|
return time.Now().After(key.ExpiresAt)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsOverUsed if key was used too many times
|
|
|
|
func (key *SetupKey) IsOverUsed() bool {
|
|
|
|
return key.Type == SetupKeyOneOff && key.UsedTimes >= 1
|
2021-08-19 21:12:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// GenerateSetupKey generates a new setup key
|
|
|
|
func GenerateSetupKey(name string, t SetupKeyType, validFor time.Duration) *SetupKey {
|
2021-08-20 22:33:43 +02:00
|
|
|
key := strings.ToUpper(uuid.New().String())
|
2021-08-19 21:12:21 +02:00
|
|
|
createdAt := time.Now()
|
|
|
|
return &SetupKey{
|
2021-08-20 22:33:43 +02:00
|
|
|
Id: strconv.Itoa(int(Hash(key))),
|
|
|
|
Key: key,
|
2021-08-19 21:12:21 +02:00
|
|
|
Name: name,
|
|
|
|
Type: t,
|
|
|
|
CreatedAt: createdAt,
|
|
|
|
ExpiresAt: createdAt.Add(validFor),
|
|
|
|
Revoked: false,
|
|
|
|
UsedTimes: 0,
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 15:01:57 +02:00
|
|
|
|
|
|
|
// GenerateDefaultSetupKey generates a default setup key
|
|
|
|
func GenerateDefaultSetupKey() *SetupKey {
|
|
|
|
return GenerateSetupKey(DefaultSetupKeyName, SetupKeyReusable, DefaultSetupKeyDuration)
|
|
|
|
}
|
2021-08-20 22:33:43 +02:00
|
|
|
|
|
|
|
func Hash(s string) uint32 {
|
|
|
|
h := fnv.New32a()
|
|
|
|
_, err := h.Write([]byte(s))
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return h.Sum32()
|
|
|
|
}
|