[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 <cappyzawa@gmail.com>
This commit is contained in:
parent
aaad1e033e
commit
c5f0efdced
4
go.mod
4
go.mod
|
|
@ -24,11 +24,11 @@ require (
|
|||
github.com/fluxcd/pkg/apis/event v0.18.0
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0
|
||||
github.com/fluxcd/pkg/auth v0.23.0
|
||||
github.com/fluxcd/pkg/auth v0.26.0
|
||||
github.com/fluxcd/pkg/cache v0.10.0
|
||||
github.com/fluxcd/pkg/http/fetch v0.17.0
|
||||
github.com/fluxcd/pkg/kustomize v1.19.0
|
||||
github.com/fluxcd/pkg/runtime v0.72.0
|
||||
github.com/fluxcd/pkg/runtime v0.80.0
|
||||
github.com/fluxcd/pkg/ssa v0.51.0
|
||||
github.com/fluxcd/pkg/tar v0.13.0
|
||||
github.com/fluxcd/pkg/testserver v0.11.0
|
||||
|
|
|
|||
8
go.sum
8
go.sum
|
|
@ -199,8 +199,8 @@ github.com/fluxcd/pkg/apis/kustomize v1.11.0 h1:0IzDgxZkc4v+5SDNCvgZhfwfkdkQLPXC
|
|||
github.com/fluxcd/pkg/apis/kustomize v1.11.0/go.mod h1:j302mJGDww8cn9qvMsRQ0LJ1HPAPs/IlX7CSsoJV7BI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0 h1:ACHrMIjlcioE9GKS7NGk62KX4NshqNewr8sBwMcXABs=
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fluxcd/pkg/auth v0.23.0 h1:Xt89QO1Hzh7X0JFwCeONyxMlgOX/zOPx0eyIyFoKyF0=
|
||||
github.com/fluxcd/pkg/auth v0.23.0/go.mod h1:YEAHpBFuW5oLlH9ekuJaQdnJ2Q3A7Ny8kha3WY7QMnY=
|
||||
github.com/fluxcd/pkg/auth v0.26.0 h1:jw128zPI4aRSvkGbFfAQcFNF3oK58P4rDdKIpj2/7yM=
|
||||
github.com/fluxcd/pkg/auth v0.26.0/go.mod h1:YEAHpBFuW5oLlH9ekuJaQdnJ2Q3A7Ny8kha3WY7QMnY=
|
||||
github.com/fluxcd/pkg/cache v0.10.0 h1:M+OGDM4da1cnz7q+sZSBtkBJHpiJsLnKVmR9OdMWxEY=
|
||||
github.com/fluxcd/pkg/cache v0.10.0/go.mod h1:pPXRzQUDQagsCniuOolqVhnAkbNgYOg8d2cTliPs7ME=
|
||||
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
|
|||
github.com/fluxcd/pkg/http/fetch v0.17.0/go.mod h1:nMozZtiSKtPGwMrR5wGjIJoQmhvFqZ5P4UsM/Lqza2I=
|
||||
github.com/fluxcd/pkg/kustomize v1.19.0 h1:2eO8lMx0/H/Yyq35LMTAMhxEElOzMW0Yi9zUNZoimlU=
|
||||
github.com/fluxcd/pkg/kustomize v1.19.0/go.mod h1:OCCW9vU3lStDh3jyg9MM/a29MSdNAVk2wjl0lDos5Fs=
|
||||
github.com/fluxcd/pkg/runtime v0.72.0 h1:9JCto84iL2FziuTuuvDwvS+cfIzGhHOk25y8ulXpNOs=
|
||||
github.com/fluxcd/pkg/runtime v0.72.0/go.mod h1:iGhdaEq+lMJQTJNAFEPOU4gUJ7kt3yeDcJPZy7O9IUw=
|
||||
github.com/fluxcd/pkg/runtime v0.80.0 h1:vknT2vdQSGTFnAhz4xGk2ZXUWCrXh3whsISStgA57Go=
|
||||
github.com/fluxcd/pkg/runtime v0.80.0/go.mod h1:iGhdaEq+lMJQTJNAFEPOU4gUJ7kt3yeDcJPZy7O9IUw=
|
||||
github.com/fluxcd/pkg/sourceignore v0.13.0 h1:ZvkzX2WsmyZK9cjlqOFFW1onHVzhPZIqDbCh96rPqbU=
|
||||
github.com/fluxcd/pkg/sourceignore v0.13.0/go.mod h1:Z9H1GoBx0ljOhptnzoV0PL6Nd/UzwKcSphP27lqb4xI=
|
||||
github.com/fluxcd/pkg/ssa v0.51.0 h1:sFarxKZcS0J8sjq9qvs/r+1XiJqNgRodEiPjV75F8R4=
|
||||
|
|
|
|||
|
|
@ -178,7 +178,8 @@ data: {}
|
|||
t.Run("object level workload identity feature gate enabled", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
t.Setenv(auth.EnvVarEnableObjectLevelWorkloadIdentity, "true")
|
||||
auth.EnableObjectLevelWorkloadIdentity()
|
||||
t.Cleanup(auth.DisableObjectLevelWorkloadIdentity)
|
||||
|
||||
kustomizationKey := types.NamespacedName{
|
||||
Name: fmt.Sprintf("invalid-config-%s", randStringRunes(5)),
|
||||
|
|
|
|||
|
|
@ -316,14 +316,17 @@ func (d *Decryptor) SetAuthOptions(ctx context.Context) {
|
|||
|
||||
switch d.kustomization.Spec.Decryption.Provider {
|
||||
case DecryptionProviderSOPS:
|
||||
var opts []auth.Option
|
||||
opts := []auth.Option{
|
||||
auth.WithClient(d.client),
|
||||
}
|
||||
|
||||
if d.kustomization.Spec.Decryption.ServiceAccountName != "" {
|
||||
serviceAccount := types.NamespacedName{
|
||||
Name: d.kustomization.Spec.Decryption.ServiceAccountName,
|
||||
Namespace: d.kustomization.GetNamespace(),
|
||||
}
|
||||
opts = append(opts, auth.WithServiceAccount(serviceAccount, d.client))
|
||||
saName := d.kustomization.Spec.Decryption.ServiceAccountName
|
||||
if saName == "" {
|
||||
saName = auth.GetDefaultDecryptionServiceAccount()
|
||||
}
|
||||
if saName != "" {
|
||||
opts = append(opts, auth.WithServiceAccountName(saName))
|
||||
opts = append(opts, auth.WithServiceAccountNamespace(d.kustomization.GetNamespace()))
|
||||
}
|
||||
|
||||
involvedObject := cache.InvolvedObject{
|
||||
|
|
|
|||
57
main.go
57
main.go
|
|
@ -80,27 +80,29 @@ func main() {
|
|||
)
|
||||
|
||||
var (
|
||||
metricsAddr string
|
||||
eventsAddr string
|
||||
healthAddr string
|
||||
concurrent int
|
||||
concurrentSSA int
|
||||
requeueDependency time.Duration
|
||||
clientOptions runtimeClient.Options
|
||||
kubeConfigOpts runtimeClient.KubeConfigOptions
|
||||
logOptions logger.Options
|
||||
leaderElectionOptions leaderelection.Options
|
||||
rateLimiterOptions runtimeCtrl.RateLimiterOptions
|
||||
watchOptions runtimeCtrl.WatchOptions
|
||||
intervalJitterOptions jitter.IntervalOptions
|
||||
aclOptions acl.Options
|
||||
noRemoteBases bool
|
||||
httpRetry int
|
||||
defaultServiceAccount string
|
||||
sopsAgeSecret string
|
||||
featureGates feathelper.FeatureGates
|
||||
disallowedFieldManagers []string
|
||||
tokenCacheOptions pkgcache.TokenFlags
|
||||
metricsAddr string
|
||||
eventsAddr string
|
||||
healthAddr string
|
||||
concurrent int
|
||||
concurrentSSA int
|
||||
requeueDependency time.Duration
|
||||
clientOptions runtimeClient.Options
|
||||
kubeConfigOpts runtimeClient.KubeConfigOptions
|
||||
logOptions logger.Options
|
||||
leaderElectionOptions leaderelection.Options
|
||||
rateLimiterOptions runtimeCtrl.RateLimiterOptions
|
||||
watchOptions runtimeCtrl.WatchOptions
|
||||
intervalJitterOptions jitter.IntervalOptions
|
||||
aclOptions acl.Options
|
||||
noRemoteBases bool
|
||||
httpRetry int
|
||||
defaultServiceAccount string
|
||||
defaultDecryptionServiceAccount string
|
||||
defaultKubeConfigServiceAccount string
|
||||
sopsAgeSecret string
|
||||
featureGates feathelper.FeatureGates
|
||||
disallowedFieldManagers []string
|
||||
tokenCacheOptions pkgcache.TokenFlags
|
||||
)
|
||||
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
||||
|
|
@ -112,7 +114,9 @@ func main() {
|
|||
flag.BoolVar(&noRemoteBases, "no-remote-bases", false,
|
||||
"Disallow remote bases usage in Kustomize overlays. When this flag is enabled, all resources must refer to local files included in the source artifact.")
|
||||
flag.IntVar(&httpRetry, "http-retry", 9, "The maximum number of retries when failing to fetch artifacts over HTTP.")
|
||||
flag.StringVar(&defaultServiceAccount, "default-service-account", "", "Default service account used for impersonation.")
|
||||
flag.StringVar(&defaultServiceAccount, auth.ControllerFlagDefaultServiceAccount, "", "Default service account used for impersonation.")
|
||||
flag.StringVar(&defaultDecryptionServiceAccount, auth.ControllerFlagDefaultDecryptionServiceAccount, "", "Default service account used for decryption.")
|
||||
flag.StringVar(&defaultKubeConfigServiceAccount, auth.ControllerFlagDefaultKubeConfigServiceAccount, "", "Default service account used for kubeconfig.")
|
||||
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.")
|
||||
flag.StringArrayVar(&disallowedFieldManagers, "override-manager", []string{}, "Field manager disallowed to perform changes on managed resources.")
|
||||
|
||||
|
|
@ -146,6 +150,15 @@ func main() {
|
|||
auth.EnableObjectLevelWorkloadIdentity()
|
||||
}
|
||||
|
||||
// NOTE: defaultServiceAccount is used for regular impersonation, not workload identity lockdown
|
||||
|
||||
if defaultDecryptionServiceAccount != "" {
|
||||
auth.SetDefaultDecryptionServiceAccount(defaultDecryptionServiceAccount)
|
||||
}
|
||||
if defaultKubeConfigServiceAccount != "" {
|
||||
auth.SetDefaultKubeConfigServiceAccount(defaultKubeConfigServiceAccount)
|
||||
}
|
||||
|
||||
if err := intervalJitterOptions.SetGlobalJitter(nil); err != nil {
|
||||
setupLog.Error(err, "unable to set global jitter")
|
||||
os.Exit(1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue