diff --git a/lib/auth/storage/storage.go b/lib/auth/storage/storage.go
index 9596f12e1e645..76db71182e982 100644
--- a/lib/auth/storage/storage.go
+++ b/lib/auth/storage/storage.go
@@ -63,7 +63,7 @@ type stateBackend interface {
// exists, updates it otherwise)
Put(ctx context.Context, i backend.Item) (*backend.Lease, error)
// Get returns a single item or not found error
- Get(ctx context.Context, key []byte) (*backend.Item, error)
+ Get(ctx context.Context, key backend.Key) (*backend.Item, error)
}
// ProcessStorage is a backend for local process state,
diff --git a/lib/backend/backend.go b/lib/backend/backend.go
index 1cac249ea0510..e3dc116a05f5a 100644
--- a/lib/backend/backend.go
+++ b/lib/backend/backend.go
@@ -60,17 +60,17 @@ type Backend interface {
Update(ctx context.Context, i Item) (*Lease, error)
// Get returns a single item or not found error
- Get(ctx context.Context, key []byte) (*Item, error)
+ Get(ctx context.Context, key Key) (*Item, error)
// GetRange returns query range
- GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*GetResult, error)
+ GetRange(ctx context.Context, startKey, endKey Key, limit int) (*GetResult, error)
// Delete deletes item by key, returns NotFound error
// if item does not exist
- Delete(ctx context.Context, key []byte) error
+ Delete(ctx context.Context, key Key) error
// DeleteRange deletes range of items with keys between startKey and endKey
- DeleteRange(ctx context.Context, startKey, endKey []byte) error
+ DeleteRange(ctx context.Context, startKey, endKey Key) error
// KeepAlive keeps object from expiring, updates lease on the existing object,
// expires contains the new expiry to set on the lease,
@@ -93,7 +93,7 @@ type Backend interface {
}
// IterateRange is a helper for stepping over a range
-func IterateRange(ctx context.Context, bk Backend, startKey []byte, endKey []byte, limit int, fn func([]Item) (stop bool, err error)) error {
+func IterateRange(ctx context.Context, bk Backend, startKey, endKey Key, limit int, fn func([]Item) (stop bool, err error)) error {
if limit == 0 || limit > 10_000 {
limit = 10_000
}
@@ -130,7 +130,7 @@ func IterateRange(ctx context.Context, bk Backend, startKey []byte, endKey []byt
//
// 2. allow individual backends to expose custom streaming methods s.t. the most performant
// impl for a given backend may be used.
-func StreamRange(ctx context.Context, bk Backend, startKey, endKey []byte, pageSize int) stream.Stream[Item] {
+func StreamRange(ctx context.Context, bk Backend, startKey, endKey Key, pageSize int) stream.Stream[Item] {
return stream.PageFunc[Item](func() ([]Item, error) {
if startKey == nil {
return nil, io.EOF
@@ -167,7 +167,7 @@ type Batch interface {
// err = backend.KeepAlive(ctx, lease, expires)
type Lease struct {
// Key is an object representing lease
- Key []byte
+ Key Key
// ID is a lease ID, could be empty
// Deprecated: use Revision instead
ID int64
@@ -187,7 +187,7 @@ type Watch struct {
Name string
// Prefixes specifies prefixes to watch,
// passed to the backend implementation
- Prefixes [][]byte
+ Prefixes []Key
// QueueSize is an optional queue size
QueueSize int
// MetricComponent if set will start reporting
@@ -231,7 +231,7 @@ type Event struct {
// Item is a key value item
type Item struct {
// Key is a key of the key value item
- Key []byte
+ Key Key
// Value is a value of the key value item
Value []byte
// Expires is an optional record expiry time
@@ -287,7 +287,7 @@ const NoLimit = 0
// nextKey returns the next possible key.
// If used with a key prefix, this will return
// the end of the range for that key prefix.
-func nextKey(key []byte) []byte {
+func nextKey(key Key) Key {
end := make([]byte, len(key))
copy(end, key)
for i := len(end) - 1; i >= 0; i-- {
@@ -301,10 +301,10 @@ func nextKey(key []byte) []byte {
return noEnd
}
-var noEnd = []byte{0}
+var noEnd = Key{0}
// RangeEnd returns end of the range for given key.
-func RangeEnd(key []byte) []byte {
+func RangeEnd(key Key) Key {
return nextKey(key)
}
@@ -325,7 +325,7 @@ type KeyedItem interface {
// have the HostID part.
func NextPaginationKey(ki KeyedItem) string {
key := GetPaginationKey(ki)
- return string(nextKey([]byte(key)))
+ return string(nextKey(Key(key)))
}
// GetPaginationKey returns the pagination key given item.
@@ -341,13 +341,13 @@ func GetPaginationKey(ki KeyedItem) string {
// MaskKeyName masks the given key name.
// e.g "123456789" -> "******789"
-func MaskKeyName(keyName string) []byte {
+func MaskKeyName(keyName string) string {
maskedBytes := []byte(keyName)
hiddenBefore := int(0.75 * float64(len(keyName)))
for i := 0; i < hiddenBefore; i++ {
maskedBytes[i] = '*'
}
- return maskedBytes
+ return string(maskedBytes)
}
// Items is a sortable list of backend items
@@ -421,7 +421,7 @@ const Separator = '/'
// NewKey joins parts into path separated by Separator,
// makes sure path always starts with Separator ("/")
-func NewKey(parts ...string) []byte {
+func NewKey(parts ...string) Key {
return internalKey("", parts...)
}
@@ -429,10 +429,10 @@ func NewKey(parts ...string) []byte {
// path of Key. This is to ensure range matching of a path will only
// math child paths and not other paths that have the resulting path
// as a prefix.
-func ExactKey(parts ...string) []byte {
+func ExactKey(parts ...string) Key {
return append(NewKey(parts...), Separator)
}
-func internalKey(internalPrefix string, parts ...string) []byte {
- return []byte(strings.Join(append([]string{internalPrefix}, parts...), string(Separator)))
+func internalKey(internalPrefix string, parts ...string) Key {
+ return Key(strings.Join(append([]string{internalPrefix}, parts...), string(Separator)))
}
diff --git a/lib/backend/buffer.go b/lib/backend/buffer.go
index 7456ce300a43d..98d8ce262011b 100644
--- a/lib/backend/buffer.go
+++ b/lib/backend/buffer.go
@@ -217,7 +217,7 @@ func (c *CircularBuffer) fanOutEvent(r Event) {
}
}
-func removeRedundantPrefixes(prefixes [][]byte) [][]byte {
+func removeRedundantPrefixes(prefixes []Key) []Key {
if len(prefixes) == 0 {
return prefixes
}
diff --git a/lib/backend/buffer_test.go b/lib/backend/buffer_test.go
index bb4b89cd181af..cea117b025406 100644
--- a/lib/backend/buffer_test.go
+++ b/lib/backend/buffer_test.go
@@ -18,6 +18,7 @@ package backend
import (
"context"
+ "fmt"
"testing"
"time"
@@ -48,17 +49,17 @@ func TestWatcherSimple(t *testing.T) {
t.Fatalf("Timeout waiting for event.")
}
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 1}})
+ b.Emit(Event{Item: Item{Key: Key("/1")}})
select {
case e := <-w.Events():
- require.Equal(t, e.Item.ID, int64(1))
+ require.Equal(t, Key("/1"), e.Item.Key)
case <-time.After(100 * time.Millisecond):
t.Fatalf("Timeout waiting for event.")
}
b.Close()
- b.Emit(Event{Item: Item{ID: 2}})
+ b.Emit(Event{Item: Item{Key: Key("/2")}})
select {
case <-w.Done():
@@ -101,12 +102,12 @@ func TestWatcherCapacity(t *testing.T) {
// emit and then consume 10 events. this is much larger than our queue size,
// but should succeed since we consume within our grace period.
for i := 0; i < 10; i++ {
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(i + 1)}})
+ b.Emit(Event{Item: Item{Key: Key(fmt.Sprintf("/%d", i+1))}})
}
for i := 0; i < 10; i++ {
select {
case e := <-w.Events():
- require.Equal(t, e.Item.ID, int64(i+1))
+ require.Equal(t, fmt.Sprintf("/%d", i+1), string(e.Item.Key))
default:
t.Fatalf("Expected events to be immediately available")
}
@@ -116,7 +117,7 @@ func TestWatcherCapacity(t *testing.T) {
clock.Advance(gracePeriod + time.Second)
// emit another event, which will cause buffer to reevaluate the grace period.
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(11)}})
+ b.Emit(Event{Item: Item{Key: Key("/11")}})
// ensure that buffer did not close watcher, since previously created backlog
// was drained within grace period.
@@ -128,13 +129,13 @@ func TestWatcherCapacity(t *testing.T) {
// create backlog again, and this time advance past grace period without draining it.
for i := 0; i < 10; i++ {
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(i + 12)}})
+ b.Emit(Event{Item: Item{Key: Key(fmt.Sprintf("/%d", i+12))}})
}
clock.Advance(gracePeriod + time.Second)
// emit another event, which will cause buffer to realize that watcher is past
// its grace period.
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(22)}})
+ b.Emit(Event{Item: Item{Key: Key("/22")}})
select {
case <-w.Done():
@@ -174,7 +175,7 @@ func TestWatcherCreationGracePeriod(t *testing.T) {
// emit enough events to create a backlog
for i := 0; i < queueSize*2; i++ {
- b.Emit(Event{Item: Item{Key: []byte{Separator}}})
+ b.Emit(Event{Item: Item{Key: Key{Separator}}})
}
select {
@@ -189,7 +190,7 @@ func TestWatcherCreationGracePeriod(t *testing.T) {
// advance well past the backlog grace period, but not past the creation grace period
clock.Advance(backlogGracePeriod * 2)
- b.Emit(Event{Item: Item{Key: []byte{Separator}}})
+ b.Emit(Event{Item: Item{Key: Key{Separator}}})
select {
case <-w.Done():
@@ -200,7 +201,7 @@ func TestWatcherCreationGracePeriod(t *testing.T) {
// advance well past creation grace period
clock.Advance(creationGracePeriod)
- b.Emit(Event{Item: Item{Key: []byte{Separator}}})
+ b.Emit(Event{Item: Item{Key: Key{Separator}}})
select {
case <-w.Done():
default:
@@ -236,29 +237,29 @@ func TestWatcherClose(t *testing.T) {
// TestRemoveRedundantPrefixes removes redundant prefixes
func TestRemoveRedundantPrefixes(t *testing.T) {
type tc struct {
- in [][]byte
- out [][]byte
+ in []Key
+ out []Key
}
tcs := []tc{
{
- in: [][]byte{},
- out: [][]byte{},
+ in: []Key{},
+ out: []Key{},
},
{
- in: [][]byte{[]byte("/a")},
- out: [][]byte{[]byte("/a")},
+ in: []Key{Key("/a")},
+ out: []Key{Key("/a")},
},
{
- in: [][]byte{[]byte("/a"), []byte("/")},
- out: [][]byte{[]byte("/")},
+ in: []Key{Key("/a"), Key("/")},
+ out: []Key{Key("/")},
},
{
- in: [][]byte{[]byte("/b"), []byte("/a")},
- out: [][]byte{[]byte("/a"), []byte("/b")},
+ in: []Key{Key("/b"), Key("/a")},
+ out: []Key{Key("/a"), Key("/b")},
},
{
- in: [][]byte{[]byte("/a/b"), []byte("/a"), []byte("/a/b/c"), []byte("/d")},
- out: [][]byte{[]byte("/a"), []byte("/d")},
+ in: []Key{Key("/a/b"), Key("/a"), Key("/a/b/c"), Key("/d")},
+ out: []Key{Key("/a"), Key("/d")},
},
}
for _, tc := range tcs {
@@ -276,7 +277,7 @@ func TestWatcherMulti(t *testing.T) {
defer b.Close()
b.SetInit()
- w, err := b.NewWatcher(ctx, Watch{Prefixes: [][]byte{[]byte("/a"), []byte("/a/b")}})
+ w, err := b.NewWatcher(ctx, Watch{Prefixes: []Key{Key("/a"), Key("/a/b")}})
require.NoError(t, err)
defer w.Close()
@@ -287,11 +288,11 @@ func TestWatcherMulti(t *testing.T) {
t.Fatalf("Timeout waiting for event.")
}
- b.Emit(Event{Item: Item{Key: []byte("/a/b/c"), ID: 1}})
+ b.Emit(Event{Item: Item{Key: Key("/a/b/c")}})
select {
case e := <-w.Events():
- require.Equal(t, e.Item.ID, int64(1))
+ require.Equal(t, Key("/a/b/c"), e.Item.Key)
case <-time.After(100 * time.Millisecond):
t.Fatalf("Timeout waiting for event.")
}
@@ -320,7 +321,7 @@ func TestWatcherReset(t *testing.T) {
t.Fatalf("Timeout waiting for event.")
}
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 1}})
+ b.Emit(Event{Item: Item{Key: Key("/1")}})
b.Clear()
// make sure watcher has been closed
@@ -341,11 +342,11 @@ func TestWatcherReset(t *testing.T) {
t.Fatalf("Timeout waiting for event.")
}
- b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 2}})
+ b.Emit(Event{Item: Item{Key: Key("/2")}})
select {
case e := <-w2.Events():
- require.Equal(t, e.Item.ID, int64(2))
+ require.Equal(t, Key("/2"), e.Item.Key)
case <-time.After(100 * time.Millisecond):
t.Fatalf("Timeout waiting for event.")
}
@@ -356,10 +357,10 @@ func TestWatcherTree(t *testing.T) {
wt := newWatcherTree()
require.Equal(t, wt.rm(nil), false)
- w1 := &BufferWatcher{Watch: Watch{Prefixes: [][]byte{[]byte("/a"), []byte("/a/a1"), []byte("/c")}}}
- require.Equal(t, wt.rm(w1), false)
+ w1 := &BufferWatcher{Watch: Watch{Prefixes: []Key{Key("/a"), Key("/a/a1"), Key("/c")}}}
+ require.False(t, wt.rm(w1))
- w2 := &BufferWatcher{Watch: Watch{Prefixes: [][]byte{[]byte("/a")}}}
+ w2 := &BufferWatcher{Watch: Watch{Prefixes: []Key{Key("/a")}}}
wt.add(w1)
wt.add(w2)
diff --git a/lib/backend/dynamo/dynamodbbk.go b/lib/backend/dynamo/dynamodbbk.go
index f8d2aa3742b75..4aba248313395 100644
--- a/lib/backend/dynamo/dynamodbbk.go
+++ b/lib/backend/dynamo/dynamodbbk.go
@@ -381,7 +381,7 @@ func (b *Backend) Update(ctx context.Context, item backend.Item) (*backend.Lease
}
// GetRange returns range of elements
-func (b *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*backend.GetResult, error) {
+func (b *Backend) GetRange(ctx context.Context, startKey, endKey backend.Key, limit int) (*backend.GetResult, error) {
if len(startKey) == 0 {
return nil, trace.BadParameter("missing parameter startKey")
}
@@ -410,7 +410,7 @@ func (b *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte,
return &backend.GetResult{Items: values}, nil
}
-func (b *Backend) getAllRecords(ctx context.Context, startKey []byte, endKey []byte, limit int) (*getResult, error) {
+func (b *Backend) getAllRecords(ctx context.Context, startKey, endKey backend.Key, limit int) (*getResult, error) {
var result getResult
// this code is being extra careful here not to introduce endless loop
@@ -444,7 +444,7 @@ const (
)
// DeleteRange deletes range of items with keys between startKey and endKey
-func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey []byte) error {
+func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey backend.Key) error {
if len(startKey) == 0 {
return trace.BadParameter("missing parameter startKey")
}
@@ -491,7 +491,7 @@ func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey []byte) erro
}
// Get returns a single item or not found error
-func (b *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (b *Backend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
r, err := b.getKey(ctx, key)
if err != nil {
return nil, err
@@ -560,7 +560,7 @@ func (b *Backend) CompareAndSwap(ctx context.Context, expected backend.Item, rep
}
// Delete deletes item by key
-func (b *Backend) Delete(ctx context.Context, key []byte) error {
+func (b *Backend) Delete(ctx context.Context, key backend.Key) error {
if len(key) == 0 {
return trace.BadParameter("missing parameter key")
}
@@ -837,13 +837,13 @@ const (
// prependPrefix adds leading 'teleport/' to the key for backwards compatibility
// with previous implementation of DynamoDB backend
-func prependPrefix(key []byte) string {
+func prependPrefix(key backend.Key) string {
return keyPrefix + string(key)
}
// trimPrefix removes leading 'teleport' from the key
-func trimPrefix(key string) []byte {
- return []byte(strings.TrimPrefix(key, keyPrefix))
+func trimPrefix(key string) backend.Key {
+ return backend.Key(strings.TrimPrefix(key, keyPrefix))
}
// create helper creates a new key/value pair in Dynamo with a given expiration
@@ -884,7 +884,7 @@ func (b *Backend) create(ctx context.Context, item backend.Item, mode int) error
return nil
}
-func (b *Backend) deleteKey(ctx context.Context, key []byte) error {
+func (b *Backend) deleteKey(ctx context.Context, key backend.Key) error {
av, err := dynamodbattribute.MarshalMap(keyLookup{
HashKey: hashKey,
FullPath: prependPrefix(key),
@@ -899,7 +899,7 @@ func (b *Backend) deleteKey(ctx context.Context, key []byte) error {
return nil
}
-func (b *Backend) deleteKeyIfExpired(ctx context.Context, key []byte) error {
+func (b *Backend) deleteKeyIfExpired(ctx context.Context, key backend.Key) error {
_, err := b.svc.DeleteItemWithContext(ctx, &dynamodb.DeleteItemInput{
TableName: aws.String(b.TableName),
Key: keyToAttributeValueMap(key),
@@ -915,7 +915,7 @@ func (b *Backend) deleteKeyIfExpired(ctx context.Context, key []byte) error {
return trace.Wrap(err)
}
-func (b *Backend) getKey(ctx context.Context, key []byte) (*record, error) {
+func (b *Backend) getKey(ctx context.Context, key backend.Key) (*record, error) {
av, err := dynamodbattribute.MarshalMap(keyLookup{
HashKey: hashKey,
FullPath: prependPrefix(key),
@@ -1001,7 +1001,7 @@ func fullPathToAttributeValueMap(fullPath string) map[string]*dynamodb.Attribute
}
}
-func keyToAttributeValueMap(key []byte) map[string]*dynamodb.AttributeValue {
+func keyToAttributeValueMap(key backend.Key) map[string]*dynamodb.AttributeValue {
return fullPathToAttributeValueMap(prependPrefix(key))
}
diff --git a/lib/backend/etcdbk/etcd.go b/lib/backend/etcdbk/etcd.go
index 205736f7d4466..64a32295c1443 100644
--- a/lib/backend/etcdbk/etcd.go
+++ b/lib/backend/etcdbk/etcd.go
@@ -642,7 +642,7 @@ func (b *EtcdBackend) NewWatcher(ctx context.Context, watch backend.Watch) (back
}
// GetRange returns query range
-func (b *EtcdBackend) GetRange(ctx context.Context, startKey, endKey []byte, limit int) (*backend.GetResult, error) {
+func (b *EtcdBackend) GetRange(ctx context.Context, startKey, endKey backend.Key, limit int) (*backend.GetResult, error) {
if len(startKey) == 0 {
return nil, trace.BadParameter("missing parameter startKey")
}
@@ -818,7 +818,7 @@ func (b *EtcdBackend) KeepAlive(ctx context.Context, lease backend.Lease, expire
}
// Get returns a single item or not found error
-func (b *EtcdBackend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (b *EtcdBackend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
re, err := b.clients.Next().Get(ctx, b.prependPrefix(key))
if err != nil {
return nil, convertErr(err)
@@ -835,7 +835,7 @@ func (b *EtcdBackend) Get(ctx context.Context, key []byte) (*backend.Item, error
}
// Delete deletes item by key
-func (b *EtcdBackend) Delete(ctx context.Context, key []byte) error {
+func (b *EtcdBackend) Delete(ctx context.Context, key backend.Key) error {
start := b.clock.Now()
re, err := b.clients.Next().Delete(ctx, b.prependPrefix(key))
writeLatencies.Observe(time.Since(start).Seconds())
@@ -851,7 +851,7 @@ func (b *EtcdBackend) Delete(ctx context.Context, key []byte) error {
}
// DeleteRange deletes range of items with keys between startKey and endKey
-func (b *EtcdBackend) DeleteRange(ctx context.Context, startKey, endKey []byte) error {
+func (b *EtcdBackend) DeleteRange(ctx context.Context, startKey, endKey backend.Key) error {
if len(startKey) == 0 {
return trace.BadParameter("missing parameter startKey")
}
@@ -1018,10 +1018,10 @@ func fromType(eventType mvccpb.Event_EventType) types.OpType {
}
}
-func (b *EtcdBackend) trimPrefix(in []byte) []byte {
- return bytes.TrimPrefix(in, []byte(b.cfg.Key))
+func (b *EtcdBackend) trimPrefix(in backend.Key) backend.Key {
+ return bytes.TrimPrefix(in, backend.Key(b.cfg.Key))
}
-func (b *EtcdBackend) prependPrefix(in []byte) string {
+func (b *EtcdBackend) prependPrefix(in backend.Key) string {
return b.cfg.Key + string(in)
}
diff --git a/lib/backend/etcdbk/etcd_test.go b/lib/backend/etcdbk/etcd_test.go
index 8c4c1d396f36c..df1f76f1326ef 100644
--- a/lib/backend/etcdbk/etcd_test.go
+++ b/lib/backend/etcdbk/etcd_test.go
@@ -116,7 +116,7 @@ func TestPrefix(t *testing.T) {
// When I push an item with a key starting with "/" into etcd via the
// _prefixed_ client...
item := backend.Item{
- Key: []byte("/foo"),
+ Key: backend.Key("/foo"),
Value: []byte("bar"),
}
_, err = prefixedUut.Put(ctx, item)
@@ -134,7 +134,7 @@ func TestPrefix(t *testing.T) {
// When I push an item with a key that does _not_ start with a separator
// char (i.e. "/") into etcd via the _prefixed_ client...
item = backend.Item{
- Key: []byte("foo"),
+ Key: backend.Key("foo"),
Value: []byte("bar"),
}
_, err = prefixedUut.Put(ctx, item)
diff --git a/lib/backend/firestore/firestorebk.go b/lib/backend/firestore/firestorebk.go
index e20bcb0654738..a2417ee011cc3 100644
--- a/lib/backend/firestore/firestorebk.go
+++ b/lib/backend/firestore/firestorebk.go
@@ -107,11 +107,11 @@ type Backend struct {
}
type record struct {
- Key []byte `firestore:"key,omitempty"`
- Timestamp int64 `firestore:"timestamp,omitempty"`
- Expires int64 `firestore:"expires,omitempty"`
- ID int64 `firestore:"id,omitempty"`
- Value []byte `firestore:"value,omitempty"`
+ Key backend.Key `firestore:"key,omitempty"`
+ Timestamp int64 `firestore:"timestamp,omitempty"`
+ Expires int64 `firestore:"expires,omitempty"`
+ ID int64 `firestore:"id,omitempty"`
+ Value []byte `firestore:"value,omitempty"`
}
// legacyRecord is an older version of record used to marshal backend.Items.
@@ -154,7 +154,7 @@ func newRecordFromDoc(doc *firestore.DocumentSnapshot) (*record, error) {
return nil, ConvertGRPCError(err)
}
r = record{
- Key: []byte(rl.Key),
+ Key: backend.Key(rl.Key),
Value: []byte(rl.Value),
Timestamp: rl.Timestamp,
Expires: rl.Expires,
@@ -382,7 +382,7 @@ func (b *Backend) Update(ctx context.Context, item backend.Item) (*backend.Lease
return b.newLease(item), nil
}
-func (b *Backend) getRangeDocs(ctx context.Context, startKey []byte, endKey []byte, limit int) ([]*firestore.DocumentSnapshot, error) {
+func (b *Backend) getRangeDocs(ctx context.Context, startKey, endKey backend.Key, limit int) ([]*firestore.DocumentSnapshot, error) {
if len(startKey) == 0 {
return nil, trace.BadParameter("missing parameter startKey")
}
@@ -417,7 +417,7 @@ func (b *Backend) getRangeDocs(ctx context.Context, startKey []byte, endKey []by
}
// GetRange returns range of elements
-func (b *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*backend.GetResult, error) {
+func (b *Backend) GetRange(ctx context.Context, startKey, endKey backend.Key, limit int) (*backend.GetResult, error) {
docSnaps, err := b.getRangeDocs(ctx, startKey, endKey, limit)
if err != nil {
return nil, trace.Wrap(err)
@@ -456,7 +456,7 @@ func (b *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte,
}
// DeleteRange deletes range of items with keys between startKey and endKey
-func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey []byte) error {
+func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey backend.Key) error {
docs, err := b.getRangeDocs(ctx, startKey, endKey, backend.DefaultRangeLimit)
if err != nil {
return trace.Wrap(err)
@@ -466,7 +466,7 @@ func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey []byte) erro
}
// Get returns a single item or not found error
-func (b *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (b *Backend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
if len(key) == 0 {
return nil, trace.BadParameter("missing parameter key")
}
@@ -550,7 +550,7 @@ func (b *Backend) CompareAndSwap(ctx context.Context, expected backend.Item, rep
}
// Delete deletes item by key
-func (b *Backend) Delete(ctx context.Context, key []byte) error {
+func (b *Backend) Delete(ctx context.Context, key backend.Key) error {
if len(key) == 0 {
return trace.BadParameter("missing parameter key")
}
@@ -638,7 +638,7 @@ func (b *Backend) newLease(item backend.Item) *backend.Lease {
// IDs. See
// https://firebase.google.com/docs/firestore/quotas#collections_documents_and_fields
// for Firestore limitations.
-func (b *Backend) keyToDocumentID(key []byte) string {
+func (b *Backend) keyToDocumentID(key backend.Key) string {
// URL-safe base64 will not have periods or forward slashes.
// This should satisfy the Firestore requirements.
return base64.URLEncoding.EncodeToString(key)
diff --git a/lib/backend/helpers.go b/lib/backend/helpers.go
index 64386e2581a48..f9eae94437032 100644
--- a/lib/backend/helpers.go
+++ b/lib/backend/helpers.go
@@ -27,20 +27,15 @@ import (
)
const (
- flagsPrefix = ".flags"
locksPrefix = ".locks"
)
-func FlagKey(parts ...string) []byte {
- return internalKey(flagsPrefix, parts...)
-}
-
-func lockKey(parts ...string) []byte {
+func lockKey(parts ...string) Key {
return internalKey(locksPrefix, parts...)
}
type Lock struct {
- key []byte
+ key Key
id []byte
ttl time.Duration
}
diff --git a/lib/backend/key.go b/lib/backend/key.go
new file mode 100644
index 0000000000000..2ff85090ef9fd
--- /dev/null
+++ b/lib/backend/key.go
@@ -0,0 +1,20 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package backend
+
+// Key is the unique identifier for an [Item].
+type Key = []byte
diff --git a/lib/backend/kubernetes/kubernetes.go b/lib/backend/kubernetes/kubernetes.go
index 04b44ae46f071..40fafcd2f584f 100644
--- a/lib/backend/kubernetes/kubernetes.go
+++ b/lib/backend/kubernetes/kubernetes.go
@@ -219,7 +219,7 @@ func (b *Backend) Exists(ctx context.Context) bool {
// Get reads the secret and extracts the key from it.
// If the secret does not exist or the key is not found it returns trace.Notfound,
// otherwise returns the underlying error.
-func (b *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (b *Backend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
b.mu.Lock()
defer b.mu.Unlock()
@@ -258,7 +258,7 @@ func (b *Backend) getSecret(ctx context.Context) (*corev1.Secret, error) {
// readSecretData reads the secret content and extracts the content for key.
// returns an error if the key does not exist or the data is empty.
-func (b *Backend) readSecretData(ctx context.Context, key []byte) (*backend.Item, error) {
+func (b *Backend) readSecretData(ctx context.Context, key backend.Key) (*backend.Item, error) {
secret, err := b.getSecret(ctx)
if err != nil {
return nil, trace.Wrap(err)
@@ -350,7 +350,7 @@ func generateSecretAnnotations(namespace, releaseNameEnv string) map[string]stri
// backendKeyToSecret replaces the "/" with "."
// "/" chars are not allowed in Kubernetes Secret keys.
-func backendKeyToSecret(k []byte) string {
+func backendKeyToSecret(k backend.Key) string {
return strings.ReplaceAll(string(k), "/", ".")
}
diff --git a/lib/backend/kubernetes/kubernetes_test.go b/lib/backend/kubernetes/kubernetes_test.go
index cc04c8f7a7fb6..2a7cb055fac6a 100644
--- a/lib/backend/kubernetes/kubernetes_test.go
+++ b/lib/backend/kubernetes/kubernetes_test.go
@@ -140,7 +140,7 @@ func TestBackend_Get(t *testing.T) {
}
type args struct {
- key []byte
+ key backend.Key
}
tests := []struct {
diff --git a/lib/backend/lite/lite.go b/lib/backend/lite/lite.go
index b578da5f24ba2..6b66d4b0544db 100644
--- a/lib/backend/lite/lite.go
+++ b/lib/backend/lite/lite.go
@@ -682,7 +682,7 @@ func (l *Backend) Update(ctx context.Context, i backend.Item) (*backend.Lease, e
}
// Get returns a single item or not found error
-func (l *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (l *Backend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
if len(key) == 0 {
return nil, trace.BadParameter("missing parameter key")
}
@@ -697,7 +697,7 @@ func (l *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
}
// getInTransaction returns an item, works in transaction
-func (l *Backend) getInTransaction(ctx context.Context, key []byte, tx *sql.Tx, item *backend.Item) error {
+func (l *Backend) getInTransaction(ctx context.Context, key backend.Key, tx *sql.Tx, item *backend.Item) error {
// When in mirror mode, don't set the current time so the SELECT query
// returns expired items.
var now time.Time
@@ -725,7 +725,7 @@ func (l *Backend) getInTransaction(ctx context.Context, key []byte, tx *sql.Tx,
}
// GetRange returns query range
-func (l *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*backend.GetResult, error) {
+func (l *Backend) GetRange(ctx context.Context, startKey, endKey backend.Key, limit int) (*backend.GetResult, error) {
if len(startKey) == 0 {
return nil, trace.BadParameter("missing parameter startKey")
}
@@ -823,7 +823,7 @@ func (l *Backend) KeepAlive(ctx context.Context, lease backend.Lease, expires ti
})
}
-func (l *Backend) deleteInTransaction(ctx context.Context, key []byte, tx *sql.Tx) error {
+func (l *Backend) deleteInTransaction(ctx context.Context, key backend.Key, tx *sql.Tx) error {
stmt, err := tx.PrepareContext(ctx, "DELETE FROM kv WHERE key = ?")
if err != nil {
return trace.Wrap(err)
@@ -858,7 +858,7 @@ func (l *Backend) deleteInTransaction(ctx context.Context, key []byte, tx *sql.T
// Delete deletes item by key, returns NotFound error
// if item does not exist
-func (l *Backend) Delete(ctx context.Context, key []byte) error {
+func (l *Backend) Delete(ctx context.Context, key backend.Key) error {
if len(key) == 0 {
return trace.BadParameter("missing parameter key")
}
@@ -869,7 +869,7 @@ func (l *Backend) Delete(ctx context.Context, key []byte) error {
// DeleteRange deletes range of items with keys between startKey and endKey
// Note that elements deleted by range do not produce any events
-func (l *Backend) DeleteRange(ctx context.Context, startKey, endKey []byte) error {
+func (l *Backend) DeleteRange(ctx context.Context, startKey, endKey backend.Key) error {
if len(startKey) == 0 {
return trace.BadParameter("missing parameter startKey")
}
@@ -889,7 +889,7 @@ func (l *Backend) DeleteRange(ctx context.Context, startKey, endKey []byte) erro
return trace.Wrap(err)
}
defer rows.Close()
- var keys [][]byte
+ var keys []backend.Key
for rows.Next() {
var key []byte
if err := rows.Scan(&key); err != nil {
diff --git a/lib/backend/lite/periodic.go b/lib/backend/lite/periodic.go
index 6c17502144d25..0b310d49b16a2 100644
--- a/lib/backend/lite/periodic.go
+++ b/lib/backend/lite/periodic.go
@@ -86,7 +86,7 @@ func (l *Backend) removeExpiredKeys() error {
return trace.Wrap(err)
}
defer rows.Close()
- var keys [][]byte
+ var keys []backend.Key
for rows.Next() {
var key []byte
if err := rows.Scan(&key); err != nil {
diff --git a/lib/backend/memory/item.go b/lib/backend/memory/item.go
index 95fb5ee1e43fc..9fe9a9262cce8 100644
--- a/lib/backend/memory/item.go
+++ b/lib/backend/memory/item.go
@@ -48,7 +48,7 @@ func (i *btreeItem) Less(iother btree.Item) bool {
// prefixItem is used for prefix matches on a B-Tree
type prefixItem struct {
// prefix is a prefix to match
- prefix []byte
+ prefix backend.Key
}
// Less is used for Btree operations
diff --git a/lib/backend/memory/memory.go b/lib/backend/memory/memory.go
index 152cb038f2d8e..b1db099f8373d 100644
--- a/lib/backend/memory/memory.go
+++ b/lib/backend/memory/memory.go
@@ -181,7 +181,7 @@ func (m *Memory) Create(ctx context.Context, i backend.Item) (*backend.Lease, er
}
// Get returns a single item or not found error
-func (m *Memory) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (m *Memory) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
if len(key) == 0 {
return nil, trace.BadParameter("missing parameter key")
}
@@ -272,7 +272,7 @@ func (m *Memory) PutRange(ctx context.Context, items []backend.Item) error {
// Delete deletes item by key, returns NotFound error
// if item does not exist
-func (m *Memory) Delete(ctx context.Context, key []byte) error {
+func (m *Memory) Delete(ctx context.Context, key backend.Key) error {
if len(key) == 0 {
return trace.BadParameter("missing parameter key")
}
@@ -297,7 +297,7 @@ func (m *Memory) Delete(ctx context.Context, key []byte) error {
// DeleteRange deletes range of items with keys between startKey and endKey
// Note that elements deleted by range do not produce any events
-func (m *Memory) DeleteRange(ctx context.Context, startKey, endKey []byte) error {
+func (m *Memory) DeleteRange(ctx context.Context, startKey, endKey backend.Key) error {
if len(startKey) == 0 {
return trace.BadParameter("missing parameter startKey")
}
@@ -322,7 +322,7 @@ func (m *Memory) DeleteRange(ctx context.Context, startKey, endKey []byte) error
}
// GetRange returns query range
-func (m *Memory) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*backend.GetResult, error) {
+func (m *Memory) GetRange(ctx context.Context, startKey, endKey backend.Key, limit int) (*backend.GetResult, error) {
if len(startKey) == 0 {
return nil, trace.BadParameter("missing parameter startKey")
}
@@ -416,7 +416,7 @@ func (m *Memory) generateID() int64 {
return atomic.AddInt64(&m.nextID, 1)
}
-func (m *Memory) getRange(ctx context.Context, startKey, endKey []byte, limit int) backend.GetResult {
+func (m *Memory) getRange(ctx context.Context, startKey, endKey backend.Key, limit int) backend.GetResult {
var res backend.GetResult
m.tree.AscendRange(&btreeItem{Item: backend.Item{Key: startKey}}, &btreeItem{Item: backend.Item{Key: endKey}}, func(item *btreeItem) bool {
res.Items = append(res.Items, item.Item)
diff --git a/lib/backend/pgbk/pgbk.go b/lib/backend/pgbk/pgbk.go
index b8ebb9daf17cb..59443880aefd6 100644
--- a/lib/backend/pgbk/pgbk.go
+++ b/lib/backend/pgbk/pgbk.go
@@ -357,7 +357,7 @@ func (b *Backend) Update(ctx context.Context, i backend.Item) (*backend.Lease, e
}
// Get implements [backend.Backend].
-func (b *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (b *Backend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
item, err := pgcommon.RetryIdempotent(ctx, b.log, func() (*backend.Item, error) {
batch := new(pgx.Batch)
// batches run in an implicit transaction
@@ -403,7 +403,7 @@ func (b *Backend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
}
// GetRange implements [backend.Backend].
-func (b *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*backend.GetResult, error) {
+func (b *Backend) GetRange(ctx context.Context, startKey, endKey backend.Key, limit int) (*backend.GetResult, error) {
if limit <= 0 {
limit = backend.DefaultRangeLimit
}
@@ -454,7 +454,7 @@ func (b *Backend) GetRange(ctx context.Context, startKey []byte, endKey []byte,
}
// Delete implements [backend.Backend].
-func (b *Backend) Delete(ctx context.Context, key []byte) error {
+func (b *Backend) Delete(ctx context.Context, key backend.Key) error {
deleted, err := pgcommon.Retry(ctx, b.log, func() (bool, error) {
tag, err := b.pool.Exec(ctx,
"DELETE FROM kv WHERE kv.key = $1 AND (kv.expires IS NULL OR kv.expires > now())", nonNil(key))
@@ -474,7 +474,7 @@ func (b *Backend) Delete(ctx context.Context, key []byte) error {
}
// DeleteRange implements [backend.Backend].
-func (b *Backend) DeleteRange(ctx context.Context, startKey []byte, endKey []byte) error {
+func (b *Backend) DeleteRange(ctx context.Context, startKey, endKey backend.Key) error {
// this is the only backend operation that might affect a disproportionate
// amount of rows at the same time; in actual operation, DeleteRange hardly
// ever deletes more than dozens of items at once, and logical decoding
diff --git a/lib/backend/pgbk/wal2json_test.go b/lib/backend/pgbk/wal2json_test.go
index eebbda9caec29..4078784bba4cb 100644
--- a/lib/backend/pgbk/wal2json_test.go
+++ b/lib/backend/pgbk/wal2json_test.go
@@ -153,7 +153,7 @@ func TestMessage(t *testing.T) {
require.Empty(t, cmp.Diff(evs[0], backend.Event{
Type: types.OpPut,
Item: backend.Item{
- Key: []byte("foo"),
+ Key: backend.Key("foo"),
Value: []byte(""),
ID: idFromRevision(rev),
},
@@ -177,7 +177,7 @@ func TestMessage(t *testing.T) {
require.Empty(t, cmp.Diff(evs[0], backend.Event{
Type: types.OpPut,
Item: backend.Item{
- Key: []byte("foo"),
+ Key: backend.Key("foo"),
Value: []byte("foo2"),
ID: idFromRevision(rev),
},
@@ -205,13 +205,13 @@ func TestMessage(t *testing.T) {
require.Empty(t, cmp.Diff(evs[0], backend.Event{
Type: types.OpDelete,
Item: backend.Item{
- Key: []byte("foo"),
+ Key: backend.Key("foo"),
},
}))
require.Empty(t, cmp.Diff(evs[1], backend.Event{
Type: types.OpPut,
Item: backend.Item{
- Key: []byte("foo2"),
+ Key: backend.Key("foo2"),
Value: []byte("foo2"),
Expires: time.Date(2023, 9, 5, 15, 57, 1, 340426000, time.UTC),
ID: idFromRevision(rev),
@@ -248,7 +248,7 @@ func TestMessage(t *testing.T) {
require.Empty(t, cmp.Diff(evs[0], backend.Event{
Type: types.OpDelete,
Item: backend.Item{
- Key: []byte("foo"),
+ Key: backend.Key("foo"),
},
}))
}
diff --git a/lib/backend/report.go b/lib/backend/report.go
index b661ecd7b7f51..3585a83581fee 100644
--- a/lib/backend/report.go
+++ b/lib/backend/report.go
@@ -118,7 +118,7 @@ func (s *Reporter) GetName() string {
}
// GetRange returns query range
-func (s *Reporter) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*GetResult, error) {
+func (s *Reporter) GetRange(ctx context.Context, startKey, endKey Key, limit int) (*GetResult, error) {
ctx, span := s.Tracer.Start(
ctx,
"backend/GetRange",
@@ -220,7 +220,7 @@ func (s *Reporter) Update(ctx context.Context, i Item) (*Lease, error) {
}
// Get returns a single item or not found error
-func (s *Reporter) Get(ctx context.Context, key []byte) (*Item, error) {
+func (s *Reporter) Get(ctx context.Context, key Key) (*Item, error) {
ctx, span := s.Tracer.Start(
ctx,
"backend/Get",
@@ -265,7 +265,7 @@ func (s *Reporter) CompareAndSwap(ctx context.Context, expected Item, replaceWit
}
// Delete deletes item by key
-func (s *Reporter) Delete(ctx context.Context, key []byte) error {
+func (s *Reporter) Delete(ctx context.Context, key Key) error {
ctx, span := s.Tracer.Start(
ctx,
"backend/Delete",
@@ -287,7 +287,7 @@ func (s *Reporter) Delete(ctx context.Context, key []byte) error {
}
// DeleteRange deletes range of items
-func (s *Reporter) DeleteRange(ctx context.Context, startKey []byte, endKey []byte) error {
+func (s *Reporter) DeleteRange(ctx context.Context, startKey, endKey Key) error {
ctx, span := s.Tracer.Start(
ctx,
"backend/DeleteRange",
@@ -376,7 +376,7 @@ type topRequestsCacheKey struct {
}
// trackRequests tracks top requests, endKey is supplied for ranges
-func (s *Reporter) trackRequest(opType types.OpType, key []byte, endKey []byte) {
+func (s *Reporter) trackRequest(opType types.OpType, key Key, endKey Key) {
if len(key) == 0 {
return
}
@@ -446,7 +446,7 @@ func buildKeyLabel(key string, sensitivePrefixes, singletonPrefixes []string, is
// if the first non-empty segment is a secret range and there are at least two non-empty
// segments, then the second non-empty segment should be masked.
if finalLen-realStart > 1 && slices.Contains(sensitivePrefixes, parts[realStart]) {
- parts[realStart+1] = string(MaskKeyName(parts[realStart+1]))
+ parts[realStart+1] = MaskKeyName(parts[realStart+1])
}
return strings.Join(parts[:finalLen], string(Separator))
diff --git a/lib/backend/sanitize.go b/lib/backend/sanitize.go
index c36828b4ca0e4..11cf6c3d649ff 100644
--- a/lib/backend/sanitize.go
+++ b/lib/backend/sanitize.go
@@ -40,12 +40,12 @@ var denyPatterns = []*regexp.Regexp{
}
// isKeySafe checks if the passed in key conforms to whitelist
-func isKeySafe(s []byte) bool {
+func isKeySafe(s Key) bool {
return allowPattern.Match(s) && !denyPatternsMatch(s) && utf8.Valid(s)
}
// denyPatternsMatch checks if the passed in key conforms to the deny patterns.
-func denyPatternsMatch(s []byte) bool {
+func denyPatternsMatch(s Key) bool {
for _, pattern := range denyPatterns {
if pattern.Match(s) {
return true
@@ -69,7 +69,7 @@ func NewSanitizer(backend Backend) *Sanitizer {
}
// GetRange returns query range
-func (s *Sanitizer) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*GetResult, error) {
+func (s *Sanitizer) GetRange(ctx context.Context, startKey, endKey Key, limit int) (*GetResult, error) {
if !isKeySafe(startKey) {
return nil, trace.BadParameter(errorMessage, startKey)
}
@@ -104,7 +104,7 @@ func (s *Sanitizer) Update(ctx context.Context, i Item) (*Lease, error) {
}
// Get returns a single item or not found error
-func (s *Sanitizer) Get(ctx context.Context, key []byte) (*Item, error) {
+func (s *Sanitizer) Get(ctx context.Context, key Key) (*Item, error) {
if !isKeySafe(key) {
return nil, trace.BadParameter(errorMessage, key)
}
@@ -122,7 +122,7 @@ func (s *Sanitizer) CompareAndSwap(ctx context.Context, expected Item, replaceWi
}
// Delete deletes item by key
-func (s *Sanitizer) Delete(ctx context.Context, key []byte) error {
+func (s *Sanitizer) Delete(ctx context.Context, key Key) error {
if !isKeySafe(key) {
return trace.BadParameter(errorMessage, key)
}
@@ -130,7 +130,7 @@ func (s *Sanitizer) Delete(ctx context.Context, key []byte) error {
}
// DeleteRange deletes range of items
-func (s *Sanitizer) DeleteRange(ctx context.Context, startKey []byte, endKey []byte) error {
+func (s *Sanitizer) DeleteRange(ctx context.Context, startKey, endKey Key) error {
// we only validate the start key, since we often compute the end key
// in order to delete a bunch of related entries
if !isKeySafe(startKey) {
diff --git a/lib/backend/sanitize_test.go b/lib/backend/sanitize_test.go
index dca2b696014be..939e9749f810f 100644
--- a/lib/backend/sanitize_test.go
+++ b/lib/backend/sanitize_test.go
@@ -142,11 +142,11 @@ func (n *nopBackend) GetName() string {
return "nop"
}
-func (n *nopBackend) Get(_ context.Context, _ []byte) (*Item, error) {
+func (n *nopBackend) Get(_ context.Context, _ Key) (*Item, error) {
return &Item{}, nil
}
-func (n *nopBackend) GetRange(_ context.Context, startKey []byte, endKey []byte, limit int) (*GetResult, error) {
+func (n *nopBackend) GetRange(_ context.Context, startKey, endKey Key, limit int) (*GetResult, error) {
return &GetResult{Items: []Item{
{Key: []byte("foo"), Value: []byte("bar")},
}}, nil
@@ -168,7 +168,7 @@ func (n *nopBackend) CompareAndSwap(_ context.Context, _ Item, _ Item) (*Lease,
return &Lease{}, nil
}
-func (n *nopBackend) Delete(_ context.Context, _ []byte) error {
+func (n *nopBackend) Delete(_ context.Context, _ Key) error {
return nil
}
diff --git a/lib/backend/test/suite.go b/lib/backend/test/suite.go
index b9265eb21b6e2..950e3a025e738 100644
--- a/lib/backend/test/suite.go
+++ b/lib/backend/test/suite.go
@@ -516,7 +516,7 @@ func testKeepAlive(t *testing.T, newBackend Constructor) {
defer cancel()
// When I create a new watcher...
- watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: [][]byte{prefix("")}})
+ watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: []backend.Key{prefix("")}})
require.NoError(t, err)
defer func() { require.NoError(t, watcher.Close()) }()
@@ -578,7 +578,7 @@ func testEvents(t *testing.T, newBackend Constructor) {
defer cancel()
// Create a new watcher for the test prefix.
- watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: [][]byte{prefix("")}})
+ watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: []backend.Key{prefix("")}})
require.NoError(t, err)
defer func() { require.NoError(t, watcher.Close()) }()
@@ -706,7 +706,7 @@ func testLimit(t *testing.T, newBackend Constructor) {
// requireEvent asserts that a given event type with the given key is emitted
// by a watcher within the supplied timeout, returning that event for further
// inspection if successful.
-func requireEvent(t *testing.T, watcher backend.Watcher, eventType types.OpType, key []byte, timeout time.Duration) backend.Event {
+func requireEvent(t *testing.T, watcher backend.Watcher, eventType types.OpType, key backend.Key, timeout time.Duration) backend.Event {
t.Helper()
select {
case e := <-watcher.Events():
@@ -755,7 +755,7 @@ func testWatchersClose(t *testing.T, newBackend Constructor) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: [][]byte{prefix("")}})
+ watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: []backend.Key{prefix("")}})
require.NoError(t, err)
// cancel context -> get watcher to close
@@ -768,7 +768,7 @@ func testWatchersClose(t *testing.T, newBackend Constructor) {
}
// closing backend should close associated watcher too
- watcher, err = uut.NewWatcher(context.Background(), backend.Watch{Prefixes: [][]byte{prefix("")}})
+ watcher, err = uut.NewWatcher(context.Background(), backend.Watch{Prefixes: []backend.Key{prefix("")}})
require.NoError(t, err)
require.NoError(t, uut.Close())
@@ -1026,7 +1026,7 @@ func testMirror(t *testing.T, newBackend Constructor) {
defer cancel()
// Create a new watcher for the test prefix.
- watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: [][]byte{prefix("")}})
+ watcher, err := uut.NewWatcher(ctx, backend.Watch{Prefixes: []backend.Key{prefix("")}})
require.NoError(t, err)
defer func() { require.NoError(t, watcher.Close()) }()
@@ -1092,7 +1092,7 @@ func testMirror(t *testing.T, newBackend Constructor) {
require.NoError(t, err)
}
-func AddItem(ctx context.Context, t *testing.T, uut backend.Backend, key []byte, value string, expires time.Time) (backend.Item, backend.Lease) {
+func AddItem(ctx context.Context, t *testing.T, uut backend.Backend, key backend.Key, value string, expires time.Time) (backend.Item, backend.Lease) {
t.Helper()
item := backend.Item{
Key: key,
@@ -1123,9 +1123,9 @@ func requireWaitGroupToFinish(ctx context.Context, t *testing.T, waitGroup *sync
// MakePrefix returns function that appends unique prefix
// to any key, used to make test suite concurrent-run proof
-func MakePrefix() func(k string) []byte {
+func MakePrefix() func(k string) backend.Key {
id := "/" + uuid.New().String()
- return func(k string) []byte {
- return []byte(id + k)
+ return func(k string) backend.Key {
+ return backend.Key(id + k)
}
}
diff --git a/lib/backend/wrap.go b/lib/backend/wrap.go
index 3994229b19f9b..a4d2581911b55 100644
--- a/lib/backend/wrap.go
+++ b/lib/backend/wrap.go
@@ -62,7 +62,7 @@ func (s *Wrapper) SetReadError(err error) {
}
// GetRange returns query range
-func (s *Wrapper) GetRange(ctx context.Context, startKey []byte, endKey []byte, limit int) (*GetResult, error) {
+func (s *Wrapper) GetRange(ctx context.Context, startKey, endKey Key, limit int) (*GetResult, error) {
if err := s.GetReadError(); err != nil {
return nil, trace.Wrap(err)
}
@@ -86,7 +86,7 @@ func (s *Wrapper) Update(ctx context.Context, i Item) (*Lease, error) {
}
// Get returns a single item or not found error
-func (s *Wrapper) Get(ctx context.Context, key []byte) (*Item, error) {
+func (s *Wrapper) Get(ctx context.Context, key Key) (*Item, error) {
if err := s.GetReadError(); err != nil {
return nil, trace.Wrap(err)
}
@@ -100,12 +100,12 @@ func (s *Wrapper) CompareAndSwap(ctx context.Context, expected Item, replaceWith
}
// Delete deletes item by key
-func (s *Wrapper) Delete(ctx context.Context, key []byte) error {
+func (s *Wrapper) Delete(ctx context.Context, key Key) error {
return s.backend.Delete(ctx, key)
}
// DeleteRange deletes range of items
-func (s *Wrapper) DeleteRange(ctx context.Context, startKey []byte, endKey []byte) error {
+func (s *Wrapper) DeleteRange(ctx context.Context, startKey, endKey Key) error {
return s.backend.DeleteRange(ctx, startKey, endKey)
}
diff --git a/lib/service/service.go b/lib/service/service.go
index 6b3b56f290803..2de84fb9d67af 100644
--- a/lib/service/service.go
+++ b/lib/service/service.go
@@ -6134,7 +6134,7 @@ type kubernetesBackend interface {
// exists, updates it otherwise)
Put(ctx context.Context, i backend.Item) (*backend.Lease, error)
// Get returns a single item or not found error
- Get(ctx context.Context, key []byte) (*backend.Item, error)
+ Get(ctx context.Context, key backend.Key) (*backend.Item, error)
}
// readHostIDFromStorages tries to read the `host_uuid` value from different storages,
diff --git a/lib/service/service_test.go b/lib/service/service_test.go
index a3ba37f2a23dc..2e366f90f3051 100644
--- a/lib/service/service_test.go
+++ b/lib/service/service_test.go
@@ -1195,7 +1195,7 @@ func (f *fakeKubeBackend) Put(ctx context.Context, i backend.Item) (*backend.Lea
}
// Get returns a single item or not found error
-func (f *fakeKubeBackend) Get(ctx context.Context, key []byte) (*backend.Item, error) {
+func (f *fakeKubeBackend) Get(ctx context.Context, key backend.Key) (*backend.Item, error) {
return f.getData, f.getErr
}
diff --git a/lib/services/local/dynamic_access.go b/lib/services/local/dynamic_access.go
index 494b6a30c68b8..4b12be98608a8 100644
--- a/lib/services/local/dynamic_access.go
+++ b/lib/services/local/dynamic_access.go
@@ -485,11 +485,11 @@ func itemToAccessRequest(item backend.Item, opts ...services.MarshalOption) (*ty
return req, nil
}
-func accessRequestKey(name string) []byte {
+func accessRequestKey(name string) backend.Key {
return backend.NewKey(accessRequestsPrefix, name, paramsPrefix)
}
-func AccessRequestAllowedPromotionKey(name string) []byte {
+func AccessRequestAllowedPromotionKey(name string) backend.Key {
return backend.NewKey(accessRequestPromotionPrefix, name, paramsPrefix)
}
diff --git a/lib/services/local/events.go b/lib/services/local/events.go
index 4e93345cc5feb..7d12267df3d0d 100644
--- a/lib/services/local/events.go
+++ b/lib/services/local/events.go
@@ -57,7 +57,7 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type
validKinds := make([]types.WatchKind, 0, len(watch.Kinds))
var parsers []resourceParser
- var prefixes [][]byte
+ var prefixes []backend.Key
for _, kind := range watch.Kinds {
if kind.Name != "" && kind.Kind != types.KindNamespace {
if watch.AllowPartialSuccess {
@@ -318,26 +318,26 @@ type resourceParser interface {
// parse parses resource from the backend event
parse(event backend.Event) (types.Resource, error)
// match returns true if event key matches
- match(key []byte) bool
+ match(key backend.Key) bool
// prefixes returns prefixes to watch
- prefixes() [][]byte
+ prefixes() []backend.Key
}
// baseParser is a partial implementation of resourceParser for the most common
// resource types (stored under a static prefix).
type baseParser struct {
- matchPrefixes [][]byte
+ matchPrefixes []backend.Key
}
-func newBaseParser(prefixes ...[]byte) baseParser {
+func newBaseParser(prefixes ...backend.Key) baseParser {
return baseParser{matchPrefixes: prefixes}
}
-func (p baseParser) prefixes() [][]byte {
+func (p baseParser) prefixes() []backend.Key {
return p.matchPrefixes
}
-func (p baseParser) match(key []byte) bool {
+func (p baseParser) match(key backend.Key) bool {
for _, prefix := range p.matchPrefixes {
if bytes.HasPrefix(key, prefix) {
return true
@@ -682,7 +682,7 @@ type namespaceParser struct {
baseParser
}
-func (p *namespaceParser) match(key []byte) bool {
+func (p *namespaceParser) match(key backend.Key) bool {
// namespaces are stored under key '/namespaces//params'
// and this code matches similar pattern
return p.baseParser.match(key) &&
@@ -752,15 +752,15 @@ func newAccessRequestParser(m map[string]string) (*accessRequestParser, error) {
type accessRequestParser struct {
filter types.AccessRequestFilter
- matchPrefix []byte
- matchSuffix []byte
+ matchPrefix backend.Key
+ matchSuffix backend.Key
}
-func (p *accessRequestParser) prefixes() [][]byte {
- return [][]byte{p.matchPrefix}
+func (p *accessRequestParser) prefixes() []backend.Key {
+ return []backend.Key{p.matchPrefix}
}
-func (p *accessRequestParser) match(key []byte) bool {
+func (p *accessRequestParser) match(key backend.Key) bool {
if !bytes.HasPrefix(key, p.matchPrefix) {
return false
}
@@ -798,7 +798,7 @@ type userParser struct {
baseParser
}
-func (p *userParser) match(key []byte) bool {
+func (p *userParser) match(key backend.Key) bool {
// users are stored under key '/web/users//params'
// and this code matches similar pattern
return p.baseParser.match(key) &&
@@ -1283,14 +1283,14 @@ func newRemoteClusterParser() *remoteClusterParser {
}
type remoteClusterParser struct {
- matchPrefix []byte
+ matchPrefix backend.Key
}
-func (p *remoteClusterParser) prefixes() [][]byte {
- return [][]byte{p.matchPrefix}
+func (p *remoteClusterParser) prefixes() []backend.Key {
+ return []backend.Key{p.matchPrefix}
}
-func (p *remoteClusterParser) match(key []byte) bool {
+func (p *remoteClusterParser) match(key backend.Key) bool {
return bytes.HasPrefix(key, p.matchPrefix)
}
@@ -1346,14 +1346,14 @@ func newNetworkRestrictionsParser() *networkRestrictionsParser {
}
type networkRestrictionsParser struct {
- matchPrefix []byte
+ matchPrefix backend.Key
}
-func (p *networkRestrictionsParser) prefixes() [][]byte {
- return [][]byte{p.matchPrefix}
+func (p *networkRestrictionsParser) prefixes() []backend.Key {
+ return []backend.Key{p.matchPrefix}
}
-func (p *networkRestrictionsParser) match(key []byte) bool {
+func (p *networkRestrictionsParser) match(key backend.Key) bool {
return bytes.HasPrefix(key, p.matchPrefix)
}
@@ -2055,7 +2055,7 @@ type EventMatcher interface {
// base returns last element delimited by separator, index is
// is an index of the key part to get counting from the end
-func base(key []byte, offset int) ([]byte, error) {
+func base(key backend.Key, offset int) ([]byte, error) {
parts := bytes.Split(key, []byte{backend.Separator})
if len(parts) < offset+1 {
return nil, trace.NotFound("failed parsing %v", string(key))
@@ -2064,7 +2064,7 @@ func base(key []byte, offset int) ([]byte, error) {
}
// baseTwoKeys returns two last keys
-func baseTwoKeys(key []byte) (string, string, error) {
+func baseTwoKeys(key backend.Key) (string, string, error) {
parts := bytes.Split(key, []byte{backend.Separator})
if len(parts) < 2 {
return "", "", trace.NotFound("failed parsing %v", string(key))
diff --git a/lib/services/local/externalauditstorage.go b/lib/services/local/externalauditstorage.go
index 954c730e43d74..f42e0ec33fca8 100644
--- a/lib/services/local/externalauditstorage.go
+++ b/lib/services/local/externalauditstorage.go
@@ -241,7 +241,7 @@ func (s *ExternalAuditStorageService) DisableClusterExternalAuditStorage(ctx con
// checkAWSIntegration checks that [integrationName] names an AWS OIDC integration that currently exists, and
// returns the backend key and revision if the AWS OIDC integration.
-func (s *ExternalAuditStorageService) checkAWSIntegration(ctx context.Context, integrationName string) (key []byte, revision string, err error) {
+func (s *ExternalAuditStorageService) checkAWSIntegration(ctx context.Context, integrationName string) (key backend.Key, revision string, err error) {
integrationsSvc, err := NewIntegrationsService(s.backend)
if err != nil {
return nil, "", trace.Wrap(err)
@@ -256,7 +256,7 @@ func (s *ExternalAuditStorageService) checkAWSIntegration(ctx context.Context, i
return integrationsSvc.svc.MakeKey(integrationName), integration.GetRevision(), nil
}
-func getExternalAuditStorage(ctx context.Context, bk backend.Backend, key []byte) (*externalauditstorage.ExternalAuditStorage, error) {
+func getExternalAuditStorage(ctx context.Context, bk backend.Backend, key backend.Key) (*externalauditstorage.ExternalAuditStorage, error) {
item, err := bk.Get(ctx, key)
if err != nil {
return nil, trace.Wrap(err)
diff --git a/lib/services/local/externalauditstorage_watcher.go b/lib/services/local/externalauditstorage_watcher.go
index af44537fe6ce9..2a610d89ee5f1 100644
--- a/lib/services/local/externalauditstorage_watcher.go
+++ b/lib/services/local/externalauditstorage_watcher.go
@@ -169,7 +169,7 @@ func (w *ClusterExternalAuditWatcher) watch(ctx context.Context) error {
func (w *ClusterExternalAuditWatcher) newWatcher(ctx context.Context) (backend.Watcher, error) {
watcher, err := w.backend.NewWatcher(ctx, backend.Watch{
Name: types.KindExternalAuditStorage,
- Prefixes: [][]byte{clusterExternalAuditStorageBackendKey},
+ Prefixes: []backend.Key{clusterExternalAuditStorageBackendKey},
})
if err != nil {
return nil, trace.Wrap(err)
diff --git a/lib/services/local/generic/generic.go b/lib/services/local/generic/generic.go
index e90f9b60467ae..2cc475d1f13fb 100644
--- a/lib/services/local/generic/generic.go
+++ b/lib/services/local/generic/generic.go
@@ -372,7 +372,7 @@ func (s *Service[T]) MakeBackendItem(resource T, name string) (backend.Item, err
}
// MakeKey will make a key for the service given a name.
-func (s *Service[T]) MakeKey(name string) []byte {
+func (s *Service[T]) MakeKey(name string) backend.Key {
return backend.NewKey(s.backendPrefix, name)
}
diff --git a/lib/services/local/generic/helpers.go b/lib/services/local/generic/helpers.go
index e681f21deb795..9d647baaa0d75 100644
--- a/lib/services/local/generic/helpers.go
+++ b/lib/services/local/generic/helpers.go
@@ -58,7 +58,7 @@ type MarshalableResource interface {
// signature used elsewhere and therefore may not be the best choice for all use cases, but it
// has the benefit of being simpler to use and not requiring the caller to undergo the revision/expiry
// ceremony at each call site.
-func FastMarshal[T MarshalableResource](key []byte, r T) (backend.Item, error) {
+func FastMarshal[T MarshalableResource](key backend.Key, r T) (backend.Item, error) {
value, err := utils.FastMarshal(r)
if err != nil {
return backend.Item{}, err
diff --git a/lib/services/local/generic/nonce.go b/lib/services/local/generic/nonce.go
index 8d9a37b232775..c1e6c91e9013c 100644
--- a/lib/services/local/generic/nonce.go
+++ b/lib/services/local/generic/nonce.go
@@ -48,7 +48,7 @@ type nonceProtectedResource interface {
// FastUpdateNonceProtectedResource is a helper for updating a resource that is protected by a nonce. The target resource must store
// its nonce value in a top-level 'nonce' field in order for correct nonce semantics to be observed.
-func FastUpdateNonceProtectedResource[T nonceProtectedResource](ctx context.Context, bk backend.Backend, key []byte, resource T) error {
+func FastUpdateNonceProtectedResource[T nonceProtectedResource](ctx context.Context, bk backend.Backend, key backend.Key, resource T) error {
if resource.GetNonce() == math.MaxUint64 {
return fastUpsertNonceProtectedResource(ctx, bk, key, resource)
}
@@ -106,7 +106,7 @@ func FastUpdateNonceProtectedResource[T nonceProtectedResource](ctx context.Cont
// fastUpsertNonceProtectedResource performs an "upsert" while preserving correct nonce ordering. necessary in order to prevent upserts
// from breaking concurrent protected updates.
-func fastUpsertNonceProtectedResource[T nonceProtectedResource](ctx context.Context, bk backend.Backend, key []byte, resource T) error {
+func fastUpsertNonceProtectedResource[T nonceProtectedResource](ctx context.Context, bk backend.Backend, key backend.Key, resource T) error {
const maxRetries = 16
for i := 0; i < maxRetries; i++ {
prev, err := bk.Get(ctx, key)
diff --git a/lib/services/local/generic/nonce_test.go b/lib/services/local/generic/nonce_test.go
index 6989ca1547b15..0dc55fd830686 100644
--- a/lib/services/local/generic/nonce_test.go
+++ b/lib/services/local/generic/nonce_test.go
@@ -60,7 +60,7 @@ func newNoncedResource(name string, nonce uint64) *noncedResource {
}
}
-func fastGetResource[T types.Resource](ctx context.Context, bk backend.Backend, key []byte) (T, error) {
+func fastGetResource[T types.Resource](ctx context.Context, bk backend.Backend, key backend.Key) (T, error) {
var value T
item, err := bk.Get(ctx, key)
diff --git a/lib/services/local/headlessauthn.go b/lib/services/local/headlessauthn.go
index 4f0a2ce55e825..a7b4334dc9ac5 100644
--- a/lib/services/local/headlessauthn.go
+++ b/lib/services/local/headlessauthn.go
@@ -155,6 +155,6 @@ func unmarshalHeadlessAuthentication(data []byte) (*types.HeadlessAuthentication
const headlessAuthenticationPrefix = "headless_authentication"
-func headlessAuthenticationKey(username, name string) []byte {
+func headlessAuthenticationKey(username, name string) backend.Key {
return backend.NewKey(headlessAuthenticationPrefix, usersPrefix, username, name)
}
diff --git a/lib/services/local/headlessauthn_watcher.go b/lib/services/local/headlessauthn_watcher.go
index a4ce5c8f7adbd..80240cd8a7e94 100644
--- a/lib/services/local/headlessauthn_watcher.go
+++ b/lib/services/local/headlessauthn_watcher.go
@@ -204,7 +204,7 @@ func (h *HeadlessAuthenticationWatcher) newWatcher(ctx context.Context) (backend
watcher, err := h.identityService.NewWatcher(ctx, backend.Watch{
Name: types.KindHeadlessAuthentication,
MetricComponent: types.KindHeadlessAuthentication,
- Prefixes: [][]byte{backend.NewKey(headlessAuthenticationPrefix)},
+ Prefixes: []backend.Key{backend.NewKey(headlessAuthenticationPrefix)},
})
if err != nil {
return nil, trace.Wrap(err)
diff --git a/lib/services/local/integrations.go b/lib/services/local/integrations.go
index f1e22e8f084cd..5d8f340b9bde5 100644
--- a/lib/services/local/integrations.go
+++ b/lib/services/local/integrations.go
@@ -140,7 +140,7 @@ func (s *IntegrationsService) DeleteIntegration(ctx context.Context, name string
// notReferencedByEAS checks that integration [name] is not referenced by any EAS (External Audit Storage)
// integration. It should be called under the externalAuditStorageLock only.
func notReferencedByEAS(ctx context.Context, bk backend.Backend, name string) error {
- for _, key := range [][]byte{draftExternalAuditStorageBackendKey, clusterExternalAuditStorageBackendKey} {
+ for _, key := range []backend.Key{draftExternalAuditStorageBackendKey, clusterExternalAuditStorageBackendKey} {
eas, err := getExternalAuditStorage(ctx, bk, key)
if err != nil {
if !trace.IsNotFound(err) {
diff --git a/lib/services/local/plugin_data.go b/lib/services/local/plugin_data.go
index 44dac74849932..795bd610c7d28 100644
--- a/lib/services/local/plugin_data.go
+++ b/lib/services/local/plugin_data.go
@@ -248,7 +248,7 @@ func itemToPluginData(item backend.Item) (types.PluginData, error) {
return data, nil
}
-func pluginDataKey(kind string, name string) []byte {
+func pluginDataKey(kind string, name string) backend.Key {
return backend.NewKey(pluginDataPrefix, kind, name, paramsPrefix)
}
diff --git a/lib/services/local/presence.go b/lib/services/local/presence.go
index 3f21eb83e362d..cdbdf29afe370 100644
--- a/lib/services/local/presence.go
+++ b/lib/services/local/presence.go
@@ -77,7 +77,7 @@ func (s *PresenceService) GetNamespaces() ([]types.Namespace, error) {
}
out := make([]types.Namespace, 0, len(result.Items))
for _, item := range result.Items {
- if !bytes.HasSuffix(item.Key, []byte(paramsPrefix)) {
+ if !bytes.HasSuffix(item.Key, backend.Key(paramsPrefix)) {
continue
}
ns, err := services.UnmarshalNamespace(
@@ -227,7 +227,7 @@ func (s *PresenceService) DeleteServerInfo(ctx context.Context, name string) err
return nil
}
-func serverInfoKey(subkind, name string) []byte {
+func serverInfoKey(subkind, name string) backend.Key {
switch subkind {
case types.SubKindCloudInfo:
return backend.NewKey(serverInfoPrefix, cloudLabelsPrefix, name)
@@ -868,7 +868,7 @@ Acquire:
// initSemaphore attempts to initialize/acquire a semaphore which does not yet exist.
// Returns AlreadyExistsError if the semaphore is concurrently created.
-func (s *PresenceService) initSemaphore(ctx context.Context, key []byte, leaseID string, req types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) {
+func (s *PresenceService) initSemaphore(ctx context.Context, key backend.Key, leaseID string, req types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) {
// create a new empty semaphore resource configured to specifically match
// this acquire request.
sem, err := req.ConfigureSemaphore()
@@ -899,7 +899,7 @@ func (s *PresenceService) initSemaphore(ctx context.Context, key []byte, leaseID
// acquireSemaphore attempts to acquire an existing semaphore. Returns NotFoundError if no semaphore exists,
// and CompareFailed if the semaphore was concurrently updated.
-func (s *PresenceService) acquireSemaphore(ctx context.Context, key []byte, leaseID string, req types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) {
+func (s *PresenceService) acquireSemaphore(ctx context.Context, key backend.Key, leaseID string, req types.AcquireSemaphoreRequest) (*types.SemaphoreLease, error) {
item, err := s.Get(ctx, key)
if err != nil {
return nil, trace.Wrap(err)
@@ -1070,7 +1070,7 @@ func (s *PresenceService) GetSemaphores(ctx context.Context, filter types.Semaph
}
items = append(items, *item)
} else {
- var startKey []byte
+ var startKey backend.Key
if filter.SemaphoreKind != "" {
startKey = backend.ExactKey(semaphoresPrefix, filter.SemaphoreKind)
} else {
@@ -1374,7 +1374,7 @@ func (s *PresenceService) KeepAliveServer(ctx context.Context, h types.KeepAlive
}
// Update the prefix off the type information in the keep alive.
- var key []byte
+ var key backend.Key
switch h.GetType() {
case constants.KeepAliveNode:
key = backend.NewKey(nodesPrefix, h.Namespace, h.Name)
diff --git a/lib/services/local/session.go b/lib/services/local/session.go
index 594557370d3ad..4e76a72a94c7d 100644
--- a/lib/services/local/session.go
+++ b/lib/services/local/session.go
@@ -502,10 +502,10 @@ type webTokens struct {
log logrus.FieldLogger
}
-func webSessionKey(sessionID string) (key []byte) {
+func webSessionKey(sessionID string) backend.Key {
return backend.NewKey(webPrefix, sessionsPrefix, sessionID)
}
-func webTokenKey(token string) (key []byte) {
+func webTokenKey(token string) backend.Key {
return backend.NewKey(webPrefix, tokensPrefix, token)
}
diff --git a/lib/services/local/unstable.go b/lib/services/local/unstable.go
index 931bba92b878e..396cccc3ea0cb 100644
--- a/lib/services/local/unstable.go
+++ b/lib/services/local/unstable.go
@@ -108,7 +108,7 @@ func (s UnstableService) GetSystemRoleAssertions(ctx context.Context, serverID s
return set, nil
}
-func systemRoleAssertionsKey(serverID string, assertionID string) []byte {
+func systemRoleAssertionsKey(serverID string, assertionID string) backend.Key {
return backend.NewKey(systemRoleAssertionsPrefix, serverID, assertionID)
}
diff --git a/lib/services/local/userpreferences.go b/lib/services/local/userpreferences.go
index 249588df54c50..326134fbf63a0 100644
--- a/lib/services/local/userpreferences.go
+++ b/lib/services/local/userpreferences.go
@@ -120,7 +120,7 @@ func (u *UserPreferencesService) getUserPreferences(ctx context.Context, usernam
}
// backendKey returns the backend key for the user preferences for the given username.
-func backendKey(username string) []byte {
+func backendKey(username string) backend.Key {
return backend.NewKey(userPreferencesPrefix, username)
}
diff --git a/lib/services/local/users.go b/lib/services/local/users.go
index 0799a2cd7d527..0be4fafa11841 100644
--- a/lib/services/local/users.go
+++ b/lib/services/local/users.go
@@ -99,7 +99,7 @@ func (s *IdentityService) GetUsers(withSecrets bool) ([]types.User, error) {
}
var out []types.User
for _, item := range result.Items {
- if !bytes.HasSuffix(item.Key, []byte(paramsPrefix)) {
+ if !bytes.HasSuffix(item.Key, backend.Key(paramsPrefix)) {
continue
}
u, err := services.UnmarshalUser(
@@ -701,11 +701,11 @@ func (s *IdentityService) GetTeleportUserByWebauthnID(ctx context.Context, webID
return user.TeleportUser, nil
}
-func webauthnLocalAuthKey(user string) []byte {
+func webauthnLocalAuthKey(user string) backend.Key {
return backend.NewKey(webPrefix, usersPrefix, user, webauthnLocalAuthPrefix)
}
-func webauthnUserKey(id []byte) []byte {
+func webauthnUserKey(id []byte) backend.Key {
key := base64.RawURLEncoding.EncodeToString(id)
return backend.NewKey(webauthnPrefix, usersPrefix, key)
}
@@ -759,7 +759,7 @@ func (s *IdentityService) DeleteWebauthnSessionData(ctx context.Context, user, s
return trace.Wrap(s.Delete(ctx, sessionDataKey(user, sessionID)))
}
-func sessionDataKey(user, sessionID string) []byte {
+func sessionDataKey(user, sessionID string) backend.Key {
return backend.NewKey(webPrefix, usersPrefix, user, webauthnSessionData, sessionID)
}
@@ -870,7 +870,7 @@ func (s *IdentityService) DeleteGlobalWebauthnSessionData(ctx context.Context, s
return nil
}
-func globalSessionDataKey(scope, id string) []byte {
+func globalSessionDataKey(scope, id string) backend.Key {
return backend.NewKey(webauthnPrefix, webauthnGlobalSessionData, scope, id)
}
diff --git a/lib/services/unified_resource.go b/lib/services/unified_resource.go
index a6eddcc95aa48..fd2b0271045ac 100644
--- a/lib/services/unified_resource.go
+++ b/lib/services/unified_resource.go
@@ -202,7 +202,7 @@ func (c *UnifiedResourceCache) getSortTree(sortField string) (*btree.BTreeG[*ite
}
-func (c *UnifiedResourceCache) getRange(ctx context.Context, startKey []byte, matchFn func(types.ResourceWithLabels) (bool, error), req *proto.ListUnifiedResourcesRequest) ([]resource, string, error) {
+func (c *UnifiedResourceCache) getRange(ctx context.Context, startKey backend.Key, matchFn func(types.ResourceWithLabels) (bool, error), req *proto.ListUnifiedResourcesRequest) ([]resource, string, error) {
if len(startKey) == 0 {
return nil, "", trace.BadParameter("missing parameter startKey")
}
@@ -218,7 +218,7 @@ func (c *UnifiedResourceCache) getRange(ctx context.Context, startKey []byte, ma
return trace.Wrap(err, "getting sort tree")
}
var iterateRange func(lessOrEqual, greaterThan *item, iterator btree.ItemIteratorG[*item])
- var endKey []byte
+ var endKey backend.Key
if req.SortBy.IsDesc {
iterateRange = tree.DescendRange
endKey = backend.NewKey(prefix)
@@ -269,10 +269,10 @@ func (c *UnifiedResourceCache) getRange(ctx context.Context, startKey []byte, ma
return res, nextKey, nil
}
-func getStartKey(req *proto.ListUnifiedResourcesRequest) []byte {
+func getStartKey(req *proto.ListUnifiedResourcesRequest) backend.Key {
// if startkey exists, return it
if req.StartKey != "" {
- return []byte(req.StartKey)
+ return backend.Key(req.StartKey)
}
// if startkey doesnt exist, we check the the sort direction.
// If sort is descending, startkey is end of the list
@@ -372,8 +372,8 @@ func resourceKey(resource types.Resource) string {
}
type resourceSortKey struct {
- byName []byte
- byType []byte
+ byName backend.Key
+ byType backend.Key
}
// resourceSortKey will generate a key to be used in the sort trees
@@ -704,7 +704,7 @@ func (i *item) Less(iother btree.Item) bool {
// prefixItem is used for prefix matches on a B-Tree
type prefixItem struct {
// prefix is a prefix to match
- prefix []byte
+ prefix backend.Key
}
// Less is used for Btree operations
@@ -721,7 +721,7 @@ type resource interface {
type item struct {
// Key is a key of the key value item. This will be different based on which sorting tree
// the item is in
- Key []byte
+ Key backend.Key
// Value will be the resourceKey used in the resources map to get the resource
Value string
}
diff --git a/lib/usagereporter/teleport/aggregating/service.go b/lib/usagereporter/teleport/aggregating/service.go
index 1d744d1f01b9d..93b51716295a4 100644
--- a/lib/usagereporter/teleport/aggregating/service.go
+++ b/lib/usagereporter/teleport/aggregating/service.go
@@ -43,7 +43,7 @@ const (
// userActivityReportKey returns the backend key for a user activity report with
// a given UUID and start time, such that reports with an earlier start time
// will appear earlier in lexicographic ordering.
-func userActivityReportKey(reportUUID uuid.UUID, startTime time.Time) []byte {
+func userActivityReportKey(reportUUID uuid.UUID, startTime time.Time) backend.Key {
return backend.NewKey(userActivityReportsPrefix, startTime.Format(time.RFC3339), reportUUID.String())
}
@@ -79,7 +79,7 @@ func prepareUserActivityReports(
// resourcePresenceReportKey returns the backend key for a resource presence report with
// a given UUID and start time, such that reports with an earlier start time
// will appear earlier in lexicographic ordering.
-func resourcePresenceReportKey(reportUUID uuid.UUID, startTime time.Time) []byte {
+func resourcePresenceReportKey(reportUUID uuid.UUID, startTime time.Time) backend.Key {
return backend.NewKey(ResourcePresenceReportsPrefix, startTime.Format(time.RFC3339), reportUUID.String())
}