mirror of
https://github.com/luscis/openlan.git
synced 2025-10-13 04:13:42 +08:00
fea: add commands for zero trust
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package api
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetEnv(key, value string) string {
|
||||
val := os.Getenv(key)
|
||||
@@ -9,3 +12,19 @@ func GetEnv(key, value string) string {
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func SplitName(name string) (string, string) {
|
||||
values := strings.SplitN(name, "@", 2)
|
||||
if len(values) == 2 {
|
||||
return values[0], values[1]
|
||||
}
|
||||
return name, ""
|
||||
}
|
||||
|
||||
func SplitSocket(value string) (string, string) {
|
||||
values := strings.SplitN(value, ":", 2)
|
||||
if len(values) == 2 {
|
||||
return values[0], values[1]
|
||||
}
|
||||
return value, ""
|
||||
}
|
||||
|
@@ -44,4 +44,6 @@ func Commands(app *api.App) {
|
||||
Policy{}.Commands(app)
|
||||
Version{}.Commands(app)
|
||||
Log{}.Commands(app)
|
||||
ZGuest{}.Commands(app)
|
||||
Knock{}.Commands(app)
|
||||
}
|
||||
|
112
cmd/api/v5/knock.go
Executable file
112
cmd/api/v5/knock.go
Executable file
@@ -0,0 +1,112 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/luscis/openlan/cmd/api"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type Knock struct {
|
||||
Cmd
|
||||
}
|
||||
|
||||
func (u Knock) Url(prefix, name string) string {
|
||||
name, network := api.SplitName(name)
|
||||
return prefix + "/api/ztrust/" + network + "/guest/" + name + "/knock"
|
||||
}
|
||||
|
||||
func (u Knock) Add(c *cli.Context) error {
|
||||
username := c.String("name")
|
||||
if !strings.Contains(username, "@") {
|
||||
return libol.NewErr("invalid username")
|
||||
}
|
||||
socket := c.String("socket")
|
||||
knock := &schema.KnockRule{
|
||||
Protocl: c.String("protocol"),
|
||||
}
|
||||
knock.Name, knock.Network = api.SplitName(username)
|
||||
knock.Dest, knock.Port = api.SplitSocket(socket)
|
||||
|
||||
url := u.Url(c.String("url"), username)
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
if err := clt.PostJSON(url, knock, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u Knock) Remove(c *cli.Context) error {
|
||||
username := c.String("name")
|
||||
if !strings.Contains(username, "@") {
|
||||
return libol.NewErr("invalid username")
|
||||
}
|
||||
socket := c.String("socket")
|
||||
knock := &schema.KnockRule{
|
||||
Protocl: c.String("protocol"),
|
||||
}
|
||||
knock.Name, knock.Network = api.SplitName(username)
|
||||
knock.Dest, knock.Port = api.SplitSocket(socket)
|
||||
|
||||
url := u.Url(c.String("url"), username)
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
if err := clt.DeleteJSON(url, knock, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u Knock) Tmpl() string {
|
||||
return `# total {{ len . }}
|
||||
{{ps -24 "username"}} {{ps -24 "address"}}
|
||||
{{- range . }}
|
||||
{{p2 -24 "%s@%s" .Name .Network}} {{ps -24 .Address}}
|
||||
{{- end }}
|
||||
`
|
||||
}
|
||||
|
||||
func (u Knock) List(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u Knock) Commands(app *api.App) {
|
||||
app.Command(&cli.Command{
|
||||
Name: "knock",
|
||||
Aliases: []string{"kn"},
|
||||
Usage: "Knock configuration",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Usage: "Add a knock",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name"},
|
||||
&cli.StringFlag{Name: "protocol"},
|
||||
&cli.StringFlag{Name: "socket"},
|
||||
},
|
||||
Action: u.Add,
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: "Remove an existing knock",
|
||||
Aliases: []string{"rm"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name"},
|
||||
&cli.StringFlag{Name: "protocol"},
|
||||
&cli.StringFlag{Name: "socket"},
|
||||
},
|
||||
Action: u.Remove,
|
||||
},
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "Display all knock",
|
||||
Aliases: []string{"ls"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "network"},
|
||||
},
|
||||
Action: u.List,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
@@ -51,7 +51,7 @@ func (u Point) Commands(app *api.App) {
|
||||
app.Command(&cli.Command{
|
||||
Name: "point",
|
||||
Aliases: []string{"ap"},
|
||||
Usage: "Point connected to this",
|
||||
Usage: "Point accessed to switch",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
|
@@ -26,22 +26,17 @@ func (u User) Url(prefix, name string) string {
|
||||
|
||||
func (u User) Add(c *cli.Context) error {
|
||||
username := c.String("name")
|
||||
if !strings.Contains(username, "@") {
|
||||
return libol.NewErr("invalid username")
|
||||
}
|
||||
user := &schema.User{
|
||||
Name: username,
|
||||
Password: c.String("password"),
|
||||
Role: c.String("role"),
|
||||
Lease: c.String("lease"),
|
||||
}
|
||||
if user.Name == "" {
|
||||
return libol.NewErr("name is empty")
|
||||
}
|
||||
if !strings.Contains(username, "@") {
|
||||
return libol.NewErr("name not contains network")
|
||||
}
|
||||
values := strings.SplitN(username, "@", 2)
|
||||
user.Name = values[0]
|
||||
user.Network = values[1]
|
||||
url := u.Url(c.String("url"), user.Name)
|
||||
user.Name, user.Network = api.SplitName(username)
|
||||
url := u.Url(c.String("url"), username)
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
if err := clt.PostJSON(url, user, nil); err != nil {
|
||||
return err
|
||||
|
110
cmd/api/v5/zguest.go
Executable file
110
cmd/api/v5/zguest.go
Executable file
@@ -0,0 +1,110 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/luscis/openlan/cmd/api"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type ZGuest struct {
|
||||
Cmd
|
||||
}
|
||||
|
||||
func (u ZGuest) Url(prefix, name string) string {
|
||||
name, network := api.SplitName(name)
|
||||
if name == "" {
|
||||
return prefix + "/api/ztrust/" + network + "/guest"
|
||||
} else {
|
||||
return prefix + "/api/ztrust/" + network + "/guest/" + name
|
||||
}
|
||||
}
|
||||
|
||||
func (u ZGuest) Add(c *cli.Context) error {
|
||||
username := c.String("name")
|
||||
if !strings.Contains(username, "@") {
|
||||
return libol.NewErr("invalid username")
|
||||
}
|
||||
guest := &schema.ZGuest{
|
||||
Name: username,
|
||||
Address: c.String("address"),
|
||||
}
|
||||
guest.Name, guest.Network = api.SplitName(username)
|
||||
url := u.Url(c.String("url"), username)
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
if err := clt.PostJSON(url, guest, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u ZGuest) Remove(c *cli.Context) error {
|
||||
username := c.String("name")
|
||||
if !strings.Contains(username, "@") {
|
||||
return libol.NewErr("invalid username")
|
||||
}
|
||||
guest := &schema.ZGuest{
|
||||
Name: username,
|
||||
Address: c.String("address"),
|
||||
}
|
||||
guest.Name, guest.Network = api.SplitName(username)
|
||||
url := u.Url(c.String("url"), username)
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
if err := clt.DeleteJSON(url, guest, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u ZGuest) Tmpl() string {
|
||||
return `# total {{ len . }}
|
||||
{{ps -24 "username"}} {{ps -24 "address"}}
|
||||
{{- range . }}
|
||||
{{p2 -24 "%s@%s" .Name .Network}} {{ps -24 .Address}}
|
||||
{{- end }}
|
||||
`
|
||||
}
|
||||
|
||||
func (u ZGuest) List(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u ZGuest) Commands(app *api.App) {
|
||||
app.Command(&cli.Command{
|
||||
Name: "zguest",
|
||||
Aliases: []string{"zg"},
|
||||
Usage: "zGuest configuration",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Usage: "Add a zGuest",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name"},
|
||||
&cli.StringFlag{Name: "address"},
|
||||
},
|
||||
Action: u.Add,
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: "Remove an existing zGuest",
|
||||
Aliases: []string{"rm"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name"},
|
||||
&cli.StringFlag{Name: "address"},
|
||||
},
|
||||
Action: u.Remove,
|
||||
},
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "Display all zGuests",
|
||||
Aliases: []string{"ls"},
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "network"},
|
||||
},
|
||||
Action: u.List,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
@@ -1,12 +1,13 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/luscis/openlan/pkg/cache"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/models"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Link struct {
|
||||
@@ -31,7 +32,7 @@ func (h Link) List(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (h Link) Get(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
libol.Info("GetPoint %s", vars["id"])
|
||||
libol.Info("Link.Get %s", vars["id"])
|
||||
|
||||
link := cache.Link.Get(vars["id"])
|
||||
if link != nil {
|
||||
|
@@ -1,8 +1,9 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/pkg/config"
|
||||
co "github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
cn "github.com/luscis/openlan/pkg/network"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
)
|
||||
|
||||
@@ -10,7 +11,7 @@ type Switcher interface {
|
||||
UUID() string
|
||||
UpTime() int64
|
||||
Alias() string
|
||||
Config() *config.Switch
|
||||
Config() *co.Switch
|
||||
Server() libol.SocketServer
|
||||
Reload()
|
||||
Save()
|
||||
@@ -28,3 +29,39 @@ func NewWorkerSchema(s Switcher) schema.Worker {
|
||||
Protocol: protocol,
|
||||
}
|
||||
}
|
||||
|
||||
type ZTruster interface {
|
||||
AddGuest(name, source string) error
|
||||
DelGuest(name, source string) error
|
||||
Knock(name string, protocol, dest, port string, age int) error
|
||||
}
|
||||
|
||||
type Networker interface {
|
||||
String() string
|
||||
ID() string
|
||||
Initialize()
|
||||
Start(v Switcher)
|
||||
Stop()
|
||||
Bridge() cn.Bridger
|
||||
Config() *co.Network
|
||||
Subnet() string
|
||||
Reload(v Switcher)
|
||||
Provider() string
|
||||
ZTruster() ZTruster
|
||||
}
|
||||
|
||||
var workers = make(map[string]Networker)
|
||||
|
||||
func AddWorker(name string, obj Networker) {
|
||||
workers[name] = obj
|
||||
}
|
||||
|
||||
func GetWorker(name string) Networker {
|
||||
return workers[name]
|
||||
}
|
||||
|
||||
func ListWorker(call func(w Networker)) {
|
||||
for _, worker := range workers {
|
||||
call(worker)
|
||||
}
|
||||
}
|
||||
|
@@ -22,4 +22,5 @@ func Add(router *mux.Router, switcher Switcher) {
|
||||
Version{}.Router(router)
|
||||
Log{}.Router(router)
|
||||
OpenAPI{}.Router(router)
|
||||
ZTrust{}.Router(router)
|
||||
}
|
||||
|
140
pkg/api/ztrust.go
Executable file
140
pkg/api/ztrust.go
Executable file
@@ -0,0 +1,140 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
)
|
||||
|
||||
type ZTrust struct {
|
||||
Switcher Switcher
|
||||
}
|
||||
|
||||
func (h ZTrust) Router(router *mux.Router) {
|
||||
router.HandleFunc("/api/ztrust", h.List).Methods("GET")
|
||||
router.HandleFunc("/api/ztrust/{id}", h.Get).Methods("GET")
|
||||
router.HandleFunc("/api/ztrust/{id}/guest/{user}", h.GetGuest).Methods("GET")
|
||||
router.HandleFunc("/api/ztrust/{id}/guest/{user}", h.AddGuest).Methods("POST")
|
||||
router.HandleFunc("/api/ztrust/{id}/guest/{user}", h.DelGuest).Methods("DELETE")
|
||||
router.HandleFunc("/api/ztrust/{id}/guest/{user}/knock", h.ListKnock).Methods("GET")
|
||||
router.HandleFunc("/api/ztrust/{id}/guest/{user}/knock", h.AddKnock).Methods("POST")
|
||||
}
|
||||
|
||||
func (h ZTrust) List(w http.ResponseWriter, r *http.Request) {
|
||||
ResponseJson(w, "TODO")
|
||||
}
|
||||
|
||||
func (h ZTrust) Get(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
libol.Info("ZTrust.GET %s", vars["id"])
|
||||
ResponseJson(w, "TODO")
|
||||
}
|
||||
|
||||
func (h ZTrust) GetGuest(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
libol.Info("ZTrust.AddGuest %s", vars["id"])
|
||||
ResponseJson(w, "TODO")
|
||||
}
|
||||
|
||||
func (h ZTrust) AddGuest(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
worker := GetWorker(id)
|
||||
if worker == nil {
|
||||
http.Error(w, "Network not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
ztrust := worker.ZTruster()
|
||||
if ztrust == nil {
|
||||
http.Error(w, "ZTrust disabled", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
guest := &schema.ZGuest{}
|
||||
if err := GetData(r, guest); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
guest.Name = vars["user"]
|
||||
libol.Info("ZTrust.AddGuest %s@%s", guest.Name, id)
|
||||
|
||||
if err := ztrust.AddGuest(guest.Name, guest.Address); err == nil {
|
||||
ResponseJson(w, "success")
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h ZTrust) DelGuest(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
worker := GetWorker(id)
|
||||
if worker == nil {
|
||||
http.Error(w, "Network not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
ztrust := worker.ZTruster()
|
||||
if ztrust == nil {
|
||||
http.Error(w, "ZTrust disabled", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
guest := &schema.ZGuest{}
|
||||
if err := GetData(r, guest); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
guest.Name = vars["user"]
|
||||
libol.Info("ZTrust.DelGuest %s@%s", guest.Name, id)
|
||||
if err := ztrust.DelGuest(guest.Name, guest.Address); err == nil {
|
||||
ResponseJson(w, "success")
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h ZTrust) ListKnock(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
libol.Info("ZTrust.ListKnock %s", vars["id"])
|
||||
ResponseJson(w, "TODO")
|
||||
}
|
||||
|
||||
func (h ZTrust) AddKnock(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
id := vars["id"]
|
||||
|
||||
worker := GetWorker(id)
|
||||
if worker == nil {
|
||||
http.Error(w, "Network not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
ztrust := worker.ZTruster()
|
||||
if ztrust == nil {
|
||||
http.Error(w, "ZTrust disabled", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rule := &schema.KnockRule{}
|
||||
if err := GetData(r, rule); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
name := vars["user"]
|
||||
libol.Info("ZTrust.AddKnock %s@%s", rule.Name, id)
|
||||
|
||||
if err := ztrust.Knock(name, rule.Protocl, rule.Dest, rule.Port, 0); err == nil {
|
||||
ResponseJson(w, "success")
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
@@ -23,7 +23,7 @@ type Network struct {
|
||||
Specifies interface{} `json:"specifies,omitempty"`
|
||||
Dhcp string `json:"dhcp,omitempty"`
|
||||
Outputs []Output `json:"outputs"`
|
||||
ZeroTrust string `json:"zerotrust"`
|
||||
ZTrust string `json:"ztrust"`
|
||||
}
|
||||
|
||||
func (n *Network) NewSpecifies() interface{} {
|
||||
|
17
pkg/schema/ztrust.go
Executable file
17
pkg/schema/ztrust.go
Executable file
@@ -0,0 +1,17 @@
|
||||
package schema
|
||||
|
||||
type ZGuest struct {
|
||||
Network string `json:"network"`
|
||||
Name string `json:"name"`
|
||||
Device string `json:"device"`
|
||||
Address string `json:"Address"`
|
||||
}
|
||||
|
||||
type KnockRule struct {
|
||||
Network string `json:"network"`
|
||||
Name string `json:"name"`
|
||||
Dest string `json:"destination"`
|
||||
Protocl string `json:"protocol"`
|
||||
Port string `json:"port"`
|
||||
Age int `json:"age"`
|
||||
}
|
@@ -147,7 +147,7 @@ func (c *ConfD) DiffLink(old *database.VirtualLink, new *database.VirtualLink) b
|
||||
}
|
||||
|
||||
func (c *ConfD) AddLink(obj *database.VirtualLink) {
|
||||
worker := GetWorker(obj.Network)
|
||||
worker := api.GetWorker(obj.Network)
|
||||
if worker == nil {
|
||||
c.out.Warn("ConfD.AddLink network %s not found.", obj.Network)
|
||||
return
|
||||
@@ -179,7 +179,7 @@ func (c *ConfD) AddLink(obj *database.VirtualLink) {
|
||||
}
|
||||
|
||||
func (c *ConfD) DelLink(obj *database.VirtualLink) {
|
||||
worker := GetWorker(obj.Network)
|
||||
worker := api.GetWorker(obj.Network)
|
||||
if worker == nil {
|
||||
c.out.Warn("ConfD.DelLink network %s not found.", obj.Network)
|
||||
return
|
||||
@@ -215,7 +215,7 @@ func (c *ConfD) UpdateName(obj *database.NameCache) {
|
||||
return
|
||||
}
|
||||
c.out.Info("ConfD.UpdateName %s %s", obj.Name, obj.Address)
|
||||
ListWorker(func(w Networker) {
|
||||
api.ListWorker(func(w api.Networker) {
|
||||
cfg := w.Config()
|
||||
spec := cfg.Specifies
|
||||
if spec == nil {
|
||||
@@ -235,7 +235,7 @@ func (c *ConfD) AddRoute(obj *database.PrefixRoute) {
|
||||
return
|
||||
}
|
||||
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
||||
worker := GetWorker(obj.Network)
|
||||
worker := api.GetWorker(obj.Network)
|
||||
if worker == nil {
|
||||
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
||||
return
|
||||
@@ -273,7 +273,7 @@ func (c *ConfD) DelRoute(obj *database.PrefixRoute) {
|
||||
return
|
||||
}
|
||||
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
||||
worker := GetWorker(obj.Network)
|
||||
worker := api.GetWorker(obj.Network)
|
||||
if worker == nil {
|
||||
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
||||
return
|
||||
@@ -297,7 +297,7 @@ func (c *ConfD) DelRoute(obj *database.PrefixRoute) {
|
||||
type LinkImpl struct {
|
||||
api api.Switcher
|
||||
out *libol.SubLogger
|
||||
worker Networker
|
||||
worker api.Networker
|
||||
}
|
||||
|
||||
func (l *LinkImpl) Add(obj *database.VirtualLink) {
|
||||
|
@@ -221,7 +221,7 @@ func (w *FabricWorker) Initialize() {
|
||||
}
|
||||
_ = w.ovs.setMode("secure")
|
||||
w.upTables()
|
||||
ListWorker(func(n Networker) {
|
||||
api.ListWorker(func(n api.Networker) {
|
||||
if w.IsSlave(n) {
|
||||
n.Initialize()
|
||||
}
|
||||
@@ -441,7 +441,7 @@ func (w *FabricWorker) Start(v api.Switcher) {
|
||||
w.AddTunnel(*tunnel)
|
||||
}
|
||||
w.WorkerImpl.Start(v)
|
||||
ListWorker(func(n Networker) {
|
||||
api.ListWorker(func(n api.Networker) {
|
||||
if w.IsSlave(n) {
|
||||
n.Start(v)
|
||||
}
|
||||
@@ -471,7 +471,7 @@ func (w *FabricWorker) DelTunnel(name string) {
|
||||
_ = w.ovs.delPort(name)
|
||||
}
|
||||
|
||||
func (w *FabricWorker) IsSlave(n Networker) bool {
|
||||
func (w *FabricWorker) IsSlave(n api.Networker) bool {
|
||||
cfg := n.Config()
|
||||
if cfg == nil || cfg.Specifies == nil {
|
||||
return false
|
||||
@@ -485,7 +485,7 @@ func (w *FabricWorker) IsSlave(n Networker) bool {
|
||||
|
||||
func (w *FabricWorker) Stop() {
|
||||
w.out.Info("FabricWorker.Stop")
|
||||
ListWorker(func(n Networker) {
|
||||
api.ListWorker(func(n api.Networker) {
|
||||
if w.IsSlave(n) {
|
||||
n.Stop()
|
||||
}
|
||||
|
@@ -13,23 +13,8 @@ import (
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
type Networker interface {
|
||||
String() string
|
||||
ID() string
|
||||
Initialize()
|
||||
Start(v api.Switcher)
|
||||
Stop()
|
||||
Bridge() cn.Bridger
|
||||
Config() *co.Network
|
||||
Subnet() string
|
||||
Reload(v api.Switcher)
|
||||
Provider() string
|
||||
}
|
||||
|
||||
var workers = make(map[string]Networker)
|
||||
|
||||
func NewNetworker(c *co.Network) Networker {
|
||||
var obj Networker
|
||||
func NewNetworker(c *co.Network) api.Networker {
|
||||
var obj api.Networker
|
||||
switch c.Provider {
|
||||
case "esp":
|
||||
obj = NewESPWorker(c)
|
||||
@@ -42,20 +27,10 @@ func NewNetworker(c *co.Network) Networker {
|
||||
default:
|
||||
obj = NewOpenLANWorker(c)
|
||||
}
|
||||
workers[c.Name] = obj
|
||||
api.AddWorker(c.Name, obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
func GetWorker(name string) Networker {
|
||||
return workers[name]
|
||||
}
|
||||
|
||||
func ListWorker(call func(w Networker)) {
|
||||
for _, worker := range workers {
|
||||
call(worker)
|
||||
}
|
||||
}
|
||||
|
||||
type LinuxPort struct {
|
||||
name string // gre:xx, vxlan:xx
|
||||
vlan int
|
||||
@@ -72,7 +47,7 @@ type WorkerImpl struct {
|
||||
setR *cn.IPSet
|
||||
setV *cn.IPSet
|
||||
vpn *OpenVPN
|
||||
trust *ZeroTrust
|
||||
ztrust *ZTrust
|
||||
}
|
||||
|
||||
func NewWorkerApi(c *co.Network) *WorkerImpl {
|
||||
@@ -104,9 +79,9 @@ func (w *WorkerImpl) Initialize() {
|
||||
w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err)
|
||||
}
|
||||
w.newVPN()
|
||||
if w.cfg.ZeroTrust == "enable" {
|
||||
w.trust = NewZeroTrust(w.cfg.Name, 30)
|
||||
w.trust.Initialize()
|
||||
if w.cfg.ZTrust == "enable" {
|
||||
w.ztrust = NewZTrust(w.cfg.Name, 30)
|
||||
w.ztrust.Initialize()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,11 +223,11 @@ func (w *WorkerImpl) Start(v api.Switcher) {
|
||||
w.vpn.Start()
|
||||
}
|
||||
|
||||
if !(w.vpn == nil || w.trust == nil) {
|
||||
w.trust.Start()
|
||||
if !(w.vpn == nil || w.ztrust == nil) {
|
||||
w.ztrust.Start()
|
||||
fire.Mangle.Pre.AddRule(cn.IpRule{
|
||||
Input: vpn.Device,
|
||||
Jump: w.trust.Chain(),
|
||||
Jump: w.ztrust.Chain(),
|
||||
})
|
||||
}
|
||||
fire.Start()
|
||||
@@ -307,8 +282,8 @@ func (w *WorkerImpl) DelOutput(bridge string, port *LinuxPort) {
|
||||
func (w *WorkerImpl) Stop() {
|
||||
w.out.Info("WorkerImpl.Stop")
|
||||
w.fire.Stop()
|
||||
if !(w.vpn == nil || w.trust == nil) {
|
||||
w.trust.Stop()
|
||||
if !(w.vpn == nil || w.ztrust == nil) {
|
||||
w.ztrust.Stop()
|
||||
}
|
||||
if !(w.vpn == nil) {
|
||||
w.vpn.Stop()
|
||||
@@ -489,3 +464,7 @@ func (w *WorkerImpl) newVPN() {
|
||||
obj.Initialize()
|
||||
w.vpn = obj
|
||||
}
|
||||
|
||||
func (w *WorkerImpl) ZTruster() api.ZTruster {
|
||||
return w.ztrust
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/luscis/openlan/pkg/api"
|
||||
"github.com/luscis/openlan/pkg/app"
|
||||
"github.com/luscis/openlan/pkg/cache"
|
||||
co "github.com/luscis/openlan/pkg/config"
|
||||
@@ -96,7 +97,7 @@ type Switch struct {
|
||||
hooks []Hook
|
||||
http *Http
|
||||
server libol.SocketServer
|
||||
worker map[string]Networker
|
||||
worker map[string]api.Networker
|
||||
uuid string
|
||||
newTime int64
|
||||
out *libol.SubLogger
|
||||
@@ -110,7 +111,7 @@ func NewSwitch(c *co.Switch) *Switch {
|
||||
v := &Switch{
|
||||
cfg: c,
|
||||
fire: network.NewFireWallGlobal(c.FireWall),
|
||||
worker: make(map[string]Networker, 32),
|
||||
worker: make(map[string]api.Networker, 32),
|
||||
server: server,
|
||||
newTime: time.Now().Unix(),
|
||||
hooks: make([]Hook, 0, 64),
|
||||
|
@@ -1,162 +0,0 @@
|
||||
package cswitch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/network"
|
||||
cn "github.com/luscis/openlan/pkg/network"
|
||||
)
|
||||
|
||||
type KnockRule struct {
|
||||
createAt int64
|
||||
protocol string
|
||||
dest string
|
||||
destPort string
|
||||
rule *cn.IpRule
|
||||
}
|
||||
|
||||
func (r *KnockRule) Id() string {
|
||||
return fmt.Sprintf("%s:%s:%s", r.protocol, r.dest, r.destPort)
|
||||
}
|
||||
|
||||
type ZeroGuest struct {
|
||||
network string
|
||||
username string
|
||||
device string
|
||||
sources map[string]string
|
||||
rules map[string]*KnockRule
|
||||
chain *cn.FireWallChain
|
||||
}
|
||||
|
||||
func NewZeroGuest(network, name string) *ZeroGuest {
|
||||
return &ZeroGuest{
|
||||
network: network,
|
||||
username: name,
|
||||
sources: make(map[string]string, 2),
|
||||
rules: make(map[string]*KnockRule, 1024),
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ZeroGuest) Chain() string {
|
||||
return "ZTT_" + z.network + "_" + z.username
|
||||
}
|
||||
|
||||
func (z *ZeroGuest) Initialize() {
|
||||
z.chain = cn.NewFireWallChain(z.Chain(), network.TMangle, "")
|
||||
}
|
||||
|
||||
func (z *ZeroGuest) AddSource(source string) {
|
||||
z.sources[source] = source
|
||||
}
|
||||
|
||||
func (z *ZeroGuest) DelSource(source string) {
|
||||
if _, ok := z.sources[source]; ok {
|
||||
delete(z.sources, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ZeroGuest) AddRule(rule *KnockRule) {
|
||||
z.rules[rule.Id()] = rule
|
||||
z.chain.AddRuleX(cn.IpRule{
|
||||
Dest: rule.dest,
|
||||
DstPort: rule.destPort,
|
||||
Jump: "ACCEPT",
|
||||
Comment: time.Now().Local().String(),
|
||||
})
|
||||
}
|
||||
|
||||
func (z *ZeroGuest) DelRule(rule *KnockRule) {
|
||||
if _, ok := z.rules[rule.Id()]; ok {
|
||||
delete(z.rules, rule.Id())
|
||||
}
|
||||
}
|
||||
|
||||
type ZeroTrust struct {
|
||||
network string
|
||||
expire int
|
||||
guests map[string]*ZeroGuest
|
||||
chain *cn.FireWallChain
|
||||
out *libol.SubLogger
|
||||
}
|
||||
|
||||
func NewZeroTrust(network string, expire int) *ZeroTrust {
|
||||
return &ZeroTrust{
|
||||
network: network,
|
||||
expire: expire,
|
||||
out: libol.NewSubLogger(network),
|
||||
guests: make(map[string]*ZeroGuest, 32),
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) Chain() string {
|
||||
return "ZTT_" + z.network
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) Initialize() {
|
||||
z.chain = cn.NewFireWallChain(z.Chain(), network.TMangle, "")
|
||||
z.chain.AddRule(cn.IpRule{
|
||||
Comment: "Zero Trust Default",
|
||||
Jump: "DROP",
|
||||
})
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) Knock(name string, dest, protocol, destPort string) {
|
||||
guest, ok := z.guests[name]
|
||||
if !ok {
|
||||
z.out.Warn("ZeroTrust.Knock: not found %s", name)
|
||||
return
|
||||
}
|
||||
guest.AddRule(&KnockRule{
|
||||
protocol: protocol,
|
||||
dest: dest,
|
||||
destPort: destPort,
|
||||
createAt: time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) Update() {
|
||||
//TODO expire knock rules.
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) AddGuest(name, device, source string) {
|
||||
guest, ok := z.guests[name]
|
||||
if !ok {
|
||||
guest = NewZeroGuest(z.network, name)
|
||||
guest.Initialize()
|
||||
z.guests[name] = guest
|
||||
}
|
||||
guest.AddSource(source)
|
||||
z.chain.AddRuleX(cn.IpRule{
|
||||
Input: device,
|
||||
Source: source,
|
||||
Comment: guest.username + "." + guest.network,
|
||||
Jump: guest.Chain(),
|
||||
Order: "-I",
|
||||
})
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) DelGuest(name, device, source string) {
|
||||
guest, ok := z.guests[name]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
z.chain.DelRuleX(cn.IpRule{
|
||||
Input: device,
|
||||
Source: source,
|
||||
Comment: guest.username + "." + guest.network,
|
||||
Jump: guest.Chain(),
|
||||
})
|
||||
guest.DelSource(source)
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) Start() {
|
||||
z.out.Info("ZeroTrust.Start")
|
||||
z.chain.Install()
|
||||
}
|
||||
|
||||
func (z *ZeroTrust) Stop() {
|
||||
z.out.Info("ZeroTrust.Stop")
|
||||
z.chain.Cancel()
|
||||
}
|
217
pkg/switch/ztrust.go
Normal file
217
pkg/switch/ztrust.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package cswitch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/network"
|
||||
cn "github.com/luscis/openlan/pkg/network"
|
||||
)
|
||||
|
||||
type KnockRule struct {
|
||||
createAt int64
|
||||
age int
|
||||
protocol string
|
||||
destination string
|
||||
port string
|
||||
rule *cn.IpRule
|
||||
}
|
||||
|
||||
func (r *KnockRule) Id() string {
|
||||
return fmt.Sprintf("%s:%s:%s", r.protocol, r.destination, r.port)
|
||||
}
|
||||
|
||||
type ZGuest struct {
|
||||
network string
|
||||
username string
|
||||
sources map[string]string
|
||||
rules map[string]*KnockRule
|
||||
chain *cn.FireWallChain
|
||||
out *libol.SubLogger
|
||||
}
|
||||
|
||||
func NewZGuest(network, name string) *ZGuest {
|
||||
return &ZGuest{
|
||||
network: network,
|
||||
username: name,
|
||||
sources: make(map[string]string, 2),
|
||||
rules: make(map[string]*KnockRule, 1024),
|
||||
out: libol.NewSubLogger(name + "@" + network),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *ZGuest) Chain() string {
|
||||
return "ZTT_" + g.network + "-" + g.username
|
||||
}
|
||||
|
||||
func (g *ZGuest) Initialize() {
|
||||
g.chain = cn.NewFireWallChain(g.Chain(), network.TMangle, "")
|
||||
}
|
||||
|
||||
func (g *ZGuest) Start() {
|
||||
g.chain.Install()
|
||||
}
|
||||
|
||||
func (g *ZGuest) AddSource(source string) {
|
||||
g.sources[source] = source
|
||||
}
|
||||
|
||||
func (g *ZGuest) DelSource(source string) {
|
||||
if _, ok := g.sources[source]; ok {
|
||||
delete(g.sources, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *ZGuest) AddRuleX(rule cn.IpRule) {
|
||||
if err := g.chain.AddRuleX(rule); err != nil {
|
||||
g.out.Warn("ZTrust.AddRuleX: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *ZGuest) DelRuleX(rule cn.IpRule) {
|
||||
if err := g.chain.DelRuleX(rule); err != nil {
|
||||
g.out.Warn("ZTrust.DelRuleX: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *ZGuest) AddRule(rule *KnockRule) {
|
||||
g.rules[rule.Id()] = rule
|
||||
g.AddRuleX(cn.IpRule{
|
||||
Dest: rule.destination,
|
||||
DstPort: rule.port,
|
||||
Proto: rule.protocol,
|
||||
Jump: "ACCEPT",
|
||||
Comment: "Knock at " + time.Now().UTC().String(),
|
||||
})
|
||||
}
|
||||
|
||||
func (g *ZGuest) DelRule(rule *KnockRule) {
|
||||
if _, ok := g.rules[rule.Id()]; ok {
|
||||
delete(g.rules, rule.Id())
|
||||
}
|
||||
g.DelRuleX(cn.IpRule{
|
||||
Proto: rule.protocol,
|
||||
Dest: rule.destination,
|
||||
DstPort: rule.port,
|
||||
Jump: "ACCEPT",
|
||||
Comment: "Knock at " + time.Now().Local().String(),
|
||||
})
|
||||
}
|
||||
|
||||
func (g *ZGuest) Stop() {
|
||||
g.chain.Cancel()
|
||||
}
|
||||
|
||||
type ZTrust struct {
|
||||
network string
|
||||
expire int
|
||||
guests map[string]*ZGuest
|
||||
chain *cn.FireWallChain
|
||||
out *libol.SubLogger
|
||||
}
|
||||
|
||||
func NewZTrust(network string, expire int) *ZTrust {
|
||||
return &ZTrust{
|
||||
network: network,
|
||||
expire: expire,
|
||||
out: libol.NewSubLogger(network),
|
||||
guests: make(map[string]*ZGuest, 32),
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ZTrust) Chain() string {
|
||||
return "ZTT_" + z.network
|
||||
}
|
||||
|
||||
func (z *ZTrust) Initialize() {
|
||||
z.chain = cn.NewFireWallChain(z.Chain(), network.TMangle, "")
|
||||
z.chain.AddRule(cn.IpRule{
|
||||
Comment: "ZTrust Default",
|
||||
Jump: "DROP",
|
||||
})
|
||||
}
|
||||
|
||||
func (z *ZTrust) Knock(name string, protocol, dest, port string, age int) error {
|
||||
guest, ok := z.guests[name]
|
||||
if !ok {
|
||||
return libol.NewErr("Knock: not found %s", name)
|
||||
}
|
||||
guest.AddRule(&KnockRule{
|
||||
protocol: protocol,
|
||||
destination: dest,
|
||||
port: port,
|
||||
createAt: time.Now().Unix(),
|
||||
age: age,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *ZTrust) Update() {
|
||||
//TODO expire knock rules.
|
||||
}
|
||||
|
||||
func (z *ZTrust) AddRuleX(rule cn.IpRule) {
|
||||
if err := z.chain.AddRuleX(rule); err != nil {
|
||||
z.out.Warn("ZTrust.AddRuleX: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ZTrust) DelRuleX(rule cn.IpRule) {
|
||||
if err := z.chain.DelRuleX(rule); err != nil {
|
||||
z.out.Warn("ZTrust.DelRuleX: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ZTrust) AddGuest(name, source string) error {
|
||||
z.out.Info("ZTrust.AddGuest: %s %s", name, source)
|
||||
if source == "" {
|
||||
return libol.NewErr("AddGuest: invalid source")
|
||||
}
|
||||
guest, ok := z.guests[name]
|
||||
if !ok {
|
||||
guest = NewZGuest(z.network, name)
|
||||
guest.Initialize()
|
||||
guest.Start()
|
||||
z.guests[name] = guest
|
||||
}
|
||||
guest.AddSource(source)
|
||||
z.AddRuleX(cn.IpRule{
|
||||
Source: source,
|
||||
Comment: "User " + guest.username + "@" + guest.network,
|
||||
Jump: guest.Chain(),
|
||||
Order: "-I",
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *ZTrust) DelGuest(name, source string) error {
|
||||
if source == "" {
|
||||
return libol.NewErr("DelGuest: invalid source")
|
||||
}
|
||||
guest, ok := z.guests[name]
|
||||
if !ok {
|
||||
return libol.NewErr("DelGuest: not found %s", name)
|
||||
}
|
||||
z.out.Info("ZTrust.DelGuest: %s %s", name, source)
|
||||
z.DelRuleX(cn.IpRule{
|
||||
Source: source,
|
||||
Comment: guest.username + "." + guest.network,
|
||||
Jump: guest.Chain(),
|
||||
})
|
||||
guest.DelSource(source)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *ZTrust) Start() {
|
||||
z.out.Info("ZTrust.Start")
|
||||
z.chain.Install()
|
||||
}
|
||||
|
||||
func (z *ZTrust) Stop() {
|
||||
z.out.Info("ZTrust.Stop")
|
||||
z.chain.Cancel()
|
||||
for _, guest := range z.guests {
|
||||
guest.Stop()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user