diff --git a/pkg/agent/api/debug/v1/service.go b/pkg/agent/api/debug/v1/service.go index 16ae4feb4a..8ba5d376f2 100644 --- a/pkg/agent/api/debug/v1/service.go +++ b/pkg/agent/api/debug/v1/service.go @@ -95,10 +95,13 @@ func (s *Service) GetInfo(context.Context, *debugv1.GetInfoRequest) (*debugv1.Ge // Reset clock and set current response s.getInfoResp.ts = s.clock.Now() s.getInfoResp.resp = &debugv1.GetInfoResponse{ - SvidChain: svidChain, - Uptime: int32(s.uptime().Seconds()), - SvidsCount: int32(s.m.CountSVIDs()), - LastSyncSuccess: s.m.GetLastSync().UTC().Unix(), + SvidChain: svidChain, + Uptime: int32(s.uptime().Seconds()), + SvidsCount: int32(s.m.CountX509SVIDs()), + CachedX509SvidsCount: int32(s.m.CountX509SVIDs()), + CachedJwtSvidsCount: int32(s.m.CountJWTSVIDs()), + CachedSvidstoreX509SvidsCount: int32(s.m.CountSVIDStoreX509SVIDs()), + LastSyncSuccess: s.m.GetLastSync().UTC().Unix(), } } diff --git a/pkg/agent/api/debug/v1/service_test.go b/pkg/agent/api/debug/v1/service_test.go index 245801159b..afeeced626 100644 --- a/pkg/agent/api/debug/v1/service_test.go +++ b/pkg/agent/api/debug/v1/service_test.go @@ -99,45 +99,62 @@ func TestGetInfo(t *testing.T) { expectResp *debugv1.GetInfoResponse expectedLogs []spiretest.LogEntry // Time to add to clock.Mock - addToClk time.Duration - initCache bool - lastSync time.Time - svidCount int - svidState svid.State + addToClk time.Duration + initCache bool + lastSync time.Time + svidCount int + x509SvidCount int + jwtSvidCount int + svidstoreX509SvidCount int + svidState svid.State }{ { - name: "svid without intermediate", - lastSync: lastSync, - svidState: x509SVIDState, - svidCount: 123, + name: "svid without intermediate", + lastSync: lastSync, + svidState: x509SVIDState, + svidCount: 123, + x509SvidCount: 123, + jwtSvidCount: 123, + svidstoreX509SvidCount: 123, expectResp: &debugv1.GetInfoResponse{ - LastSyncSuccess: lastSync.UTC().Unix(), - SvidsCount: 123, - SvidChain: x509SVIDChain, + LastSyncSuccess: lastSync.UTC().Unix(), + SvidChain: x509SVIDChain, + SvidsCount: 123, + CachedX509SvidsCount: 123, + CachedJwtSvidsCount: 123, + CachedSvidstoreX509SvidsCount: 123, }, }, { - name: "svid with intermediate", - lastSync: lastSync, - svidState: stateWithIntermediate, - svidCount: 456, + name: "svid with intermediate", + lastSync: lastSync, + svidState: stateWithIntermediate, + svidCount: 456, + x509SvidCount: 456, + jwtSvidCount: 456, + svidstoreX509SvidCount: 456, expectResp: &debugv1.GetInfoResponse{ - LastSyncSuccess: lastSync.UTC().Unix(), - SvidsCount: 456, - SvidChain: svidWithIntermediateChain, + LastSyncSuccess: lastSync.UTC().Unix(), + SvidChain: svidWithIntermediateChain, + SvidsCount: 456, + CachedX509SvidsCount: 456, + CachedJwtSvidsCount: 456, + CachedSvidstoreX509SvidsCount: 456, }, }, { name: "get response from cache", expectResp: &debugv1.GetInfoResponse{ - LastSyncSuccess: cachedLastSync.Unix(), - SvidsCount: 99999, - SvidChain: x509SVIDChain, + LastSyncSuccess: cachedLastSync.Unix(), + SvidsCount: 99999, + CachedX509SvidsCount: 99999, + SvidChain: x509SVIDChain, }, - initCache: true, - lastSync: lastSync, - svidState: stateWithIntermediate, - svidCount: 456, + initCache: true, + lastSync: lastSync, + svidState: stateWithIntermediate, + svidCount: 253, + x509SvidCount: 253, }, { name: "expires cache", @@ -182,6 +199,7 @@ func TestGetInfo(t *testing.T) { // Set a success state before running actual test case and expire time if tt.initCache { test.m.svidCount = 99999 + test.m.x509SvidCount = 99999 test.m.svidState = x509SVIDState test.m.lastSync = cachedLastSync @@ -192,6 +210,9 @@ func TestGetInfo(t *testing.T) { test.clk.Add(tt.addToClk) test.m.svidCount = tt.svidCount + test.m.x509SvidCount = tt.x509SvidCount + test.m.jwtSvidCount = tt.jwtSvidCount + test.m.svidstoreX509SvidCount = tt.svidstoreX509SvidCount test.m.svidState = tt.svidState test.m.lastSync = tt.lastSync @@ -264,10 +285,13 @@ func setupServiceTest(t *testing.T) *serviceTest { type fakeManager struct { manager.Manager - bundle *cache.Bundle - svidState svid.State - svidCount int - lastSync time.Time + bundle *cache.Bundle + svidState svid.State + svidCount int + x509SvidCount int + jwtSvidCount int + svidstoreX509SvidCount int + lastSync time.Time } func (m *fakeManager) GetCurrentCredentials() svid.State { @@ -278,6 +302,18 @@ func (m *fakeManager) CountSVIDs() int { return m.svidCount } +func (m *fakeManager) CountX509SVIDs() int { + return m.x509SvidCount +} + +func (m *fakeManager) CountJWTSVIDs() int { + return m.jwtSvidCount +} + +func (m *fakeManager) CountSVIDStoreX509SVIDs() int { + return m.svidstoreX509SvidCount +} + func (m *fakeManager) GetLastSync() time.Time { return m.lastSync } diff --git a/pkg/agent/manager/cache/cache.go b/pkg/agent/manager/cache/cache.go index 8aad51f5f0..7ad5293090 100644 --- a/pkg/agent/manager/cache/cache.go +++ b/pkg/agent/manager/cache/cache.go @@ -166,7 +166,7 @@ func (c *Cache) Identities() []Identity { return out } -func (c *Cache) CountSVIDs() int { +func (c *Cache) CountX509SVIDs() int { c.mu.RLock() defer c.mu.RUnlock() @@ -183,6 +183,10 @@ func (c *Cache) CountSVIDs() int { return records } +func (c *Cache) CountJWTSVIDs() int { + return c.JWTSVIDCache.CountJWTSVIDs() +} + func (c *Cache) MatchingIdentities(selectors []*common.Selector) []Identity { set, setDone := allocSelectorSet(selectors...) defer setDone() diff --git a/pkg/agent/manager/cache/cache_test.go b/pkg/agent/manager/cache/cache_test.go index 151a301f58..9dd0d03e60 100644 --- a/pkg/agent/manager/cache/cache_test.go +++ b/pkg/agent/manager/cache/cache_test.go @@ -99,7 +99,7 @@ func TestCountSVIDs(t *testing.T) { cache.UpdateEntries(updateEntries, nil) // No SVIDs expected - require.Equal(t, 0, cache.CountSVIDs()) + require.Equal(t, 0, cache.CountX509SVIDs()) updateSVIDs := &UpdateSVIDs{ X509SVIDs: makeX509SVIDs(foo), @@ -107,7 +107,7 @@ func TestCountSVIDs(t *testing.T) { cache.UpdateSVIDs(updateSVIDs) // Only one SVID expected - require.Equal(t, 1, cache.CountSVIDs()) + require.Equal(t, 1, cache.CountX509SVIDs()) } func TestBundleChanges(t *testing.T) { diff --git a/pkg/agent/manager/cache/jwt_cache.go b/pkg/agent/manager/cache/jwt_cache.go index e0d1378572..7058fd443b 100644 --- a/pkg/agent/manager/cache/jwt_cache.go +++ b/pkg/agent/manager/cache/jwt_cache.go @@ -16,6 +16,10 @@ type JWTSVIDCache struct { svids map[string]*client.JWTSVID } +func (c *JWTSVIDCache) CountJWTSVIDs() int { + return len(c.svids) +} + func NewJWTSVIDCache() *JWTSVIDCache { return &JWTSVIDCache{ svids: make(map[string]*client.JWTSVID), diff --git a/pkg/agent/manager/cache/lru_cache.go b/pkg/agent/manager/cache/lru_cache.go index fedbb20ad5..8d01fd07bd 100644 --- a/pkg/agent/manager/cache/lru_cache.go +++ b/pkg/agent/manager/cache/lru_cache.go @@ -171,13 +171,20 @@ func (c *LRUCache) Entries() []*common.RegistrationEntry { return out } -func (c *LRUCache) CountSVIDs() int { +func (c *LRUCache) CountX509SVIDs() int { c.mu.RLock() defer c.mu.RUnlock() return len(c.svids) } +func (c *LRUCache) CountJWTSVIDs() int { + c.mu.RLock() + defer c.mu.RUnlock() + + return len(c.JWTSVIDCache.svids) +} + func (c *LRUCache) CountRecords() int { c.mu.RLock() defer c.mu.RUnlock() @@ -446,7 +453,7 @@ func (c *LRUCache) UpdateEntries(update *UpdateEntries, checkSVID func(*common.R func (c *LRUCache) UpdateSVIDs(update *UpdateSVIDs) { c.mu.Lock() - defer func() { agentmetrics.SetSVIDMapSize(c.metrics, c.CountSVIDs()) }() + defer func() { agentmetrics.SetSVIDMapSize(c.metrics, c.CountX509SVIDs()) }() defer c.mu.Unlock() // Allocate a set of selectors that diff --git a/pkg/agent/manager/cache/lru_cache_test.go b/pkg/agent/manager/cache/lru_cache_test.go index 2abc00d334..4691826842 100644 --- a/pkg/agent/manager/cache/lru_cache_test.go +++ b/pkg/agent/manager/cache/lru_cache_test.go @@ -92,7 +92,7 @@ func TestLRUCacheCountSVIDs(t *testing.T) { cache.UpdateEntries(updateEntries, nil) // No SVIDs expected - require.Equal(t, 0, cache.CountSVIDs()) + require.Equal(t, 0, cache.CountX509SVIDs()) updateSVIDs := &UpdateSVIDs{ X509SVIDs: makeX509SVIDs(foo), @@ -100,7 +100,7 @@ func TestLRUCacheCountSVIDs(t *testing.T) { cache.UpdateSVIDs(updateSVIDs) // Only one SVID expected - require.Equal(t, 1, cache.CountSVIDs()) + require.Equal(t, 1, cache.CountX509SVIDs()) } func TestLRUCacheCountRecords(t *testing.T) { @@ -705,10 +705,10 @@ func TestLRUCacheSVIDCacheExpiry(t *testing.T) { sub.Finish() } } - assert.Equal(t, 12, cache.CountSVIDs()) + assert.Equal(t, 12, cache.CountX509SVIDs()) cache.UpdateEntries(updateEntries, nil) - assert.Equal(t, 10, cache.CountSVIDs()) + assert.Equal(t, 10, cache.CountX509SVIDs()) // foo SVID should be removed from cache as it does not have active subscriber assert.False(t, cache.notifySubscriberIfSVIDAvailable(makeSelectors("A"), subA.(*lruCacheSubscriber))) @@ -724,7 +724,7 @@ func TestLRUCacheSVIDCacheExpiry(t *testing.T) { require.Len(t, cache.GetStaleEntries(), 1) assert.Equal(t, foo, cache.GetStaleEntries()[0].Entry) - assert.Equal(t, 10, cache.CountSVIDs()) + assert.Equal(t, 10, cache.CountX509SVIDs()) } func TestLRUCacheMaxSVIDCacheSize(t *testing.T) { @@ -741,7 +741,7 @@ func TestLRUCacheMaxSVIDCacheSize(t *testing.T) { X509SVIDs: makeX509SVIDsFromStaleEntries(cache.GetStaleEntries()), }) require.Len(t, cache.GetStaleEntries(), 0) - assert.Equal(t, 10, cache.CountSVIDs()) + assert.Equal(t, 10, cache.CountX509SVIDs()) // Validate that active subscriber will still get SVID even if SVID count is at maxSvidCacheSize foo := makeRegistrationEntry("FOO", "A") @@ -752,12 +752,12 @@ func TestLRUCacheMaxSVIDCacheSize(t *testing.T) { cache.UpdateEntries(updateEntries, nil) require.Len(t, cache.GetStaleEntries(), 1) - assert.Equal(t, 10, cache.CountSVIDs()) + assert.Equal(t, 10, cache.CountX509SVIDs()) cache.UpdateSVIDs(&UpdateSVIDs{ X509SVIDs: makeX509SVIDs(foo), }) - assert.Equal(t, 11, cache.CountSVIDs()) + assert.Equal(t, 11, cache.CountX509SVIDs()) require.Len(t, cache.GetStaleEntries(), 0) } @@ -770,7 +770,7 @@ func TestSyncSVIDsWithSubscribers(t *testing.T) { cache.UpdateSVIDs(&UpdateSVIDs{ X509SVIDs: makeX509SVIDsFromStaleEntries(cache.GetStaleEntries()), }) - assert.Equal(t, 5, cache.CountSVIDs()) + assert.Equal(t, 5, cache.CountX509SVIDs()) // Update foo but its SVID is not yet cached foo := makeRegistrationEntry("FOO", "A") @@ -788,7 +788,7 @@ func TestSyncSVIDsWithSubscribers(t *testing.T) { require.Len(t, cache.GetStaleEntries(), 1) assert.Equal(t, []*StaleEntry{{Entry: cache.records[foo.EntryId].entry}}, cache.GetStaleEntries()) - assert.Equal(t, 5, cache.CountSVIDs()) + assert.Equal(t, 5, cache.CountX509SVIDs()) } func TestNotifySubscriberWhenSVIDIsAvailable(t *testing.T) { @@ -863,7 +863,7 @@ func TestSubscribeToWorkloadUpdatesLRUNoSelectors(t *testing.T) { cache.UpdateSVIDs(&UpdateSVIDs{ X509SVIDs: makeX509SVIDs(foo, bar), }) - assert.Equal(t, 2, cache.CountSVIDs()) + assert.Equal(t, 2, cache.CountX509SVIDs()) select { case err := <-subErrCh: @@ -932,7 +932,7 @@ func TestSubscribeToLRUCacheChanges(t *testing.T) { cache.UpdateSVIDs(&UpdateSVIDs{ X509SVIDs: makeX509SVIDs(foo, bar), }) - assert.Equal(t, 2, cache.CountSVIDs()) + assert.Equal(t, 2, cache.CountX509SVIDs()) clk.WaitForAfter(time.Second, "waiting for after to get called") clk.Add(SVIDSyncInterval * 4) diff --git a/pkg/agent/manager/manager.go b/pkg/agent/manager/manager.go index 40ce50f6b6..b0dec8290c 100644 --- a/pkg/agent/manager/manager.go +++ b/pkg/agent/manager/manager.go @@ -77,8 +77,14 @@ type Manager interface { // is no JWT cached, the manager will get one signed upstream. FetchJWTSVID(ctx context.Context, entry *common.RegistrationEntry, audience []string) (*client.JWTSVID, error) - // CountSVIDs returns the amount of X509 SVIDs on memory - CountSVIDs() int + // CountX509SVIDs returns the amount of X509 SVIDs on memory + CountX509SVIDs() int + + // CountJWTSVIDs returns the amount of JWT SVIDs on memory + CountJWTSVIDs() int + + // CountSVIDStoreX509SVIDs returns the amount of x509 SVIDs on SVIDStore in-memory cache + CountSVIDStoreX509SVIDs() int // GetLastSync returns the last successful rotation timestamp GetLastSync() time.Time @@ -107,8 +113,11 @@ type Cache interface { // MatchingRegistrationEntries with given selectors MatchingRegistrationEntries(selectors []*common.Selector) []*common.RegistrationEntry - // CountSVIDs in cache stored - CountSVIDs() int + // CountX509SVIDs in cache stored + CountX509SVIDs() int + + // CountJWTSVIDs in cache stored + CountJWTSVIDs() int // FetchWorkloadUpdate for given selectors FetchWorkloadUpdate(selectors []*common.Selector) *cache.WorkloadUpdate @@ -251,8 +260,16 @@ func (m *manager) MatchingRegistrationEntries(selectors []*common.Selector) []*c return m.cache.MatchingRegistrationEntries(selectors) } -func (m *manager) CountSVIDs() int { - return m.cache.CountSVIDs() +func (m *manager) CountX509SVIDs() int { + return m.cache.CountX509SVIDs() +} + +func (m *manager) CountJWTSVIDs() int { + return m.cache.CountJWTSVIDs() +} + +func (m *manager) CountSVIDStoreX509SVIDs() int { + return m.svidStoreCache.CountX509SVIDs() } // FetchWorkloadUpdates gets the latest workload update for the selectors @@ -317,7 +334,7 @@ func (m *manager) runSynchronizer(ctx context.Context) error { // Clamp the sync interval to the default value when the agent doesn't have any SVIDs cached // AND the previous sync request succeeded - if m.cache.CountSVIDs() == 0 { + if m.cache.CountX509SVIDs() == 0 { syncInterval = min(syncInterval, defaultSyncInterval) } } diff --git a/pkg/agent/manager/manager_test.go b/pkg/agent/manager/manager_test.go index 6521f6f9b3..ed67df7b5a 100644 --- a/pkg/agent/manager/manager_test.go +++ b/pkg/agent/manager/manager_test.go @@ -243,7 +243,7 @@ func TestHappyPathWithoutSyncNorRotation(t *testing.T) { require.Equal(t, api.bundle, m.GetBundle()) // Expect three SVIDs on cache - require.Equal(t, 3, m.CountSVIDs()) + require.Equal(t, 3, m.CountX509SVIDs()) // Expect last sync require.Equal(t, clk.Now(), m.GetLastSync()) @@ -335,7 +335,7 @@ func TestRotationWithRSAKey(t *testing.T) { require.Equal(t, api.bundle, m.GetBundle()) // Expect three SVIDs on cache - require.Equal(t, 3, m.CountSVIDs()) + require.Equal(t, 3, m.CountX509SVIDs()) // Expect last sync require.Equal(t, clk.Now(), m.GetLastSync()) @@ -1229,7 +1229,7 @@ func TestSyncSVIDsWithLRUCache(t *testing.T) { assert.NoError(t, subErr, "subscriber error") // ensure 2 SVIDs corresponding to selectors are cached. - assert.Equal(t, 2, m.cache.CountSVIDs()) + assert.Equal(t, 2, m.cache.CountX509SVIDs()) // cancel the ctx to stop go routines cancel() diff --git a/pkg/agent/manager/storecache/cache.go b/pkg/agent/manager/storecache/cache.go index a938051250..f12225bd00 100644 --- a/pkg/agent/manager/storecache/cache.go +++ b/pkg/agent/manager/storecache/cache.go @@ -250,6 +250,12 @@ func (c *Cache) GetStaleEntries() []*cache.StaleEntry { return staleEntries } +func (c *Cache) CountX509SVIDs() int { + c.mtx.RLock() + defer c.mtx.RUnlock() + return len(c.records) +} + // ReadyToStore returns all records that are ready to be stored func (c *Cache) ReadyToStore() []*Record { c.mtx.Lock()