Skip to content

Commit bddf652

Browse files
committed
[RFC-0010] Add multi-tenancy lockdown for decryption and kubeconfig
Adds two new controller flags to enforce ServiceAccount usage in multi-tenant clusters where administrators need to lock down workload identity access: - --default-decryption-service-account - --default-kubeconfig-service-account These flags complement the existing --default-service-account flag to provide complete multi-tenancy lockdown coverage for all three classes of ServiceAccount fields in the Kustomization API. Signed-off-by: cappyzawa <[email protected]>
1 parent aaad1e0 commit bddf652

File tree

5 files changed

+52
-35
lines changed

5 files changed

+52
-35
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ require (
2424
github.com/fluxcd/pkg/apis/event v0.18.0
2525
github.com/fluxcd/pkg/apis/kustomize v1.11.0
2626
github.com/fluxcd/pkg/apis/meta v1.18.0
27-
github.com/fluxcd/pkg/auth v0.23.0
27+
github.com/fluxcd/pkg/auth v0.26.0
2828
github.com/fluxcd/pkg/cache v0.10.0
2929
github.com/fluxcd/pkg/http/fetch v0.17.0
3030
github.com/fluxcd/pkg/kustomize v1.19.0
31-
github.com/fluxcd/pkg/runtime v0.72.0
31+
github.com/fluxcd/pkg/runtime v0.80.0
3232
github.com/fluxcd/pkg/ssa v0.51.0
3333
github.com/fluxcd/pkg/tar v0.13.0
3434
github.com/fluxcd/pkg/testserver v0.11.0

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ github.com/fluxcd/pkg/apis/kustomize v1.11.0 h1:0IzDgxZkc4v+5SDNCvgZhfwfkdkQLPXC
199199
github.com/fluxcd/pkg/apis/kustomize v1.11.0/go.mod h1:j302mJGDww8cn9qvMsRQ0LJ1HPAPs/IlX7CSsoJV7BI=
200200
github.com/fluxcd/pkg/apis/meta v1.18.0 h1:ACHrMIjlcioE9GKS7NGk62KX4NshqNewr8sBwMcXABs=
201201
github.com/fluxcd/pkg/apis/meta v1.18.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
202-
github.com/fluxcd/pkg/auth v0.23.0 h1:Xt89QO1Hzh7X0JFwCeONyxMlgOX/zOPx0eyIyFoKyF0=
203-
github.com/fluxcd/pkg/auth v0.23.0/go.mod h1:YEAHpBFuW5oLlH9ekuJaQdnJ2Q3A7Ny8kha3WY7QMnY=
202+
github.com/fluxcd/pkg/auth v0.26.0 h1:jw128zPI4aRSvkGbFfAQcFNF3oK58P4rDdKIpj2/7yM=
203+
github.com/fluxcd/pkg/auth v0.26.0/go.mod h1:YEAHpBFuW5oLlH9ekuJaQdnJ2Q3A7Ny8kha3WY7QMnY=
204204
github.com/fluxcd/pkg/cache v0.10.0 h1:M+OGDM4da1cnz7q+sZSBtkBJHpiJsLnKVmR9OdMWxEY=
205205
github.com/fluxcd/pkg/cache v0.10.0/go.mod h1:pPXRzQUDQagsCniuOolqVhnAkbNgYOg8d2cTliPs7ME=
206206
github.com/fluxcd/pkg/envsubst v1.4.0 h1:pYsb6wrmXOSfHXuXQHaaBBMt3LumhgCb8SMdBNAwV/U=
@@ -209,8 +209,8 @@ github.com/fluxcd/pkg/http/fetch v0.17.0 h1:U/Fuh+H1cRL2d/EOfdsjJPaPDPtL3pFanPSE
209209
github.com/fluxcd/pkg/http/fetch v0.17.0/go.mod h1:nMozZtiSKtPGwMrR5wGjIJoQmhvFqZ5P4UsM/Lqza2I=
210210
github.com/fluxcd/pkg/kustomize v1.19.0 h1:2eO8lMx0/H/Yyq35LMTAMhxEElOzMW0Yi9zUNZoimlU=
211211
github.com/fluxcd/pkg/kustomize v1.19.0/go.mod h1:OCCW9vU3lStDh3jyg9MM/a29MSdNAVk2wjl0lDos5Fs=
212-
github.com/fluxcd/pkg/runtime v0.72.0 h1:9JCto84iL2FziuTuuvDwvS+cfIzGhHOk25y8ulXpNOs=
213-
github.com/fluxcd/pkg/runtime v0.72.0/go.mod h1:iGhdaEq+lMJQTJNAFEPOU4gUJ7kt3yeDcJPZy7O9IUw=
212+
github.com/fluxcd/pkg/runtime v0.80.0 h1:vknT2vdQSGTFnAhz4xGk2ZXUWCrXh3whsISStgA57Go=
213+
github.com/fluxcd/pkg/runtime v0.80.0/go.mod h1:iGhdaEq+lMJQTJNAFEPOU4gUJ7kt3yeDcJPZy7O9IUw=
214214
github.com/fluxcd/pkg/sourceignore v0.13.0 h1:ZvkzX2WsmyZK9cjlqOFFW1onHVzhPZIqDbCh96rPqbU=
215215
github.com/fluxcd/pkg/sourceignore v0.13.0/go.mod h1:Z9H1GoBx0ljOhptnzoV0PL6Nd/UzwKcSphP27lqb4xI=
216216
github.com/fluxcd/pkg/ssa v0.51.0 h1:sFarxKZcS0J8sjq9qvs/r+1XiJqNgRodEiPjV75F8R4=

internal/controller/kustomization_configuration_error_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ data: {}
178178
t.Run("object level workload identity feature gate enabled", func(t *testing.T) {
179179
g := NewWithT(t)
180180

181-
t.Setenv(auth.EnvVarEnableObjectLevelWorkloadIdentity, "true")
181+
auth.EnableObjectLevelWorkloadIdentity()
182+
t.Cleanup(auth.DisableObjectLevelWorkloadIdentity)
182183

183184
kustomizationKey := types.NamespacedName{
184185
Name: fmt.Sprintf("invalid-config-%s", randStringRunes(5)),

internal/decryptor/decryptor.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,15 @@ func (d *Decryptor) SetAuthOptions(ctx context.Context) {
318318
case DecryptionProviderSOPS:
319319
var opts []auth.Option
320320

321-
if d.kustomization.Spec.Decryption.ServiceAccountName != "" {
322-
serviceAccount := types.NamespacedName{
323-
Name: d.kustomization.Spec.Decryption.ServiceAccountName,
324-
Namespace: d.kustomization.GetNamespace(),
325-
}
326-
opts = append(opts, auth.WithServiceAccount(serviceAccount, d.client))
321+
opts = append(opts, auth.WithClient(d.client))
322+
323+
saName := d.kustomization.Spec.Decryption.ServiceAccountName
324+
if saName == "" {
325+
saName = auth.GetDefaultDecryptionServiceAccount()
326+
}
327+
if saName != "" {
328+
opts = append(opts, auth.WithServiceAccountName(saName))
329+
opts = append(opts, auth.WithServiceAccountNamespace(d.kustomization.GetNamespace()))
327330
}
328331

329332
involvedObject := cache.InvolvedObject{

main.go

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -80,27 +80,29 @@ func main() {
8080
)
8181

8282
var (
83-
metricsAddr string
84-
eventsAddr string
85-
healthAddr string
86-
concurrent int
87-
concurrentSSA int
88-
requeueDependency time.Duration
89-
clientOptions runtimeClient.Options
90-
kubeConfigOpts runtimeClient.KubeConfigOptions
91-
logOptions logger.Options
92-
leaderElectionOptions leaderelection.Options
93-
rateLimiterOptions runtimeCtrl.RateLimiterOptions
94-
watchOptions runtimeCtrl.WatchOptions
95-
intervalJitterOptions jitter.IntervalOptions
96-
aclOptions acl.Options
97-
noRemoteBases bool
98-
httpRetry int
99-
defaultServiceAccount string
100-
sopsAgeSecret string
101-
featureGates feathelper.FeatureGates
102-
disallowedFieldManagers []string
103-
tokenCacheOptions pkgcache.TokenFlags
83+
metricsAddr string
84+
eventsAddr string
85+
healthAddr string
86+
concurrent int
87+
concurrentSSA int
88+
requeueDependency time.Duration
89+
clientOptions runtimeClient.Options
90+
kubeConfigOpts runtimeClient.KubeConfigOptions
91+
logOptions logger.Options
92+
leaderElectionOptions leaderelection.Options
93+
rateLimiterOptions runtimeCtrl.RateLimiterOptions
94+
watchOptions runtimeCtrl.WatchOptions
95+
intervalJitterOptions jitter.IntervalOptions
96+
aclOptions acl.Options
97+
noRemoteBases bool
98+
httpRetry int
99+
defaultServiceAccount string
100+
defaultDecryptionServiceAccount string
101+
defaultKubeConfigServiceAccount string
102+
sopsAgeSecret string
103+
featureGates feathelper.FeatureGates
104+
disallowedFieldManagers []string
105+
tokenCacheOptions pkgcache.TokenFlags
104106
)
105107

106108
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
@@ -112,7 +114,9 @@ func main() {
112114
flag.BoolVar(&noRemoteBases, "no-remote-bases", false,
113115
"Disallow remote bases usage in Kustomize overlays. When this flag is enabled, all resources must refer to local files included in the source artifact.")
114116
flag.IntVar(&httpRetry, "http-retry", 9, "The maximum number of retries when failing to fetch artifacts over HTTP.")
115-
flag.StringVar(&defaultServiceAccount, "default-service-account", "", "Default service account used for impersonation.")
117+
flag.StringVar(&defaultServiceAccount, auth.ControllerFlagDefaultServiceAccount, "", "Default service account used for impersonation.")
118+
flag.StringVar(&defaultDecryptionServiceAccount, auth.ControllerFlagDefaultDecryptionServiceAccount, "", "Default service account used for decryption.")
119+
flag.StringVar(&defaultKubeConfigServiceAccount, auth.ControllerFlagDefaultKubeConfigServiceAccount, "", "Default service account used for kubeconfig.")
116120
flag.StringVar(&sopsAgeSecret, "sops-age-secret", "", "The name of a Kubernetes secret in the RUNTIME_NAMESPACE containing a SOPS age decryption key for fallback usage.")
117121
flag.StringArrayVar(&disallowedFieldManagers, "override-manager", []string{}, "Field manager disallowed to perform changes on managed resources.")
118122

@@ -146,6 +150,15 @@ func main() {
146150
auth.EnableObjectLevelWorkloadIdentity()
147151
}
148152

153+
// NOTE: defaultServiceAccount is used for regular impersonation, not workload identity lockdown
154+
155+
if defaultDecryptionServiceAccount != "" {
156+
auth.SetDefaultDecryptionServiceAccount(defaultDecryptionServiceAccount)
157+
}
158+
if defaultKubeConfigServiceAccount != "" {
159+
auth.SetDefaultKubeConfigServiceAccount(defaultKubeConfigServiceAccount)
160+
}
161+
149162
if err := intervalJitterOptions.SetGlobalJitter(nil); err != nil {
150163
setupLog.Error(err, "unable to set global jitter")
151164
os.Exit(1)

0 commit comments

Comments
 (0)