Skip to content

✨ Support serviceaccount pull secrets #2005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 44 additions & 21 deletions cmd/catalogd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ import (
"github.com/operator-framework/operator-controller/internal/catalogd/serverutil"
"github.com/operator-framework/operator-controller/internal/catalogd/storage"
"github.com/operator-framework/operator-controller/internal/catalogd/webhook"
sharedcontrollers "github.com/operator-framework/operator-controller/internal/shared/controllers"
fsutil "github.com/operator-framework/operator-controller/internal/shared/util/fs"
imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image"
sautil "github.com/operator-framework/operator-controller/internal/shared/util/sa"
"github.com/operator-framework/operator-controller/internal/shared/version"
)

Expand Down Expand Up @@ -246,18 +248,40 @@ func run(ctx context.Context) error {
cacheOptions := crcache.Options{
ByObject: map[client.Object]crcache.ByObject{},
}
if cfg.globalPullSecretKey != nil {
cacheOptions.ByObject[&corev1.Secret{}] = crcache.ByObject{
Namespaces: map[string]crcache.Config{
cfg.globalPullSecretKey.Namespace: {
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.SelectorFromSet(map[string]string{
"metadata.name": cfg.globalPullSecretKey.Name,
}),
},

saKey, err := sautil.GetServiceAccount()
if err != nil {
setupLog.Error(err, "Unable to get pod namesapce and serviceaccount")
return err
}

setupLog.Info("Read token", "serviceaccount", saKey)
cacheOptions.ByObject[&corev1.ServiceAccount{}] = crcache.ByObject{
Namespaces: map[string]crcache.Config{
saKey.Namespace: {
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.SelectorFromSet(map[string]string{
"metadata.name": saKey.Name,
}),
},
},
}

secretCache := crcache.ByObject{}
secretCache.Namespaces = make(map[string]crcache.Config, 2)
secretCache.Namespaces[saKey.Namespace] = crcache.Config{
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.Everything(),
}
if cfg.globalPullSecretKey != nil {
secretCache.Namespaces[cfg.globalPullSecretKey.Namespace] = crcache.Config{
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.SelectorFromSet(map[string]string{
"metadata.name": cfg.globalPullSecretKey.Name,
}),
}
}
cacheOptions.ByObject[&corev1.Secret{}] = secretCache

// Create manager
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Expand Down Expand Up @@ -312,7 +336,7 @@ func run(ctx context.Context) error {
DockerCertPath: cfg.pullCasDir,
OCICertPath: cfg.pullCasDir,
}
if _, err := os.Stat(authFilePath); err == nil && cfg.globalPullSecretKey != nil {
if _, err := os.Stat(authFilePath); err == nil {
logger.Info("using available authentication information for pulling image")
srcContext.AuthFilePath = authFilePath
} else if os.IsNotExist(err) {
Expand Down Expand Up @@ -370,17 +394,16 @@ func run(ctx context.Context) error {
return err
}

if cfg.globalPullSecretKey != nil {
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
err := (&corecontrollers.PullSecretReconciler{
Client: mgr.GetClient(),
AuthFilePath: authFilePath,
SecretKey: *cfg.globalPullSecretKey,
}).SetupWithManager(mgr)
if err != nil {
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
return err
}
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
err = (&sharedcontrollers.PullSecretReconciler{
Client: mgr.GetClient(),
AuthFilePath: authFilePath,
SecretKey: cfg.globalPullSecretKey,
ServiceAccountKey: saKey,
}).SetupWithManager(mgr)
if err != nil {
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
return err
}
//+kubebuilder:scaffold:builder

Expand Down
65 changes: 44 additions & 21 deletions cmd/operator-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render/certproviders"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render/registryv1"
"github.com/operator-framework/operator-controller/internal/operator-controller/scheme"
sharedcontrollers "github.com/operator-framework/operator-controller/internal/shared/controllers"
fsutil "github.com/operator-framework/operator-controller/internal/shared/util/fs"
httputil "github.com/operator-framework/operator-controller/internal/shared/util/http"
imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image"
sautil "github.com/operator-framework/operator-controller/internal/shared/util/sa"
"github.com/operator-framework/operator-controller/internal/shared/version"
)

Expand Down Expand Up @@ -217,18 +219,40 @@ func run() error {
},
DefaultLabelSelector: k8slabels.Nothing(),
}
if globalPullSecretKey != nil {
cacheOptions.ByObject[&corev1.Secret{}] = crcache.ByObject{
Namespaces: map[string]crcache.Config{
globalPullSecretKey.Namespace: {
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.SelectorFromSet(map[string]string{
"metadata.name": globalPullSecretKey.Name,
}),
},

saKey, err := sautil.GetServiceAccount()
if err != nil {
setupLog.Error(err, "Unable to get pod namesapce and serviceaccount")
return err
}

setupLog.Info("Read token", "serviceaccount", saKey)
cacheOptions.ByObject[&corev1.ServiceAccount{}] = crcache.ByObject{
Namespaces: map[string]crcache.Config{
saKey.Namespace: {
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.SelectorFromSet(map[string]string{
"metadata.name": saKey.Name,
}),
},
},
}

secretCache := crcache.ByObject{}
secretCache.Namespaces = make(map[string]crcache.Config, 2)
secretCache.Namespaces[saKey.Namespace] = crcache.Config{
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.Everything(),
}
if globalPullSecretKey != nil {
secretCache.Namespaces[globalPullSecretKey.Namespace] = crcache.Config{
LabelSelector: k8slabels.Everything(),
FieldSelector: fields.SelectorFromSet(map[string]string{
"metadata.name": globalPullSecretKey.Name,
}),
}
}
cacheOptions.ByObject[&corev1.Secret{}] = secretCache

metricsServerOptions := server.Options{}
if len(cfg.certFile) > 0 && len(cfg.keyFile) > 0 {
Expand Down Expand Up @@ -360,7 +384,7 @@ func run() error {
OCICertPath: cfg.pullCasDir,
}
logger := log.FromContext(ctx)
if _, err := os.Stat(authFilePath); err == nil && globalPullSecretKey != nil {
if _, err := os.Stat(authFilePath); err == nil {
logger.Info("using available authentication information for pulling image")
srcContext.AuthFilePath = authFilePath
} else if os.IsNotExist(err) {
Expand Down Expand Up @@ -482,17 +506,16 @@ func run() error {
return err
}

if globalPullSecretKey != nil {
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
err := (&controllers.PullSecretReconciler{
Client: mgr.GetClient(),
AuthFilePath: authFilePath,
SecretKey: *globalPullSecretKey,
}).SetupWithManager(mgr)
if err != nil {
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
return err
}
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
err = (&sharedcontrollers.PullSecretReconciler{
Client: mgr.GetClient(),
AuthFilePath: authFilePath,
SecretKey: globalPullSecretKey,
ServiceAccountKey: saKey,
}).SetupWithManager(mgr)
if err != nil {
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
return err
}

//+kubebuilder:scaffold:builder
Expand Down
16 changes: 16 additions & 0 deletions config/base/catalogd/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,19 @@ rules:
- get
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: manager-role
namespace: system
rules:
- apiGroups:
- ""
resources:
- secrets
- serviceaccounts
verbs:
- get
- list
- watch
17 changes: 17 additions & 0 deletions config/base/catalogd/rbac/role_binding.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,20 @@ subjects:
- kind: ServiceAccount
name: controller-manager
namespace: system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/part-of: olm
app.kubernetes.io/name: catalogd
name: manager-rolebinding
namespace: system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: manager-role
subjects:
- kind: ServiceAccount
name: controller-manager
namespace: system
8 changes: 8 additions & 0 deletions config/base/operator-controller/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,11 @@ rules:
- patch
- update
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- get
- list
- watch
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ require (
github.com/containers/image/v5 v5.35.0
github.com/fsnotify/fsnotify v1.9.0
github.com/go-logr/logr v1.4.3
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/google/go-cmp v0.7.0
github.com/google/go-containerregistry v0.20.3
github.com/google/renameio/v2 v2.0.0
github.com/gorilla/handlers v1.5.2
github.com/klauspost/compress v1.18.0
github.com/opencontainers/go-digest v1.0.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
Expand Down Expand Up @@ -253,6 +255,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4 h1:gD0vax+4I+mAj+jEChEf25Ia07Jq7kYOFO5PPhAxFl4=
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ type storedCatalogData struct {
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs/finalizers,verbs=update
//+kubebuilder:rbac:namespace=system,groups=core,resources=secrets,verbs=get;list;watch
//+kubebuilder:rbac:namespace=system,groups=core,resources=serviceaccounts,verbs=get;list;watch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
111 changes: 0 additions & 111 deletions internal/catalogd/controllers/core/pull_secret_controller.go

This file was deleted.

Loading
Loading