diff options
author | Sebastien Douheret <sebastien.douheret@iot.bzh> | 2017-05-23 22:56:16 +0200 |
---|---|---|
committer | Sebastien Douheret <sebastien.douheret@iot.bzh> | 2017-05-23 23:04:10 +0200 |
commit | 32bf4cb0c949f44343849607d0439a61d1e6ea49 (patch) | |
tree | e9ff143800a277aa8ecb99f890e00d3e843f14b0 /lib | |
parent | 3cdf92cf07607d60b266e2a458f503af753020f3 (diff) |
Add API KEY support to allow CORS requests.
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/agent/agent.go | 4 | ||||
-rw-r--r-- | lib/webserver/server.go (renamed from lib/xdsserver/server.go) | 72 | ||||
-rw-r--r-- | lib/xdsconfig/fileconfig.go | 7 |
3 files changed, 69 insertions, 14 deletions
diff --git a/lib/agent/agent.go b/lib/agent/agent.go index 80c97f7..74872f7 100644 --- a/lib/agent/agent.go +++ b/lib/agent/agent.go @@ -11,7 +11,7 @@ import ( "github.com/codegangsta/cli" "github.com/iotbzh/xds-agent/lib/syncthing" "github.com/iotbzh/xds-agent/lib/xdsconfig" - "github.com/iotbzh/xds-agent/lib/xdsserver" + "github.com/iotbzh/xds-agent/lib/webserver" ) // Context holds the Agent context structure @@ -22,7 +22,7 @@ type Context struct { SThg *st.SyncThing SThgCmd *exec.Cmd SThgInotCmd *exec.Cmd - WWWServer *xdsserver.ServerService + WWWServer *webserver.ServerService Exit chan os.Signal } diff --git a/lib/xdsserver/server.go b/lib/webserver/server.go index 67b3e9a..b835a65 100644 --- a/lib/xdsserver/server.go +++ b/lib/webserver/server.go @@ -1,8 +1,9 @@ -package xdsserver +package webserver import ( "fmt" "net/http" + "strings" "github.com/Sirupsen/logrus" "github.com/gin-gonic/gin" @@ -27,8 +28,8 @@ type ServerService struct { const indexFilename = "index.html" const cookieMaxAge = "3600" -// NewServer creates an instance of ServerService -func NewServer(conf *xdsconfig.Config, log *logrus.Logger) *ServerService { +// New creates an instance of ServerService +func New(conf *xdsconfig.Config, log *logrus.Logger) *ServerService { // Setup logging for gin router if log.Level == logrus.DebugLevel { @@ -67,12 +68,15 @@ func (s *ServerService) Serve() error { // Setup middlewares s.router.Use(gin.Logger()) s.router.Use(gin.Recovery()) - s.router.Use(s.middlewareXDSDetails()) s.router.Use(s.middlewareCORS()) + s.router.Use(s.middlewareXDSDetails()) + s.router.Use(s.middlewareCSRF()) // Sessions manager s.sessions = session.NewClientSessions(s.router, s.log, cookieMaxAge) + s.router.GET("", s.slashHandler) + // Create REST API s.api = apiv1.New(s.sessions, s.cfg, s.log, s.router) @@ -117,6 +121,11 @@ func (s *ServerService) Stop() { close(s.stop) } +// serveSlash provides response to GET "/" +func (s *ServerService) slashHandler(c *gin.Context) { + c.String(200, "Hello from XDS agent!") +} + // Add details in Header func (s *ServerService) middlewareXDSDetails() gin.HandlerFunc { return func(c *gin.Context) { @@ -126,20 +135,65 @@ func (s *ServerService) middlewareXDSDetails() gin.HandlerFunc { } } +func (s *ServerService) isValidAPIKey(key string) bool { + return (key == s.cfg.FileConf.XDSAPIKey && key != "") +} + +func (s *ServerService) middlewareCSRF() gin.HandlerFunc { + return func(c *gin.Context) { + // Allow requests carrying a valid API key + if s.isValidAPIKey(c.Request.Header.Get("X-API-Key")) { + // Set the access-control-allow-origin header for CORS requests + // since a valid API key has been provided + c.Header("Access-Control-Allow-Origin", "*") + c.Next() + return + } + + // Allow io.socket request + if strings.HasPrefix(c.Request.URL.Path, "/socket.io") { + c.Next() + return + } + + /* FIXME Add really CSRF support + + // Allow requests for anything not under the protected path prefix, + // and set a CSRF cookie if there isn't already a valid one. + if !strings.HasPrefix(c.Request.URL.Path, prefix) { + cookie, err := c.Cookie("CSRF-Token-" + unique) + if err != nil || !validCsrfToken(cookie.Value) { + s.log.Debugln("new CSRF cookie in response to request for", c.Request.URL) + c.SetCookie("CSRF-Token-"+unique, newCsrfToken(), 600, "/", "", false, false) + } + c.Next() + return + } + + // Verify the CSRF token + token := c.Request.Header.Get("X-CSRF-Token-" + unique) + if !validCsrfToken(token) { + c.AbortWithError(403, "CSRF Error") + return + } + + c.Next() + */ + c.AbortWithError(403, fmt.Errorf("Not valid API key")) + } +} + // CORS middleware func (s *ServerService) middlewareCORS() gin.HandlerFunc { return func(c *gin.Context) { - if c.Request.Method == "OPTIONS" { c.Header("Access-Control-Allow-Origin", "*") - c.Header("Access-Control-Allow-Headers", "Content-Type") - c.Header("Access-Control-Allow-Methods", "POST, DELETE, GET, PUT") - c.Header("Content-Type", "application/json") + c.Header("Access-Control-Allow-Headers", "Content-Type, X-API-Key") + c.Header("Access-Control-Allow-Methods", "GET, POST, DELETE") c.Header("Access-Control-Max-Age", cookieMaxAge) c.AbortWithStatus(204) return } - c.Next() } } diff --git a/lib/xdsconfig/fileconfig.go b/lib/xdsconfig/fileconfig.go index 535ee59..3c834fc 100644 --- a/lib/xdsconfig/fileconfig.go +++ b/lib/xdsconfig/fileconfig.go @@ -18,9 +18,10 @@ type SyncThingConf struct { } type FileConfig struct { - HTTPPort string `json:"httpPort"` - LogsDir string `json:"logsDir"` - SThgConf *SyncThingConf `json:"syncthing"` + HTTPPort string `json:"httpPort"` + LogsDir string `json:"logsDir"` + XDSAPIKey string `json:"xds-apikey"` + SThgConf *SyncThingConf `json:"syncthing"` } // getConfigFromFile reads configuration from a config file. |