1 package clientctl
2
3 import (
4 "context"
5 "fmt"
6 "strings"
7
8 "golang.org/x/crypto/bcrypt"
9 apiv1 "k8s.io/api/core/v1"
10 ctrl "sigs.k8s.io/controller-runtime"
11 logger "sigs.k8s.io/controller-runtime/pkg/log"
12
13 api "edge-infra.dev/pkg/edge/iam/api/v1alpha1"
14 iamclient "edge-infra.dev/pkg/edge/iam/client"
15 "edge-infra.dev/pkg/edge/iam/config"
16 )
17
18 func (r *ClientReconciler) registerClient(ctx context.Context, req ctrl.Request, client api.Client, secret *apiv1.Secret) (api.Client, error) {
19 if err := r.saveClientProfile(ctx, &client, secret); err != nil {
20 return api.MarkNotReady(client, ClientRegistrationFailed, err.Error()), err
21 }
22
23 return client, r.ensureEmptyStatusError(ctx, req, &client)
24 }
25
26 func (r *ClientReconciler) ensureEmptyStatusError(ctx context.Context, req ctrl.Request, c *api.Client) error {
27 c.Status.ReconciliationError = api.ReconciliationError{}
28 return r.updateClientStatus(ctx, req, c.Status)
29 }
30
31 func (r *ClientReconciler) saveClientProfile(ctx context.Context, client *api.Client, secret *apiv1.Secret) error {
32 log := logger.FromContext(ctx)
33
34 clientID := string(secret.Data["client_id"])
35 clientProfile := &iamclient.Profile{
36 ClientName: client.Spec.ClientName,
37 Name: client.Name,
38 Owner: fmt.Sprintf("%s/%s", client.Name, client.Namespace),
39 RedirectURIs: client.Spec.RedirectURIs,
40 PrintBarcodeURI: client.Spec.PrintBarcodeURI,
41 PrintBarcodeTypes: client.Spec.PrintBarcodeTypes,
42 GrantTypes: client.Spec.GrantTypes,
43 ResponseTypes: client.Spec.ResponseTypes,
44 ResponseModes: client.Spec.ResponseModes,
45 Roles: client.Spec.Roles,
46 Scopes: strings.Split(client.Spec.Scope, " "),
47 }
48 storage, err := getClientStorer(log)
49 if err != nil {
50 return err
51 }
52 _, saveErr := storage.SaveClientProfile(ctx, clientID, clientProfile)
53
54 if saveErr != nil {
55 log.Error(saveErr, "failed to save client profile to db", "id", clientID)
56 return saveErr
57 }
58
59 return nil
60 }
61
62
63 func (r *ClientReconciler) unregisterClient(ctx context.Context, req ctrl.Request) error {
64 log := logger.FromContext(ctx)
65 _, err := isCouchDBUp()
66 if err != nil {
67 return err
68 }
69 storage, err := getClientStorer(log)
70 if err != nil {
71 return err
72 }
73 owner := fmt.Sprintf("%s/%s", req.Name, req.Namespace)
74
75 clients, err := storage.GetClients(ctx, owner)
76 if err != nil {
77 return err
78 }
79
80 for _, c := range clients {
81 if err := storage.DeleteClient(ctx, c.ID); err != nil {
82 log.Info("failed to delete client from db", "id", c.ID)
83 return err
84 }
85 }
86
87 return nil
88 }
89
90 func (r *ClientReconciler) saveClientCredentials(ctx context.Context, secret *apiv1.Secret) error {
91 log := logger.FromContext(ctx)
92 clientSecret, _ := bcrypt.GenerateFromPassword(secret.Data["client_secret"], config.BcryptCost())
93 clientID := string(secret.Data["client_id"])
94
95 credsDB := &iamclient.Credentials{
96 Secret: string(clientSecret),
97 }
98 storage, err := getClientStorer(log)
99 if err != nil {
100 return err
101 }
102 _, err = storage.SaveClientCredentials(ctx, clientID, credsDB)
103 if err != nil {
104 return fmt.Errorf("failed to save client credentials of '%v' to db, due to %v", clientID, err.Error())
105 }
106
107 log.Info("successfully saved client credentials to db", "id", clientID)
108
109 return nil
110 }
111
View as plain text