From 6eb7fc925882c577f931b5ff702ea08f104f445f Mon Sep 17 00:00:00 2001 From: yuvalavra Date: Thu, 1 Sep 2022 17:24:28 +0300 Subject: [PATCH] identify legacyTokenSecrets when collection is scoped to a namespace --- cmd/root.go | 1 + pkg/collect/discover_protections.go | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 9ef9c6c..ed1281d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -35,6 +35,7 @@ func Execute() { func init() { rootCmd.PersistentFlags().StringVarP(&outFile, "out-file", "o", "", "save results to file") rootCmd.PersistentFlags().BoolVarP(&loudMode, "loud", "l", false, "loud mode, print results regardless of -o") + // Collect config rootCmd.PersistentFlags().BoolVarP(&collectConfig.AllServiceAccounts, "all-serviceaccounts", "a", false, "collect data on all serviceAccounts, not only those assigned to a pod") rootCmd.PersistentFlags().BoolVarP(&collectConfig.DiscoverProtections, "discover-protections", "w", false, "discover features gates and admission controllers that protect against certain attacks, partly by emulating the attacks via impersonation & dry-run write operations") rootCmd.PersistentFlags().BoolVar(&collectConfig.IgnoreControlPlane, "ignore-controlplane", false, "don't collect data on control plane nodes and pods. Identified by either the 'node-role.kubernetes.io/control-plane' or 'node-role.kubernetes.io/master' labels. ServiceAccounts will not be linked to control plane components") diff --git a/pkg/collect/discover_protections.go b/pkg/collect/discover_protections.go index d5cb909..ca2f62d 100644 --- a/pkg/collect/discover_protections.go +++ b/pkg/collect/discover_protections.go @@ -16,7 +16,7 @@ import ( // and populate the cluster's metadata with them for policies to consume. // NOTE: Uses impersonation and dry-run write operations, which won't affect the cluster, but may be logged / audited on. func discoverRelevantControlPlaneFeatures(collectConfig CollectConfig, kubeConfig clientcmd.ClientConfig, clusterDb *ClusterDb, metadata *ClusterMetadata) { - if legacyTokenSecretsReducted(clusterDb) { + if legacyTokenSecretsReducted(clusterDb, collectConfig.Namespace) { metadata.Features = append(metadata.Features, "LegacyTokenSecretsReducted") } // If NodeAuthorization is used, check for NodeRestriction @@ -38,13 +38,21 @@ func discoverRelevantControlPlaneFeatures(collectConfig CollectConfig, kubeConfi } // Best effort test for whether serviceAccount tokens are stored as secrets -func legacyTokenSecretsReducted(clusterDb *ClusterDb) bool { +func legacyTokenSecretsReducted(clusterDb *ClusterDb, ns string) bool { + // If collection is scoped to ns, use it's default serviceAccount for testing, + // Otherwise use kube-system:replicaset-controller + saName := "default" + if ns == "" { + ns = "kube-system" + saName = "replicaset-controller" + } + for _, serviceAccount := range clusterDb.ServiceAccounts { - if serviceAccount.ObjectMeta.Namespace != "kube-system" { + if serviceAccount.ObjectMeta.Namespace != ns { continue } - // Arbitrarily chose the replicaset-controller for testing - if serviceAccount.ObjectMeta.Name != "replicaset-controller" { + + if serviceAccount.ObjectMeta.Name != saName { continue } // Return true if there are no auto-generated secrets for the serviceAccount