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

Add support for using cert manager to generate webhook certificates #2373

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions charts/spark-operator-chart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall) for command docum
| webhook.portName | string | `"webhook"` | Specifies webhook service port name. |
| webhook.failurePolicy | string | `"Fail"` | Specifies how unrecognized errors are handled. Available options are `Ignore` or `Fail`. |
| webhook.timeoutSeconds | int | `10` | Specifies the timeout seconds of the webhook, the value must be between 1 and 30. |
| webhook.certManager.enable | bool | `false` | Specifies whether to use cert-manager to generate certificates for webhook. |
| webhook.certManager.issuerRef | object | `{}` | The reference to the issuer. |
| webhook.certManager.duration | string | `""` | The duration of the certificate validity. |
| webhook.certManager.renewBefore | string | `""` | The duration before the certificate expiration to renew the certificate. |
| webhook.resourceQuotaEnforcement.enable | bool | `false` | Specifies whether to enable the ResourceQuota enforcement for SparkApplication resources. |
| webhook.serviceAccount.create | bool | `true` | Specifies whether to create a service account for the webhook. |
| webhook.serviceAccount.name | string | `""` | Optional name for the webhook service account. |
Expand Down
6 changes: 6 additions & 0 deletions charts/spark-operator-chart/templates/webhook/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ Create the name of the secret to be used by webhook
{{ include "spark-operator.webhook.name" . }}-certs
{{- end -}}

{{/*
Create the name of the certificate to be used by webhook
*/}}
{{- define "spark-operator.webhook.certificateName" -}}
{{ include "spark-operator.webhook.name" . }}-certificate
{{- end -}}

{{/*
Create the name of the service to be used by webhook
Expand Down
48 changes: 48 additions & 0 deletions charts/spark-operator-chart/templates/webhook/certificate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{{/*
Copyright 2024 The Kubeflow authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}

{{- if and .Values.webhook.enable .Values.webhook.certManager.enable }}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "spark-operator.webhook.certificateName" . }}
labels:
{{- include "spark-operator.labels" . | nindent 4 }}
spec:
secretName: {{ include "spark-operator.webhook.secretName" . }}
{{- with .Values.webhook.certManager.issuerRef }}
issuerRef:
{{- toYaml . | nindent 4 }}
{{- else }}
{{ fail "webhook.certManager.issuerRef is required when certManager is enabled"}}
{{- end }}
commonName: {{ include "spark-operator.webhook.serviceName" . }}.{{ .Release.Namespace }}.svc
dnsNames:
- {{ include "spark-operator.webhook.serviceName" . }}.svc
- {{ include "spark-operator.webhook.serviceName" . }}.svc.cluster.local
subject:
organizationalUnits:
- spark-operator
usages:
- server auth
- client auth
{{- with .Values.webhook.certManager.duration }}
duration: {{ . }}
{{- end }}
{{- with .Values.webhook.certManager.renewBefore }}
renewBefore: {{ . }}
{{- end }}
{{- end }}
12 changes: 12 additions & 0 deletions charts/spark-operator-chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,18 @@ webhook:
# -- Specifies the timeout seconds of the webhook, the value must be between 1 and 30.
timeoutSeconds: 10

certManager:
# -- Specifies whether to use cert-manager to generate certificates for webhook.
enable: false
# -- The reference to the issuer.
issuerRef: {}
# name: selfsigned
# kind: ClusterIssuer
# -- The duration of the certificate validity.
duration: ""
# -- The duration before the certificate expiration to renew the certificate.
renewBefore: ""

resourceQuotaEnforcement:
# -- Specifies whether to enable the ResourceQuota enforcement for SparkApplication resources.
enable: false
Expand Down
1 change: 0 additions & 1 deletion cmd/operator/webhook/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ func start() {
Jitter: 0.1,
},
func() (bool, error) {
logger.Info("Syncing webhook secret", "name", webhookSecretName, "namespace", webhookSecretNamespace)
if err := certProvider.SyncSecret(context.TODO(), webhookSecretName, webhookSecretNamespace); err != nil {
if errors.IsAlreadyExists(err) || errors.IsConflict(err) {
return false, nil
Expand Down
20 changes: 20 additions & 0 deletions pkg/certificate/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/cert"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/kubeflow/spark-operator/pkg/common"
Expand Down Expand Up @@ -63,6 +64,9 @@ func NewProvider(client client.Client, name, namespace string) *Provider {

// SyncSecret syncs the secret containing the certificates to the given name and namespace.
func (cp *Provider) SyncSecret(ctx context.Context, name, namespace string) error {
logger := ctrl.LoggerFrom(ctx, "name", name, "namespace", namespace)
logger.Info("Syncing webhook secret")

secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Expand All @@ -73,10 +77,13 @@ func (cp *Provider) SyncSecret(ctx context.Context, name, namespace string) erro
Name: name,
Namespace: namespace,
}

if err := cp.client.Get(ctx, key, secret); err != nil {
if !errors.IsNotFound(err) {
return err
}

logger.Info("Creating secret as it does not exist")
if err := cp.client.Create(ctx, secret); err != nil {
if errors.IsAlreadyExists(err) {
return err
Expand Down Expand Up @@ -194,6 +201,9 @@ func (cp *Provider) WriteFile(path, certName, keyName string) error {
}

func (cp *Provider) Generate() error {
logger := ctrl.Log.WithName("")
logger.Info("Generating certificates.")

// Generate CA private caKey
caKey, err := NewPrivateKey()
if err != nil {
Expand Down Expand Up @@ -277,22 +287,32 @@ func (cp *Provider) parseSecret(secret *corev1.Secret) error {
}

func (cp *Provider) updateSecret(ctx context.Context, secret *corev1.Secret) error {
if secret == nil {
return fmt.Errorf("secret is nil")
}

caKey, err := cp.CAKey()
if err != nil {
return fmt.Errorf("failed to get CA key: %v", err)
}

caCert, err := cp.CACert()
if err != nil {
return fmt.Errorf("failed to get CA certificate: %v", err)
}

serverKey, err := cp.ServerKey()
if err != nil {
return fmt.Errorf("failed to get server key: %v", err)
}

serverCert, err := cp.ServerCert()
if err != nil {
return fmt.Errorf("failed to get server certificate: %v", err)
}

logger := ctrl.LoggerFrom(ctx, "name", secret.Name, "namespace", secret.Namespace)
logger.Info("Updating secret")
if secret.Data == nil {
secret.Data = make(map[string][]byte)
}
Expand Down
Loading