-
Notifications
You must be signed in to change notification settings - Fork 69
/
server.go
105 lines (92 loc) · 2.83 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package api
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"log/slog"
"net/http"
"os"
"strings"
"github.com/aquasecurity/harbor-scanner-trivy/pkg/etc"
"golang.org/x/net/context"
)
type Server struct {
config etc.API
server *http.Server
}
func NewServer(config etc.API, handler http.Handler) (server *Server, err error) {
server = &Server{
config: config,
server: &http.Server{
Handler: handler,
Addr: config.Addr,
ReadTimeout: config.ReadTimeout,
WriteTimeout: config.WriteTimeout,
IdleTimeout: config.IdleTimeout,
},
}
if config.IsTLSEnabled() {
server.server.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
// The API server prefers elliptic curves which have assembly implementations
// to ensure performance under heavy loads.
CurvePreferences: []tls.CurveID{
tls.X25519,
tls.CurveP256,
},
// The API server only supports cipher suites which use ECDHE (forward secrecy)
// and does not support weak cipher suites that use RC4, 3DES or CBC.
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
},
}
if len(config.ClientCAs) > 0 {
certPool := x509.NewCertPool()
for _, clientCAPath := range config.ClientCAs {
clientCA, err := os.ReadFile(clientCAPath)
if err != nil {
return nil, fmt.Errorf("cound not read file %s: %w", clientCAPath, err)
}
certPool.AppendCertsFromPEM(clientCA)
}
server.server.TLSConfig.ClientCAs = certPool
server.server.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
}
return
}
func (s *Server) ListenAndServe() {
go func() {
if err := s.listenAndServe(); errors.Is(err, http.ErrServerClosed) {
slog.Error("Error", slog.String("err", err.Error()))
os.Exit(1)
}
slog.Debug("API server stopped listening for incoming connections")
}()
}
func (s *Server) listenAndServe() error {
if s.config.IsTLSEnabled() {
slog.Debug("Starting API server with TLS",
slog.String("certificate", s.config.TLSCertificate),
slog.String("key", s.config.TLSKey),
slog.String("clientCAs", strings.Join(s.config.ClientCAs, ", ")),
slog.String("addr", s.config.Addr),
)
return s.server.ListenAndServeTLS(s.config.TLSCertificate, s.config.TLSKey)
}
slog.Warn("Starting API server without TLS", slog.String("addr", s.config.Addr))
return s.server.ListenAndServe()
}
func (s *Server) Shutdown() {
slog.Debug("API server shutdown started")
if err := s.server.Shutdown(context.Background()); err != nil {
slog.Error("Error while shutting down API server", slog.String("err", err.Error()))
}
slog.Debug("API server shutdown completed")
}