1 package magpie
2
3 import (
4 "context"
5 "crypto/rsa"
6 "fmt"
7 "io"
8 "net/http"
9
10 "github.com/gin-contrib/cors"
11 "github.com/gin-contrib/requestid"
12 "github.com/gin-gonic/gin"
13 "github.com/go-logr/logr"
14 "sigs.k8s.io/controller-runtime/pkg/client"
15
16 "edge-infra.dev/pkg/edge/edgeencrypt"
17 "edge-infra.dev/pkg/lib/fog"
18 )
19
20 const (
21 DecryptionBodySize = 3
22 ChannelParam = "channel"
23 )
24
25 type Server struct {
26 cfg *Config
27 router *gin.Engine
28 metric *gin.Engine
29 client client.Client
30 decrypt edgeencrypt.DecryptFunc
31 }
32
33 func NewDecryptionServer(cfg *Config, cl client.Client, log logr.Logger, decrypt edgeencrypt.DecryptFunc) *Server {
34 router := gin.New()
35 router.ContextWithFallback = true
36
37 metric := edgeencrypt.MetricServer(router)
38
39 router.Use(requestid.New(requestid.WithCustomHeaderStrKey(edgeencrypt.CorrelationIDKey)))
40 router.Use(edgeencrypt.RequestLogger(log))
41 router.Use(gin.Recovery())
42
43
44 corsConfig := cors.DefaultConfig()
45 corsConfig.AllowAllOrigins = true
46 corsConfig.AllowHeaders = []string{"*"}
47 router.Use(cors.New(corsConfig))
48
49 router.Use(edgeencrypt.MaxRequestBodySize(edgeencrypt.EncryptionDefaultBodySize * DecryptionBodySize))
50
51 server := &Server{
52 cfg: cfg,
53 router: router,
54 metric: metric,
55 decrypt: decrypt,
56 client: cl,
57 }
58
59 router.GET("/health", func(c *gin.Context) {
60 c.String(http.StatusOK, "ok")
61 })
62
63 router.GET("/ready", func(c *gin.Context) {
64 if _, err := edgeencrypt.GetPublicKey(c, cl, cfg.Namespace, cfg.JWTSecret); err != nil {
65 _ = c.Error(fmt.Errorf("failed to get decryption public key: %w", err))
66 c.AbortWithStatus(http.StatusServiceUnavailable)
67 return
68 }
69 c.String(http.StatusOK, "ok")
70 })
71
72 router.Use(edgeencrypt.BearerToken(server.GetPublicKey, edgeencrypt.Decryption))
73
74 encrypt := router.Group("/v1/decrypt/:" + ChannelParam)
75 {
76 encrypt.POST("", server.decryptHandler)
77 }
78
79 router.NoRoute(func(c *gin.Context) {
80 c.AbortWithStatus(404)
81 })
82
83 return server
84 }
85
86 func (s *Server) Start(address, metricAddress string) error {
87 go func() {
88 if err := s.metric.Run(metricAddress); err != nil {
89 panic(fmt.Errorf("failed to start metric server: %w", err))
90 }
91 }()
92 return s.router.Run(address)
93 }
94
95 func (s *Server) decryptHandler(c *gin.Context) {
96 ctx := c.Request.Context()
97 log := fog.FromContext(ctx)
98
99 claims := edgeencrypt.ClaimsFromContext(ctx)
100 if claims == nil {
101 _ = c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("claims not found in context"))
102 return
103 }
104
105 data, err := io.ReadAll(c.Request.Body)
106 if err != nil {
107 _ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("failed to read request body: %w", err))
108 return
109 }
110
111 if len(data) == 0 {
112 _ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("body is empty"))
113 return
114 }
115
116 e := &edgeencrypt.EncryptedData{}
117 if err = e.FromDecryptionRequest(data); err != nil {
118 _ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("failed to unmarshal encrypted data: %w", err))
119 return
120 }
121
122 if err = e.Valid(); err != nil {
123 _ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid encrypted data: %w", err))
124 return
125 }
126
127 channel := c.Param(ChannelParam)
128 if e.Channel != channel {
129 _ = c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("invalid channel for encrypted data"))
130 return
131 }
132
133 res, err := edgeencrypt.DecryptData(ctx, e, claims, s.decrypt)
134 if err != nil {
135 _ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("failed to decrypt data: %w", err))
136 return
137 }
138
139 log.Info("successfully decrypted data")
140
141 c.Data(http.StatusOK, gin.MIMEPlain, res)
142 }
143
144 func (s *Server) GetPublicKey(ctx context.Context) (*rsa.PublicKey, error) {
145 pk, err := edgeencrypt.GetPublicKey(ctx, s.client, s.cfg.Namespace, s.cfg.JWTSecret)
146 if err != nil {
147 return nil, fmt.Errorf("failed to get decryption jwt public key: %w", err)
148 }
149 return pk.ToRSAPublicKey()
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 type decryptedTextResponse struct {
187
188
189 Body string
190 }
191
View as plain text