Skip to content

Commit

Permalink
Switch to Flow router
Browse files Browse the repository at this point in the history
  • Loading branch information
jessepeterson committed Jan 16, 2023
1 parent cccf80a commit c2b2fdb
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 84 deletions.
215 changes: 132 additions & 83 deletions cmd/kmfddm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"time"

"github.com/alexedwards/flow"
"github.com/cespare/xxhash"
httpddm "github.com/jessepeterson/kmfddm/http"
apihttp "github.com/jessepeterson/kmfddm/http/api"
Expand All @@ -27,25 +28,6 @@ var version = "unknown"
const (
apiUsername = "kmfddm"
apiRealm = "kmfddm"

endpointVersion = "/version"

// DDM endpoints for devices/enrollments (passed from MDM)
endpointDeclaration = "/declaration/"
endpointDeclarationItems = "/declaration-items"
endpointTokens = "/tokens"
endpointStatus = "/status"

// API endpoints
endpointDeclarations = "/v1/declarations"
endpointDeclarationsID = "/v1/declarations/"
endpointSets = "/v1/sets"
endpointSetDeclarationsID = "/v1/set-declarations/"
endpointEnrollmentSetsID = "/v1/enrollment-sets/"
endpointDeclarationSetsID = "/v1/declaration-sets/"
endpointDeclarationStatusID = "/v1/declaration-status/"
endpointStatusErrorsID = "/v1/status-errors/"
endpointStatusValuesID = "/v1/status-values/"
)

