mirror of
https://forge.liiib.re/indiehost/libre.sh/libre.sh.git
synced 2024-12-28 14:46:41 +00:00
feat(realm): configure smtp settings
This commit is contained in:
parent
3ea48d2908
commit
bf053d6598
4 changed files with 80 additions and 0 deletions
|
@ -19,6 +19,7 @@ package v1alpha1
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
lshmeta "libre.sh/api/meta/v1alpha1"
|
lshmeta "libre.sh/api/meta/v1alpha1"
|
||||||
|
@ -83,6 +84,8 @@ type RealmSpec struct {
|
||||||
// Disable brute force
|
// Disable brute force
|
||||||
// +kubebuilder:validation:Optional
|
// +kubebuilder:validation:Optional
|
||||||
DisableBruteForce bool `json:"disableBruteForce,omitempty"`
|
DisableBruteForce bool `json:"disableBruteForce,omitempty"`
|
||||||
|
//+kubebuilder:validation:Required
|
||||||
|
MailboxRef corev1.LocalObjectReference `json:"mailboxRef"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RealmStatus defines the observed state of Realm
|
// RealmStatus defines the observed state of Realm
|
||||||
|
|
|
@ -110,6 +110,7 @@ func (in *RealmSpec) DeepCopyInto(out *RealmSpec) {
|
||||||
out.Spec = in.Spec
|
out.Spec = in.Spec
|
||||||
out.Themes = in.Themes
|
out.Themes = in.Themes
|
||||||
in.Locale.DeepCopyInto(&out.Locale)
|
in.Locale.DeepCopyInto(&out.Locale)
|
||||||
|
out.MailboxRef = in.MailboxRef
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RealmSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RealmSpec.
|
||||||
|
|
|
@ -79,6 +79,16 @@ spec:
|
||||||
default: fr
|
default: fr
|
||||||
type: string
|
type: string
|
||||||
type: object
|
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:
|
metrics:
|
||||||
description: Are metrics enabled
|
description: Are metrics enabled
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -105,6 +115,8 @@ spec:
|
||||||
description: Theme name for Login page
|
description: Theme name for Login page
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- mailboxRef
|
||||||
type: object
|
type: object
|
||||||
status:
|
status:
|
||||||
description: RealmStatus defines the observed state of Realm
|
description: RealmStatus defines the observed state of Realm
|
||||||
|
|
|
@ -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 what do we do with OIDCClient and SAMLCLient ? should we delete them when realm is deleted
|
||||||
// TODO delete Realm in keycloak
|
// TODO delete Realm in keycloak
|
||||||
return lshr.Finalize(ctx, r, patcher, &realm, func() error {
|
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" {
|
if realm.Annotations != nil && realm.Annotations["realm.keycloak.libre.sh/delete-protection"] == "true" {
|
||||||
r.log.Info("resource is protected")
|
r.log.Info("resource is protected")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -120,6 +133,39 @@ func (r *RealmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
|
||||||
}
|
}
|
||||||
|
|
||||||
MutateRealmRepresentation(realm, realmRepresentation)
|
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)
|
err = keycloakClient.UpdateRealm(ctx, keycloakClient.AccessToken(), *realmRepresentation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return internal.HandleError(ctx, r, patcher, &realm, err)
|
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 {
|
func (r *RealmReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
return ctrl.NewControllerManagedBy(mgr).
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
For(&keycloakv1alpha1.Realm{}).
|
For(&keycloakv1alpha1.Realm{}).
|
||||||
|
Owns(&lshcore.Mailbox{}).
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,6 +642,23 @@ func contains(s []string, str string) bool {
|
||||||
return false
|
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) {
|
func MutateRealmRepresentation(realm keycloakv1alpha1.Realm, realmRepresentation *gocloak.RealmRepresentation) {
|
||||||
realmName := realm.GetRealmName()
|
realmName := realm.GetRealmName()
|
||||||
realmRepresentation.Realm = &realmName
|
realmRepresentation.Realm = &realmName
|
||||||
|
|
Loading…
Reference in a new issue