diff --git a/pkg/serviceaccount/legacy.go b/pkg/serviceaccount/legacy.go index 9fbc6639c64..37210959fe6 100644 --- a/pkg/serviceaccount/legacy.go +++ b/pkg/serviceaccount/legacy.go @@ -28,6 +28,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apiserver/pkg/audit" apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/warning" applyv1 "k8s.io/client-go/applyconfigurations/core/v1" @@ -144,12 +145,26 @@ func (v *legacyValidator) Validate(ctx context.Context, tokenData string, public return nil, fmt.Errorf("ServiceAccount UID (%s) does not match claim (%s)", serviceAccount.UID, serviceAccountUID) } + // Track secret-based long-lived service account tokens and add audit annotations and metrics. + autoGenerated := false + + // Check if it is an auto-generated secret-based token for _, ref := range serviceAccount.Secrets { if ref.Name == secret.Name { + autoGenerated = true warning.AddWarning(ctx, "", "Use tokens from the TokenRequest API or manually created secret-based tokens instead of auto-generated secret-based tokens.") + audit.AddAuditAnnotation(ctx, "authentication.k8s.io/legacy-token-autogenerated-secret", secret.Name) + autoGeneratedTokensTotal.WithContext(ctx).Inc() break } } + + // Check if it's a manually created secret-based token + if !autoGenerated { + audit.AddAuditAnnotation(ctx, "authentication.k8s.io/legacy-token-manual-secret", secret.Name) + manuallyCreatedTokensTotal.WithContext(ctx).Inc() + } + now := time.Now().UTC() today := now.Format("2006-01-02") tomorrow := now.AddDate(0, 0, 1).Format("2006-01-02") diff --git a/pkg/serviceaccount/metrics.go b/pkg/serviceaccount/metrics.go index 2c614a9f930..4b317b8fd55 100644 --- a/pkg/serviceaccount/metrics.go +++ b/pkg/serviceaccount/metrics.go @@ -47,6 +47,26 @@ var ( }, ) + // mauallyCreatedTokensTotal is the number of manually created secret-based long lived tokens. + manuallyCreatedTokensTotal = metrics.NewCounter( + &metrics.CounterOpts{ + Subsystem: kubeServiceAccountSubsystem, + Name: "legacy_manual_token_uses_total", + Help: "Cumulative manually created legacy tokens used", + StabilityLevel: metrics.ALPHA, + }, + ) + + // autoGeneratedTokensTotal is the number of automatically generated secret-based long lived tokens. + autoGeneratedTokensTotal = metrics.NewCounter( + &metrics.CounterOpts{ + Subsystem: kubeServiceAccountSubsystem, + Name: "legacy_auto_token_uses_total", + Help: "Cumulative auto-generated legacy tokens used", + StabilityLevel: metrics.ALPHA, + }, + ) + // ValidTokensTotal is the number of valid projected tokens used. validTokensTotal = metrics.NewCounter( &metrics.CounterOpts{ @@ -64,6 +84,8 @@ func RegisterMetrics() { registerMetricsOnce.Do(func() { legacyregistry.MustRegister(legacyTokensTotal) legacyregistry.MustRegister(staleTokensTotal) + legacyregistry.MustRegister(manuallyCreatedTokensTotal) + legacyregistry.MustRegister(autoGeneratedTokensTotal) legacyregistry.MustRegister(validTokensTotal) }) }