Skip to content

Commit af4701a

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 af4701a

File tree

5 files changed

+42
-31
lines changed

5 files changed

+42
-31
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ 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.25.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

go.sum

Lines changed: 2 additions & 2 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.25.0 h1:q8iJ9vdADiJxNA7EKNgEbIXNGbgqqTz6u975ziI3omk=
203+
github.com/fluxcd/pkg/auth v0.25.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=

internal/controller/kustomization_configuration_error_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ 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+
t.Setenv(auth.EnvEnableObjectLevelWorkloadIdentity, "true")
182182

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

internal/decryptor/decryptor.go

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

321+
opts = append(opts, auth.WithClient(d.client))
322+
opts = append(opts, auth.WithServiceAccountNamespace(d.kustomization.GetNamespace()))
321323
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))
324+
opts = append(opts, auth.WithServiceAccountName(d.kustomization.Spec.Decryption.ServiceAccountName))
327325
}
328326

329327
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)