Skip to content

Commit

Permalink
cmd: introduced admin sub command
Browse files Browse the repository at this point in the history
  • Loading branch information
rkonfj committed Jun 22, 2024
1 parent a1e7487 commit b26246d
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 110 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ $ pgmap -l 127.0.0.1:9987 --secret-key 5172554832d76672d1959a5ac63c5ab9 \
```
$ caddy reverse-proxy --from https://synf.in/pg --to 127.0.0.1:9987
```
### pgcli uses pre-shared secret file instead of oidc auth
```
PG_SECRET_KEY=5172554832d76672d1959a5ac63c5ab9 PG_SERVER=wss://synf.in/pg pgcli admin secret --network "<email>" --duration 24h > psns.json
pgcli vpn -s wss://synf.in/pg -4 100.64.0.1/24 -f psns.json
```
## License
[GNU General Public License v3.0](https://github.com/rkonfj/peerguard/blob/main/LICENSE)

Expand Down
41 changes: 41 additions & 0 deletions cmd/pgcli/admin/admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package admin

import (
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

var Cmd *cobra.Command

func init() {
Cmd = &cobra.Command{
Use: "admin",
Short: "The pgmap manager tool",
SilenceUsage: true,
}
Cmd.PersistentFlags().String("secret-key", "", "key to generate network secret")
Cmd.AddCommand(secretCmd())
Cmd.AddCommand(networksCmd())
Cmd.AddCommand(peersCmd())
Cmd.AddCommand(putMetaCmd())
Cmd.AddCommand(getMetaCmd())
}

func requiredArg(flagSet *pflag.FlagSet, argName string) (string, error) {
value := os.Getenv(fmt.Sprintf("PG_%s", strings.ReplaceAll(strings.ToUpper(argName), "-", "_")))
arg, err := flagSet.GetString(argName)
if err != nil {
return "", err
}
if arg != "" {
value = arg
}
if value == "" {
return value, fmt.Errorf("required flag \"%s\" not set", argName)
}
return value, nil
}
86 changes: 86 additions & 0 deletions cmd/pgcli/admin/meta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package admin

import (
"encoding/json"
"fmt"
"os"
"reflect"

"github.com/rkonfj/peerguard/peermap/exporter"
"github.com/spf13/cobra"
)

func getMetaCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "get-meta <network>",
Short: "Query network metadata from pgmap",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
secretKey, err := requiredArg(cmd.InheritedFlags(), "secret-key")
if err != nil {
return err
}
server, err := requiredArg(cmd.Flags(), "server")
if err != nil {
return err
}
c, err := exporter.NewClient(server, secretKey)
if err != nil {
return err
}
networkMeta, err := c.NetworkMeta(args[0])
if err != nil {
return err
}
return json.NewEncoder(os.Stdout).Encode(networkMeta)
},
}
cmd.Flags().StringP("server", "s", "", "peermap server url")
return cmd
}

func putMetaCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set-meta <network>",
Short: "Set network metadata to pgmap",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
secretKey, err := requiredArg(cmd.InheritedFlags(), "secret-key")
if err != nil {
return err
}
server, err := requiredArg(cmd.Flags(), "server")
if err != nil {
return err
}
key, err := cmd.Flags().GetString("key")
if err != nil {
return err
}
value, err := cmd.Flags().GetString("value")
if err != nil {
return err
}
c, err := exporter.NewClient(server, secretKey)
if err != nil {
return err
}
networkMeta, err := c.NetworkMeta(args[0])
if err != nil {
return err
}
v := reflect.ValueOf(networkMeta).Elem().FieldByName(key)
if !v.IsValid() {
return fmt.Errorf("meta %s not found", key)
}
v.SetString(value)
json.NewEncoder(os.Stdout).Encode(networkMeta)
return c.PutNetworkMeta(args[0], *networkMeta)
},
}
cmd.Flags().StringP("server", "s", "", "peermap server url")
cmd.Flags().StringP("key", "k", "", "metadata key")
cmd.Flags().StringP("value", "v", "", "metadata value")
cmd.MarkFlagRequired("key")
return cmd
}
38 changes: 38 additions & 0 deletions cmd/pgcli/admin/networks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package admin

