...
1 package services
2
3 import (
4 "context"
5 "net/http"
6 "strings"
7
8 "sigs.k8s.io/controller-runtime/pkg/client"
9
10 "github.com/gin-gonic/gin"
11
12 "edge-infra.dev/pkg/edge/device-registrar/config"
13
14 api "edge-infra.dev/pkg/edge/device-registrar/api/v1alpha1"
15 )
16
17
18
19 type DiscoverServiceResponse struct {
20
21 Name string `json:"name"`
22
23 URL *string `json:"url"`
24 }
25
26
27
28 type DiscoverInput struct {
29 Name string `uri:"serviceName" binding:"required"`
30 }
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 func DiscoverService(c *gin.Context) {
48 k8sClient, ctx, cancel := config.GetClientandContext(c)
49 defer cancel()
50
51
52 clientDN := c.GetHeader("X-Client-DN")
53 if clientDN == "" {
54 c.JSON(http.StatusUnauthorized, gin.H{"error": "X-Client-DN is required"})
55 return
56 }
57
58
59 serialNumber := parseSerialNumber(clientDN)
60 if serialNumber == "" {
61 c.JSON(http.StatusUnauthorized, gin.H{"error": "Serial Number is required in X-Client-DN"})
62 return
63 }
64
65
66 if !isSNAuthorized(ctx, k8sClient, serialNumber) {
67 c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized Serial Number"})
68 return
69 }
70
71 var serviceName DiscoverInput
72 if err := c.ShouldBindUri(&serviceName); err != nil {
73 c.JSON(http.StatusBadRequest, gin.H{"error": "serviceName is required"})
74 return
75 }
76
77 discoveryList := &api.DiscoveryList{}
78 err := k8sClient.List(ctx, discoveryList)
79 if err != nil {
80 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
81 return
82 }
83
84 configURL := ""
85 for i := range discoveryList.Items {
86 service := discoveryList.Items[i]
87 if service.Spec.Name == serviceName.Name {
88 configURL = service.Spec.URL
89 break
90 }
91 }
92
93 resp := DiscoverServiceResponse{
94 Name: serviceName.Name,
95 URL: &configURL,
96 }
97
98 if configURL == "" {
99 resp.URL = nil
100 }
101
102 c.JSON(http.StatusOK, resp)
103 }
104
105
106 func parseSerialNumber(dn string) string {
107 parts := strings.Split(dn, "+")
108 for _, part := range parts {
109 if strings.HasPrefix(part, "OU=urn:SN:") {
110 return strings.TrimSpace(strings.TrimPrefix(part, "OU=urn:SN:"))
111 }
112 }
113 return ""
114 }
115
116
117 func isSNAuthorized(ctx context.Context, k8sClient client.Client, sn string) bool {
118
119 deviceList := &api.ExternalDeviceList{}
120 err := k8sClient.List(ctx, deviceList)
121 if err != nil {
122 return false
123 }
124
125
126 if len(deviceList.Items) == 0 {
127 return false
128 }
129
130
131 for _, device := range deviceList.Items {
132 if sn == device.Spec.SN {
133 return true
134 }
135 }
136 return false
137 }
138
View as plain text