Data source proxy: Convert 401 from data source to 400 (#28962)
* Data source proxy: Convert 401 from data source to 400 Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
@@ -98,13 +98,8 @@ func (proxy *DataSourceProxy) HandleRequest() {
|
||||
return
|
||||
}
|
||||
|
||||
proxyErrorLogger := logger.New("userId", proxy.ctx.UserId, "orgId", proxy.ctx.OrgId, "uname", proxy.ctx.Login, "path", proxy.ctx.Req.URL.Path, "remote_addr", proxy.ctx.RemoteAddr(), "referer", proxy.ctx.Req.Referer())
|
||||
|
||||
reverseProxy := &httputil.ReverseProxy{
|
||||
Director: proxy.getDirector(),
|
||||
FlushInterval: time.Millisecond * 200,
|
||||
ErrorLog: log.New(&logWrapper{logger: proxyErrorLogger}, "", 0),
|
||||
}
|
||||
proxyErrorLogger := logger.New("userId", proxy.ctx.UserId, "orgId", proxy.ctx.OrgId, "uname", proxy.ctx.Login,
|
||||
"path", proxy.ctx.Req.URL.Path, "remote_addr", proxy.ctx.RemoteAddr(), "referer", proxy.ctx.Req.Referer())
|
||||
|
||||
transport, err := proxy.ds.GetHttpTransport()
|
||||
if err != nil {
|
||||
@@ -112,16 +107,43 @@ func (proxy *DataSourceProxy) HandleRequest() {
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxy.Transport = &handleResponseTransport{
|
||||
transport: transport,
|
||||
reverseProxy := &httputil.ReverseProxy{
|
||||
Director: proxy.director,
|
||||
FlushInterval: time.Millisecond * 200,
|
||||
ErrorLog: log.New(&logWrapper{logger: proxyErrorLogger}, "", 0),
|
||||
Transport: &handleResponseTransport{
|
||||
transport: transport,
|
||||
},
|
||||
ModifyResponse: func(resp *http.Response) error {
|
||||
if resp.StatusCode == 401 {
|
||||
// The data source rejected the request as unauthorized, convert to 400 (bad request)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read data source response body: %w", err)
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
|
||||
proxyErrorLogger.Info("Authentication to data source failed", "body", string(body), "statusCode",
|
||||
resp.StatusCode)
|
||||
msg := "Authentication to data source failed"
|
||||
*resp = http.Response{
|
||||
StatusCode: 400,
|
||||
Status: "Bad Request",
|
||||
Body: ioutil.NopCloser(strings.NewReader(msg)),
|
||||
ContentLength: int64(len(msg)),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
proxy.logRequest()
|
||||
|
||||
span, ctx := opentracing.StartSpanFromContext(proxy.ctx.Req.Context(), "datasource reverse proxy")
|
||||
defer span.Finish()
|
||||
|
||||
proxy.ctx.Req.Request = proxy.ctx.Req.WithContext(ctx)
|
||||
|
||||
defer span.Finish()
|
||||
span.SetTag("datasource_id", proxy.ds.Id)
|
||||
span.SetTag("datasource_type", proxy.ds.Type)
|
||||
span.SetTag("user_id", proxy.ctx.SignedInUser.UserId)
|
||||
@@ -148,70 +170,65 @@ func (proxy *DataSourceProxy) addTraceFromHeaderValue(span opentracing.Span, hea
|
||||
}
|
||||
}
|
||||
|
||||
func (proxy *DataSourceProxy) getDirector() func(req *http.Request) {
|
||||
return func(req *http.Request) {
|
||||
req.URL.Scheme = proxy.targetUrl.Scheme
|
||||
req.URL.Host = proxy.targetUrl.Host
|
||||
req.Host = proxy.targetUrl.Host
|
||||
func (proxy *DataSourceProxy) director(req *http.Request) {
|
||||
req.URL.Scheme = proxy.targetUrl.Scheme
|
||||
req.URL.Host = proxy.targetUrl.Host
|
||||
req.Host = proxy.targetUrl.Host
|
||||
|
||||
reqQueryVals := req.URL.Query()
|
||||
reqQueryVals := req.URL.Query()
|
||||
|
||||
switch proxy.ds.Type {
|
||||
case models.DS_INFLUXDB_08:
|
||||
req.URL.Path = util.JoinURLFragments(proxy.targetUrl.Path, "db/"+proxy.ds.Database+"/"+proxy.proxyPath)
|
||||
reqQueryVals.Add("u", proxy.ds.User)
|
||||
reqQueryVals.Add("p", proxy.ds.DecryptedPassword())
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
case models.DS_INFLUXDB:
|
||||
req.URL.Path = util.JoinURLFragments(proxy.targetUrl.Path, proxy.proxyPath)
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
if !proxy.ds.BasicAuth {
|
||||
req.Header.Del("Authorization")
|
||||
req.Header.Add("Authorization", util.GetBasicAuthHeader(proxy.ds.User, proxy.ds.DecryptedPassword()))
|
||||
}
|
||||
default:
|
||||
req.URL.Path = util.JoinURLFragments(proxy.targetUrl.Path, proxy.proxyPath)
|
||||
switch proxy.ds.Type {
|
||||
case models.DS_INFLUXDB_08:
|
||||
req.URL.Path = util.JoinURLFragments(proxy.targetUrl.Path, "db/"+proxy.ds.Database+"/"+proxy.proxyPath)
|
||||
reqQueryVals.Add("u", proxy.ds.User)
|
||||
reqQueryVals.Add("p", proxy.ds.DecryptedPassword())
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
case models.DS_INFLUXDB:
|
||||
req.URL.Path = util.JoinURLFragments(proxy.targetUrl.Path, proxy.proxyPath)
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
if !proxy.ds.BasicAuth {
|
||||
req.Header.Set("Authorization", util.GetBasicAuthHeader(proxy.ds.User, proxy.ds.DecryptedPassword()))
|
||||
}
|
||||
default:
|
||||
req.URL.Path = util.JoinURLFragments(proxy.targetUrl.Path, proxy.proxyPath)
|
||||
}
|
||||
|
||||
if proxy.ds.BasicAuth {
|
||||
req.Header.Del("Authorization")
|
||||
req.Header.Add("Authorization", util.GetBasicAuthHeader(proxy.ds.BasicAuthUser, proxy.ds.DecryptedBasicAuthPassword()))
|
||||
if proxy.ds.BasicAuth {
|
||||
req.Header.Set("Authorization", util.GetBasicAuthHeader(proxy.ds.BasicAuthUser,
|
||||
proxy.ds.DecryptedBasicAuthPassword()))
|
||||
}
|
||||
|
||||
dsAuth := req.Header.Get("X-DS-Authorization")
|
||||
if len(dsAuth) > 0 {
|
||||
req.Header.Del("X-DS-Authorization")
|
||||
req.Header.Set("Authorization", dsAuth)
|
||||
}
|
||||
|
||||
applyUserHeader(proxy.cfg.SendUserHeader, req, proxy.ctx.SignedInUser)
|
||||
|
||||
keepCookieNames := []string{}
|
||||
if proxy.ds.JsonData != nil {
|
||||
if keepCookies := proxy.ds.JsonData.Get("keepCookies"); keepCookies != nil {
|
||||
keepCookieNames = keepCookies.MustStringArray()
|
||||
}
|
||||
}
|
||||
|
||||
dsAuth := req.Header.Get("X-DS-Authorization")
|
||||
if len(dsAuth) > 0 {
|
||||
req.Header.Del("X-DS-Authorization")
|
||||
req.Header.Del("Authorization")
|
||||
req.Header.Add("Authorization", dsAuth)
|
||||
}
|
||||
proxyutil.ClearCookieHeader(req, keepCookieNames)
|
||||
proxyutil.PrepareProxyRequest(req)
|
||||
|
||||
applyUserHeader(proxy.cfg.SendUserHeader, req, proxy.ctx.SignedInUser)
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", setting.BuildVersion))
|
||||
|
||||
keepCookieNames := []string{}
|
||||
if proxy.ds.JsonData != nil {
|
||||
if keepCookies := proxy.ds.JsonData.Get("keepCookies"); keepCookies != nil {
|
||||
keepCookieNames = keepCookies.MustStringArray()
|
||||
}
|
||||
}
|
||||
// Clear Origin and Referer to avoir CORS issues
|
||||
req.Header.Del("Origin")
|
||||
req.Header.Del("Referer")
|
||||
|
||||
proxyutil.ClearCookieHeader(req, keepCookieNames)
|
||||
proxyutil.PrepareProxyRequest(req)
|
||||
if proxy.route != nil {
|
||||
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.route, proxy.ds)
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", setting.BuildVersion))
|
||||
|
||||
// Clear Origin and Referer to avoir CORS issues
|
||||
req.Header.Del("Origin")
|
||||
req.Header.Del("Referer")
|
||||
|
||||
if proxy.route != nil {
|
||||
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.route, proxy.ds)
|
||||
}
|
||||
|
||||
if oauthtoken.IsOAuthPassThruEnabled(proxy.ds) {
|
||||
if token := oauthtoken.GetCurrentOAuthToken(proxy.ctx.Req.Context(), proxy.ctx.SignedInUser); token != nil {
|
||||
req.Header.Del("Authorization")
|
||||
req.Header.Add("Authorization", fmt.Sprintf("%s %s", token.Type(), token.AccessToken))
|
||||
}
|
||||
if oauthtoken.IsOAuthPassThruEnabled(proxy.ds) {
|
||||
if token := oauthtoken.GetCurrentOAuthToken(proxy.ctx.Req.Context(), proxy.ctx.SignedInUser); token != nil {
|
||||
req.Header.Set("Authorization", fmt.Sprintf("%s %s", token.Type(), token.AccessToken))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user