diff --git a/cmd/hvpn-node/hvpn-node.go b/cmd/hvpn-node/hvpn-node.go index 34b64ce..b7f9293 100644 --- a/cmd/hvpn-node/hvpn-node.go +++ b/cmd/hvpn-node/hvpn-node.go @@ -44,15 +44,19 @@ func main() { } else if uid == 0 { slog.Warn("Running as root! avoid running as root by setting CAP_NET_ADMIN") } + uuid, err := hvpnnode3.InitNodeUUID() + if err != nil { + slog.Error(err.Error()) + os.Exit(-1) + } + slog.Info("Node UUID: " + uuid.String()) app := createCliApp() - err := app.Run(os.Args) + err = app.Run(os.Args) if err != nil { slog.Error(err.Error()) os.Exit(1) } - - } func run(ctx *cli.Context) { diff --git a/node.go b/node.go new file mode 100644 index 0000000..45740ff --- /dev/null +++ b/node.go @@ -0,0 +1,64 @@ +package hvpnnode3 + +import ( + "errors" + "fmt" + "log/slog" + "os" + + "github.com/google/uuid" +) + +const UUID_PATH = "/etc/hvpn/uuid" +const CONFIG_PATH = "/etc/hvpn" +const UUIDV4_LEN = 16 + +// Gets or creates a UUID for this node +func InitNodeUUID() (*uuid.UUID, error) { + + // TODO: check and write to os.UserHomeDir() to avoid root + _, err := os.Stat(UUID_PATH) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + slog.Info(UUID_PATH + " does not exist. Creating...") + return createNodeUUID() + } + } + + f, err := os.Open(UUID_PATH) + if err != nil { + return nil, err + } + buffer := make([]byte, UUIDV4_LEN) + n, err := f.Read(buffer) + if err != nil { + return nil, err + } + slog.Debug("UUID: Read " + fmt.Sprint(n) + "bytes" ) + + uuid, err := uuid.FromBytes(buffer) + return &uuid, err +} + +func createNodeUUID() (*uuid.UUID, error) { + err := os.MkdirAll(CONFIG_PATH, 0600) + if err != nil { + return nil, err + } + + mode := os.O_RDWR | os.O_CREATE | os.O_EXCL + f, err := os.OpenFile(UUID_PATH, mode, 0600) + if err != nil { + return nil, err + } + uuid, err := uuid.NewRandom() + if err != nil { + return nil, err + } + n, err := f.Write(uuid[:]) + if err != nil { + return nil, err + } + slog.Debug("UUID: Wrote " + fmt.Sprint(n) + "bytes") + return &uuid, nil +}