Skip to content

Commit 24c8972

Browse files
committed
Extend the key repo with teh configuration logic.
1 parent c4f3806 commit 24c8972

6 files changed

Lines changed: 110 additions & 23 deletions

File tree

src/go/cmd/token-vendor/app/tokenvendor.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,8 @@ func (tv *TokenVendor) ReadPublicKey(ctx context.Context, deviceID string) (stri
6363

6464
func (tv *TokenVendor) ConfigurePublicKey(ctx context.Context, deviceID string, opts repository.KeyOptions) error {
6565
slog.Debug("Configuring public key", slog.String("DeviceID", deviceID))
66-
// Extend repository with ConfigureKey method and use that instead
67-
// return tv.repo.ConfigureKey(ctx, deviceID, opts)
68-
key, err := tv.repo.LookupKey(ctx, deviceID)
69-
if key != nil {
70-
// TODO: update config from opts
71-
slog.Info("Apply new opts:", "opts", opts)
72-
return nil
73-
}
74-
return err
66+
// Shall we sanity check the opts?
67+
return tv.repo.ConfigureKey(ctx, deviceID, opts)
7568
}
7669

7770
var (

src/go/cmd/token-vendor/repository/k8s/k8s.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,35 @@ func (k *K8sRepository) PublishKey(ctx context.Context, deviceID, publicKey stri
158158
return nil
159159
}
160160

161+
func (k *K8sRepository) ConfigureKey(ctx context.Context, deviceID string, opts repository.KeyOptions) error {
162+
obj, exists, err := k.cmInformer.GetStore().GetByKey(k.ns + "/" + deviceID)
163+
if err != nil {
164+
return errors.Wrapf(err, "failed to retrieve configmap %q/%q from cache", k.ns, deviceID)
165+
}
166+
if !exists {
167+
return errors.Wrapf(repository.ErrNotFound, "failed to retrieve configmap %q/%q", k.ns, deviceID)
168+
}
169+
cm, ok := obj.(*corev1.ConfigMap)
170+
if !ok {
171+
return fmt.Errorf("unexpected object type: %T", obj)
172+
}
173+
if cm.ObjectMeta.Annotations == nil {
174+
cm.ObjectMeta.Annotations = make(map[string]string)
175+
}
176+
cm.ObjectMeta.Annotations[serviceAccountAnnotation] = opts.ServiceAccount
177+
cm.ObjectMeta.Annotations[serviceAccountDelegateAnnotation] = opts.ServiceAccountDelegate
178+
// We do not want to override any other keys besides the public key here.
179+
// createPubKeyDeviceConfig only creates a minimum configmap so updating is safe here.
180+
if _, err := k.kcl.CoreV1().ConfigMaps(k.ns).Update(ctx, cm, metav1.UpdateOptions{}); err != nil {
181+
return errors.Wrapf(err, "failed to update configmap %q/%q", k.ns, deviceID)
182+
}
183+
// Update the informer store so that LookupKey can be used immediately.
184+
if err := k.cmInformer.GetStore().Update(cm); err != nil {
185+
slog.Warn("failed to update informer store", slog.String("DeviceID", deviceID), ilog.Err(err))
186+
}
187+
return nil
188+
}
189+
161190
// createPubKeyDeviceConfig creates a configmap with only the public key in it.
162191
//
163192
// This is used also during update of existing devices. Make sure no default values

src/go/cmd/token-vendor/repository/k8s/k8s_test.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,21 @@ import (
2626

2727
// Publish a key, retrieve it again and check listing of all keys.
2828
func TestPublishListLookup(t *testing.T) {
29+
ctx := context.Background()
2930
cs := fake.NewSimpleClientset()
30-
kcl, err := NewK8sRepository(context.TODO(), cs, "default")
31+
kcl, err := NewK8sRepository(ctx, cs, "default")
3132
if err != nil {
3233
t.Fatal(err)
3334
}
3435
const id = "testdevice"
3536
const key = "testkey"
36-
if err = kcl.PublishKey(context.TODO(), id, key); err != nil {
37+
if err = kcl.PublishKey(ctx, id, key); err != nil {
3738
t.Fatal(err)
3839
}
39-
if _, err = kcl.LookupKey(context.TODO(), id); err != nil {
40+
if _, err = kcl.LookupKey(ctx, id); err != nil {
4041
t.Fatal(err)
4142
}
42-
devices, err := kcl.ListAllDeviceIDs(context.TODO())
43+
devices, err := kcl.ListAllDeviceIDs(ctx)
4344
if err != nil {
4445
t.Fatal(err)
4546
}
@@ -50,20 +51,21 @@ func TestPublishListLookup(t *testing.T) {
5051

5152
// Publish a key and override it with another one.
5253
func TestPublishKeyUpdate(t *testing.T) {
54+
ctx := context.Background()
5355
cs := fake.NewSimpleClientset()
54-
kcl, err := NewK8sRepository(context.TODO(), cs, "default")
56+
kcl, err := NewK8sRepository(ctx, cs, "default")
5557
if err != nil {
5658
t.Fatal(err)
5759
}
5860
const id = "testdevice"
5961
const key2 = "testkey2"
60-
if err = kcl.PublishKey(context.TODO(), id, "testkey"); err != nil {
62+
if err = kcl.PublishKey(ctx, id, "testkey"); err != nil {
6163
t.Fatal(err)
6264
}
63-
if err = kcl.PublishKey(context.TODO(), id, key2); err != nil {
65+
if err = kcl.PublishKey(ctx, id, key2); err != nil {
6466
t.Fatal(err)
6567
}
66-
k, err := kcl.LookupKey(context.TODO(), id)
68+
k, err := kcl.LookupKey(ctx, id)
6769
if err != nil {
6870
t.Fatal(err)
6971
}
@@ -72,18 +74,43 @@ func TestPublishKeyUpdate(t *testing.T) {
7274
}
7375
}
7476

75-
// Test if Lookup returns an empty key string in case the configmap is not found.
7677
func TestLookupDoesNotExist(t *testing.T) {
78+
ctx := context.Background()
7779
cs := fake.NewSimpleClientset()
78-
kcl, err := NewK8sRepository(context.TODO(), cs, "default")
80+
kcl, err := NewK8sRepository(ctx, cs, "default")
7981
if err != nil {
8082
t.Fatal(err)
8183
}
82-
k, err := kcl.LookupKey(context.TODO(), "testdevice")
84+
k, err := kcl.LookupKey(ctx, "testdevice")
8385
if !errors.Is(err, repository.ErrNotFound) {
8486
t.Fatalf("LookupKey produced wrong error: got %v, want %v", err, repository.ErrNotFound)
8587
}
8688
if k != nil {
8789
t.Fatalf("LookupKey(..) = %q, want nil", k)
8890
}
8991
}
92+
93+
func TestConfigure(t *testing.T) {
94+
ctx := context.Background()
95+
cs := fake.NewSimpleClientset()
96+
kcl, err := NewK8sRepository(ctx, cs, "default")
97+
if err != nil {
98+
t.Fatal(err)
99+
}
100+
const id = "testdevice"
101+
const key = "testkey"
102+
if err = kcl.PublishKey(ctx, id, key); err != nil {
103+
t.Fatal(err)
104+
}
105+
opts := repository.KeyOptions{"svc@example.com", ""}
106+
if err := kcl.ConfigureKey(ctx, id, opts); err != nil {
107+
t.Fatal(err)
108+
}
109+
k, err := kcl.LookupKey(ctx, id)
110+
if err != nil {
111+
t.Fatal(err)
112+
}
113+
if k.SAName != "svc@example.com" {
114+
t.Fatalf("LookupKey: got %q, expected %q", k.SAName, "svc@example.com")
115+
}
116+
}

src/go/cmd/token-vendor/repository/memory/memory.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ import (
2525
// Used only for integration tests.
2626
type MemoryRepository struct {
2727
keys map[string]string
28+
opts map[string]repository.KeyOptions
2829
}
2930

3031
func NewMemoryRepository(ctx context.Context) (*MemoryRepository, error) {
31-
return &MemoryRepository{keys: map[string]string{}}, nil
32+
return &MemoryRepository{
33+
keys: map[string]string{},
34+
opts: map[string]repository.KeyOptions{},
35+
}, nil
3236
}
3337

3438
func (m *MemoryRepository) PublishKey(ctx context.Context, deviceID, publicKey string) error {
@@ -44,5 +48,14 @@ func (m *MemoryRepository) LookupKey(ctx context.Context, deviceID string) (*rep
4448
if !found {
4549
return nil, repository.ErrNotFound
4650
}
47-
return &repository.Key{k, "", ""}, nil
51+
opts, found := m.opts[deviceID]
52+
if !found {
53+
opts = repository.KeyOptions{}
54+
}
55+
return &repository.Key{k, opts.ServiceAccount, opts.ServiceAccountDelegate}, nil
56+
}
57+
58+
func (m *MemoryRepository) ConfigureKey(ctx context.Context, deviceID string, opts repository.KeyOptions) error {
59+
m.opts[deviceID] = opts
60+
return nil
4861
}

src/go/cmd/token-vendor/repository/memory/memory_test.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
)
2424

2525
// Test publish and lookup key
26-
func TestMemoryBackend(t *testing.T) {
26+
func TestMemoryPublishAndLookup(t *testing.T) {
2727
m, err := NewMemoryRepository(context.TODO())
2828
if err != nil {
2929
t.Fatal(err)
@@ -63,3 +63,26 @@ func TestMemoryNotFound(t *testing.T) {
6363
t.Fatalf("LookupKey: got %q, expected empty response", k)
6464
}
6565
}
66+
67+
// Test publish and lookup key
68+
func TestMemoryConfigure(t *testing.T) {
69+
ctx := context.Background()
70+
m, err := NewMemoryRepository(ctx)
71+
if err != nil {
72+
t.Fatal(err)
73+
}
74+
if err := m.PublishKey(ctx, "a", "akey"); err != nil {
75+
t.Fatal(err)
76+
}
77+
opts := repository.KeyOptions{"svc@example.com", ""}
78+
if err := m.ConfigureKey(ctx, "a", opts); err != nil {
79+
t.Fatal(err)
80+
}
81+
k, err := m.LookupKey(ctx, "a")
82+
if err != nil {
83+
t.Fatal(err)
84+
}
85+
if k.SAName != "svc@example.com" {
86+
t.Fatalf("LookupKey: got %q, expected %q", k.SAName, "svc@example.com")
87+
}
88+
}

src/go/cmd/token-vendor/repository/repository.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ type PubKeyRepository interface {
4848
// that the device is blocked.
4949
LookupKey(ctx context.Context, deviceID string) (*Key, error)
5050
PublishKey(ctx context.Context, deviceID, publicKey string) error
51+
// ConfigureKey applies the given opts to the key store.
52+
ConfigureKey(ctx context.Context, deviceID string, opts KeyOptions) error
5153
}

0 commit comments

Comments
 (0)