Skip to content
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

feat(cert-manager): additional options for targeting WebhookConfigurations and CRDs #1276

Merged
merged 26 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
03e4160
added interface for resource retrieval
bacherfl Apr 24, 2023
d8dbd88
added implementation for resource retriever
bacherfl Apr 24, 2023
670f080
implementation of resource name and label selector retrievers
bacherfl Apr 24, 2023
6b776d7
make use of new retriever interface in certificate controller
bacherfl Apr 24, 2023
c243dfd
adapted unit tests
bacherfl Apr 24, 2023
05b4eec
added library for watching certificate secret and registering webhooks
bacherfl Apr 25, 2023
b735f92
Merge branch 'main' into feat/cert-operator-config
bacherfl Apr 27, 2023
fbf4fdf
fix linting issues
bacherfl Apr 27, 2023
06ed238
initialize reconciler using New() method
bacherfl Apr 27, 2023
e7b5db5
Merge branch 'main' into feat/cert-operator-config
bacherfl Apr 27, 2023
8797b1b
adapt filter predicate
bacherfl Apr 27, 2023
a479586
Merge remote-tracking branch 'origin/feat/cert-operator-config' into …
bacherfl Apr 27, 2023
2641231
fix linting error
bacherfl Apr 27, 2023
b1d094f
adapted readme
bacherfl Apr 27, 2023
5d2669a
Merge remote-tracking branch 'upstream/main' into feat/cert-operator-…
bacherfl Apr 28, 2023
774a16f
clean up dependencies
bacherfl Apr 28, 2023
7b30f07
adapted readme
bacherfl Apr 28, 2023
cd461b7
markdown lint
bacherfl Apr 28, 2023
fe7bf2e
markdown lint
bacherfl Apr 28, 2023
534ea14
markdown lint
bacherfl Apr 28, 2023
329c246
Merge branch 'main' into feat/cert-operator-config
bacherfl May 3, 2023
78ffedc
updated dependencies
bacherfl May 3, 2023
2f63552
Merge remote-tracking branch 'upstream/main' into feat/cert-operator-…
bacherfl May 3, 2023
2990829
added comment
bacherfl May 3, 2023
715d230
Merge branch 'main' into feat/cert-operator-config
bacherfl May 3, 2023
bd7d39c
fix typo
bacherfl May 4, 2023
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
259 changes: 258 additions & 1 deletion klt-cert-manager/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# klt-cert-manager

The Keptn certificate manager ensures that the webhooks in the Lifecycle Toolkit operator can obtain a valid certificate
The Keptn certificate manager ensures that the webhooks of an operator can obtain a valid certificate
to access the Kubernetes API server.

## Description
Expand All @@ -9,6 +9,263 @@ This `klt-cert-manager` operator should only be installed when paired with the L
or above.
The TLS certificate is mounted as a volume in the LT operator pod and is renewed every 12 hours or every time the LT
operator deployment changes.
THe `klt-cert-manager` retrieves all `MutatingWebhookConfigurations`, `ValidatingWebhookConfigurations` and
bacherfl marked this conversation as resolved.
Show resolved Hide resolved
`CustomResourceDefinitions` based on a label selector that can be defined using the following environment variables:

- `LABEL_SELECTOR_KEY`: Label key used or identifying resources for certificate injection.
Default: `keptn.sh/inject-cert`
- `LABEL_SELECTOR_VALUE`: Label value used for identifying resources for certificate injection.
Default: `true`.

Using these label selectors, `MutatingWebhookConfigurations`, `ValidatingWebhookConfigurations` and
`CustomResourceDefinitions` can be enabled for certificate injection by adding the required labels to their metadata:

````yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
labels:
keptn.sh/inject-cert: true
name: keptnconfigs.options.keptn.sh
````

## Using the klt-cert-manager library

The functionality provided by this operator can also be added to other operators by using the `klt-cert-manager` as
a library.
To do this, add the library as a dependency to your application:

```shell
go get github.com/keptn/lifecycle-toolkit/klt-cert-manager
```

Then, in your operator's setup logic, an instance of the `KeptnWebhookCertificateReconciler` can be
created and registered to your operator's controller manager:

