Add authorization from jwt token

This commit is contained in:
Daniel Lundin
2019-05-03 20:06:03 +02:00
parent bf60a2c206
commit 879ff9acd0
4 changed files with 94 additions and 11 deletions
+2
View File
@@ -5,7 +5,9 @@ go 1.12
require (
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/google/nftables v0.0.0-20190430150743-07c974e3643d
github.com/julienschmidt/httprouter v1.2.0
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d // indirect
github.com/mdlayher/wireguardctrl v0.0.0-20190419142446-a4a944b88a6b
github.com/sirupsen/logrus v1.4.1
+4
View File
@@ -3,10 +3,14 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/nftables v0.0.0-20190430150743-07c974e3643d h1:TC4HtISCtWOTUVPQmq4CAqe0+8R2fvnkJlQn47ep2hI=
github.com/google/nftables v0.0.0-20190430150743-07c974e3643d/go.mod h1:H/FvZdk1xWxiE2Ad0wX6mq/oqHvEE1LDDujRgYwi3ns=
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d h1:MFX8DxRnKMY/2M3H61iSsVbo/n3h0MWGmWNN1UViOU0=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQikUahfcRVPcEXiUgFsdIstGqlurL0XL4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+83 -9
View File
@@ -1,11 +1,16 @@
package main
import (
"context"
"encoding/json"
"net/http"
"os"
"strings"
"github.com/dgrijalva/jwt-go"
"github.com/google/nftables"
"github.com/google/nftables/expr"
"github.com/julienschmidt/httprouter"
"github.com/mdlayher/wireguardctrl"
"github.com/mdlayher/wireguardctrl/wgtypes"
log "github.com/sirupsen/logrus"
@@ -15,15 +20,16 @@ import (
)
var (
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
wgLinkName = kingpin.Flag("wg-device-name", "Wireguard network device name").Default("wg0").String()
wgLinkAddr = kingpin.Flag("wg-link-addr", "Wireguard interface address").Default("172.72.72.1/32").String()
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
wgListenPort = kingpin.Flag("wg-listen-port", "Wireguard UDP port to listen to").Default("51820").Int()
wgEndpoint = kingpin.Flag("wg-endpoint", "Wireguard endpoint address").Default("127.0.0.1").String()
)
type Server struct {
mux *http.ServeMux
storage *Storage
config *ServerConfig
}
@@ -32,6 +38,9 @@ type WgLink struct {
attrs *netlink.LinkAttrs
}
type jwtClaims struct {
}
func (w *WgLink) Attrs() *netlink.LinkAttrs {
return w.attrs
}
@@ -50,13 +59,10 @@ func NewServer() *Server {
storage := NewStorage()
server := &Server{
mux: http.NewServeMux(),
storage: storage,
config: storage.GetServerConfig(),
}
server.mux.HandleFunc("/", server.Hello)
return server
}
@@ -95,7 +101,7 @@ func (s *Server) initInterface() error {
conn := nftables.Conn{NetNS: int(ns)}
log.Debug("Flushing nftable rulesets")
conn.FlushRuleset()
// conn.FlushRuleset()
log.Debug("Setting up nftable rules for ip masquerading")
@@ -162,10 +168,78 @@ func (s *Server) Start() error {
return err
}
router := httprouter.New()
router.GET("/", s.Index)
router.GET("/api/v1/users/:user/devices", s.withAuth(s.GetDevices))
log.WithField("listenAddr", *listenAddr).Info("Starting server")
return http.ListenAndServe(*listenAddr, s.mux)
return http.ListenAndServe(*listenAddr, router)
}
func (s *Server) Hello(w http.ResponseWriter, r *http.Request) {
func userFromJwtToken(r *http.Request) string {
authHeader := r.Header.Get("authorization")
if authHeader == "" {
log.Debug("No Authorization header")
return ""
}
if !strings.HasPrefix(authHeader, "Bearer ") {
log.Debug("Incorrect Authorization header: ", authHeader)
return ""
}
claims := jwt.MapClaims{}
token, err := jwt.ParseWithClaims(authHeader[7:], &claims, func(token *jwt.Token) (interface{}, error) {
return []byte(""), nil
})
if token == nil {
log.Debug("Error parsing JWT token: ", err)
return ""
}
user, ok := claims["email"]
if ok {
return user.(string)
}
user, ok = claims["sub"]
if ok {
return user.(string)
}
return ""
}
func (s *Server) withAuth(handler httprouter.Handle) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
log.Debug("Auth required")
user := userFromJwtToken(r)
if user == "" {
user = "anonymous"
}
ctx := context.WithValue(r.Context(), "user", user)
handler(w, r.WithContext(ctx), ps)
}
}
func (s *Server) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
log.Debug("Index")
w.Write([]byte("Hello World"))
}
func (s *Server) GetDevices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user := r.Context().Value("user")
if user != ps.ByName("user") {
log.WithField("user", user).WithField("path", r.URL.Path).Warn("Unauthorized access")
w.WriteHeader(http.StatusUnauthorized)
return
}
err := json.NewEncoder(w).Encode(s.config)
if err != nil {
log.Error(err)
w.WriteHeader(http.StatusInternalServerError)
}
}
+5 -2
View File
@@ -18,15 +18,18 @@ var (
type ServerConfig struct {
PrivateKey string
PublicKey string
Users []*UserConfig
}
type UserConfig struct {
Name string
Devices []DeviceConfig
Devices []*DeviceConfig
}
type DeviceConfig struct {
PublicKey string
Name string
PrivateKey string
PublicKey string
}
type Storage struct {