Skip to content

Commit efc6657

Browse files
authored
✨ Support serviceaccount pull secrets (#2005)
* Support serviceaccount pull secrets Serviceaccounts reference pull secrets! * Determine our serviceaccount (via the new internal/shared/util/sa package). * Use a common pull_secret_controller * Update the pull_secret_controller to know about the service account * Update the pull_secret_controller to watch the namespace-local secrets * Update caching to include sa, and use filters for additional secrets * Add RBAC to access these secrets and sa * Update writing the auth.json file to handle dockercfg and dockerconfigjson * Update writing the auth.json file to include multiple secrets Signed-off-by: Todd Short <tshort@redhat.com> * fixup! Support serviceaccount pull secrets Signed-off-by: Todd Short <tshort@redhat.com> * fixup! Support serviceaccount pull secrets Signed-off-by: Todd Short <tshort@redhat.com> * fixup! Support serviceaccount pull secrets Signed-off-by: Todd Short <tshort@redhat.com> * fixup! Support serviceaccount pull secrets * fixup! Support serviceaccount pull secrets * fixup! Support serviceaccount pull secrets Signed-off-by: Todd Short <tshort@redhat.com> * fixup! Support serviceaccount pull secrets Signed-off-by: Todd Short <tshort@redhat.com> --------- Signed-off-by: Todd Short <tshort@redhat.com>
1 parent 3441d90 commit efc6657

File tree

19 files changed

+682
-466
lines changed

19 files changed

+682
-466
lines changed

cmd/catalogd/main.go

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ import (
3030

3131
"github.com/containers/image/v5/types"
3232
"github.com/spf13/cobra"
33-
corev1 "k8s.io/api/core/v1"
34-
"k8s.io/apimachinery/pkg/fields"
35-
k8slabels "k8s.io/apimachinery/pkg/labels"
3633
"k8s.io/apimachinery/pkg/runtime"
3734
k8stypes "k8s.io/apimachinery/pkg/types"
3835
apimachineryrand "k8s.io/apimachinery/pkg/util/rand"
@@ -61,8 +58,11 @@ import (
6158
"github.com/operator-framework/operator-controller/internal/catalogd/serverutil"
6259
"github.com/operator-framework/operator-controller/internal/catalogd/storage"
6360
"github.com/operator-framework/operator-controller/internal/catalogd/webhook"
61+
sharedcontrollers "github.com/operator-framework/operator-controller/internal/shared/controllers"
6462
fsutil "github.com/operator-framework/operator-controller/internal/shared/util/fs"
6563
imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image"
64+
"github.com/operator-framework/operator-controller/internal/shared/util/pullsecretcache"
65+
sautil "github.com/operator-framework/operator-controller/internal/shared/util/sa"
6666
"github.com/operator-framework/operator-controller/internal/shared/version"
6767
)
6868

@@ -246,17 +246,19 @@ func run(ctx context.Context) error {
246246
cacheOptions := crcache.Options{
247247
ByObject: map[client.Object]crcache.ByObject{},
248248
}
249-
if cfg.globalPullSecretKey != nil {
250-
cacheOptions.ByObject[&corev1.Secret{}] = crcache.ByObject{
251-
Namespaces: map[string]crcache.Config{
252-
cfg.globalPullSecretKey.Namespace: {
253-
LabelSelector: k8slabels.Everything(),
254-
FieldSelector: fields.SelectorFromSet(map[string]string{
255-
"metadata.name": cfg.globalPullSecretKey.Name,
256-
}),
257-
},
258-
},
259-
}
249+
250+
saKey, err := sautil.GetServiceAccount()
251+
if err != nil {
252+
setupLog.Error(err, "Failed to extract serviceaccount from JWT")
253+
return err
254+
}
255+
setupLog.Info("Successfully extracted serviceaccount from JWT", "serviceaccount",
256+
fmt.Sprintf("%s/%s", saKey.Namespace, saKey.Name))
257+
258+
err = pullsecretcache.SetupPullSecretCache(&cacheOptions, cfg.globalPullSecretKey, saKey)
259+
if err != nil {
260+
setupLog.Error(err, "Unable to setup pull-secret cache")
261+
return err
260262
}
261263

262264
// Create manager
@@ -312,7 +314,7 @@ func run(ctx context.Context) error {
312314
DockerCertPath: cfg.pullCasDir,
313315
OCICertPath: cfg.pullCasDir,
314316
}
315-
if _, err := os.Stat(authFilePath); err == nil && cfg.globalPullSecretKey != nil {
317+
if _, err := os.Stat(authFilePath); err == nil {
316318
logger.Info("using available authentication information for pulling image")
317319
srcContext.AuthFilePath = authFilePath
318320
} else if os.IsNotExist(err) {
@@ -370,17 +372,16 @@ func run(ctx context.Context) error {
370372
return err
371373
}
372374

373-
if cfg.globalPullSecretKey != nil {
374-
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
375-
err := (&corecontrollers.PullSecretReconciler{
376-
Client: mgr.GetClient(),
377-
AuthFilePath: authFilePath,
378-
SecretKey: *cfg.globalPullSecretKey,
379-
}).SetupWithManager(mgr)
380-
if err != nil {
381-
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
382-
return err
383-
}
375+
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
376+
err = (&sharedcontrollers.PullSecretReconciler{
377+
Client: mgr.GetClient(),
378+
AuthFilePath: authFilePath,
379+
SecretKey: cfg.globalPullSecretKey,
380+
ServiceAccountKey: saKey,
381+
}).SetupWithManager(mgr)
382+
if err != nil {
383+
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
384+
return err
384385
}
385386
//+kubebuilder:scaffold:builder
386387

cmd/operator-controller/main.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ import (
3030

3131
"github.com/containers/image/v5/types"
3232
"github.com/spf13/cobra"
33-
corev1 "k8s.io/api/core/v1"
3433
rbacv1 "k8s.io/api/rbac/v1"
3534
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
36-
"k8s.io/apimachinery/pkg/fields"
3735
k8slabels "k8s.io/apimachinery/pkg/labels"
3836
k8stypes "k8s.io/apimachinery/pkg/types"
3937
apimachineryrand "k8s.io/apimachinery/pkg/util/rand"
@@ -71,9 +69,12 @@ import (
7169
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render/certproviders"
7270
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render/registryv1"
7371
"github.com/operator-framework/operator-controller/internal/operator-controller/scheme"
72+
sharedcontrollers "github.com/operator-framework/operator-controller/internal/shared/controllers"
7473
fsutil "github.com/operator-framework/operator-controller/internal/shared/util/fs"
7574
httputil "github.com/operator-framework/operator-controller/internal/shared/util/http"
7675
imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image"
76+
"github.com/operator-framework/operator-controller/internal/shared/util/pullsecretcache"
77+
sautil "github.com/operator-framework/operator-controller/internal/shared/util/sa"
7778
"github.com/operator-framework/operator-controller/internal/shared/version"
7879
)
7980

@@ -217,17 +218,19 @@ func run() error {
217218
},
218219
DefaultLabelSelector: k8slabels.Nothing(),
219220
}
220-
if globalPullSecretKey != nil {
221-
cacheOptions.ByObject[&corev1.Secret{}] = crcache.ByObject{
222-
Namespaces: map[string]crcache.Config{
223-
globalPullSecretKey.Namespace: {
224-
LabelSelector: k8slabels.Everything(),
225-
FieldSelector: fields.SelectorFromSet(map[string]string{
226-
"metadata.name": globalPullSecretKey.Name,
227-
}),
228-
},
229-
},
230-
}
221+
222+
saKey, err := sautil.GetServiceAccount()
223+
if err != nil {
224+
setupLog.Error(err, "Failed to extract serviceaccount from JWT")
225+
return err
226+
}
227+
setupLog.Info("Successfully extracted serviceaccount from JWT", "serviceaccount",
228+
fmt.Sprintf("%s/%s", saKey.Namespace, saKey.Name))
229+
230+
err = pullsecretcache.SetupPullSecretCache(&cacheOptions, globalPullSecretKey, saKey)
231+
if err != nil {
232+
setupLog.Error(err, "Unable to setup pull-secret cache")
233+
return err
231234
}
232235

233236
metricsServerOptions := server.Options{}
@@ -360,7 +363,7 @@ func run() error {
360363
OCICertPath: cfg.pullCasDir,
361364
}
362365
logger := log.FromContext(ctx)
363-
if _, err := os.Stat(authFilePath); err == nil && globalPullSecretKey != nil {
366+
if _, err := os.Stat(authFilePath); err == nil {
364367
logger.Info("using available authentication information for pulling image")
365368
srcContext.AuthFilePath = authFilePath
366369
} else if os.IsNotExist(err) {
@@ -482,17 +485,16 @@ func run() error {
482485
return err
483486
}
484487

485-
if globalPullSecretKey != nil {
486-
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
487-
err := (&controllers.PullSecretReconciler{
488-
Client: mgr.GetClient(),
489-
AuthFilePath: authFilePath,
490-
SecretKey: *globalPullSecretKey,
491-
}).SetupWithManager(mgr)
492-
if err != nil {
493-
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
494-
return err
495-
}
488+
setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", cfg.globalPullSecret)
489+
err = (&sharedcontrollers.PullSecretReconciler{
490+
Client: mgr.GetClient(),
491+
AuthFilePath: authFilePath,
492+
SecretKey: globalPullSecretKey,
493+
ServiceAccountKey: saKey,
494+
}).SetupWithManager(mgr)
495+
if err != nil {
496+
setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer")
497+
return err
496498
}
497499

498500
//+kubebuilder:scaffold:builder

config/base/catalogd/rbac/role.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,19 @@ rules:
3030
- get
3131
- patch
3232
- update
33+
---
34+
apiVersion: rbac.authorization.k8s.io/v1
35+
kind: Role
36+
metadata:
37+
name: manager-role
38+
namespace: system
39+
rules:
40+
- apiGroups:
41+
- ""
42+
resources:
43+
- secrets
44+
- serviceaccounts
45+
verbs:
46+
- get
47+
- list
48+
- watch

config/base/catalogd/rbac/role_binding.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,20 @@ subjects:
1313
- kind: ServiceAccount
1414
name: controller-manager
1515
namespace: system
16+
---
17+
apiVersion: rbac.authorization.k8s.io/v1
18+
kind: RoleBinding
19+
metadata:
20+
labels:
21+
app.kubernetes.io/part-of: olm
22+
app.kubernetes.io/name: catalogd
23+
name: manager-rolebinding
24+
namespace: system
25+
roleRef:
26+
apiGroup: rbac.authorization.k8s.io
27+
kind: Role
28+
name: manager-role
29+
subjects:
30+
- kind: ServiceAccount
31+
name: controller-manager
32+
namespace: system

config/base/operator-controller/rbac/role.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,11 @@ rules:
7777
- patch
7878
- update
7979
- watch
80+
- apiGroups:
81+
- ""
82+
resources:
83+
- serviceaccounts
84+
verbs:
85+
- get
86+
- list
87+
- watch

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ require (
1111
github.com/containers/image/v5 v5.35.0
1212
github.com/fsnotify/fsnotify v1.9.0
1313
github.com/go-logr/logr v1.4.3
14+
github.com/golang-jwt/jwt/v5 v5.2.2
1415
github.com/google/go-cmp v0.7.0
1516
github.com/google/go-containerregistry v0.20.3
17+
github.com/google/renameio/v2 v2.0.0
1618
github.com/gorilla/handlers v1.5.2
1719
github.com/klauspost/compress v1.18.0
1820
github.com/opencontainers/go-digest v1.0.0

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
209209
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
210210
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
211211
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
212+
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
213+
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
212214
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
213215
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
214216
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -253,6 +255,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
253255
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
254256
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4 h1:gD0vax+4I+mAj+jEChEf25Ia07Jq7kYOFO5PPhAxFl4=
255257
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
258+
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
259+
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
256260
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
257261
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
258262
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

internal/catalogd/controllers/core/clustercatalog_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ type storedCatalogData struct {
7979
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs,verbs=get;list;watch;create;update;patch;delete
8080
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs/status,verbs=get;update;patch
8181
//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs/finalizers,verbs=update
82+
//+kubebuilder:rbac:namespace=system,groups=core,resources=secrets,verbs=get;list;watch
83+
//+kubebuilder:rbac:namespace=system,groups=core,resources=serviceaccounts,verbs=get;list;watch
8284

8385
// Reconcile is part of the main kubernetes reconciliation loop which aims to
8486
// move the current state of the cluster closer to the desired state.

internal/catalogd/controllers/core/pull_secret_controller.go

Lines changed: 0 additions & 111 deletions
This file was deleted.

0 commit comments

Comments
 (0)