2021-11-02 13:44:37 +00:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
2022-08-08 19:00:45 +00:00
|
|
|
"bytes"
|
2021-11-02 13:44:37 +00:00
|
|
|
"encoding/json"
|
2022-11-15 15:05:29 +00:00
|
|
|
"fmt"
|
2022-08-08 19:00:45 +00:00
|
|
|
"io"
|
2021-11-02 13:44:37 +00:00
|
|
|
"net/http"
|
2022-11-15 15:05:29 +00:00
|
|
|
"net/url"
|
|
|
|
"strconv"
|
2021-11-02 13:44:37 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"goauthentik.io/internal/config"
|
|
|
|
)
|
|
|
|
|
|
|
|
type SentryRequest struct {
|
|
|
|
DSN string `json:"dsn"`
|
|
|
|
}
|
|
|
|
|
2022-11-15 15:05:29 +00:00
|
|
|
func (ws *WebServer) APISentryProxy() http.HandlerFunc {
|
|
|
|
fallbackHandler := func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
}
|
2022-07-26 09:33:35 +00:00
|
|
|
if !config.Get().ErrorReporting.Enabled {
|
2021-11-02 13:44:37 +00:00
|
|
|
ws.log.Debug("error reporting disabled")
|
2022-11-15 15:05:29 +00:00
|
|
|
return fallbackHandler
|
2021-11-02 13:44:37 +00:00
|
|
|
}
|
2022-11-15 15:05:29 +00:00
|
|
|
dsn, err := url.Parse(config.Get().ErrorReporting.SentryDSN)
|
2021-11-02 13:44:37 +00:00
|
|
|
if err != nil {
|
2022-11-15 15:05:29 +00:00
|
|
|
ws.log.WithError(err).Warning("invalid sentry DSN")
|
|
|
|
return fallbackHandler
|
2021-11-02 13:44:37 +00:00
|
|
|
}
|
2022-11-15 15:05:29 +00:00
|
|
|
projectId, err := strconv.Atoi(strings.TrimPrefix(dsn.Path, "/"))
|
2021-11-02 13:44:37 +00:00
|
|
|
if err != nil {
|
2022-11-15 15:05:29 +00:00
|
|
|
ws.log.WithError(err).Warning("failed to get sentry project id")
|
|
|
|
return fallbackHandler
|
2021-11-02 13:44:37 +00:00
|
|
|
}
|
2022-11-15 15:05:29 +00:00
|
|
|
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)
|
2021-11-02 13:44:37 +00:00
|
|
|
}
|
|
|
|
}
|