Skip to content

Commit d9c01a9

Browse files
author
Aurélien Baumann
committed
Add support for restricting the secrets watch list in cainjector
The --secrets-field-selector flag is introduced and accepts a field selector expression The following example makes cainjector ignore all secrets whose type is "helm.sh/release.v1". ``` --secrets-field-selector type!=helm.sh/release.v1 ``` Signed-off-by: Aurélien Baumann <aur.baumann@gmail.com>
1 parent 95dc198 commit d9c01a9

2 files changed

Lines changed: 33 additions & 10 deletions

File tree

cmd/cainjector/app/start.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
// InjectorControllerOptions is a struct having injector controller options values
4545
type InjectorControllerOptions struct {
4646
Namespace string
47+
SecretsFieldSelector string
4748
LeaderElect bool
4849
LeaderElectionNamespace string
4950
LeaseDuration time.Duration
@@ -69,6 +70,9 @@ func (o *InjectorControllerOptions) AddFlags(fs *pflag.FlagSet) {
6970
"If set, this limits the scope of cainjector to a single namespace. "+
7071
"If set, cainjector will not update resources with certificates outside of the "+
7172
"configured namespace.")
73+
fs.StringVar(&o.SecretsFieldSelector, "secrets-field-selector", "", ""+
74+
"If set, this restricts the secrets watch list to the objects that match the given field expression. "+
75+
"Example value is type!=helm.sh/release.v1.")
7276
fs.BoolVar(&o.LeaderElect, "leader-elect", cmdutil.DefaultLeaderElect, ""+
7377
"If true, cainjector will perform leader election between instances to ensure no more "+
7478
"than one instance of cainjector operates at a time")
@@ -215,7 +219,7 @@ func (o InjectorControllerOptions) RunInjectorController(ctx context.Context) er
215219
// Never retry if the controller exits cleanly.
216220
g.Go(func() (err error) {
217221
for {
218-
err = cainjector.RegisterCertificateBased(gctx, mgr)
222+
err = cainjector.RegisterCertificateBased(gctx, mgr, o.SecretsFieldSelector)
219223
if err == nil {
220224
return
221225
}
@@ -234,7 +238,7 @@ func (o InjectorControllerOptions) RunInjectorController(ctx context.Context) er
234238
// We do not retry this controller because it only interacts with core APIs
235239
// which should always be in a working state.
236240
g.Go(func() (err error) {
237-
if err = cainjector.RegisterSecretBased(gctx, mgr); err != nil {
241+
if err = cainjector.RegisterSecretBased(gctx, mgr, o.SecretsFieldSelector); err != nil {
238242
return fmt.Errorf("error registering secret controller: %v", err)
239243
}
240244
return

pkg/controller/cainjector/setup.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import (
2121
"fmt"
2222
"os"
2323

24-
logf "github.com/cert-manager/cert-manager/pkg/logs"
2524
"github.com/go-logr/logr"
2625
"golang.org/x/sync/errgroup"
2726
admissionreg "k8s.io/api/admissionregistration/v1"
27+
corev1 "k8s.io/api/core/v1"
2828
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2929
"k8s.io/apimachinery/pkg/api/meta"
30+
"k8s.io/apimachinery/pkg/fields"
3031
"k8s.io/apimachinery/pkg/runtime"
3132
apireg "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
3233
ctrl "sigs.k8s.io/controller-runtime"
@@ -37,6 +38,8 @@ import (
3738
"sigs.k8s.io/controller-runtime/pkg/handler"
3839
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3940
"sigs.k8s.io/controller-runtime/pkg/source"
41+
42+
logf "github.com/cert-manager/cert-manager/pkg/logs"
4043
)
4144

4245
// injectorSet describes a particular setup of the injector controller
@@ -180,8 +183,8 @@ func dataFromSliceOrFile(data []byte, file string) ([]byte, error) {
180183
// indices.
181184
// The registered controllers require the cert-manager API to be available
182185
// in order to run.
183-
func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager) error {
184-
cache, client, err := newIndependentCacheAndDelegatingClient(mgr)
186+
func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager, secretsFieldSelector string) error {
187+
cache, client, err := newIndependentCacheAndDelegatingClient(mgr, secretsFieldSelector)
185188
if err != nil {
186189
return err
187190
}
@@ -202,8 +205,8 @@ func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager) error {
202205
// indices.
203206
// The registered controllers only require the corev1 APi to be available in
204207
// order to run.
205-
func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager) error {
206-
cache, client, err := newIndependentCacheAndDelegatingClient(mgr)
208+
func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager, secretsFieldSelector string) error {
209+
cache, client, err := newIndependentCacheAndDelegatingClient(mgr, secretsFieldSelector)
207210
if err != nil {
208211
return err
209212
}
@@ -226,10 +229,15 @@ func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager) error {
226229
// cert-manager Certificates CRDs have been installed and before the CA bundles
227230
// have been injected into the cert-manager CRDs, by the secrets based injector,
228231
// which is running in a separate goroutine.
229-
func newIndependentCacheAndDelegatingClient(mgr ctrl.Manager) (cache.Cache, client.Client, error) {
232+
func newIndependentCacheAndDelegatingClient(mgr ctrl.Manager, secretsFieldSelector string) (cache.Cache, client.Client, error) {
233+
selector, err := selectorFromFieldSelectorExpressions(secretsFieldSelector)
234+
if err != nil {
235+
return nil, nil, fmt.Errorf("invalid field selector expression %s: %w", secretsFieldSelector, err)
236+
}
230237
cacheOptions := cache.Options{
231-
Scheme: mgr.GetScheme(),
232-
Mapper: mgr.GetRESTMapper(),
238+
Scheme: mgr.GetScheme(),
239+
Mapper: mgr.GetRESTMapper(),
240+
SelectorsByObject: selector,
233241
}
234242
ca, err := cache.New(mgr.GetConfig(), cacheOptions)
235243
if err != nil {
@@ -247,3 +255,14 @@ func newIndependentCacheAndDelegatingClient(mgr ctrl.Manager) (cache.Cache, clie
247255
}
248256
return ca, client, nil
249257
}
258+
259+
func selectorFromFieldSelectorExpressions(expression string) (cache.SelectorsByObject, error) {
260+
if expression == "" {
261+
return nil, nil
262+
}
263+
selector, err := fields.ParseSelector(expression)
264+
if err != nil {
265+
return nil, fmt.Errorf("invalid field selector expression %s: %w", expression, err)
266+
}
267+
return map[client.Object]cache.ObjectSelector{&corev1.Secret{}: {Field: selector}}, nil
268+
}

0 commit comments

Comments
 (0)