Skip to content

Commit 4c67c93

Browse files
committed
fix(services): add timeouts and encode error handling
1 parent cde92dd commit 4c67c93

File tree

3 files changed

+83
-23
lines changed

3 files changed

+83
-23
lines changed

services/authz/server/server.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,12 @@ func New(cfg Config) (*Server, error) {
163163
}
164164

165165
s.httpSrv = &http.Server{
166-
Addr: cfg.HTTPAddr,
167-
Handler: r,
166+
Addr: cfg.HTTPAddr,
167+
Handler: r,
168+
ReadHeaderTimeout: 10 * time.Second,
169+
ReadTimeout: 30 * time.Second,
170+
WriteTimeout: 30 * time.Second,
171+
IdleTimeout: 60 * time.Second,
168172
TLSConfig: &tls.Config{
169173
Certificates: []tls.Certificate{cert},
170174
ClientAuth: tls.NoClientCert,
@@ -175,7 +179,14 @@ func New(cfg Config) (*Server, error) {
175179
s.useTLS = true
176180
s.rootCAPEM = rootCAPEM
177181
} else {
178-
s.httpSrv = &http.Server{Addr: cfg.HTTPAddr, Handler: r}
182+
s.httpSrv = &http.Server{
183+
Addr: cfg.HTTPAddr,
184+
Handler: r,
185+
ReadHeaderTimeout: 10 * time.Second,
186+
ReadTimeout: 30 * time.Second,
187+
WriteTimeout: 30 * time.Second,
188+
IdleTimeout: 60 * time.Second,
189+
}
179190
var err error
180191
s.rootCAPEM, err = ca.CertificatePEM()
181192
if err != nil {
@@ -185,7 +196,13 @@ func New(cfg Config) (*Server, error) {
185196

186197
// Set up Tailscale HTTP server if Tailscale is configured
187198
if tailscaleListener != nil {
188-
s.tsHTTP = &http.Server{Handler: r}
199+
s.tsHTTP = &http.Server{
200+
Handler: r,
201+
ReadHeaderTimeout: 10 * time.Second,
202+
ReadTimeout: 30 * time.Second,
203+
WriteTimeout: 30 * time.Second,
204+
IdleTimeout: 60 * time.Second,
205+
}
189206
s.tsListener = tailscaleListener
190207
log.Printf("Tailscale HTTP server configured on %s", tailscaleListener.Addr().String())
191208
}
@@ -248,7 +265,9 @@ func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) {
248265

249266
w.Header().Set("Content-Type", "application/json")
250267
w.WriteHeader(http.StatusOK)
251-
json.NewEncoder(w).Encode(health)
268+
if err := json.NewEncoder(w).Encode(health); err != nil {
269+
log.Printf("failed to encode health response: %v", err)
270+
}
252271
}
253272

254273
type verifyRequest struct {
@@ -285,7 +304,9 @@ func (s *Server) verifyHandler(w http.ResponseWriter, r *http.Request) {
285304
return
286305
}
287306

288-
json.NewEncoder(w).Encode(verifyResponse{Decision: decision})
307+
if err := json.NewEncoder(w).Encode(verifyResponse{Decision: decision}); err != nil {
308+
log.Printf("failed to encode verify response: %v", err)
309+
}
289310
}
290311

291312
func (s *Server) envoyAuthHandler(w http.ResponseWriter, r *http.Request) {
@@ -364,7 +385,9 @@ func (s *Server) envoyAuthHandler(w http.ResponseWriter, r *http.Request) {
364385
"device_id": deviceID,
365386
"session_id": middleware.GetReqID(r.Context()),
366387
}
367-
json.NewEncoder(w).Encode(response)
388+
if err := json.NewEncoder(w).Encode(response); err != nil {
389+
log.Printf("failed to encode envoy auth response: %v", err)
390+
}
368391
default:
369392
http.Error(w, "forbidden", http.StatusForbidden)
370393
}
@@ -587,7 +610,9 @@ func (s *Server) deviceCertHandler(w http.ResponseWriter, r *http.Request) {
587610
return
588611
}
589612

590-
json.NewEncoder(w).Encode(map[string]any{"certificate": string(certPEM)})
613+
if err := json.NewEncoder(w).Encode(map[string]any{"certificate": string(certPEM)}); err != nil {
614+
log.Printf("failed to encode device cert response: %v", err)
615+
}
591616
}
592617

593618
func (s *Server) caHandler(w http.ResponseWriter, r *http.Request) {
@@ -597,7 +622,9 @@ func (s *Server) caHandler(w http.ResponseWriter, r *http.Request) {
597622
}
598623
w.Header().Set("Content-Type", "application/x-pem-file")
599624
w.WriteHeader(http.StatusOK)
600-
w.Write(s.rootCAPEM)
625+
if _, err := w.Write(s.rootCAPEM); err != nil {
626+
log.Printf("failed to write CA response: %v", err)
627+
}
601628
}
602629

603630
func decodePEMBlock(p string) ([]byte, error) {
@@ -751,7 +778,9 @@ func (s *Server) tailscaleStatusHandler(w http.ResponseWriter, r *http.Request)
751778
status := s.getTailscaleInfo()
752779
w.Header().Set("Content-Type", "application/json")
753780
w.WriteHeader(http.StatusOK)
754-
json.NewEncoder(w).Encode(status)
781+
if err := json.NewEncoder(w).Encode(status); err != nil {
782+
log.Printf("failed to encode tailscale status: %v", err)
783+
}
755784
}
756785

757786
// loggingMiddleware provides structured logging for all requests

services/inventory/server/server.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,14 @@ func NewServer(cfg Config) (*Server, error) {
8282
})
8383
})
8484

