Skip to content

Commit

Permalink
Merge pull request #39 from dnstapir/gobify
Browse files Browse the repository at this point in the history
Gobify
  • Loading branch information
oej authored May 27, 2024
2 parents 9e3a847 + 03e92d5 commit 1238710
Show file tree
Hide file tree
Showing 18 changed files with 929 additions and 531 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,23 @@ default: ${PROG}

${PROG}: build


version.go:
/bin/sh make-version.sh $(VERSION)-$(COMMIT) $(APPDATE) $(PROG)

build: version.go
build: version.go # ../tapir/tapir.pb.go
$(GO) build $(GOFLAGS) -o ${PROG}

# ../tapir/tapir.pb.go: ../tapir/tapir.proto
# make -C ../tapir tapir.pb.go

linux:
/bin/sh make-version.sh $(VERSION)-$(COMMIT) $(APPDATE) $(PROG)
GOOS=linux GOARCH=amd64 go build $(GOFLAGS) -o ${PROG}.linux

netbsd:
/bin/sh make-version.sh $(VERSION)-$(COMMIT) $(APPDATE) $(PROG)
GOOS=netbsd GOARCH=amd64 go build $(GOFLAGS) -o ${PROG}.netbsd

gen-mqtt-msg-new-qname.go: checkout/events-mqtt-message-new_qname.json
go-jsonschema checkout/events-mqtt-message-new_qname.json --package main --tags json --only-models --output gen-mqtt-msg-new-qname.go

Expand Down
206 changes: 181 additions & 25 deletions apihandler.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Johan Stenstam, [email protected]
* Johan Stenstam, [email protected]
*/
package main

Expand Down Expand Up @@ -183,34 +183,135 @@ func APIcommand(conf *Config) func(w http.ResponseWriter, r *http.Request) {
// Msg: "Daemon was happy, but now winding down",
// }

case "export-greylist-dns-tapir":
// exportGreylistDnsTapir(w, r, conf.TemData)
// End of Selection
default:
resp.Error = true
resp.ErrorMsg = fmt.Sprintf("Unknown command: %s", cp.Command)
}
}
}

func APIbootstrap(conf *Config) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
resp := tapir.BootstrapResponse{
Status: "ok", // only status we know, so far
Msg: "We're happy, but send more cookies",
}

defer func() {
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(resp)
if err != nil {
log.Printf("Error from json encoder: %v", err)
log.Printf("resp: %v", resp)
}
}()

decoder := json.NewDecoder(r.Body)
var bp tapir.BootstrapPost
err := decoder.Decode(&bp)
if err != nil {
log.Println("APIbootstrap: error decoding command post:", err)
resp.Error = true
resp.ErrorMsg = fmt.Sprintf("Error decoding command post: %v", err)
return
}

log.Printf("API: received /bootstrap request (cmd: %s) from %s.\n", bp.Command, r.RemoteAddr)

