mirror of
https://github.com/slackhq/nebula.git
synced 2025-12-15 15:20:44 -08:00
info socket
This commit is contained in:
parent
5cff83b282
commit
c4b4edec35
3 changed files with 119 additions and 0 deletions
|
|
@ -35,6 +35,7 @@ type Control struct {
|
|||
dnsStart func()
|
||||
lighthouseStart func()
|
||||
connectionManagerStart func(context.Context)
|
||||
infoStart func()
|
||||
}
|
||||
|
||||
type ControlHostInfo struct {
|
||||
|
|
@ -70,6 +71,9 @@ func (c *Control) Start() {
|
|||
if c.lighthouseStart != nil {
|
||||
c.lighthouseStart()
|
||||
}
|
||||
if c.infoStart != nil {
|
||||
go c.infoStart()
|
||||
}
|
||||
|
||||
// Start reading packets.
|
||||
c.f.run()
|
||||
|
|
|
|||
109
info.go
Normal file
109
info.go
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
package nebula
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/slackhq/nebula/config"
|
||||
)
|
||||
|
||||
func handleHostmapList(l *logrus.Logger, hm *HostMap, w http.ResponseWriter, r *http.Request) {
|
||||
type HostListItem struct {
|
||||
VpnAddrs []netip.Addr `json:"vpnAddrs"`
|
||||
//Remote netip.AddrPort `json:"remote"`
|
||||
Relayed bool `json:"relayed,omitempty"`
|
||||
LastHandshakeTime time.Time `json:"lastHandshakeTime"`
|
||||
Groups []string `json:"groups"`
|
||||
}
|
||||
|
||||
out := map[string]HostListItem{}
|
||||
hm.ForEachVpnAddr(func(hi *HostInfo) {
|
||||
cert := hi.GetCert().Certificate
|
||||
out[cert.Name()] = HostListItem{
|
||||
VpnAddrs: hi.vpnAddrs,
|
||||
//Remote: hi.remote,
|
||||
Relayed: !hi.remote.IsValid(),
|
||||
LastHandshakeTime: time.Unix(0, int64(hi.lastHandshakeTime)),
|
||||
Groups: cert.Groups(),
|
||||
}
|
||||
})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
js := json.NewEncoder(w)
|
||||
err := js.Encode(out)
|
||||
if err != nil {
|
||||
http.Error(w, "json error: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func handleHostCertLookup(l *logrus.Logger, hm *HostMap, w http.ResponseWriter, r *http.Request) {
|
||||
ipStr := r.PathValue("ipStr")
|
||||
if ipStr == "" {
|
||||
http.Error(w, "you must provide an IP address", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
addr, err := netip.ParseAddr(ipStr)
|
||||
if err != nil {
|
||||
//todo filter non-Nebula IPs?
|
||||
http.Error(w, fmt.Sprintf("Invalid IP address: %s", ipStr), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
hi := hm.QueryVpnAddr(addr)
|
||||
if hi == nil {
|
||||
http.Error(w, "IP address not found", http.StatusNotFound)
|
||||
return
|
||||
} else if hi.ConnectionState == nil {
|
||||
http.Error(w, "Host not connected", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
out, err := hi.ConnectionState.peerCert.Certificate.MarshalJSON()
|
||||
if err != nil {
|
||||
l.WithError(err).Error("failed to marshal peer certificate")
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write(out)
|
||||
}
|
||||
|
||||
func setupInfoServer(l *logrus.Logger, hm *HostMap) *http.ServeMux {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("GET /hostmap", func(w http.ResponseWriter, r *http.Request) { handleHostmapList(l, hm, w, r) })
|
||||
mux.HandleFunc("GET /host/{ipStr}", func(w http.ResponseWriter, r *http.Request) { handleHostCertLookup(l, hm, w, r) })
|
||||
return mux
|
||||
}
|
||||
|
||||
// startInfo stands up a REST API that serves information about what Nebula is doing to other services
|
||||
// Right now, this is just hostmap info,
|
||||
func startInfo(l *logrus.Logger, c *config.C, configTest bool, hm *HostMap) (func(), error) {
|
||||
listen := c.GetString("info.listen", "") //todo this should probably refuse non-localhost, right?
|
||||
if listen == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var startFn func()
|
||||
if configTest {
|
||||
return startFn, nil
|
||||
}
|
||||
|
||||
startFn = func() {
|
||||
mux := setupInfoServer(l, hm)
|
||||
l.WithField("bind", listen).Info("Info listener starting")
|
||||
err := http.ListenAndServe(listen, mux)
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
l.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return startFn, nil
|
||||
}
|
||||
6
main.go
6
main.go
|
|
@ -268,6 +268,11 @@ func Main(c *config.C, configTest bool, buildVersion string, logger *logrus.Logg
|
|||
return nil, util.ContextualizeIfNeeded("Failed to start stats emitter", err)
|
||||
}
|
||||
|
||||
infoStart, err := startInfo(l, c, configTest, hostMap)
|
||||
if err != nil {
|
||||
return nil, util.ContextualizeIfNeeded("Failed to start info socket", err)
|
||||
}
|
||||
|
||||
if configTest {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -293,5 +298,6 @@ func Main(c *config.C, configTest bool, buildVersion string, logger *logrus.Logg
|
|||
dnsStart,
|
||||
lightHouse.StartUpdateWorker,
|
||||
connManager.Start,
|
||||
infoStart,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue