Skip to content
This repository has been archived by the owner on Jul 23, 2023. It is now read-only.

Commit

Permalink
log all sorts of rpc/http access errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
fiatjaf committed Aug 12, 2020
1 parent 082092e commit d9ff7de
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 54 deletions.
93 changes: 49 additions & 44 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"net/http"
"strings"

"github.com/fiatjaf/lightningd-gjson-rpc/plugin"
)

func defaultAuth(r *http.Request) error {
Expand Down Expand Up @@ -35,59 +37,62 @@ func defaultAuth(r *http.Request) error {
return fmt.Errorf("Invalid access key.")
}

func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, "/")
func authMiddleware(p *plugin.Plugin) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, "/")

if path == "" || path == "rpc" || path == "stream" {
// default key / login
if err := defaultAuth(r); err == nil {
// set cookie
user := strings.Split(login, ":")[0]
if encoded, err := scookie.Encode("user", user); err == nil {
cookie := &http.Cookie{
Name: "user",
Value: encoded,
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
MaxAge: 2592000,
if path == "" || path == "rpc" || path == "stream" {
// default key / login
if err := defaultAuth(r); err == nil {
// set cookie
user := strings.Split(login, ":")[0]
if encoded, err := scookie.Encode("user", user); err == nil {
cookie := &http.Cookie{
Name: "user",
Value: encoded,
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
MaxAge: 2592000,
}
http.SetCookie(w, cookie)
}
http.SetCookie(w, cookie)
}

next.ServeHTTP(w, r)
return
}
next.ServeHTTP(w, r)
return
}

// extra keys -- only access the /rpc and /stream endpoints
if path == "rpc" || path == "stream" {
for key, permissions := range keys {
if r.Header.Get("X-Access") == key ||
r.URL.Query().Get("access-key") == key {
// extra keys -- only access the /rpc and /stream endpoints
if path == "rpc" || path == "stream" {
for key, permissions := range keys {
if r.Header.Get("X-Access") == key ||
r.URL.Query().Get("access-key") == key {

r = r.WithContext(context.WithValue(
r.Context(),
"permissions", permissions,
))
r = r.WithContext(context.WithValue(
r.Context(),
"permissions", permissions,
))

next.ServeHTTP(w, r)
return
next.ServeHTTP(w, r)
return
}
}
}
}

w.Header().Set("WWW-Authenticate", `Basic realm="Private Area"`)
w.WriteHeader(401)
return
}
p.Logf("auth failed at /%s", path)
w.Header().Set("WWW-Authenticate", `Basic realm="Private Area"`)
w.WriteHeader(401)
return
}

// if you know where the manifest is you can have it
if manifestKey != "" && path == "manifest-"+manifestKey+"/manifest.json" {
r.URL.Path = "/manifest/manifest.json"
}
// if you know where the manifest is you can have it
if manifestKey != "" && path == "manifest-"+manifestKey+"/manifest.json" {
r.URL.Path = "/manifest/manifest.json"
}

next.ServeHTTP(w, r)
return
})
next.ServeHTTP(w, r)
return
})
}
}
10 changes: 2 additions & 8 deletions listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ func listen(p *plugin.Plugin, router http.Handler) {
},
Handler: router,
BaseContext: func(_ net.Listener) context.Context {
return context.WithValue(
context.Background(),
"client", p.Client,
)
return context.WithValue(context.Background(), "plugin", p)
},
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
}
Expand All @@ -74,10 +71,7 @@ func listen(p *plugin.Plugin, router http.Handler) {
Addr: host + ":" + port,
Handler: router,
BaseContext: func(_ net.Listener) context.Context {
return context.WithValue(
context.Background(),
"client", p.Client,
)
return context.WithValue(context.Background(), "plugin", p)
},
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
}
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func main() {
// declare routes
router := mux.NewRouter()

router.Use(authMiddleware)
router.Use(authMiddleware(p))
router.Use(gziphandler.GzipHandler)

router.Path("/stream").Methods("GET").Handler(
Expand Down
8 changes: 7 additions & 1 deletion rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import (
"time"

lightning "github.com/fiatjaf/lightningd-gjson-rpc"
"github.com/fiatjaf/lightningd-gjson-rpc/plugin"
)

func handleRPC(w http.ResponseWriter, r *http.Request) {
p := r.Context().Value("plugin").(*plugin.Plugin)

var req lightning.JSONRPCMessage
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
p.Log("got invalid JSON on RPC call")
w.WriteHeader(400)
return
}
Expand All @@ -22,15 +26,17 @@ func handleRPC(w http.ResponseWriter, r *http.Request) {
if permissions, ok := r.Context().Value("permissions").(map[string]bool); ok {
if len(permissions) > 0 {
if _, allowed := permissions[req.Method]; !allowed {
p.Logf("insufficient permissions for '%s' call", req.Method)
w.WriteHeader(401)
return
}
}
}

// actually do the call
respbytes, err := r.Context().Value("client").(*lightning.Client).CallMessageRaw(time.Second*30, req)
respbytes, err := p.Client.CallMessageRaw(time.Second*30, req)
if err != nil {
p.Logf("'%s' call returned an error", req.Method)
w.WriteHeader(500)

if cmderr, ok := err.(lightning.ErrorCommand); ok {
Expand Down

0 comments on commit d9ff7de

Please sign in to comment.