85-
s.http = &http.Server{Addr: cfg.Addr, Handler: r}
85+
s.http = &http.Server{
86+
Addr: cfg.Addr,
87+
Handler: r,
88+
ReadHeaderTimeout: 10 * time.Second,
89+
ReadTimeout: 30 * time.Second,
90+
WriteTimeout: 30 * time.Second,
91+
IdleTimeout: 60 * time.Second,
92+
}
8693
return s, nil
8794
}
8895

@@ -185,7 +192,9 @@ func (s *Server) requireClientCertMiddleware(next http.Handler) http.Handler {
185192

186193
func (s *Server) health(w http.ResponseWriter, r *http.Request) {
187194
w.WriteHeader(http.StatusOK)
188-
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
195+
if err := json.NewEncoder(w).Encode(map[string]string{"status": "ok"}); err != nil {
196+
log.Printf("failed to encode health response: %v", err)
197+
}
189198
}
190199

191200
// updateDevicePosture handles posture update requests
@@ -209,7 +218,9 @@ func (s *Server) updateDevicePosture(w http.ResponseWriter, r *http.Request) {
209218
http.Error(w, "db error", http.StatusInternalServerError)
210219
return
211220
}
212-
json.NewEncoder(w).Encode(map[string]string{"status": "updated"})
221+
if err := json.NewEncoder(w).Encode(map[string]string{"status": "updated"}); err != nil {
222+
log.Printf("failed to encode posture update response: %v", err)
223+
}
213224
}
214225

215226
type Device struct {
@@ -252,7 +263,9 @@ func (s *Server) listDevices(w http.ResponseWriter, r *http.Request) {
252263
list = append(list, d)
253264
}
254265

255-
json.NewEncoder(w).Encode(list)
266+
if err := json.NewEncoder(w).Encode(list); err != nil {
267+
log.Printf("failed to encode list devices response: %v", err)
268+
}
256269
}
257270

