repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

commit
4cbf498
parent
7389d00
author
Antonio Mika
date
2025-03-20 22:11:24 -0400 EDT
Use durable tunnel ids and fix logs
9 files changed,  +78, -30
M go.sum
M Makefile
+2, -1
 1@@ -127,10 +127,11 @@ migrate:
 2 	$(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20241125_add_content_type_to_analytics.sql
 3 	$(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20241202_add_more_idx_analytics.sql
 4 	$(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250319_add_tuns_event_logs_table.sql
 5+	$(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250320_add_tunnel_id_to_tuns_event_logs_table.sql
 6 .PHONY: migrate
 7 
 8 latest:
 9-	$(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250319_add_tuns_event_logs_table.sql
10+	$(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250320_add_tunnel_id_to_tuns_event_logs_table.sql
11 .PHONY: latest
12 
13 psql:
M go.sum
+0, -2
1@@ -31,8 +31,6 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4
2 git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
3 git.sr.ht/~delthas/senpai v0.3.1-0.20250311003540-18f699aaf9b0 h1:Knm2mHQwLsh1svD15lE27Cr6BMV2wH2t0OKUoSCNhuY=
4 git.sr.ht/~delthas/senpai v0.3.1-0.20250311003540-18f699aaf9b0/go.mod h1:RzVz1R7QRHGcRDnJTcr7AN/cD3rj9scdgvupkXTJLYk=
5-git.sr.ht/~rockorager/vaxis v0.12.1-0.20250312161844-81636f76af83 h1:9eVqJxJzMdnpfqfKKjvEvNDpVg6sIBvbI4FdTjhHqx8=
6-git.sr.ht/~rockorager/vaxis v0.12.1-0.20250312161844-81636f76af83/go.mod h1:h94aKek3frIV1hJbdXjqnBqaLkbWXvV+UxAsQHg9bns=
7 git.sr.ht/~rockorager/vaxis v0.13.0 h1:+F3ze1t4X5x87QEsyn/b9b9pWXw9MDqoHynoR/PHqKg=
8 git.sr.ht/~rockorager/vaxis v0.13.0/go.mod h1:h94aKek3frIV1hJbdXjqnBqaLkbWXvV+UxAsQHg9bns=
9 github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
M pkg/apps/auth/api.go
+9, -0
 1@@ -748,6 +748,15 @@ func tunsEventLogDrainSub(ctx context.Context, dbpool db.DB, logger *slog.Logger
 2 				continue
 3 			}
 4 
 5+			if log.TunnelType == "tcp" {
 6+				newID, err := shared.ParseTunsTCP(log.TunnelID, log.ServerID)
 7+				if err != nil {
 8+					logger.Error("could not parse tunnel ID", "err", err)
 9+				} else {
10+					log.TunnelID = newID
11+				}
12+			}
13+
14 			logger.Info("inserting tuns event log", "log", log)
15 			err = dbpool.InsertTunsEventLog(&log)
16 			if err != nil {
M pkg/db/db.go
+1, -1
 1@@ -331,9 +331,9 @@ type TunsEventLog struct {
 2 	UserId         string     `json:"user_id"`
 3 	RemoteAddr     string     `json:"remote_addr"`
 4 	EventType      string     `json:"event_type"`
 5+	TunnelID       string     `json:"tunnel_id"`
 6 	TunnelType     string     `json:"tunnel_type"`
 7 	ConnectionType string     `json:"connection_type"`
 8-	TunnelAddrs    []string   `json:"tunnel_addrs"`
 9 	CreatedAt      *time.Time `json:"created_at"`
10 }
11 
M pkg/db/postgres/storage.go
+8, -8
 1@@ -12,7 +12,7 @@ import (
 2 
 3 	"slices"
 4 
 5-	"github.com/lib/pq"
 6+	_ "github.com/lib/pq"
 7 	"github.com/picosh/pico/pkg/db"
 8 	"github.com/picosh/utils"
 9 )
10@@ -1799,11 +1799,11 @@ func (me *PsqlDB) findPagesStats(userID string) (*db.UserServiceStats, error) {
11 func (me *PsqlDB) InsertTunsEventLog(log *db.TunsEventLog) error {
12 	_, err := me.Db.Exec(
13 		`INSERT INTO tuns_event_logs
14-			(user_id, server_id, remote_addr, event_type, tunnel_type, connection_type, tunnel_addrs)
15+			(user_id, server_id, remote_addr, event_type, tunnel_type, connection_type, tunnel_id)
16 		VALUES
17 			($1, $2, $3, $4, $5, $6, $7)`,
18 		log.UserId, log.ServerID, log.RemoteAddr, log.EventType, log.TunnelType,
19-		log.ConnectionType, pq.Array(log.TunnelAddrs),
20+		log.ConnectionType, log.TunnelID,
21 	)
22 	return err
23 }
24@@ -1812,8 +1812,8 @@ func (me *PsqlDB) FindTunsEventLogsByAddr(userID, addr string) ([]*db.TunsEventL
25 	logs := []*db.TunsEventLog{}
26 	fmt.Println(addr)
27 	rs, err := me.Db.Query(
28-		`SELECT id, user_id, server_id, remote_addr, event_type, tunnel_type, connection_type, tunnel_addrs, created_at
29-		FROM tuns_event_logs WHERE user_id=$1 AND tunnel_addrs @> ARRAY[$2] ORDER BY created_at DESC`, userID, addr)
30+		`SELECT id, user_id, server_id, remote_addr, event_type, tunnel_type, connection_type, tunnel_id, created_at
31+		FROM tuns_event_logs WHERE user_id=$1 AND tunnel_id=$2 ORDER BY created_at DESC`, userID, addr)
32 	if err != nil {
33 		return nil, err
34 	}
35@@ -1823,7 +1823,7 @@ func (me *PsqlDB) FindTunsEventLogsByAddr(userID, addr string) ([]*db.TunsEventL
36 		err := rs.Scan(
37 			&log.ID, &log.UserId, &log.ServerID, &log.RemoteAddr,
38 			&log.EventType, &log.TunnelType, &log.ConnectionType,
39-			(*pq.StringArray)(&log.TunnelAddrs), &log.CreatedAt,
40+			&log.TunnelID, &log.CreatedAt,
41 		)
42 		if err != nil {
43 			return nil, err
44@@ -1841,7 +1841,7 @@ func (me *PsqlDB) FindTunsEventLogsByAddr(userID, addr string) ([]*db.TunsEventL
45 func (me *PsqlDB) FindTunsEventLogs(userID string) ([]*db.TunsEventLog, error) {
46 	logs := []*db.TunsEventLog{}
47 	rs, err := me.Db.Query(
48-		`SELECT id, user_id, server_id, remote_addr, event_type, tunnel_type, connection_type, tunnel_addrs, created_at
49+		`SELECT id, user_id, server_id, remote_addr, event_type, tunnel_type, connection_type, tunnel_id, created_at
50 		FROM tuns_event_logs WHERE user_id=$1 ORDER BY created_at DESC`, userID)
51 	if err != nil {
52 		return nil, err
53@@ -1852,7 +1852,7 @@ func (me *PsqlDB) FindTunsEventLogs(userID string) ([]*db.TunsEventLog, error) {
54 		err := rs.Scan(
55 			&log.ID, &log.UserId, &log.ServerID, &log.RemoteAddr,
56 			&log.EventType, &log.TunnelType, &log.ConnectionType,
57-			(*pq.StringArray)(&log.TunnelAddrs), &log.CreatedAt,
58+			&log.TunnelID, &log.CreatedAt,
59 		)
60 		if err != nil {
61 			return nil, err
M pkg/shared/feed.go
+3, -4
 1@@ -3,7 +3,6 @@ package shared
 2 import (
 3 	"fmt"
 4 	"sort"
 5-	"strings"
 6 	"time"
 7 
 8 	"github.com/gorilla/feeds"
 9@@ -137,16 +136,16 @@ Event type: %s<br />
10 Connection type: %s<br />
11 Remote addr: %s<br />
12 Tunnel type: %s<br />
13-Tunnel addrs: %s<br />
14+Tunnel ID: %s<br />
15 Server: %s`,
16 			eventLog.CreatedAt.Format(time.RFC3339), eventLog.EventType, eventLog.ConnectionType,
17-			eventLog.RemoteAddr, eventLog.TunnelType, eventLog.TunnelAddrs, eventLog.ServerID,
18+			eventLog.RemoteAddr, eventLog.TunnelType, eventLog.TunnelID, eventLog.ServerID,
19 		)
20 		logItem := &feeds.Item{
21 			Id: fmt.Sprintf("%d", eventLog.CreatedAt.Unix()),
22 			Title: fmt.Sprintf(
23 				"%s tuns event for %s",
24-				eventLog.EventType, strings.Join(eventLog.TunnelAddrs, ", "),
25+				eventLog.EventType, eventLog.TunnelID,
26 			),
27 			Link:        &feeds.Link{Href: "https://pico.sh"},
28 			Content:     content,
A pkg/shared/tuns.go
+23, -0
 1@@ -0,0 +1,23 @@
 2+package shared
 3+
 4+import (
 5+	"fmt"
 6+	"strings"
 7+)
 8+
 9+// ParseTunsTCP parses the tunnelID and tunsInstance to return a user friendly address
10+func ParseTunsTCP(tunnelID string, tunsInstance string) (string, error) {
11+	// example string:
12+	// tcp://10.0.0.89:33652,tcp6://[2603:c020:400a:d000:bd71:c59f:720c:484b]:33652
13+	splitData := strings.Split(tunnelID, ":")
14+	if len(splitData) < 3 {
15+		return "", fmt.Errorf("invalid tunnelID: %s", tunnelID)
16+	}
17+
18+	port := splitData[len(splitData)-1]
19+	if port == "" {
20+		return "", fmt.Errorf("invalid tunnelID: %s", tunnelID)
21+	}
22+
23+	return fmt.Sprintf("%s:%s", tunsInstance, port), nil
24+}
M pkg/tui/tuns.go
+29, -14
  1@@ -67,9 +67,9 @@ type ResultLog struct {
  2 	ResponseBody       string              `json:"response_body"`
  3 	ResponseCode       int                 `json:"response_code"`
  4 	ResponseStatus     string              `json:"response_status"`
  5+	TunnelID           string              `json:"tunnel_id"`
  6 	TunnelType         string              `json:"tunnel_type"`
  7 	ConnectionType     string              `json:"connection_type"`
  8-	TunnelAddrs        []string            `json:"tunnel_addrs"`
  9 	// RequestURL         string              `json:"request_url"`
 10 }
 11 
 12@@ -141,6 +141,7 @@ func (m *TunsPage) getLogWidget(i uint, cursor uint) vxfw.Widget {
 13 		codestyle = vaxis.Style{Foreground: oj}
 14 	}
 15 	txt := richtext.New([]vaxis.Segment{
 16+		{Text: log.CurrentTime + " "},
 17 		{Text: log.ResponseStatus + " ", Style: codestyle},
 18 		{Text: log.RequestTime + " "},
 19 		{Text: log.RequestIP + " "},
 20@@ -192,10 +193,19 @@ func (m *TunsPage) connectToLogs() error {
 21 			continue
 22 		}
 23 
 24+		if parsedData.TunnelType == "tcp" {
 25+			newTunID, err := shared.ParseTunsTCP(parsedData.TunnelID, parsedData.ServerID)
 26+			if err != nil {
 27+				m.shared.Logger.Error("parse tun addr", "err", err)
 28+			} else {
 29+				parsedData.TunnelID = newTunID
 30+			}
 31+		}
 32+
 33 		user := parsedData.User
 34 		userId := parsedData.UserId
 35 		isUser := user == m.shared.User.Name || userId == m.shared.User.ID
 36-		if m.isAdmin || isUser {
 37+		if (m.isAdmin || isUser) && parsedData.TunnelID == m.selected {
 38 			m.shared.App.PostEvent(ResultLogLineLoaded{parsedData})
 39 		}
 40 	}
 41@@ -419,14 +429,7 @@ func fetch(fqdn, auth string) (map[string]*TunsClient, error) {
 42 }
 43 
 44 func (m *TunsPage) fetchEventLogs() {
 45-	site := m.findSelected()
 46-	addr := m.selected
 47-	if site.TunType == "http" {
 48-		addr = "http://" + addr
 49-	} else if site.TunType == "https" {
 50-		addr = "https://" + addr
 51-	}
 52-	logs, err := m.shared.Dbpool.FindTunsEventLogsByAddr(m.shared.User.ID, addr)
 53+	logs, err := m.shared.Dbpool.FindTunsEventLogsByAddr(m.shared.User.ID, m.selected)
 54 	if err != nil {
 55 		m.err = err
 56 		return
 57@@ -464,7 +467,7 @@ func (m *TunsPage) fetchTuns() {
 58 
 59 		for k := range val.RouteListeners.TcpAliases {
 60 			ls = append(ls, TunsClientSimple{
 61-				TunType:           "tcp-alias",
 62+				TunType:           "alias",
 63 				TunAddress:        k,
 64 				RemoteAddr:        val.RemoteAddr,
 65 				User:              val.User,
 66@@ -473,9 +476,15 @@ func (m *TunsPage) fetchTuns() {
 67 		}
 68 
 69 		for k := range val.RouteListeners.Listeners {
 70+			tunAddr, err := shared.ParseTunsTCP(k, "tuns.sh")
 71+			if err != nil {
 72+				m.shared.Session.Logger.Info("parse tun addr", "err", err)
 73+				tunAddr = k
 74+			}
 75+
 76 			ls = append(ls, TunsClientSimple{
 77 				TunType:           "tcp",
 78-				TunAddress:        k,
 79+				TunAddress:        tunAddr,
 80 				RemoteAddr:        val.RemoteAddr,
 81 				User:              val.User,
 82 				PubkeyFingerprint: val.PubkeyFingerprint,
 83@@ -500,7 +509,7 @@ func (m *TunsPage) fetchTuns() {
 84 
 85 		for k := range val.RouteListeners.TcpAliases {
 86 			ls = append(ls, TunsClientSimple{
 87-				TunType:           "tcp-alias",
 88+				TunType:           "alias",
 89 				TunAddress:        k,
 90 				RemoteAddr:        val.RemoteAddr,
 91 				User:              val.User,
 92@@ -509,9 +518,15 @@ func (m *TunsPage) fetchTuns() {
 93 		}
 94 
 95 		for k := range val.RouteListeners.Listeners {
 96+			tunAddr, err := shared.ParseTunsTCP(k, "tuns.sh")
 97+			if err != nil {
 98+				m.shared.Session.Logger.Info("parse tun addr", "err", err)
 99+				tunAddr = k
100+			}
101+
102 			ls = append(ls, TunsClientSimple{
103 				TunType:           "tcp",
104-				TunAddress:        k,
105+				TunAddress:        tunAddr,
106 				RemoteAddr:        val.RemoteAddr,
107 				User:              val.User,
108 				PubkeyFingerprint: val.PubkeyFingerprint,
A sql/migrations/20250320_add_tunnel_id_to_tuns_event_logs_table.sql
+3, -0
1@@ -0,0 +1,3 @@
2+DELETE FROM tuns_event_logs;
3+ALTER TABLE tuns_event_logs ADD COLUMN tunnel_id text NOT NULL;
4+ALTER TABLE tuns_event_logs DROP COLUMN tunnel_addrs;