Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efe95b4c21 | ||
|
|
a14c2d674a | ||
|
|
262d642d77 | ||
|
|
5e6893c425 |
2
go.mod
2
go.mod
@@ -400,7 +400,7 @@ require (
|
||||
)
|
||||
|
||||
// Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream
|
||||
replace github.com/crewjam/saml => github.com/grafana/saml v0.4.13-0.20230203140620-5f476db5c00a
|
||||
replace github.com/crewjam/saml => github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6
|
||||
|
||||
// Thema's thema CLI requires cobra, which eventually works its way down to go-hclog@v1.0.0.
|
||||
// Upgrading affects backend plugins: https://github.com/grafana/grafana/pull/47653#discussion_r850508593
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1284,8 +1284,8 @@ github.com/grafana/phlare/api v0.1.3 h1:mYTaE9mLsAW/uzPXlW/PQSLsZ4ojBFA+oAMfR/PD
|
||||
github.com/grafana/phlare/api v0.1.3/go.mod h1:29vcLwFDmZBDce2jwFIMtzvof7fzPadT8VMKw9ks7FU=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20230308154952-78fedf89728b h1:VQOGGGJ2lKcVPANyzIESKYhSeA0QIvUQwfA3CbrkDfA=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20230308154952-78fedf89728b/go.mod h1:MnBfDPXJqXmmfPwQlCLvVUdqfnvrAw+hSPtDeaaFwj4=
|
||||
github.com/grafana/saml v0.4.13-0.20230203140620-5f476db5c00a h1:aWSTt/pTOI4uGY9DhBMG1l0GOnGjIYtaqxzYR3/q82o=
|
||||
github.com/grafana/saml v0.4.13-0.20230203140620-5f476db5c00a/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
|
||||
github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6 h1:oHn/OOUkECNX06DPHksS7R3UY5Qdye04b/sBj2/OJ5E=
|
||||
github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA=
|
||||
github.com/grafana/sqlds/v2 v2.3.10 h1:HWKhE0vR6LoEiE+Is8CSZOgaB//D1yqb2ntkass9Fd4=
|
||||
github.com/grafana/sqlds/v2 v2.3.10/go.mod h1:c6ibxnxRVGxV/0YkEgvy7QpQH/lyifFyV7K/14xvdIs=
|
||||
github.com/grafana/thema v0.0.0-20230302221249-6952e4a999b7 h1:XOxaBjhozlleshff3mKNdp55ul74nXJEX3wz8ckjTpc=
|
||||
|
||||
@@ -206,6 +206,14 @@ var Versions = VersionMap{
|
||||
},
|
||||
CloudMode: {
|
||||
Variants: []Variant{
|
||||
VariantArmV6,
|
||||
VariantArmV7,
|
||||
VariantArmV7Musl,
|
||||
VariantArm64,
|
||||
VariantArm64Musl,
|
||||
VariantDarwinAmd64,
|
||||
VariantWindowsAmd64,
|
||||
VariantLinuxAmd64,
|
||||
VariantLinuxAmd64Musl,
|
||||
},
|
||||
PluginSignature: PluginSignature{
|
||||
@@ -216,9 +224,12 @@ var Versions = VersionMap{
|
||||
ShouldSave: true,
|
||||
Architectures: []Architecture{
|
||||
ArchAMD64,
|
||||
ArchARM64,
|
||||
ArchARMv7,
|
||||
},
|
||||
Distribution: []Distribution{
|
||||
Alpine,
|
||||
Ubuntu,
|
||||
},
|
||||
PrereleaseBucket: "grafana-prerelease/artifacts/docker",
|
||||
},
|
||||
|
||||
@@ -19,6 +19,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
|
||||
const authQueryParamName = "auth_token"
|
||||
|
||||
var _ authn.ContextAwareClient = new(JWT)
|
||||
|
||||
var (
|
||||
@@ -50,6 +52,7 @@ func (s *JWT) Name() string {
|
||||
|
||||
func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identity, error) {
|
||||
jwtToken := s.retrieveToken(r.HTTPRequest)
|
||||
s.stripSensitiveParam(r.HTTPRequest)
|
||||
|
||||
claims, err := s.jwtService.Verify(ctx, jwtToken)
|
||||
if err != nil {
|
||||
@@ -120,6 +123,18 @@ func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identi
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// remove sensitive query param
|
||||
// avoid JWT URL login passing auth_token in URL
|
||||
func (s *JWT) stripSensitiveParam(httpRequest *http.Request) {
|
||||
if s.cfg.JWTAuthURLLogin {
|
||||
params := httpRequest.URL.Query()
|
||||
if params.Has(authQueryParamName) {
|
||||
params.Del(authQueryParamName)
|
||||
httpRequest.URL.RawQuery = params.Encode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// retrieveToken retrieves the JWT token from the request.
|
||||
func (s *JWT) retrieveToken(httpRequest *http.Request) string {
|
||||
jwtToken := httpRequest.Header.Get(s.cfg.JWTAuthHeaderName)
|
||||
|
||||
@@ -307,3 +307,47 @@ func TestJWTTest(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWTStripParam(t *testing.T) {
|
||||
jwtService := &jwt.FakeJWTService{
|
||||
VerifyProvider: func(context.Context, string) (jwt.JWTClaims, error) {
|
||||
return jwt.JWTClaims{
|
||||
"sub": "1234567890",
|
||||
"email": "eai.doe@cor.po",
|
||||
"preferred_username": "eai-doe",
|
||||
"name": "Eai Doe",
|
||||
"roles": "Admin",
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
jwtHeaderName := "X-Forwarded-User"
|
||||
|
||||
cfg := &setting.Cfg{
|
||||
JWTAuthEnabled: true,
|
||||
JWTAuthHeaderName: jwtHeaderName,
|
||||
JWTAuthAutoSignUp: true,
|
||||
JWTAuthAllowAssignGrafanaAdmin: true,
|
||||
JWTAuthURLLogin: true,
|
||||
JWTAuthRoleAttributeStrict: false,
|
||||
JWTAuthRoleAttributePath: "roles",
|
||||
JWTAuthEmailClaim: "email",
|
||||
JWTAuthUsernameClaim: "preferred_username",
|
||||
}
|
||||
|
||||
// #nosec G101 -- This is a dummy/test token
|
||||
token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o"
|
||||
|
||||
httpReq := &http.Request{
|
||||
URL: &url.URL{RawQuery: "auth_token=" + token + "&other_param=other_value"},
|
||||
}
|
||||
jwtClient := ProvideJWT(jwtService, cfg)
|
||||
_, err := jwtClient.Authenticate(context.Background(), &authn.Request{
|
||||
OrgID: 1,
|
||||
HTTPRequest: httpReq,
|
||||
Resp: nil,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// auth_token should be removed from the query string
|
||||
assert.Equal(t, "other_param=other_value", httpReq.URL.RawQuery)
|
||||
}
|
||||
|
||||
@@ -15,12 +15,14 @@ import (
|
||||
loginsvc "github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
InvalidJWT = "Invalid JWT"
|
||||
InvalidRole = "Invalid Role"
|
||||
UserNotFound = "User not found"
|
||||
InvalidJWT = "Invalid JWT"
|
||||
InvalidRole = "Invalid Role"
|
||||
UserNotFound = "User not found"
|
||||
authQueryParamName = "auth_token"
|
||||
)
|
||||
|
||||
func (h *ContextHandler) initContextWithJWT(ctx *contextmodel.ReqContext, orgId int64) bool {
|
||||
@@ -30,13 +32,15 @@ func (h *ContextHandler) initContextWithJWT(ctx *contextmodel.ReqContext, orgId
|
||||
|
||||
jwtToken := ctx.Req.Header.Get(h.Cfg.JWTAuthHeaderName)
|
||||
if jwtToken == "" && h.Cfg.JWTAuthURLLogin {
|
||||
jwtToken = ctx.Req.URL.Query().Get("auth_token")
|
||||
jwtToken = ctx.Req.URL.Query().Get(authQueryParamName)
|
||||
}
|
||||
|
||||
if jwtToken == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
stripSensitiveParam(h.Cfg, ctx.Req)
|
||||
|
||||
// Strip the 'Bearer' prefix if it exists.
|
||||
jwtToken = strings.TrimPrefix(jwtToken, "Bearer ")
|
||||
|
||||
@@ -204,3 +208,15 @@ func searchClaimsForStringAttr(attributePath string, claims map[string]interface
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// remove sensitive query params
|
||||
// avoid JWT URL login passing auth_token in URL
|
||||
func stripSensitiveParam(cfg *setting.Cfg, httpRequest *http.Request) {
|
||||
if cfg.JWTAuthURLLogin {
|
||||
params := httpRequest.URL.Query()
|
||||
if params.Has(authQueryParamName) {
|
||||
params.Del(authQueryParamName)
|
||||
httpRequest.URL.RawQuery = params.Encode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Map as OpenLayersMap } from 'ol';
|
||||
import { FeatureLike } from 'ol/Feature';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { getFrameMatchers, MapLayerHandler, MapLayerOptions, PanelData } from '@grafana/data/src';
|
||||
import { getFrameMatchers, MapLayerHandler, MapLayerOptions, PanelData, textUtil } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime/src';
|
||||
|
||||
import { GeomapPanel } from '../GeomapPanel';
|
||||
@@ -114,6 +114,10 @@ export async function initLayer(
|
||||
return Promise.reject('unknown layer: ' + options.type);
|
||||
}
|
||||
|
||||
if (options.config?.attribution) {
|
||||
options.config.attribution = textUtil.sanitizeTextPanelContent(options.config.attribution);
|
||||
}
|
||||
|
||||
const handler = await item.create(map, options, panel.props.eventBus, config.theme2);
|
||||
const layer = handler.init(); // eslint-disable-line
|
||||
if (options.opacity != null) {
|
||||
|
||||
Reference in New Issue
Block a user