fix: operate ztrust from user

This commit is contained in:
Daniel Ding
2024-01-02 20:49:28 +08:00
parent d8f2a2193a
commit a3373babd4
8 changed files with 121 additions and 19 deletions

View File

@@ -127,3 +127,4 @@ OpenLAN提供一种局域网数据报文在广域网的传输实现并能够
- [多区域互联](docs/multiarea.md)
- [全互连网络](docs/fabric.md)
- [IPSec网络](docs/ipsec.md)
- [零信任网络](docs/ztrust.md)

View File

@@ -124,3 +124,4 @@ If you have more flexible VPN business needs and need to use VPN to access the e
- [Multi-region Interconnection](docs/multiarea.md)
- [Fullly Interconnected Network](docs/fabric.md)
- [IPSec Network](docs/ipsec.md)
- [Zero Trust Network](docs/ztrust.md)

View File

@@ -13,6 +13,14 @@ func GetEnv(key, value string) string {
return val
}
func GetUser(name string) string {
values := strings.SplitN(name, ":", 2)
if strings.Contains(values[0], "@") {
return values[0]
}
return ""
}
func SplitName(name string) (string, string) {
values := strings.SplitN(name, "@", 2)
if len(values) == 2 {

View File

@@ -3,10 +3,12 @@ package v5
import (
"bytes"
"encoding/json"
"github.com/luscis/openlan/cmd/api"
"github.com/luscis/openlan/pkg/libol"
"io/ioutil"
"net/http"
"strings"
"github.com/luscis/openlan/cmd/api"
"github.com/luscis/openlan/pkg/libol"
)
type Client struct {
@@ -104,9 +106,16 @@ type Cmd struct {
}
func (c Cmd) NewHttp(token string) Client {
values := strings.SplitN(token, ":", 2)
username := values[0]
password := values[0]
if len(values) == 2 {
password = values[1]
}
client := Client{
Auth: libol.Auth{
Username: token,
Username: username,
Password: password,
},
}
return client

View File

@@ -15,8 +15,8 @@ type Guest struct {
func (u Guest) Url(prefix, name string) string {
name, network := api.SplitName(name)
if name == "" {
return prefix + "/api/network/" + network + "/guest"
if network == "" {
return prefix + "/api/network/" + name + "/guest"
}
return prefix + "/api/network/" + network + "/guest/" + name
}
@@ -69,7 +69,7 @@ func (u Guest) Tmpl() string {
func (u Guest) List(c *cli.Context) error {
network := c.String("network")
url := u.Url(c.String("url"), "@"+network)
url := u.Url(c.String("url"), network)
clt := u.NewHttp(c.String("token"))
var items []schema.ZGuest
@@ -81,6 +81,7 @@ func (u Guest) List(c *cli.Context) error {
}
func (u Guest) Commands(app *api.App) {
name := api.GetUser(api.Token)
app.Command(&cli.Command{
Name: "guest",
Aliases: []string{"gu"},
@@ -90,7 +91,7 @@ func (u Guest) Commands(app *api.App) {
Name: "add",
Usage: "Add a zGuest",
Flags: []cli.Flag{
&cli.StringFlag{Name: "name"},
&cli.StringFlag{Name: "name", Value: name},
&cli.StringFlag{Name: "address"},
},
Action: u.Add,
@@ -100,7 +101,7 @@ func (u Guest) Commands(app *api.App) {
Usage: "Remove an existing zGuest",
Aliases: []string{"rm"},
Flags: []cli.Flag{
&cli.StringFlag{Name: "name"},
&cli.StringFlag{Name: "name", Value: name},
&cli.StringFlag{Name: "address"},
},
Action: u.Remove,
@@ -110,7 +111,7 @@ func (u Guest) Commands(app *api.App) {
Usage: "Display all zGuests",
Aliases: []string{"ls"},
Flags: []cli.Flag{
&cli.StringFlag{Name: "network"},
&cli.StringFlag{Name: "network", Value: name},
},
Action: u.List,
},

View File

@@ -83,6 +83,7 @@ func (u Knock) List(c *cli.Context) error {
}
func (u Knock) Commands(app *api.App) {
name := api.GetUser(api.Token)
app.Command(&cli.Command{
Name: "knock",
Aliases: []string{"kn"},
@@ -92,7 +93,7 @@ func (u Knock) Commands(app *api.App) {
Name: "add",
Usage: "Add a knock",
Flags: []cli.Flag{
&cli.StringFlag{Name: "name"},
&cli.StringFlag{Name: "name", Value: name},
&cli.StringFlag{Name: "protocol"},
&cli.StringFlag{Name: "socket"},
&cli.IntFlag{Name: "age", Value: 60},
@@ -104,7 +105,7 @@ func (u Knock) Commands(app *api.App) {
Usage: "Remove an existing knock",
Aliases: []string{"rm"},
Flags: []cli.Flag{
&cli.StringFlag{Name: "name"},
&cli.StringFlag{Name: "name", Value: name},
&cli.StringFlag{Name: "protocol"},
&cli.StringFlag{Name: "socket"},
},
@@ -115,7 +116,7 @@ func (u Knock) Commands(app *api.App) {
Usage: "Display all knock",
Aliases: []string{"ls"},
Flags: []cli.Flag{
&cli.StringFlag{Name: "name"},
&cli.StringFlag{Name: "name", Value: name},
},
Action: u.List,
},

42
docs/ztrust.md Normal file
View File

@@ -0,0 +1,42 @@
# Zero Trust
## Enable ztrust on a network
```
$ cat /etc/openlan/switch/network/example.json
{
...
"ztrust": "enable"
}
$
```
## Add yourself to ztrust
```
$ export TOKEN="daniel@example:g4nlzmk5nxek1hbcqsbr"
$ export URL="https://your-central-switch-address:10000"
$ openlan guest add
$ openlan guest ls
# total 1
username address
daniel@internal 169.254.15.6
$
```
## Knock a host service
```
$ openlan knock add --protocol icmp --socket 192.168.20.10
$ openlan knock add --protocol tcp --socket 192.168.20.10:22
$ openlan knock ls
# total 2
username protocol socket age createAt
daniel@internal tcp 192.168.20.10:22 57 2024-01-02 12:42:06 +0000 UTC
daniel@internal icmp 192.168.20.10: 46 2024-01-02 12:41:55 +0000 UTC
$
```
## Connect to a host service
```
$ ssh root@192.168.20.10 who
root pts/0 2024-01-02 06:49 (100.66.88.1)
$
```

View File

@@ -2,6 +2,7 @@ package api
import (
"net/http"
"strings"
"github.com/gorilla/mux"
"github.com/luscis/openlan/pkg/cache"
@@ -16,12 +17,21 @@ type ZTrust struct {
func (h ZTrust) Router(router *mux.Router) {
router.HandleFunc("/api/network/{id}/ztrust", h.List).Methods("GET")
router.HandleFunc("/api/network/{id}/guest", h.ListGuest).Methods("GET")
router.HandleFunc("/api/network/{id}/guest/{user}", h.ListGuest).Methods("GET")
router.HandleFunc("/api/network/{id}/guest/{user}", h.AddGuest).Methods("POST")
router.HandleFunc("/api/network/{id}/guest/{user}", h.DelGuest).Methods("DELETE")
router.HandleFunc("/api/network/{id}/guest/{user}/knock", h.ListKnock).Methods("GET")
router.HandleFunc("/api/network/{id}/guest/{user}/knock", h.AddKnock).Methods("POST")
}
func CheckUser(r *http.Request) (bool, string) {
user, _, _ := r.BasicAuth()
if strings.Contains(user, "@") {
return false, strings.SplitN(user, "@", 2)[0]
}
return true, ""
}
func (h ZTrust) List(w http.ResponseWriter, r *http.Request) {
ResponseJson(w, "TODO")
}
@@ -47,9 +57,17 @@ func (h ZTrust) ListGuest(w http.ResponseWriter, r *http.Request) {
return
}
admin, name := CheckUser(r)
guests := make([]schema.ZGuest, 0, 1024)
ztrust.ListGuest(func(obj schema.ZGuest) {
guests = append(guests, obj)
if !admin {
if obj.Name == name {
guests = append(guests, obj)
}
} else {
guests = append(guests, obj)
}
})
ResponseJson(w, guests)
@@ -77,7 +95,10 @@ func (h ZTrust) AddGuest(w http.ResponseWriter, r *http.Request) {
}
guest.Name = vars["user"]
libol.Info("ZTrust.AddGuest %s@%s", guest.Name, id)
admin, name := CheckUser(r)
if !admin {
guest.Name = name
}
if guest.Address == "" {
client := cache.VPNClient.Get(id, guest.Name)
if client != nil {
@@ -85,6 +106,9 @@ func (h ZTrust) AddGuest(w http.ResponseWriter, r *http.Request) {
guest.Device = client.Device
}
}
libol.Info("ZTrust.AddGuest %s@%s", guest.Name, id)
if guest.Address == "" {
http.Error(w, "invalid address", http.StatusBadRequest)
return
@@ -120,6 +144,11 @@ func (h ZTrust) DelGuest(w http.ResponseWriter, r *http.Request) {
}
guest.Name = vars["user"]
admin, name := CheckUser(r)
if !admin {
guest.Name = name
}
libol.Info("ZTrust.DelGuest %s@%s", guest.Name, id)
if err := ztrust.DelGuest(guest.Name, guest.Address); err == nil {
ResponseJson(w, "success")
@@ -144,9 +173,14 @@ func (h ZTrust) ListKnock(w http.ResponseWriter, r *http.Request) {
return
}
name := vars["user"]
user := vars["user"]
admin, name := CheckUser(r)
if !admin {
user = name
}
rules := make([]schema.KnockRule, 0, 1024)
ztrust.ListKnock(name, func(obj schema.KnockRule) {
ztrust.ListKnock(user, func(obj schema.KnockRule) {
rules = append(rules, obj)
})
@@ -173,10 +207,15 @@ func (h ZTrust) AddKnock(w http.ResponseWriter, r *http.Request) {
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.Protocol, rule.Dest, rule.Port, rule.Age); err == nil {
user := vars["user"]
admin, name := CheckUser(r)
if !admin {
user = name
}
libol.Info("ZTrust.AddKnock %s@%s", user, id)
if err := ztrust.Knock(user, rule.Protocol, rule.Dest, rule.Port, rule.Age); err == nil {
ResponseJson(w, "success")
} else {
http.Error(w, err.Error(), http.StatusInternalServerError)