Merge pull request #5694 from irbekrm/fix_cainjector_namespace

Fix cainjector's namespace flag
This commit is contained in:
jetstack-bot 2023-01-06 10:43:41 +00:00 committed by GitHub
commit 248eff5bce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 17 deletions

View File

@ -215,7 +215,7 @@ func (o InjectorControllerOptions) RunInjectorController(ctx context.Context) er
// Never retry if the controller exits cleanly.
g.Go(func() (err error) {
for {
err = cainjector.RegisterCertificateBased(gctx, mgr)
err = cainjector.RegisterCertificateBased(gctx, mgr, o.Namespace)
if err == nil {
return
}
@ -234,7 +234,7 @@ func (o InjectorControllerOptions) RunInjectorController(ctx context.Context) er
// We do not retry this controller because it only interacts with core APIs
// which should always be in a working state.
g.Go(func() (err error) {
if err = cainjector.RegisterSecretBased(gctx, mgr); err != nil {
if err = cainjector.RegisterSecretBased(gctx, mgr, o.Namespace); err != nil {
return fmt.Errorf("error registering secret controller: %v", err)
}
return

View File

@ -106,6 +106,9 @@ type genericInjectReconciler struct {
log logr.Logger
client.Client
// if set, the reconciler is namespace scoped
namespace string
resourceName string // just used for logging
}
@ -157,11 +160,16 @@ func (r *genericInjectReconciler) Reconcile(_ context.Context, req ctrl.Request)
return ctrl.Result{}, nil
}
caData, err := dataSource.ReadCA(ctx, log, metaObj)
caData, err := dataSource.ReadCA(ctx, log, metaObj, r.namespace)
if apierrors.IsForbidden(err) {
log.V(logf.InfoLevel).Info("cainjector was forbidden to retrieve the ca data source")
return ctrl.Result{}, nil
}
if err != nil {
log.Error(err, "failed to read CA from data source")
return ctrl.Result{}, err
}
if caData == nil {
log.V(logf.InfoLevel).Info("could not find any ca data in data source for target")
return ctrl.Result{}, nil

View File

@ -77,10 +77,10 @@ var (
// registerAllInjectors registers all injectors and based on the
// graduation state of the injector decides how to log no kind/resource match errors
func registerAllInjectors(ctx context.Context, groupName string, mgr ctrl.Manager, sources []caDataSource, client client.Client, ca cache.Cache) error {
func registerAllInjectors(ctx context.Context, groupName string, mgr ctrl.Manager, sources []caDataSource, client client.Client, ca cache.Cache, namespace string) error {
controllers := make([]controller.Controller, len(injectorSetups))
for i, setup := range injectorSetups {
controller, err := newGenericInjectionController(ctx, groupName, mgr, setup, sources, ca, client)
controller, err := newGenericInjectionController(ctx, groupName, mgr, setup, sources, ca, client, namespace)
if err != nil {
if !meta.IsNoMatchError(err) || !setup.injector.IsAlpha() {
return err
@ -126,7 +126,7 @@ func registerAllInjectors(ctx context.Context, groupName string, mgr ctrl.Manage
// * https://github.com/kubernetes-sigs/controller-runtime/issues/764
func newGenericInjectionController(ctx context.Context, groupName string, mgr ctrl.Manager,
setup injectorSetup, sources []caDataSource, ca cache.Cache,
client client.Client) (controller.Controller, error) {
client client.Client, namespace string) (controller.Controller, error) {
log := ctrl.Log.WithName(groupName).WithName(setup.resourceName)
typ := setup.injector.NewTarget().AsObject()
@ -140,6 +140,7 @@ func newGenericInjectionController(ctx context.Context, groupName string, mgr ct
log: log.WithName("generic-inject-reconciler"),
resourceName: setup.resourceName,
injector: setup.injector,
namespace: namespace,
},
LogConstructor: func(request *reconcile.Request) logr.Logger { return log },
})
@ -180,8 +181,8 @@ func dataFromSliceOrFile(data []byte, file string) ([]byte, error) {
// indices.
// The registered controllers require the cert-manager API to be available
// in order to run.
func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager) error {
cache, client, err := newIndependentCacheAndDelegatingClient(mgr)
func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager, namespace string) error {
cache, client, err := newIndependentCacheAndDelegatingClient(mgr, namespace)
if err != nil {
return err
}
@ -194,6 +195,7 @@ func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager) error {
},
client,
cache,
namespace,
)
}
@ -202,8 +204,8 @@ func RegisterCertificateBased(ctx context.Context, mgr ctrl.Manager) error {
// indices.
// The registered controllers only require the corev1 APi to be available in
// order to run.
func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager) error {
cache, client, err := newIndependentCacheAndDelegatingClient(mgr)
func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager, namespace string) error {
cache, client, err := newIndependentCacheAndDelegatingClient(mgr, namespace)
if err != nil {
return err
}
@ -217,6 +219,7 @@ func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager) error {
},
client,
cache,
namespace,
)
}
@ -226,11 +229,14 @@ func RegisterSecretBased(ctx context.Context, mgr ctrl.Manager) error {
// cert-manager Certificates CRDs have been installed and before the CA bundles
// have been injected into the cert-manager CRDs, by the secrets based injector,
// which is running in a separate goroutine.
func newIndependentCacheAndDelegatingClient(mgr ctrl.Manager) (cache.Cache, client.Client, error) {
func newIndependentCacheAndDelegatingClient(mgr ctrl.Manager, namespace string) (cache.Cache, client.Client, error) {
cacheOptions := cache.Options{
Scheme: mgr.GetScheme(),
Mapper: mgr.GetRESTMapper(),
}
if namespace != "" {
cacheOptions.Namespace = namespace
}
ca, err := cache.New(mgr.GetConfig(), cacheOptions)
if err != nil {
return nil, nil, err

View File

@ -18,11 +18,11 @@ package cainjector
import (
"context"
logf "github.com/cert-manager/cert-manager/pkg/logs"
"fmt"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
@ -34,6 +34,7 @@ import (
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
logf "github.com/cert-manager/cert-manager/pkg/logs"
)
// caDataSource knows how to extract CA data given a provided InjectTarget.
@ -52,7 +53,7 @@ type caDataSource interface {
// In this case, the caller should not retry the operation.
// It is up to the ReadCA implementation to inform the user why the CA
// failed to read.
ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object) (ca []byte, err error)
ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object, namespace string) (ca []byte, err error)
// ApplyTo applies any required watchers to the given controller.
ApplyTo(ctx context.Context, mgr ctrl.Manager, setup injectorSetup, controller controller.Controller, ca cache.Cache) error
@ -69,7 +70,7 @@ func (c *kubeconfigDataSource) Configured(log logr.Logger, metaObj metav1.Object
return metaObj.GetAnnotations()[cmapi.WantInjectAPIServerCAAnnotation] == "true"
}
func (c *kubeconfigDataSource) ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object) (ca []byte, err error) {
func (c *kubeconfigDataSource) ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object, namespace string) (ca []byte, err error) {
return c.apiserverCABundle, nil
}
@ -99,15 +100,22 @@ func (c *certificateDataSource) Configured(log logr.Logger, metaObj metav1.Objec
return true
}
func (c *certificateDataSource) ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object) (ca []byte, err error) {
func (c *certificateDataSource) ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object, namespace string) (ca []byte, err error) {
certNameRaw := metaObj.GetAnnotations()[cmapi.WantInjectAnnotation]
certName := splitNamespacedName(certNameRaw)
log = log.WithValues("certificate", certName)
if certName.Namespace == "" {
log.Error(nil, "invalid certificate name; needs a namespace/ prefix")
// TODO: should an error be returned here to prevent the caller from proceeding?
// don't return an error, requeuing won't help till this is changed
return nil, nil
}
if namespace != "" && certName.Namespace != namespace {
err := fmt.Errorf("cannot read CA data from Certificate in namespace %s, cainjector is scoped to namespace %s", certName.Namespace, namespace)
forbidenErr := apierrors.NewForbidden(cmapi.Resource("certificates"), certName.Name, err)
log.Error(forbidenErr, "cannot read data source")
return nil, forbidenErr
}
var cert cmapi.Certificate
if err := c.client.Get(ctx, certName, &cert); err != nil {
@ -185,16 +193,24 @@ func (c *secretDataSource) Configured(log logr.Logger, metaObj metav1.Object) bo
return true
}
func (c *secretDataSource) ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object) ([]byte, error) {
func (c *secretDataSource) ReadCA(ctx context.Context, log logr.Logger, metaObj metav1.Object, namespace string) ([]byte, error) {
secretNameRaw := metaObj.GetAnnotations()[cmapi.WantInjectFromSecretAnnotation]
secretName := splitNamespacedName(secretNameRaw)
log = log.WithValues("secret", secretName)
if secretName.Namespace == "" {
log.Error(nil, "invalid certificate name")
// TODO: should we return error here to prevent the caller from proceeding?
// don't return an error, requeuing won't help till this is changed
return nil, nil
}
if namespace != "" && secretName.Namespace != namespace {
err := fmt.Errorf("cannot read CA data from Secret in namespace %s, cainjector is scoped to namespace %s", secretName.Namespace, namespace)
forbidenErr := apierrors.NewForbidden(cmapi.Resource("certificates"), secretName.Name, err)
log.Error(forbidenErr, "cannot read data source")
return nil, forbidenErr
}
// grab the associated secret
var secret corev1.Secret
if err := c.client.Get(ctx, secretName, &secret); err != nil {