Skip to content

Commit

Permalink
Add proxy for network and resolution endpoints (#124)
Browse files Browse the repository at this point in the history
* Add proxy for network and resolution endpoints

Forward the requests to the network and resolution endpoints to the
Supervisor. This will allow the landing page to get insights when
the Supervisor detects issues on first startup (e.g. problematic
DNS servers). The network endpoint will allow to resolve these issues.

Note: This makes the two mentioned endpoints available unauthenticated.
However, the landing page will be replaced with Core as soon as it has
been downloaded, so this unauthenticated forwarding will only be during
a brief phase on initial setup. A bad actor could also just setup a new
user from the onboarding page at this point in time. So this effectly
does not change the security posture.

* Be less verbose in proxying
  • Loading branch information
agners authored Oct 3, 2024
1 parent 6ebe22a commit b7bbad6
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
55 changes: 55 additions & 0 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import (
"io"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"path"
"regexp"
"strings"
)

var regexASCII = regexp.MustCompile(`\[\d+m`)
Expand Down Expand Up @@ -48,3 +52,54 @@ func httpLogs(w http.ResponseWriter, r *http.Request) {
logs := regexASCII.ReplaceAllLiteralString(string(data), "")
w.Write([]byte(logs))
}

func httpSupervisorProxy(w http.ResponseWriter, r *http.Request) {
log.Printf("Proxy request: %s", r.URL.Path)

// Base Supervisor URL
u, err := url.Parse("http://supervisor/")
if err != nil {
// Handle error in parsing URL
w.Write([]byte(err.Error()))
return
}

// Strip "/supervisor/" from the path
trimmedPath := strings.TrimPrefix(r.URL.Path, "/supervisor/")

// Split the path into parts, the first part is the subpath (e.g., resolution or network)
parts := strings.SplitN(trimmedPath, "/", 2)
if len(parts) < 2 {
http.Error(w, "Bad request: missing path", http.StatusBadRequest)
log.Printf("Invalid path: %s", r.URL.Path)
return
}

// Extract subpath (e.g., resolution or network)
subPath := parts[0]

// The remainder path (after the subpath) to be sanitized
remainderPath := "/" + parts[1]

// Clean the remainder path to avoid path traversal attacks
cleanPath := path.Clean(remainderPath)

// Ensure it's under the intended subpath (e.g., /resolution or /network)
if cleanPath != remainderPath {
http.Error(w, "Forbidden: Invalid path", http.StatusForbidden)
log.Printf("Blocked path traversal attempt: %s", cleanPath)
return
}

// Update the request path to be forwarded
r.URL.Path = "/" + subPath + cleanPath

// Create the reverse proxy
proxy := httputil.NewSingleHostReverseProxy(u)

// Add authorization header
r.Header.Add("Authorization", "Bearer "+os.Getenv("SUPERVISOR_TOKEN"))

// Forward the request
proxy.ServeHTTP(w, r)
}
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func main() {
http.HandleFunc("/api/", httpUnauthorized)
http.HandleFunc("/auth/token", httpBad)
http.HandleFunc("/observer/logs", httpLogs)
http.HandleFunc("/supervisor/resolution/", httpSupervisorProxy)
http.HandleFunc("/supervisor/network/", httpSupervisorProxy)

// Serve static help files
staticFiles := http.FileServer(http.Dir(wwwRoot))
Expand Down

0 comments on commit b7bbad6

Please sign in to comment.