```golang
package main

import (
"flag"
"log"
"os"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

"github.com/keptn/lifecycle-toolkit/klt-cert-manager/controllers/keptnwebhookcontroller"
"github.com/keptn/lifecycle-toolkit/klt-cert-manager/pkg/webhook"
// +kubebuilder:scaffold:imports
)

func main() {
// operator setup ...
certificateReconciler := keptnwebhookcontroller.NewReconciler(keptnwebhookcontroller.CertificateReconcilerConfig{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.Log.WithName("KeptnWebhookCert Controller"),
Namespace: "my-namespace",
MatchLabels: map[string]string{
"inject-cert": "true",
},
})
if err = certificateReconciler.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Deployment")
os.Exit(1)
}
//...
// register mutating/validating webhooks
webhookBuilder := webhook.NewWebhookBuilder().
SetNamespace(env.PodNamespace).
SetPodName(env.PodName).
SetConfigProvider(cmdConfig.NewKubeConfigProvider())

setupLog.Info("starting webhook and manager")
if err := webhookBuilder.Run(mgr, map[string]*admission.Webhook{
"/webhook-path": &webhook.Admission{},
}); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}
```

Using this approach will require the following `ClusterRole` permissions to be bound to your operator's ServiceAccount:

```yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: certificate-operator-role
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: certificate-operator-role
namespace: my-operator-system
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
```

The required permissions can also be reduced by only allowing access to a specific set of resources, by providing
the `KeptnWebhookCertificateReconciler` with a list of resources that should by enabled for certificate injection,
instead of specifying the `MatchLabels`:

```golang
package main

import (
"flag"
"log"
"os"

"github.com/keptn/lifecycle-toolkit/klt-cert-manager/controllers/keptnwebhookcontroller"
// +kubebuilder:scaffold:imports
)

func main() {
// operator setup ...
certificateReconciler := keptnwebhookcontroller.NewReconciler(keptnwebhookcontroller.CertificateReconcilerConfig{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.Log.WithName("KeptnWebhookCert Controller"),
Namespace: "my-namespace",
WatchResources: &keptnwebhookcontroller.ObservedObjects{
MutatingWebhooks: []string{"my-mwh-1", "my-mwh-2"},
ValidatingWebhooks: []string{"my-vwh-1", "my-vwh-2"},
CustomResourceDefinitions: []string{"my-crd-1", "my-crd-2"},
Deployments: []string{"my-operator-deployment"},
},
})
if err = certificateReconciler.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Deployment")
os.Exit(1)
}
//...
}
```

Using this configuration, you can limit the required permissions as follows:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: certificate-operator-role
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
verbs:
- get
- patch
- update
- watch
resourceNames:
- my-mwh-1
- my-mwh-2
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- patch
- update
- watch
resourceNames:
- my-vwh-1
- my-vwh-2
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- patch
- update
- watch
resourceNames:
- my-crd-1
- my-crd-2
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: certificate-operator-role
namespace: my-operator-system
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
```

## Getting Started

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/go-logr/logr"
"github.com/keptn/lifecycle-toolkit/klt-cert-manager/kubeutils"
"github.com/keptn/lifecycle-toolkit/klt-cert-manager/pkg/common"
"github.com/pkg/errors"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -76,7 +77,7 @@ func (certSecret *certificateSecret) setCertificates(namespace string) error {
}

func buildSecretName() string {
return secretName
return common.SecretName
}

func getDomain(namespace string) string {
Expand Down Expand Up @@ -117,7 +118,7 @@ func (certSecret *certificateSecret) createOrUpdateIfNecessary(ctx context.Conte
func (certSecret *certificateSecret) loadCombinedBundle() ([]byte, error) {
data, hasData := certSecret.secret.Data[RootCert]
if !hasData {
return nil, errors.New(certificatesSecretEmptyErr)
return nil, errors.New(common.CertificatesSecretEmptyErr)
}

if oldData, hasOldData := certSecret.secret.Data[RootCertOld]; hasOldData {
Expand Down
12 changes: 0 additions & 12 deletions klt-cert-manager/controllers/keptnwebhookcontroller/config.go

This file was deleted.

Loading