feat(realm): configure smtp settings

This commit is contained in:
unteem 2024-04-26 13:22:28 +02:00
parent 3ea48d2908
commit bf053d6598
4 changed files with 80 additions and 0 deletions

View file

@ -19,6 +19,7 @@ package v1alpha1
import (
"fmt"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
lshmeta "libre.sh/api/meta/v1alpha1"
@ -83,6 +84,8 @@ type RealmSpec struct {
// Disable brute force
// +kubebuilder:validation:Optional
DisableBruteForce bool `json:"disableBruteForce,omitempty"`
//+kubebuilder:validation:Required
MailboxRef corev1.LocalObjectReference `json:"mailboxRef"`
}
// RealmStatus defines the observed state of Realm

View file

@ -110,6 +110,7 @@ func (in *RealmSpec) DeepCopyInto(out *RealmSpec) {
out.Spec = in.Spec
out.Themes = in.Themes
in.Locale.DeepCopyInto(&out.Locale)
out.MailboxRef = in.MailboxRef
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RealmSpec.

View file

@ -79,6 +79,16 @@ spec:
default: fr
type: string
type: object
mailboxRef:
description: LocalObjectReference contains enough information to let
you locate the referenced object inside the same namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
metrics:
description: Are metrics enabled
type: boolean
@ -105,6 +115,8 @@ spec:
description: Theme name for Login page
type: string
type: object
required:
- mailboxRef
type: object
status:
description: RealmStatus defines the observed state of Realm

View file

@ -77,10 +77,23 @@ func (r *RealmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
// TODO what do we do with OIDCClient and SAMLCLient ? should we delete them when realm is deleted
// TODO delete Realm in keycloak
return lshr.Finalize(ctx, r, patcher, &realm, func() error {
var mailbox lshcore.Bucket
mailbox.Name = realm.Spec.MailboxRef.Name
mailbox.Namespace = realm.Namespace
err := r.Get(ctx, client.ObjectKeyFromObject(&mailbox), &mailbox)
if err != nil {
return client.IgnoreNotFound(err)
}
err = lshr.UnsetControllerReference(ctx, r, &realm, &mailbox)
if err != nil {
return err
}
if realm.Annotations != nil && realm.Annotations["realm.keycloak.libre.sh/delete-protection"] == "true" {
r.log.Info("resource is protected")
return nil
}
return nil
})
}
@ -120,6 +133,39 @@ func (r *RealmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
}
MutateRealmRepresentation(realm, realmRepresentation)
mailbox := &lshcore.Mailbox{}
mailbox.Namespace = realm.Namespace
mailbox.Name = realm.Spec.MailboxRef.Name
err = r.Get(ctx, client.ObjectKeyFromObject(mailbox), mailbox)
if err != nil {
return ctrl.Result{}, err
}
mailbox.ManagedFields = nil
controllerutil.SetOwnerReference(&realm, mailbox, r.Scheme())
opts := []client.PatchOption{
client.FieldOwner(r.Name()),
}
err = r.Patch(ctx, mailbox, client.Apply, opts...)
if err != nil {
return ctrl.Result{}, err
}
mailboxSecret := corev1.Secret{}
mailboxSecret.Name = mailbox.SecretName()
mailboxSecret.Namespace = mailbox.Namespace
err = r.Get(ctx, client.ObjectKeyFromObject(&mailboxSecret), &mailboxSecret)
if err != nil {
return ctrl.Result{}, err
}
r.SetRealmSMTPSettings(ctx, realmRepresentation, mailboxSecret)
err = keycloakClient.UpdateRealm(ctx, keycloakClient.AccessToken(), *realmRepresentation)
if err != nil {
return internal.HandleError(ctx, r, patcher, &realm, err)
@ -180,6 +226,7 @@ func (r *RealmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
func (r *RealmReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&keycloakv1alpha1.Realm{}).
Owns(&lshcore.Mailbox{}).
Complete(r)
}
@ -595,6 +642,23 @@ func contains(s []string, str string) bool {
return false
}
func (r *RealmReconciler) SetRealmSMTPSettings(ctx context.Context, realmRepresentation *gocloak.RealmRepresentation, mailboxSecret corev1.Secret) {
smtp := map[string]string{
"auth": strconv.FormatBool(true),
"user": string(mailboxSecret.Data[lshmeta.SecretUsernameKey]),
"from": string(mailboxSecret.Data[lshmeta.SecretLocalPartsKey]),
"password": string(mailboxSecret.Data[lshmeta.SecretPasswordKey]),
"host": string(mailboxSecret.Data[lshmeta.SecretHostKey]),
"Host": string(mailboxSecret.Data[lshmeta.SecretHostKey]),
"port": string(mailboxSecret.Data[lshmeta.SecretPortKey]),
"Port": string(mailboxSecret.Data[lshmeta.SecretPortKey]),
// TODO should be in secret ?
"starttls": strconv.FormatBool(true),
}
realmRepresentation.SMTPServer = &smtp
}
func MutateRealmRepresentation(realm keycloakv1alpha1.Realm, realmRepresentation *gocloak.RealmRepresentation) {
realmName := realm.GetRealmName()
realmRepresentation.Realm = &realmName