import (
"encoding/json"
"os"

"github.com/rkonfj/peerguard/peermap/exporter"
"github.com/spf13/cobra"
)

func networksCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "networks",
Short: "Query networks from pgmap",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
secretKey, err := requiredArg(cmd.InheritedFlags(), "secret-key")
if err != nil {
return err
}
server, err := requiredArg(cmd.Flags(), "server")
if err != nil {
return err
}
c, err := exporter.NewClient(server, secretKey)
if err != nil {
return err
}
networks, err := c.Networks()
if err != nil {
return err
}
return json.NewEncoder(os.Stdout).Encode(networks)
},
}
cmd.Flags().StringP("server", "s", "", "peermap server url")
return cmd
}
39 changes: 39 additions & 0 deletions cmd/pgcli/admin/peers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package admin

import (
"encoding/json"
"os"

"github.com/rkonfj/peerguard/peermap/exporter"
"github.com/spf13/cobra"
)

func peersCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "peers",
Short: "Query peers from pgmap",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
secretKey, err := requiredArg(cmd.InheritedFlags(), "secret-key")
if err != nil {
return err
}
server, err := requiredArg(cmd.Flags(), "server")
if err != nil {
return err
}
c, err := exporter.NewClient(server, secretKey)
if err != nil {
return err
}
peers, err := c.Peers()
if err != nil {
return err
}
return json.NewEncoder(os.Stdout).Encode(peers)
},
}

cmd.Flags().StringP("server", "s", "", "peermap server url")
return cmd
}
19 changes: 8 additions & 11 deletions cmd/pgcli/secret/secret.go → cmd/pgcli/admin/secret.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package secret
package admin

