mirror of
https://github.com/sigcn/pg.git
synced 2025-12-24 11:31:03 +08:00
peermap: add map exporter api
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,6 @@
|
|||||||
*.exe
|
*.exe
|
||||||
pgcli-*
|
pgcli-*
|
||||||
pgserve-*
|
pgmap-*
|
||||||
wintun/
|
wintun/
|
||||||
*.zip
|
*.zip
|
||||||
*.dll
|
*.dll
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -24,6 +25,14 @@ func main() {
|
|||||||
Version: fmt.Sprintf("%s, commit %s", Version, Commit),
|
Version: fmt.Sprintf("%s, commit %s", Version, Commit),
|
||||||
Short: "Run a peermap server daemon",
|
Short: "Run a peermap server daemon",
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
verbose, err := cmd.Flags().GetInt("verbose")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
slog.SetLogLoggerLevel(slog.Level(verbose))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: run,
|
RunE: run,
|
||||||
}
|
}
|
||||||
|
|||||||
47
peermap/exporter/auth.go
Normal file
47
peermap/exporter/auth.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package exporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/rkonfj/peerguard/secure"
|
||||||
|
"github.com/rkonfj/peerguard/secure/aescbc"
|
||||||
|
)
|
||||||
|
|
||||||
|
var algo secure.SymmAlgo
|
||||||
|
|
||||||
|
func SetSecretKey(key string) {
|
||||||
|
sum := sha256.Sum256([]byte(key))
|
||||||
|
algo = aescbc.New(func(pubKey string) ([]byte, error) {
|
||||||
|
return sum[:], nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Instruction struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckToken(token string) (*Instruction, error) {
|
||||||
|
b, err := base64.StdEncoding.DecodeString(token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
plain, err := algo.Decrypt(b, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var ins Instruction
|
||||||
|
return &ins, json.Unmarshal(plain, &ins)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateToken(ins Instruction) (string, error) {
|
||||||
|
b, err := json.Marshal(ins)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
chiper, err := algo.Encrypt(b, "")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(chiper), nil
|
||||||
|
}
|
||||||
12
peermap/exporter/exporter.go
Normal file
12
peermap/exporter/exporter.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package exporter
|
||||||
|
|
||||||
|
type NetworkHead struct {
|
||||||
|
ID string `json:"n"`
|
||||||
|
PeersCount int `json:"c"`
|
||||||
|
CreateTime string `json:"t"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Network struct {
|
||||||
|
ID string `json:"n"`
|
||||||
|
Peers []string `json:"p"`
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package peermap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/md5"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -17,16 +16,11 @@ import (
|
|||||||
cmap "github.com/orcaman/concurrent-map/v2"
|
cmap "github.com/orcaman/concurrent-map/v2"
|
||||||
"github.com/rkonfj/peerguard/peer"
|
"github.com/rkonfj/peerguard/peer"
|
||||||
"github.com/rkonfj/peerguard/peermap/auth"
|
"github.com/rkonfj/peerguard/peermap/auth"
|
||||||
|
"github.com/rkonfj/peerguard/peermap/exporter"
|
||||||
"github.com/rkonfj/peerguard/peermap/oidc"
|
"github.com/rkonfj/peerguard/peermap/oidc"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Network struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
PeersCount int `json:"peersCount"`
|
|
||||||
CreateTime string `json:"createTime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
peerMap *PeerMap
|
peerMap *PeerMap
|
||||||
secret auth.JSONSecret
|
secret auth.JSONSecret
|
||||||
@@ -236,6 +230,7 @@ func New(cfg Config) (*PeerMap, error) {
|
|||||||
if err := cfg.applyDefaults(); err != nil {
|
if err := cfg.applyDefaults(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
exporter.SetSecretKey(cfg.SecretKey)
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
pm := PeerMap{
|
pm := PeerMap{
|
||||||
httpServer: &http.Server{Handler: mux, Addr: cfg.Listen},
|
httpServer: &http.Server{Handler: mux, Addr: cfg.Listen},
|
||||||
@@ -247,6 +242,7 @@ func New(cfg Config) (*PeerMap, error) {
|
|||||||
mux.HandleFunc("/", pm.handleWebsocket)
|
mux.HandleFunc("/", pm.handleWebsocket)
|
||||||
mux.HandleFunc("/networks", pm.handleQueryNetworks)
|
mux.HandleFunc("/networks", pm.handleQueryNetworks)
|
||||||
mux.HandleFunc("/peers", pm.handleQueryNetworkPeers)
|
mux.HandleFunc("/peers", pm.handleQueryNetworkPeers)
|
||||||
|
|
||||||
mux.HandleFunc("/network/token", oidc.HandleNotifyToken)
|
mux.HandleFunc("/network/token", oidc.HandleNotifyToken)
|
||||||
mux.HandleFunc("/oidc/", oidc.RedirectAuthURL)
|
mux.HandleFunc("/oidc/", oidc.RedirectAuthURL)
|
||||||
mux.HandleFunc("/oidc/authorize/", pm.handleOIDCAuthorize)
|
mux.HandleFunc("/oidc/authorize/", pm.handleOIDCAuthorize)
|
||||||
@@ -254,10 +250,17 @@ func New(cfg Config) (*PeerMap, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PeerMap) handleQueryNetworks(w http.ResponseWriter, r *http.Request) {
|
func (pm *PeerMap) handleQueryNetworks(w http.ResponseWriter, r *http.Request) {
|
||||||
|
exporterToken := r.Header.Get("X-Token")
|
||||||
|
_, err := exporter.CheckToken(exporterToken)
|
||||||
|
if err != nil {
|
||||||
|
slog.Debug("ExporterAuthFailed", "details", err)
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
items := pm.networkMap.Items()
|
items := pm.networkMap.Items()
|
||||||
networks := make([]Network, 0, len(items))
|
networks := make([]exporter.NetworkHead, 0, len(items))
|
||||||
for k, v := range items {
|
for k, v := range items {
|
||||||
networks = append(networks, Network{
|
networks = append(networks, exporter.NetworkHead{
|
||||||
ID: k,
|
ID: k,
|
||||||
PeersCount: v.Count(),
|
PeersCount: v.Count(),
|
||||||
CreateTime: fmt.Sprintf("%d", v.createTime.UnixNano()),
|
CreateTime: fmt.Sprintf("%d", v.createTime.UnixNano()),
|
||||||
@@ -267,22 +270,25 @@ func (pm *PeerMap) handleQueryNetworks(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PeerMap) handleQueryNetworkPeers(w http.ResponseWriter, r *http.Request) {
|
func (pm *PeerMap) handleQueryNetworkPeers(w http.ResponseWriter, r *http.Request) {
|
||||||
jsonSecret, err := pm.authenticator.ParseSecret(r.Header.Get("X-Network"))
|
exporterToken := r.Header.Get("X-Token")
|
||||||
|
_, err := exporter.CheckToken(exporterToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug("Authenticate failed", "err", err, "network", r.Header.Get("X-Network"))
|
slog.Debug("ExporterAuthFailed", "details", err)
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if networkContext, ok := pm.networkMap.Get(jsonSecret.Network); ok {
|
var networks []exporter.Network
|
||||||
items := networkContext.Items()
|
for item := range pm.networkMap.IterBuffered() {
|
||||||
peers := make([]string, 0, len(items))
|
var peers []string
|
||||||
for _, v := range items {
|
for _, peer := range item.Val.Items() {
|
||||||
peers = append(peers, v.String())
|
peers = append(peers, peer.String())
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(peers)
|
networks = append(networks, exporter.Network{
|
||||||
return
|
ID: item.Key,
|
||||||
|
Peers: peers,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNotFound)
|
json.NewEncoder(w).Encode(networks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PeerMap) handleOIDCAuthorize(w http.ResponseWriter, r *http.Request) {
|
func (pm *PeerMap) handleOIDCAuthorize(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -298,9 +304,7 @@ func (pm *PeerMap) handleOIDCAuthorize(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusBadGateway)
|
w.WriteHeader(http.StatusBadGateway)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
networkB := md5.Sum([]byte(email))
|
secret, err := pm.generateSecret(email)
|
||||||
network := base64.URLEncoding.EncodeToString(networkB[:])
|
|
||||||
secret, err := pm.generateSecret(network)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user