switch bp.Command {
case "export-greylist":
td := conf.TemData
td.mu.RLock()
defer td.mu.RUnlock()

greylist, ok := td.Lists["greylist"]["dns-tapir"]
greylist, ok := td.Lists["greylist"][bp.ListName]
if !ok {
resp.Error = true
resp.ErrorMsg = "Greylist 'dns-tapir' not found"
resp.ErrorMsg = fmt.Sprintf("Greylist '%s' not found", bp.ListName)
return
}
log.Printf("Found dns-tapir greylist: %v", greylist)

w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=greylist-dns-tapir.gob")
log.Printf("Found %s greylist containing %d names", bp.ListName, len(greylist.Names))

switch bp.Encoding {
case "gob":
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=greylist-%s.gob", bp.ListName))

encoder := gob.NewEncoder(w)
err := encoder.Encode(greylist)
if err != nil {
log.Printf("Error encoding greylist: %v", err)
resp.Error = true
resp.ErrorMsg = err.Error()
return
}

encoder := gob.NewEncoder(w)
err := encoder.Encode(greylist)
if err != nil {
log.Printf("Error encoding greylist: %v", err)
// case "protobuf":
// w.Header().Set("Content-Type", "application/octet-stream")
// w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=greylist-%s.protobuf", bp.ListName))
//
// data, err := proto.Marshal(greylist)
// if err != nil {
// log.Printf("Error encoding greylist to protobuf: %v", err)
// resp.Error = true
// resp.ErrorMsg = err.Error()
// return
// }

// _, err = w.Write(data)
// if err != nil {
// log.Printf("Error writing protobuf data to response: %v", err)
// resp.Error = true
// resp.ErrorMsg = err.Error()
// return
// }

// case "flatbuffer":
// w.Header().Set("Content-Type", "application/octet-stream")
// w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=greylist-%s.flatbuffer", bp.ListName))

// builder := flatbuffers.NewBuilder(0)
// names := make([]flatbuffers.UOffsetT, len(greylist.Names))

// i := 0
// for name := range greylist.Names {
// nameOffset := builder.CreateString(name)
// tapir.NameStart(builder)
// tapir.NameAddName(builder, nameOffset)
// names[i] = tapir.NameEnd(builder)
// i++
// }

// tapir.GreylistStartNamesVector(builder, len(names))
// for j := len(names) - 1; j >= 0; j-- {
// builder.PrependUOffsetT(names[j])
// }
// namesVector := builder.EndVector(len(names))

// tapir.GreylistStart(builder)
// tapir.GreylistAddNames(builder, namesVector)
// greylistOffset := tapir.GreylistEnd(builder)

// builder.Finish(greylistOffset)
// buf := builder.FinishedBytes()

// _, err := w.Write(buf)
// if err != nil {
// log.Printf("Error writing flatbuffer data to response: %v", err)
// resp.Error = true
// resp.ErrorMsg = err.Error()
// return
// }

default:
resp.Error = true
resp.ErrorMsg = err.Error()
resp.ErrorMsg = fmt.Sprintf("Unknown encoding: %s", bp.Encoding)
return
}

default:
resp.ErrorMsg = fmt.Sprintf("Unknown command: %s", cp.Command)
resp.ErrorMsg = fmt.Sprintf("Unknown command: %s", bp.Command)
resp.Error = true
}
}
Expand Down Expand Up @@ -280,9 +381,9 @@ func APIdebug(conf *Config) func(w http.ResponseWriter, r *http.Request) {
resp.ReaperStats = make(map[string]map[time.Time][]string)
for SrcName, list := range td.Lists["greylist"] {
resp.ReaperStats[SrcName] = make(map[time.Time][]string)
for ts, items := range list.ReaperData {
for _, item := range items {
resp.ReaperStats[SrcName][ts] = append(resp.ReaperStats[SrcName][ts], item.Name)
for ts, names := range list.ReaperData {
for name := range names {
resp.ReaperStats[SrcName][ts] = append(resp.ReaperStats[SrcName][ts], name)
}
}
}
Expand Down Expand Up @@ -333,12 +434,25 @@ func SetupRouter(conf *Config) *mux.Router {
viper.GetString("apiserver.key")).Subrouter()
sr.HandleFunc("/ping", tapir.APIping("tem", conf.BootTime)).Methods("POST")
sr.HandleFunc("/command", APIcommand(conf)).Methods("POST")
sr.HandleFunc("/bootstrap", APIbootstrap(conf)).Methods("POST")
sr.HandleFunc("/debug", APIdebug(conf)).Methods("POST")
// sr.HandleFunc("/show/api", tapir.APIshowAPI(r)).Methods("GET")

return r
}

func SetupBootstrapRouter(conf *Config) *mux.Router {
r := mux.NewRouter().StrictSlash(true)

sr := r.PathPrefix("/api/v1").Headers("X-API-Key", viper.GetString("apiserver.key")).Subrouter()
sr.HandleFunc("/ping", tapir.APIping("tem", conf.BootTime)).Methods("POST")
sr.HandleFunc("/bootstrap", APIbootstrap(conf)).Methods("POST")
// sr.HandleFunc("/debug", APIdebug(conf)).Methods("POST")
// sr.HandleFunc("/show/api", tapir.APIshowAPI(r)).Methods("GET")

return r
}

func walkRoutes(router *mux.Router, address string) {
log.Printf("Defined API endpoints for router on: %s\n", address)

Expand Down Expand Up @@ -370,6 +484,10 @@ func APIdispatcher(conf *Config, done <-chan struct{}) {
certfile := viper.GetString("certs.tem.cert")
keyfile := viper.GetString("certs.tem.key")

bootstrapaddress := viper.GetString("bootstrapserver.address")
bootstraptlsaddress := viper.GetString("bootstrapserver.tlsaddress")
bootstraprouter := SetupBootstrapRouter(conf)

tlspossible := true

_, err := os.Stat(certfile)
Expand All @@ -384,7 +502,7 @@ func APIdispatcher(conf *Config, done <-chan struct{}) {
tlsConfig, err := tapir.NewServerConfig(viper.GetString("certs.cacertfile"), tls.VerifyClientCertIfGiven)
// Alternatives are: tls.RequireAndVerifyClientCert, tls.VerifyClientCertIfGiven,
// tls.RequireAnyClientCert, tls.RequestClientCert, tls.NoClientCert
// We would like to request a client cert, but until all labgroup servers have certs we cannot do that.

if err != nil {
TEMExiter("Error creating API server tls config: %v\n", err)
}
Expand All @@ -394,27 +512,65 @@ func APIdispatcher(conf *Config, done <-chan struct{}) {
Handler: router,
TLSConfig: tlsConfig,
}
bootstrapTlsServer := &http.Server{
Addr: bootstraptlsaddress,
Handler: bootstraprouter,
TLSConfig: tlsConfig,
}

var wg sync.WaitGroup

go func() {
log.Println("Starting API dispatcher #1. Listening on", address)
TEMExiter(http.ListenAndServe(address, router))
}()
log.Println("*** API: Starting API dispatcher #1. Listening on", address)

if address != "" {
wg.Add(1)
go func(wg *sync.WaitGroup) {
log.Println("*** API: Starting API dispatcher #1. Listening on", address)
wg.Done()
TEMExiter(http.ListenAndServe(address, router))
}(&wg)
}

if tlsaddress != "" {
if tlspossible {
wg.Add(1)
go func(wg *sync.WaitGroup) {
log.Println("Starting TLS API dispatcher #1. Listening on", tlsaddress)
log.Println("*** API: Starting TLS API dispatcher #1. Listening on", tlsaddress)
wg.Done()
TEMExiter(tlsServer.ListenAndServeTLS(certfile, keyfile))
}(&wg)
} else {
log.Printf("*** API: APIdispatcher: Error: Cannot provide TLS service without cert and key files.\n")
}
}

if bootstrapaddress != "" {
wg.Add(1)
go func(wg *sync.WaitGroup) {
log.Println("*** API: Starting Bootstrap API dispatcher #1. Listening on", bootstrapaddress)
wg.Done()
TEMExiter(http.ListenAndServe(bootstrapaddress, bootstraprouter))
}(&wg)
} else {
log.Println("*** API: No bootstrap address specified")
}

if bootstraptlsaddress != "" {
if tlspossible {
wg.Add(1)
go func(wg *sync.WaitGroup) {
log.Println("*** API: Starting Bootstrap TLS API dispatcher #1. Listening on", bootstraptlsaddress)
wg.Done()
TEMExiter(bootstrapTlsServer.ListenAndServeTLS(certfile, keyfile))
}(&wg)
} else {
log.Printf("APIdispatch Error: Cannot provide TLS service without cert and key files.\n")
log.Printf("*** API: APIdispatcher: Error: Cannot provide Bootstrap TLS service without cert and key files.\n")
}
} else {
log.Println("*** API: No bootstrap TLS address specified")
}

wg.Wait()
log.Println("API dispatcher: unclear how to stop the http server nicely.")
}

Expand Down
Loading

0 comments on commit 1238710

Please sign in to comment.