github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/monitor/remoteapi/server/server.go (about) 1 package server 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net" 8 "net/http" 9 "regexp" 10 "strconv" 11 12 "go.aporeto.io/enforcerd/trireme-lib/common" 13 "go.aporeto.io/enforcerd/trireme-lib/monitor/registerer" 14 "go.uber.org/zap" 15 ) 16 17 // EventServer is a new event server 18 type EventServer struct { 19 socketPath string 20 server *http.Server 21 registerer registerer.Registerer 22 } 23 24 // NewEventServer creates a new event server 25 func NewEventServer(address string, registerer registerer.Registerer) (*EventServer, error) { 26 27 err := cleanupPipe(address) 28 if err != nil { 29 return nil, err 30 } 31 32 return &EventServer{ 33 socketPath: address, 34 registerer: registerer, 35 }, nil 36 } 37 38 // ServeHTTP is called for every request. 39 func (e *EventServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { 40 e.create(w, r) 41 } 42 43 // Run runs the server. The server will run in the background. It will 44 // gracefully die with the provided context. 45 func (e *EventServer) Run(ctx context.Context) error { 46 47 // Create the handler 48 e.server = &http.Server{ 49 Handler: e, 50 } 51 52 listener, err := e.makePipe() 53 54 if err != nil { 55 return err 56 } 57 58 // Start serving HTTP requests in the background 59 go e.server.Serve(listener) // nolint 60 61 // Listen for context cancellation to close the socket. 62 go func() { 63 <-ctx.Done() 64 listener.Close() // nolint 65 }() 66 67 return nil 68 } 69 70 // create is the main hadler that process and validates the events 71 // before calling the actual monitor handlers to process the event. 72 func (e *EventServer) create(w http.ResponseWriter, r *http.Request) { 73 event := &common.EventInfo{} 74 defer r.Body.Close() // nolint 75 76 if err := json.NewDecoder(r.Body).Decode(event); err != nil { 77 http.Error(w, "Invalid request", http.StatusBadRequest) 78 return 79 } 80 81 if err := validateTypes(event); err != nil { 82 zap.L().Error("Error in validating types", zap.Error(err), zap.Reflect("Event", event)) 83 http.Error(w, fmt.Sprintf("Invalid request fields: %s", err), http.StatusBadRequest) 84 return 85 } 86 87 if err := validateUser(r, event); err != nil { 88 http.Error(w, fmt.Sprintf("Invalid user to pid mapping found: %s", err), http.StatusForbidden) 89 return 90 } 91 92 if err := validateEvent(event); err != nil { 93 http.Error(w, fmt.Sprintf("Bad request: %s", err), http.StatusBadRequest) 94 return 95 } 96 97 if err := e.processEvent(r.Context(), event); err != nil { 98 zap.L().Error("Error in processing event", zap.Error(err), zap.Reflect("Event", event)) 99 http.Error(w, fmt.Sprintf("Cannot handle request: %s", err), http.StatusInternalServerError) 100 return 101 } 102 103 w.WriteHeader(http.StatusAccepted) 104 } 105 106 // processEvent processes the event by retrieving the right monitor handler. 107 func (e *EventServer) processEvent(ctx context.Context, eventInfo *common.EventInfo) (err error) { 108 109 if e.registerer == nil { 110 return fmt.Errorf("No registered handlers") 111 } 112 113 f, err := e.registerer.GetHandler(eventInfo.PUType, eventInfo.EventType) 114 if err != nil { 115 return fmt.Errorf("Handler not found: %s", err) 116 } 117 118 return f(ctx, eventInfo) 119 } 120 121 // validateTypes validates the various types and prevents any bad strings. 122 func validateTypes(event *common.EventInfo) error { 123 124 regexStrings := regexp.MustCompile("^[a-zA-Z0-9_:.$%/-]{0,256}$") 125 regexNS := regexp.MustCompile("^[a-zA-Z0-9/-]{0,128}$") 126 regexCgroup := regexp.MustCompile("^/trireme/(uid/){0,1}[a-zA-Z0-9_:.$%]{1,64}$") 127 128 if _, ok := common.EventMap[event.EventType]; !ok { 129 return fmt.Errorf("invalid event: %s", string(event.EventType)) 130 } 131 132 if event.PUType > common.TransientPU { 133 return fmt.Errorf("invalid pu type %v", event.PUType) 134 } 135 136 if len(event.Cgroup) > 0 && !regexCgroup.Match([]byte(event.Cgroup)) { 137 return fmt.Errorf("Invalid cgroup format: %s", event.Cgroup) 138 } 139 140 if !regexNS.Match([]byte(event.NS)) { 141 return fmt.Errorf("Namespace is not of the right format") 142 } 143 144 for k, v := range event.IPs { 145 if !regexStrings.Match([]byte(k)) { 146 return fmt.Errorf("Invalid IP name: %s", k) 147 } 148 149 if ip := net.ParseIP(v); ip == nil { 150 return fmt.Errorf("Invalid IP address: %s", v) 151 } 152 } 153 154 return nil 155 } 156 157 // validateEvent validates that this is reasonable event and 158 // modifies the default values. 159 func validateEvent(event *common.EventInfo) error { 160 161 if event.EventType == common.EventCreate || event.EventType == common.EventStart { 162 if event.HostService { 163 if event.NetworkOnlyTraffic { 164 if event.Name == "" { 165 return fmt.Errorf("Service name must be provided and must not be default") 166 } 167 } 168 } else { 169 if event.PUID == "" { 170 event.PUID = strconv.Itoa(int(event.PID)) 171 } 172 } 173 } 174 175 if event.EventType == common.EventStop || event.EventType == common.EventDestroy { 176 regStop := regexp.MustCompile("^/trireme/[a-zA-Z0-9_]{1,11}$") 177 if event.Cgroup != "" && !regStop.Match([]byte(event.Cgroup)) { 178 return fmt.Errorf("Cgroup is not of the right format") 179 } 180 } 181 182 return nil 183 }