import (
"encoding/json"
Expand All @@ -10,15 +10,13 @@ import (
"github.com/spf13/cobra"
)

var Cmd *cobra.Command

func init() {
Cmd = &cobra.Command{
func secretCmd() *cobra.Command {
secretCmd := &cobra.Command{
Use: "secret",
Short: "Generate a pre-shared network secret",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
secretKey, err := cmd.Flags().GetString("secret-key")
secretKey, err := requiredArg(cmd.InheritedFlags(), "secret-key")
if err != nil {
return err
}
Expand Down Expand Up @@ -48,10 +46,9 @@ func init() {
})
},
}
Cmd.Flags().String("alias", "", "network alias")
Cmd.Flags().String("network", "default", "network")
Cmd.Flags().String("secret-key", "", "key to generate network secret")
Cmd.Flags().Duration("duration", 365*24*time.Hour, "secret duration to expire")
secretCmd.Flags().String("alias", "", "network alias")
secretCmd.Flags().String("network", "default", "network")
secretCmd.Flags().Duration("duration", 365*24*time.Hour, "secret duration to expire")

Cmd.MarkFlagRequired("secret-key")
return secretCmd
}
4 changes: 2 additions & 2 deletions cmd/pgcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"fmt"
"log/slog"

"github.com/rkonfj/peerguard/cmd/pgcli/admin"
"github.com/rkonfj/peerguard/cmd/pgcli/curve25519"
"github.com/rkonfj/peerguard/cmd/pgcli/download"
"github.com/rkonfj/peerguard/cmd/pgcli/secret"
"github.com/rkonfj/peerguard/cmd/pgcli/share"
"github.com/rkonfj/peerguard/cmd/pgcli/vpn"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -36,7 +36,7 @@ func main() {
vpn.Version = Version
vpn.Commit = Commit
cmd.AddCommand(vpn.Cmd)
cmd.AddCommand(secret.Cmd)
cmd.AddCommand(admin.Cmd)
cmd.AddCommand(curve25519.Cmd)
cmd.AddCommand(share.Cmd)
cmd.AddCommand(download.Cmd)
Expand Down
2 changes: 1 addition & 1 deletion cmd/pgcli/vpn/vpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func init() {
Cmd.Flags().Int("mtu", 1428, "mtu")

Cmd.Flags().String("key", "", "curve25519 private key in base58 format (default generate a new one)")
Cmd.Flags().String("secret-file", "", "p2p network secret file (default ~/.peerguard_network_secret.json)")
Cmd.Flags().StringP("secret-file", "f", "", "p2p network secret file (default ~/.peerguard_network_secret.json)")
Cmd.Flags().StringP("server", "s", "", "peermap server url")
Cmd.Flags().StringSlice("allowed-ip", []string{}, "declare IPs that can be routed/NATed by this machine (e.g. 192.168.0.0/24)")
Cmd.Flags().StringSlice("peer", []string{}, "specify peers instead of auto-discovery (pg://<peerID>?alias1=<ipv4>&alias2=<ipv6>)")
Expand Down
2 changes: 1 addition & 1 deletion cmd/pgmap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func run(cmd *cobra.Command, args []string) error {
cfg, _ := peermap.ReadConfig(configFile)
cfg.Overwrite(cfg1)

srv, err := peermap.New(nil, cfg)
srv, err := peermap.New(cfg)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/mdp/qrterminal/v3 v3.2.0
github.com/schollz/progressbar/v3 v3.14.2
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/vishvananda/netlink v1.2.1-beta.2
golang.org/x/crypto v0.19.0
golang.org/x/net v0.21.0
Expand All @@ -27,7 +28,6 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
golang.org/x/term v0.19.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
Expand Down
26 changes: 24 additions & 2 deletions peermap/exporter/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ func NewClient(peermapURL, secretKey string) (*Client, error) {
if err != nil {
return nil, fmt.Errorf("invalid peermap url: %w", err)
}
switch pURL.Scheme {
case "ws":
pURL.Scheme = "http"
case "wss":
pURL.Scheme = "https"
}
return &Client{
peermapURL: pURL,
c: &http.Client{
Expand Down Expand Up @@ -80,9 +86,25 @@ func (c *Client) Peers() ([]Network, error) {
return networks, nil
}

func (c *Client) PutNetworkMeta(network string, request PutNetworkMetaRequest) error {
func (c *Client) NetworkMeta(network string) (*NetworkMeta, error) {
peermap := *c.peermapURL
peermap.Path = path.Join(peermap.Path, fmt.Sprintf("/networks/%s/meta", network))
resp, err := c.c.Get(peermap.String())
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errors.New("got unexpected status: " + resp.Status)
}
defer resp.Body.Close()
var meta NetworkMeta
json.NewDecoder(resp.Body).Decode(&meta)
return &meta, nil
}

func (c *Client) PutNetworkMeta(network string, request NetworkMeta) error {
peermap := *c.peermapURL
peermap.Path = path.Join(peermap.Path, fmt.Sprintf("/network/%s/meta", network))
peermap.Path = path.Join(peermap.Path, fmt.Sprintf("/networks/%s/meta", network))
b, err := json.Marshal(request)
if err != nil {
return fmt.Errorf("marshal request: %w", err)
Expand Down
4 changes: 3 additions & 1 deletion peermap/exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ package exporter

type NetworkHead struct {
ID string `json:"n"`
Alias string `json:"n1"`
PeersCount int `json:"c"`
CreateTime string `json:"t"`
}

type Network struct {
ID string `json:"n"`
Alias string `json:"n1"`
Peers []string `json:"p"`
}

type PutNetworkMetaRequest struct {
type NetworkMeta struct {
Alias string `json:"alias"`
Neighbors []string `json:"neighbors"`
}
6 changes: 2 additions & 4 deletions peermap/oidc/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"net/http"
"path"
"sync"
"time"

Expand Down Expand Up @@ -51,11 +50,10 @@ func HandleNotifyToken(w http.ResponseWriter, r *http.Request) {
}

func RedirectAuthURL(w http.ResponseWriter, r *http.Request) {
providerName := path.Base(r.URL.Path)
provider, ok := Provider(providerName)
provider, ok := Provider(r.PathValue("provider"))
if !ok {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "provider %s not found", providerName)
fmt.Fprintf(w, "provider %s not found", r.PathValue("provider"))
return
}
authURL := provider.oAuthConfig.AuthCodeURL(r.URL.Query().Get("state"))
Expand Down
Loading

0 comments on commit b26246d

Please sign in to comment.