258271
func (s *Server) registerDevice(w http.ResponseWriter, r *http.Request) {
@@ -271,7 +284,9 @@ func (s *Server) registerDevice(w http.ResponseWriter, r *http.Request) {
271284
http.Error(w, "db error", http.StatusInternalServerError)
272285
return
273286
}
274-
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
287+
if err := json.NewEncoder(w).Encode(map[string]string{"status": "ok"}); err != nil {
288+
log.Printf("failed to encode registration response: %v", err)
289+
}
275290
}
276291

277292
func (s *Server) getDevice(w http.ResponseWriter, r *http.Request) {
@@ -285,7 +300,9 @@ func (s *Server) getDevice(w http.ResponseWriter, r *http.Request) {
285300
http.Error(w, "db error", http.StatusInternalServerError)
286301
return
287302
}
288-
json.NewEncoder(w).Encode(d)
303+
if err := json.NewEncoder(w).Encode(d); err != nil {
304+
log.Printf("failed to encode get device response: %v", err)
305+
}
289306
}
290307

291308
func (s *Server) updateDevice(w http.ResponseWriter, r *http.Request) {
@@ -303,5 +320,7 @@ func (s *Server) updateDevice(w http.ResponseWriter, r *http.Request) {
303320
http.Error(w, "db error", http.StatusInternalServerError)
304321
return
305322
}
306-
json.NewEncoder(w).Encode(map[string]string{"status": "updated"})
323+
if err := json.NewEncoder(w).Encode(map[string]string{"status": "updated"}); err != nil {
324+
log.Printf("failed to encode update device response: %v", err)
325+
}
307326
}

services/mfa/server.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,12 @@ func (s *Server) Start(ctx context.Context) error {
9090
go s.cleanupExpiredSessions(ctx)
9191

9292
server := &http.Server{
93-
Addr: s.cfg.Addr,
94-
Handler: r,
93+
Addr: s.cfg.Addr,
94+
Handler: r,
95+
ReadHeaderTimeout: 10 * time.Second,
96+
ReadTimeout: 30 * time.Second,
97+
WriteTimeout: 30 * time.Second,
98+
IdleTimeout: 60 * time.Second,
9599
}
96100

97101
go func() {
@@ -150,7 +154,9 @@ func (s *Server) challengeHandler(w http.ResponseWriter, r *http.Request) {
150154
"expires_at": session.ExpiresAt,
151155
"code": code, // Only for PoC testing
152156
}
153-
json.NewEncoder(w).Encode(response)
157+
if err := json.NewEncoder(w).Encode(response); err != nil {
158+
log.Error().Err(err).Msg("failed to encode MFA challenge response")
159+
}
154160
}
155161

156162
// verifyHandler verifies an MFA code
@@ -214,7 +220,9 @@ func (s *Server) verifyHandler(w http.ResponseWriter, r *http.Request) {
214220
"message": "MFA verification successful",
215221
"token": s.generateMFAToken(session), // Short-lived MFA verification token
216222
}
217-
json.NewEncoder(w).Encode(response)
223+
if err := json.NewEncoder(w).Encode(response); err != nil {
224+
log.Error().Err(err).Msg("failed to encode MFA verify response")
225+
}
218226
}
219227

220228
// statusHandler returns MFA session status
@@ -236,7 +244,9 @@ func (s *Server) statusHandler(w http.ResponseWriter, r *http.Request) {
236244
}
237245

238246
w.Header().Set("Content-Type", "application/json")
239-
json.NewEncoder(w).Encode(session)
247+
if err := json.NewEncoder(w).Encode(session); err != nil {
248+
log.Error().Err(err).Msg("failed to encode MFA status response")
249+
}
240250
}
241251

242252
// healthHandler returns service health
@@ -251,7 +261,9 @@ func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) {
251261
}
252262

253263
w.Header().Set("Content-Type", "application/json")
254-
json.NewEncoder(w).Encode(health)
264+
if err := json.NewEncoder(w).Encode(health); err != nil {
265+
log.Error().Err(err).Msg("failed to encode MFA health response")
266+
}
255267
}
256268

257269
// generateMFACode generates a random numeric code

0 commit comments

Comments
 (0)