-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
147 lines (125 loc) · 3.26 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
import (
"embed"
"html/template"
"io/fs"
"net"
"os"
"strings"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"go.uber.org/zap"
"golang.zx2c4.com/wireguard/wgctrl"
)
var logger *zap.Logger
// Embedding all the files in the `spa` folder
//go:embed spa
var spaFiles embed.FS
type peerInfo struct {
LastHandshake string
Endpoint *net.UDPAddr
}
type deviceInfo struct {
DeviceName string
PeerInfo []peerInfo
}
type appConfig struct {
BindAddress string
ExternalUrl string
}
var ac appConfig
func init() {
logger, _ = zap.NewDevelopment()
defer logger.Sync() // flushes buffer, if any
// app configuration
viper.SetDefault("BIND_ADDRESS", "localhost:3001")
viper.SetDefault("EXTERNAL_URL", "http://localhost:3001")
viper.SetEnvPrefix("WG")
viper.AutomaticEnv()
ac.BindAddress = viper.GetString("BIND_ADDRESS")
ac.ExternalUrl = viper.GetString("EXTERNAL_URL")
logger.Sugar().Infof("App will be available under: %s", ac.BindAddress)
}
func main() {
logger.Info("Starting up.")
if os.Geteuid() > 0 {
logger.Fatal("Must be run as root, exiting.")
}
r := gin.Default()
r.Use(cors.Default())
// Returning the filesystem containing all the html files
sub, err := fs.Sub(spaFiles, "spa")
if err != nil {
logger.Fatal("Error during initial load of html templates")
}
t, err := loadTemplates(sub)
if err != nil {
logger.Sugar().Fatal(err)
}
r.SetHTMLTemplate(t)
r.GET("/", indexHandler)
r.GET("/dashboard", dashboardHandler)
r.GET("/info", wireguardHandler)
r.Run(ac.BindAddress)
}
func loadTemplates(f fs.FS) (*template.Template, error) {
logger.Debug("Loading Templates")
t := template.New("")
fs.WalkDir(f, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
logger.Sugar().Fatal(err)
}
// Check if its an html file, if nope skip
if !strings.HasSuffix(path, ".html") {
return nil
}
// Read that file
h, err := fs.ReadFile(f, path)
if err != nil {
logger.Sugar().Fatal(err)
}
// Generate a new template from it
t, err = t.New(path).Parse(string(h))
if err != nil {
logger.Sugar().Fatal(err)
}
return nil
})
return t, nil
}
func indexHandler(c *gin.Context) {
c.JSON(200, gin.H{"message": "wireguard status api"})
}
func wireguardHandler(c *gin.Context) {
wgc, err := wgctrl.New()
if err != nil {
c.JSON(500, gin.H{"error": "could not create wireguard client"})
}
devices, err := wgc.Devices()
if err != nil {
c.JSON(500, gin.H{"error": "could not get wireguard devices"})
}
// Holds the device info of this client
di := []deviceInfo{}
for _,v := range devices {
// Temporary device info buffer to hold the current device info
tdi := deviceInfo{}
tdi.DeviceName = v.Name
for _,j := range v.Peers {
// Temporary peer info
tpi := peerInfo{}
// Format Time to a readable string which can be used in the frontend.
tpi.LastHandshake = j.LastHandshakeTime.Format(time.RFC1123)
tpi.Endpoint = j.Endpoint
tdi.PeerInfo = append(tdi.PeerInfo, tpi)
}
// append to the clients list of devices
di = append(di, tdi)
}
c.JSON(200, di)
}
func dashboardHandler(c *gin.Context) {
c.HTML(200, "index.html", ac)
}