mirror of
https://github.com/Threnklyn/wg-ui.git
synced 2026-05-22 06:43:35 +02:00
Add authorization from jwt token
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user