func main() {
Expand All @@ -61,6 +43,7 @@ func main() {

flEnqueueURL = flag.String("enqueue", "http://[::1]:9000/v1/enqueue/", "URL of NanoMDM enqueue endpoint")
flEnqueueKey = flag.String("enqueue-key", "", "NanoMDM API key")
flCORSOrigin = flag.String("cors-origin", "", "CORS Origin; for browser-based API access")
)
flag.Parse()

Expand All @@ -86,80 +69,146 @@ func main() {

nanoNotif := notifier.New(storage, *flEnqueueURL, *flEnqueueKey, logger.With("service", "notifier"))

mux := http.NewServeMux()
mux := flow.New()

mux.Handle("/version", httpddm.VersionHandler(version))

mux.Handle(endpointVersion, httpddm.VersionHandler(version))
mux.Handle(
"/declaration-items",
ddmhttp.TokensDeclarationItemsHandler(storage, false, logger.With("handler", "declaration-items")),
"GET",
)

var diHandler http.Handler
diHandler = ddmhttp.TokensDeclarationItemsHandler(storage, false, logger.With("handler", "declaration-items"))
mux.Handle(endpointDeclarationItems, diHandler)
mux.Handle(
"/tokens",
ddmhttp.TokensDeclarationItemsHandler(storage, true, logger.With("handler", "tokens")),
"GET",
)

var tokHandler http.Handler
tokHandler = ddmhttp.TokensDeclarationItemsHandler(storage, true, logger.With("handler", "tokens"))
mux.Handle(endpointTokens, tokHandler)
mux.Handle(
"/declaration/:type/:id",
http.StripPrefix("/declaration/",
ddmhttp.DeclarationHandler(storage, logger.With("handler", "declaration")),
),
"GET",
)

var sHandler http.Handler
sHandler = ddmhttp.StatusReportHandler(storage, logger.With("handler", "status"))
var statusHandler http.Handler = ddmhttp.StatusReportHandler(storage, logger.With("handler", "status"))
if *flDumpStatus {
sHandler = DumpHandler(sHandler, os.Stdout)
statusHandler = DumpHandler(statusHandler, os.Stdout)
}
mux.Handle(endpointStatus, sHandler)

var dHandler http.Handler
dHandler = ddmhttp.DeclarationHandler(storage, logger.With("handler", "declaration"))
dHandler = http.StripPrefix(endpointDeclaration, dHandler)
mux.Handle(endpointDeclaration, dHandler)
mux.Handle("/status", statusHandler, "PUT")

if *flAPIKey != "" {
declsMux := httpddm.NewMethodMux()
declsMux.Handle("PUT", apihttp.PutDeclarationHandler(storage, nanoNotif, logger.With("handler", "put-declaration")))
declsMux.Handle("GET", apihttp.GetDeclarationsHandler(storage, logger.With("get-declarations")))
declsHandler := httpddm.BasicAuthMiddleware(declsMux, apiUsername, *flAPIKey, apiRealm)
mux.Handle(endpointDeclarations, declsHandler)

var setsHandler http.Handler
setsHandler = apihttp.GetSetsHandler(storage, logger.With("get-sets"))
setsHandler = httpddm.BasicAuthMiddleware(setsHandler, apiUsername, *flAPIKey, apiRealm)
mux.Handle(endpointSets, setsHandler)

handleStrippedAPI := func(prefix string, h http.Handler) {
h = http.StripPrefix(prefix, h)
h = httpddm.BasicAuthMiddleware(h, apiUsername, *flAPIKey, apiRealm)
mux.Handle(prefix, h)
if *flCORSOrigin != "" {
// for middleware to work on the OPTIONS method using flow router
// we must define a middleware on the "root" mux
mux.Use(func(h http.Handler) http.Handler {
return httpddm.CORSMiddleware(h, *flCORSOrigin)
})
}

declMux := httpddm.NewMethodMux()
declMux.Handle("GET", apihttp.GetDeclarationHandler(storage, logger.With("handler", "get-declaration")))
declMux.Handle("DELETE", apihttp.DeleteDeclarationHandler(storage, logger.With("handler", "delete-declaration")))
handleStrippedAPI(endpointDeclarationsID, declMux)

setDeclMux := httpddm.NewMethodMux()
setDeclMux.Handle("GET", apihttp.GetSetDeclarationsHandler(storage, logger.With("handler", "get-set-declarations")))
setDeclMux.Handle("PUT", apihttp.PutSetDeclarationHandler(storage, nanoNotif, logger.With("handler", "put-set-declarations")))
setDeclMux.Handle("DELETE", apihttp.DeleteSetDeclarationHandler(storage, nanoNotif, logger.With("handler", "delete-set-delcarations")))
handleStrippedAPI(endpointSetDeclarationsID, setDeclMux)

enrSetMux := httpddm.NewMethodMux()
enrSetMux.Handle("GET", apihttp.GetEnrollmentSetsHandler(storage, logger.With("handler", "get-enrollment-sets")))
enrSetMux.Handle("PUT", apihttp.PutEnrollmentSetHandler(storage, nanoNotif, logger.With("handler", "put-enrollment-sets")))
enrSetMux.Handle("DELETE", apihttp.DeleteEnrollmentSetHandler(storage, nanoNotif, logger.With("handler", "delete-enrollment-sets")))
handleStrippedAPI(endpointEnrollmentSetsID, enrSetMux)

var dsHandler http.Handler
dsHandler = apihttp.GetDeclarationSetsHandler(storage, logger.With("handler", "get-declaration-sets"))
handleStrippedAPI(endpointDeclarationSetsID, dsHandler)

var siHandler http.Handler
siHandler = apihttp.GetDeclarationStatusHandler(storage, logger.With("handler", "get-declaration-status"))
handleStrippedAPI(endpointDeclarationStatusID, siHandler)

var seHandler http.Handler
seHandler = apihttp.GetStatusErrorsHandler(storage, logger.With("handler", "get-status-errors"))
handleStrippedAPI(endpointStatusErrorsID, seHandler)

var svHandler http.Handler
svHandler = apihttp.GetStatusValuesHandler(storage, logger.With("handler", "get-status-values"))
handleStrippedAPI(endpointStatusValuesID, svHandler)
mux.Group(func(mux *flow.Mux) {
mux.Use(func(h http.Handler) http.Handler {
return httpddm.BasicAuthMiddleware(h, apiUsername, *flAPIKey, apiRealm)
})

// declarations
mux.Handle(
"/v1/declarations",
apihttp.GetDeclarationsHandler(storage, logger.With("get-declarations")),
"GET",
)

mux.Handle(
"/v1/declarations",
apihttp.PutDeclarationHandler(storage, nanoNotif, logger.With("handler", "put-declaration")),
"PUT",
)

mux.Handle(
"/v1/declarations/:id",
apihttp.GetDeclarationHandler(storage, logger.With("handler", "get-declaration")),
"GET",
)

mux.Handle(
"/v1/declarations/:id",
apihttp.DeleteDeclarationHandler(storage, logger.With("handler", "delete-declaration")),
"DELETE",
)

// sets
mux.Handle(
"/v1/sets",
apihttp.GetSetsHandler(storage, logger.With("get-sets")),
"GET",
)

// set declarations
mux.Handle(
"/v1/set-declarations/:id",
apihttp.GetSetDeclarationsHandler(storage, logger.With("handler", "get-set-declarations")),
"GET",
)

mux.Handle(
"/v1/set-declarations/:id",
apihttp.PutSetDeclarationHandler(storage, nanoNotif, logger.With("handler", "put-set-declarations")),
"PUT",
)

mux.Handle(
"/v1/set-declarations/:id",
apihttp.DeleteSetDeclarationHandler(storage, nanoNotif, logger.With("handler", "delete-set-delcarations")),
"DELETE",
)

// enrollment sets
mux.Handle(
"/v1/enrollment-sets/:id",
apihttp.GetEnrollmentSetsHandler(storage, logger.With("handler", "get-enrollment-sets")),
"GET",
)

mux.Handle(
"/v1/enrollment-sets/:id",
apihttp.PutEnrollmentSetHandler(storage, nanoNotif, logger.With("handler", "put-enrollment-sets")),
"PUT",
)

mux.Handle(
"/v1/enrollment-sets/:id",
apihttp.DeleteEnrollmentSetHandler(storage, nanoNotif, logger.With("handler", "delete-enrollment-sets")),
"DELETE",
)

// declarations sets
mux.Handle(
"/v1/declaration-sets/:id",
apihttp.GetDeclarationSetsHandler(storage, logger.With("handler", "get-declaration-sets")),
"GET",
)

// status queries
mux.Handle(
"/v1/declaration-status/:id",
apihttp.GetDeclarationStatusHandler(storage, logger.With("handler", "get-declaration-status")),
"GET",
)

mux.Handle(
"/v1/status-errors/:id",
apihttp.GetStatusErrorsHandler(storage, logger.With("handler", "get-status-errors")),
"GET",
)

mux.Handle(
"/v1/status-values/:id",
apihttp.GetStatusValuesHandler(storage, logger.With("handler", "get-status-values")),
"GET",
)
})
}

// init for newTraceID()
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ require (
github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5
github.com/valyala/fastjson v1.6.3
)

require github.com/alexedwards/flow v0.0.0-20220806114457-cf11be9e0e03 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alexedwards/flow v0.0.0-20220806114457-cf11be9e0e03 h1:r07xZN3ENBWdxGuU/feCsnpsgHJ7+3uLm7cq9S0sqoI=
github.com/alexedwards/flow v0.0.0-20220806114457-cf11be9e0e03/go.mod h1:1rjOQiOqQlmMdUMuvlJFjldqTnE/tQULE7qPIu4aq3U=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
Expand Down
3 changes: 2 additions & 1 deletion http/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
"net/url"

"github.com/alexedwards/flow"
"github.com/jessepeterson/kmfddm/log"
"github.com/jessepeterson/kmfddm/log/ctxlog"
)
Expand Down Expand Up @@ -108,7 +109,7 @@ func simpleChangeResourceHandler(logger log.Logger, chgFn func(context.Context,
}

func getResourceID(r *http.Request) string {
return r.URL.Path
return flow.Param(r.Context(), "id")
}

type Notifier interface {
Expand Down
15 changes: 15 additions & 0 deletions http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,18 @@ func TraceLoggingMiddleware(next http.Handler, logger log.Logger, traceID func(*
next.ServeHTTP(w, r.WithContext(ctx))
}
}

// CORSMiddleware adds "Access-Control-Allow-" headers to the response.
// Optionally specify an origin.
func CORSMiddleware(next http.Handler, origin string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
h := w.Header()
if origin != "" {
h.Add("Access-Control-Allow-Origin", origin)
}
h.Add("Access-Control-Allow-Headers", "Authorization")
h.Add("Access-Control-Allow-Credentials", "true")
h.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT")
next.ServeHTTP(w, r)
}
}

0 comments on commit c2b2fdb

Please sign in to comment.