* make sentry DSN configurable Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * make proxy smarter Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix typo in config struct Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
		
			
				
	
	
		
			79 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package web
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"net/http"
 | 
						|
	"net/url"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"goauthentik.io/internal/config"
 | 
						|
)
 | 
						|
 | 
						|
type SentryRequest struct {
 | 
						|
	DSN string `json:"dsn"`
 | 
						|
}
 | 
						|
 | 
						|
func (ws *WebServer) APISentryProxy() http.HandlerFunc {
 | 
						|
	fallbackHandler := func(w http.ResponseWriter, r *http.Request) {
 | 
						|
		w.WriteHeader(http.StatusBadRequest)
 | 
						|
	}
 | 
						|
	if !config.Get().ErrorReporting.Enabled {
 | 
						|
		ws.log.Debug("error reporting disabled")
 | 
						|
		return fallbackHandler
 | 
						|
	}
 | 
						|
	dsn, err := url.Parse(config.Get().ErrorReporting.SentryDSN)
 | 
						|
	if err != nil {
 | 
						|
		ws.log.WithError(err).Warning("invalid sentry DSN")
 | 
						|
		return fallbackHandler
 | 
						|
	}
 | 
						|
	projectId, err := strconv.Atoi(strings.TrimPrefix(dsn.Path, "/"))
 | 
						|
	if err != nil {
 | 
						|
		ws.log.WithError(err).Warning("failed to get sentry project id")
 | 
						|
		return fallbackHandler
 | 
						|
	}
 | 
						|
	return func(rw http.ResponseWriter, r *http.Request) {
 | 
						|
		fb := &bytes.Buffer{}
 | 
						|
		_, err := io.Copy(fb, r.Body)
 | 
						|
		if err != nil {
 | 
						|
			ws.log.Debug("failed to read body")
 | 
						|
			rw.WriteHeader(http.StatusBadRequest)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		lines := strings.Split(fb.String(), "\n")
 | 
						|
		if len(lines) < 1 {
 | 
						|
			rw.WriteHeader(http.StatusBadRequest)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		sd := SentryRequest{}
 | 
						|
		err = json.Unmarshal([]byte(lines[0]), &sd)
 | 
						|
		if err != nil {
 | 
						|
			ws.log.WithError(err).Warning("failed to parse sentry request")
 | 
						|
			rw.WriteHeader(http.StatusBadRequest)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		if sd.DSN != config.Get().ErrorReporting.SentryDSN {
 | 
						|
			rw.WriteHeader(http.StatusBadRequest)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		res, err := http.DefaultClient.Post(
 | 
						|
			fmt.Sprintf(
 | 
						|
				"https://%s/api/%d/envelope/",
 | 
						|
				dsn.Host,
 | 
						|
				projectId,
 | 
						|
			),
 | 
						|
			"application/x-sentry-envelope",
 | 
						|
			fb,
 | 
						|
		)
 | 
						|
		if err != nil {
 | 
						|
			ws.log.WithError(err).Warning("failed to proxy sentry")
 | 
						|
			rw.WriteHeader(http.StatusBadRequest)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		rw.WriteHeader(res.StatusCode)
 | 
						|
	}
 | 
						|
}
 |