package clientctl import ( "context" "fmt" "strings" "golang.org/x/crypto/bcrypt" apiv1 "k8s.io/api/core/v1" ctrl "sigs.k8s.io/controller-runtime" logger "sigs.k8s.io/controller-runtime/pkg/log" api "edge-infra.dev/pkg/edge/iam/api/v1alpha1" iamclient "edge-infra.dev/pkg/edge/iam/client" "edge-infra.dev/pkg/edge/iam/config" ) func (r *ClientReconciler) registerClient(ctx context.Context, req ctrl.Request, client api.Client, secret *apiv1.Secret) (api.Client, error) { if err := r.saveClientProfile(ctx, &client, secret); err != nil { return api.MarkNotReady(client, ClientRegistrationFailed, err.Error()), err } return client, r.ensureEmptyStatusError(ctx, req, &client) } func (r *ClientReconciler) ensureEmptyStatusError(ctx context.Context, req ctrl.Request, c *api.Client) error { c.Status.ReconciliationError = api.ReconciliationError{} return r.updateClientStatus(ctx, req, c.Status) } func (r *ClientReconciler) saveClientProfile(ctx context.Context, client *api.Client, secret *apiv1.Secret) error { log := logger.FromContext(ctx) clientID := string(secret.Data["client_id"]) clientProfile := &iamclient.Profile{ ClientName: client.Spec.ClientName, Name: client.Name, Owner: fmt.Sprintf("%s/%s", client.Name, client.Namespace), RedirectURIs: client.Spec.RedirectURIs, PrintBarcodeURI: client.Spec.PrintBarcodeURI, PrintBarcodeTypes: client.Spec.PrintBarcodeTypes, GrantTypes: client.Spec.GrantTypes, ResponseTypes: client.Spec.ResponseTypes, ResponseModes: client.Spec.ResponseModes, Roles: client.Spec.Roles, Scopes: strings.Split(client.Spec.Scope, " "), } storage, err := getClientStorer(log) if err != nil { return err } _, saveErr := storage.SaveClientProfile(ctx, clientID, clientProfile) if saveErr != nil { log.Error(saveErr, "failed to save client profile to db", "id", clientID) return saveErr } return nil } // unregisterClient will delete the client that has the same owner as the one in the reconcile request func (r *ClientReconciler) unregisterClient(ctx context.Context, req ctrl.Request) error { log := logger.FromContext(ctx) _, err := isCouchDBUp() if err != nil { return err } storage, err := getClientStorer(log) if err != nil { return err } owner := fmt.Sprintf("%s/%s", req.Name, req.Namespace) clients, err := storage.GetClients(ctx, owner) if err != nil { return err } for _, c := range clients { if err := storage.DeleteClient(ctx, c.ID); err != nil { log.Info("failed to delete client from db", "id", c.ID) return err } } return nil } func (r *ClientReconciler) saveClientCredentials(ctx context.Context, secret *apiv1.Secret) error { log := logger.FromContext(ctx) clientSecret, _ := bcrypt.GenerateFromPassword(secret.Data["client_secret"], config.BcryptCost()) clientID := string(secret.Data["client_id"]) credsDB := &iamclient.Credentials{ Secret: string(clientSecret), } storage, err := getClientStorer(log) if err != nil { return err } _, err = storage.SaveClientCredentials(ctx, clientID, credsDB) if err != nil { return fmt.Errorf("failed to save client credentials of '%v' to db, due to %v", clientID, err.Error()) } log.Info("successfully saved client credentials to db", "id", clientID) return nil }