...
1 package server
2
3 import (
4 "context"
5 "flag"
6 "fmt"
7 "net/http"
8 "net/url"
9 "os"
10
11 "github.com/gin-contrib/requestid"
12 "github.com/gin-gonic/gin"
13 "github.com/go-logr/logr"
14 "github.com/peterbourgon/ff/v3"
15
16 "edge-infra.dev/pkg/edge/api/middleware"
17 "edge-infra.dev/pkg/lib/fog"
18 "edge-infra.dev/pkg/sds/emergencyaccess/client"
19 "edge-infra.dev/pkg/sds/emergencyaccess/config"
20 "edge-infra.dev/pkg/sds/emergencyaccess/eaconst"
21 "edge-infra.dev/pkg/sds/emergencyaccess/eagateway"
22 eamiddleware "edge-infra.dev/pkg/sds/emergencyaccess/middleware"
23 "edge-infra.dev/pkg/sds/emergencyaccess/msgsvc"
24 "edge-infra.dev/pkg/sds/emergencyaccess/remotecli"
25 "edge-infra.dev/pkg/sds/emergencyaccess/requestservice"
26 )
27
28 const (
29 defaultAuthorizeCommandPath = "authorizeCommand"
30 defaultAuthorizeRequestPath = "authorizeRequest"
31 defaultAuthorizeTargetPath = "authorizeTarget"
32 defaultAuthorizeUserPath = "authorizeUser"
33 defaultResolveTargetPath = "resolveTarget"
34 )
35
36 var (
37 ErrUnauthorizedUser = fmt.Errorf("user is unauthorized")
38 )
39
40 type GatewayServer struct {
41 GinEngine *gin.Engine
42 rcli eagateway.RemoteCLI
43 log logr.Logger
44 client *http.Client
45 requestService *requestservice.RequestService
46
47 authorizeCommandURL *url.URL
48 authorizeRequestURL *url.URL
49 resolveTargetURL *url.URL
50 authorizeTargetURL *url.URL
51 authorizeUserURL *url.URL
52 }
53
54
55
56 func New(config eagateway.Config, router *gin.Engine, log logr.Logger, rcli eagateway.RemoteCLI, requestService *requestservice.RequestService, checks ...func() error) (server *GatewayServer, err error) {
57 cl := client.New()
58 server = &GatewayServer{
59 GinEngine: router,
60 rcli: rcli,
61 requestService: requestService,
62 log: log,
63 client: cl,
64 }
65 err = server.setAuthServiceURLs(config)
66 if err != nil {
67 return nil, err
68 }
69 server.newGinServer(checks...)
70 return server, nil
71 }
72
73 func (server *GatewayServer) setAuthServiceURLs(config eagateway.Config) error {
74 host, err := url.Parse("http://" + config.AuthServiceHost)
75 if err != nil {
76 return err
77 }
78 server.authorizeCommandURL = host.JoinPath(defaultAuthorizeCommandPath)
79 server.authorizeRequestURL = host.JoinPath(defaultAuthorizeRequestPath)
80 server.resolveTargetURL = host.JoinPath(defaultResolveTargetPath)
81 server.authorizeTargetURL = host.JoinPath(defaultAuthorizeTargetPath)
82 server.authorizeUserURL = host.JoinPath(defaultAuthorizeUserPath)
83 return nil
84 }
85
86 func (server *GatewayServer) newGinServer(checks ...func() error) {
87 router := server.GinEngine
88 router.ContextWithFallback = true
89
90 router.Use(middleware.SetRequestContext())
91 router.Use(gin.Recovery())
92
93
94 router.Any("/health", eamiddleware.HealthCheck(checks...))
95
96 router.Any("/ready", func(c *gin.Context) {
97 c.String(http.StatusOK, "ok")
98 })
99
100 public := router.Group("/ea")
101 public.Use(requestid.New(requestid.WithCustomHeaderStrKey(eamiddleware.CorrelationIDKey)))
102 public.Use(eamiddleware.VerifyAPIVersion(eaconst.APIVersion))
103 public.Use(eamiddleware.SetLoggerInContext(server.log))
104 public.Use(eamiddleware.RequestBookendLogs())
105 public.Use(eamiddleware.SaveAuthToContext())
106
107
108 authorized := public.Group("/")
109
110 authorized.POST("/startSession", server.StartSession)
111 authorized.POST("/sendCommand", server.SendCommand)
112 authorized.POST("/endSession", server.EndSession)
113 }
114
115 func Run() error {
116 conf := Config{}
117 flags := flag.NewFlagSet("eagateway", flag.ExitOnError)
118 conf.BindFlags(flags)
119
120 if err := ff.Parse(flags, os.Args[1:], ff.WithEnvVarNoPrefix(), ff.WithIgnoreUndefined(true)); err != nil {
121 return err
122 }
123
124 router := gin.New()
125 log := newLogger()
126
127
128 ctx := fog.IntoContext(context.Background(), log)
129
130 ms, err := msgsvc.NewMessageService(ctx)
131 if err != nil {
132 return fmt.Errorf("failed to initialise message service: %w", err)
133 }
134
135 rcli := remotecli.New(ctx, ms)
136
137 db, check, err := config.DB(conf.SQL)
138 if err != nil {
139 return fmt.Errorf("error connecting to database: %w", err)
140 }
141 requestService, err := requestservice.New(db)
142 if err != nil {
143 return fmt.Errorf("failed to initialise request service: %w", err)
144 }
145
146 server, err := New(conf.EAGAteway, router, log, rcli, requestService, check)
147 if err != nil {
148 return err
149 }
150 return server.GinEngine.Run()
151 }
152
View as plain text