mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
parent
1ec68b6917
commit
a82d01214d
4
go.mod
4
go.mod
@ -73,8 +73,8 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
|
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
|
||||||
github.com/gorilla/websocket v1.5.0 // @grafana/grafana-app-platform-squad
|
github.com/gorilla/websocket v1.5.0 // @grafana/grafana-app-platform-squad
|
||||||
github.com/grafana/alerting v0.0.0-20241010165806-807ddf183724 // @grafana/alerting-backend
|
github.com/grafana/alerting v0.0.0-20241010165806-807ddf183724 // @grafana/alerting-backend
|
||||||
github.com/grafana/authlib v0.0.0-20241014135010-3e1f37f75699 // @grafana/identity-access-team
|
github.com/grafana/authlib v0.0.0-20241018103850-afc1195d8240 // @grafana/identity-access-team
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0 // @grafana/identity-access-team
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e // @grafana/identity-access-team
|
||||||
github.com/grafana/codejen v0.0.3 // @grafana/dataviz-squad
|
github.com/grafana/codejen v0.0.3 // @grafana/dataviz-squad
|
||||||
github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code
|
github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code
|
||||||
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
||||||
|
8
go.sum
8
go.sum
@ -2244,10 +2244,10 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
|
|||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grafana/alerting v0.0.0-20241010165806-807ddf183724 h1:u+ZM5TLkdeEoSWXgYWxc4XRfPHhXpR63MyHXJxbBLrc=
|
github.com/grafana/alerting v0.0.0-20241010165806-807ddf183724 h1:u+ZM5TLkdeEoSWXgYWxc4XRfPHhXpR63MyHXJxbBLrc=
|
||||||
github.com/grafana/alerting v0.0.0-20241010165806-807ddf183724/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
github.com/grafana/alerting v0.0.0-20241010165806-807ddf183724/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||||
github.com/grafana/authlib v0.0.0-20241014135010-3e1f37f75699 h1:+xSpRpQPhMXAE9z68u0zMzzIa78jy1UqFb4tMJczFNc=
|
github.com/grafana/authlib v0.0.0-20241018103850-afc1195d8240 h1:bBn6sCbBjxjYlvs5JAIGHQSOs8xbDEBWbezxarA/DDo=
|
||||||
github.com/grafana/authlib v0.0.0-20241014135010-3e1f37f75699/go.mod h1:fhuI+ulquEIVcLsbwPml9JapWQzg8EYBp29HteO62DM=
|
github.com/grafana/authlib v0.0.0-20241018103850-afc1195d8240/go.mod h1:RKqhn8E5PY2k5Xo6X8FHFgP45/qt9qqfAY7YYJ2mtB8=
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0 h1:XT/WvQCWVVOvXRJy0SCQHkhxXFHNRJ3+jzhW5PutEk8=
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e h1:I0sSXcqdt/ttiOJ/BVhpfa2q/xAyWSweQwaypGmvLss=
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||||
github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw=
|
github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw=
|
||||||
github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s=
|
github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s=
|
||||||
github.com/grafana/cue v0.0.0-20230926092038-971951014e3f h1:TmYAMnqg3d5KYEAaT6PtTguL2GjLfvr6wnAX8Azw6tQ=
|
github.com/grafana/cue v0.0.0-20230926092038-971951014e3f h1:TmYAMnqg3d5KYEAaT6PtTguL2GjLfvr6wnAX8Azw6tQ=
|
||||||
|
@ -3,8 +3,8 @@ module github.com/grafana/grafana/pkg/apimachinery
|
|||||||
go 1.23.1
|
go 1.23.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/grafana/authlib v0.0.0-20241014135010-3e1f37f75699 // @grafana/identity-access-team
|
github.com/grafana/authlib v0.0.0-20241018103850-afc1195d8240 // @grafana/identity-access-team
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0 // @grafana/identity-access-team
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e // @grafana/identity-access-team
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
k8s.io/apimachinery v0.31.1
|
k8s.io/apimachinery v0.31.1
|
||||||
k8s.io/apiserver v0.31.1
|
k8s.io/apiserver v0.31.1
|
||||||
|
@ -28,10 +28,10 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
|||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/grafana/authlib v0.0.0-20241014135010-3e1f37f75699 h1:+xSpRpQPhMXAE9z68u0zMzzIa78jy1UqFb4tMJczFNc=
|
github.com/grafana/authlib v0.0.0-20241018103850-afc1195d8240 h1:bBn6sCbBjxjYlvs5JAIGHQSOs8xbDEBWbezxarA/DDo=
|
||||||
github.com/grafana/authlib v0.0.0-20241014135010-3e1f37f75699/go.mod h1:fhuI+ulquEIVcLsbwPml9JapWQzg8EYBp29HteO62DM=
|
github.com/grafana/authlib v0.0.0-20241018103850-afc1195d8240/go.mod h1:RKqhn8E5PY2k5Xo6X8FHFgP45/qt9qqfAY7YYJ2mtB8=
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0 h1:XT/WvQCWVVOvXRJy0SCQHkhxXFHNRJ3+jzhW5PutEk8=
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e h1:I0sSXcqdt/ttiOJ/BVhpfa2q/xAyWSweQwaypGmvLss=
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
@ -4,7 +4,7 @@ go 1.23.1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/go-cmp v0.6.0
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1
|
||||||
github.com/prometheus/client_golang v1.20.4
|
github.com/prometheus/client_golang v1.20.4
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
|
@ -78,8 +78,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0 h1:XT/WvQCWVVOvXRJy0SCQHkhxXFHNRJ3+jzhW5PutEk8=
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e h1:I0sSXcqdt/ttiOJ/BVhpfa2q/xAyWSweQwaypGmvLss=
|
||||||
github.com/grafana/authlib/claims v0.0.0-20240926100702-4aee62663da0/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
github.com/grafana/authlib/claims v0.0.0-20241018085709-130ad686d80e/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1 h1:ItDcDxUjVLPKja+hogpqgW/kj8LxUL2qscelXIsN1Bs=
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1 h1:ItDcDxUjVLPKja+hogpqgW/kj8LxUL2qscelXIsN1Bs=
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1/go.mod h1:DkxMin+qOh1Fgkxfbt+CUfBqqsCQJMG9op8Os/irBPA=
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1/go.mod h1:DkxMin+qOh1Fgkxfbt+CUfBqqsCQJMG9op8Os/irBPA=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
gfauthorizer "github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer"
|
gfauthorizer "github.com/grafana/grafana/pkg/services/apiserver/auth/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newLegacyAuthorizer(ac accesscontrol.AccessControl, store legacy.LegacyIdentityStore) (authorizer.Authorizer, claims.AccessClient) {
|
func newLegacyAuthorizer(ac accesscontrol.AccessControl, store legacy.LegacyIdentityStore) (authorizer.Authorizer, authz.AccessClient) {
|
||||||
client := accesscontrol.NewLegacyAccessClient(
|
client := accesscontrol.NewLegacyAccessClient(
|
||||||
ac,
|
ac,
|
||||||
accesscontrol.ResourceAuthorizerOptions{
|
accesscontrol.ResourceAuthorizerOptions{
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
|
||||||
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||||
"github.com/grafana/grafana/pkg/services/team"
|
"github.com/grafana/grafana/pkg/services/team"
|
||||||
@ -48,7 +48,7 @@ type ListFunc[T Resource] func(ctx context.Context, ns claims.NamespaceInfo, p P
|
|||||||
func List[T Resource](
|
func List[T Resource](
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
resourceName string,
|
resourceName string,
|
||||||
ac claims.AccessClient,
|
ac authz.AccessClient,
|
||||||
p Pagination,
|
p Pagination,
|
||||||
fn ListFunc[T],
|
fn ListFunc[T],
|
||||||
) (*ListResponse[T], error) {
|
) (*ListResponse[T], error) {
|
||||||
@ -62,11 +62,10 @@ func List[T Resource](
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
check := func(_ string, _ string) bool { return true }
|
check := func(_, _, _ string) bool { return true }
|
||||||
if ac != nil {
|
if ac != nil {
|
||||||
var err error
|
var err error
|
||||||
check, err = ac.Compile(ctx, ident, claims.AccessRequest{
|
check, err = ac.Compile(ctx, ident, authz.ListRequest{
|
||||||
Verb: utils.VerbList,
|
|
||||||
Resource: resourceName,
|
Resource: resourceName,
|
||||||
Namespace: ns.Value,
|
Namespace: ns.Value,
|
||||||
})
|
})
|
||||||
@ -84,7 +83,7 @@ func List[T Resource](
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range first.Items {
|
for _, item := range first.Items {
|
||||||
if !check(ns.Value, item.AuthID()) {
|
if !check(ns.Value, item.AuthID(), "") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
res.Items = append(res.Items, item)
|
res.Items = append(res.Items, item)
|
||||||
@ -107,7 +106,7 @@ outer:
|
|||||||
break outer
|
break outer
|
||||||
}
|
}
|
||||||
|
|
||||||
if !check(ns.Value, item.AuthID()) {
|
if !check(ns.Value, item.AuthID(), "") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +40,6 @@ func NewLegacySQLStores(sql legacysql.LegacyDatabaseProvider) LegacyIdentityStor
|
|||||||
|
|
||||||
type legacySQLStore struct {
|
type legacySQLStore struct {
|
||||||
sql legacysql.LegacyDatabaseProvider
|
sql legacysql.LegacyDatabaseProvider
|
||||||
ac claims.AccessClient
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *legacySQLStore) WithAccessClient(ac claims.AccessClient) {
|
|
||||||
s.ac = ac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Templates setup.
|
// Templates setup.
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
common "k8s.io/kube-openapi/pkg/common"
|
common "k8s.io/kube-openapi/pkg/common"
|
||||||
|
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
@ -32,7 +32,7 @@ var _ builder.APIGroupBuilder = (*IdentityAccessManagementAPIBuilder)(nil)
|
|||||||
type IdentityAccessManagementAPIBuilder struct {
|
type IdentityAccessManagementAPIBuilder struct {
|
||||||
store legacy.LegacyIdentityStore
|
store legacy.LegacyIdentityStore
|
||||||
authorizer authorizer.Authorizer
|
authorizer authorizer.Authorizer
|
||||||
accessClient claims.AccessClient
|
accessClient authz.AccessClient
|
||||||
|
|
||||||
// Not set for multi-tenant deployment for now
|
// Not set for multi-tenant deployment for now
|
||||||
sso ssosettings.Service
|
sso ssosettings.Service
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||||
@ -28,13 +29,13 @@ var (
|
|||||||
|
|
||||||
var resource = iamv0.ServiceAccountResourceInfo
|
var resource = iamv0.ServiceAccountResourceInfo
|
||||||
|
|
||||||
func NewLegacyStore(store legacy.LegacyIdentityStore, ac claims.AccessClient) *LegacyStore {
|
func NewLegacyStore(store legacy.LegacyIdentityStore, ac authz.AccessClient) *LegacyStore {
|
||||||
return &LegacyStore{store, ac}
|
return &LegacyStore{store, ac}
|
||||||
}
|
}
|
||||||
|
|
||||||
type LegacyStore struct {
|
type LegacyStore struct {
|
||||||
store legacy.LegacyIdentityStore
|
store legacy.LegacyIdentityStore
|
||||||
ac claims.AccessClient
|
ac authz.AccessClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LegacyStore) New() runtime.Object {
|
func (s *LegacyStore) New() runtime.Object {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||||
@ -29,13 +30,13 @@ var (
|
|||||||
|
|
||||||
var resource = iamv0.TeamResourceInfo
|
var resource = iamv0.TeamResourceInfo
|
||||||
|
|
||||||
func NewLegacyStore(store legacy.LegacyIdentityStore, ac claims.AccessClient) *LegacyStore {
|
func NewLegacyStore(store legacy.LegacyIdentityStore, ac authz.AccessClient) *LegacyStore {
|
||||||
return &LegacyStore{store, ac}
|
return &LegacyStore{store, ac}
|
||||||
}
|
}
|
||||||
|
|
||||||
type LegacyStore struct {
|
type LegacyStore struct {
|
||||||
store legacy.LegacyIdentityStore
|
store legacy.LegacyIdentityStore
|
||||||
ac claims.AccessClient
|
ac authz.AccessClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LegacyStore) New() runtime.Object {
|
func (s *LegacyStore) New() runtime.Object {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||||
@ -29,13 +30,13 @@ var (
|
|||||||
|
|
||||||
var resource = iamv0.UserResourceInfo
|
var resource = iamv0.UserResourceInfo
|
||||||
|
|
||||||
func NewLegacyStore(store legacy.LegacyIdentityStore, ac claims.AccessClient) *LegacyStore {
|
func NewLegacyStore(store legacy.LegacyIdentityStore, ac authz.AccessClient) *LegacyStore {
|
||||||
return &LegacyStore{store, ac}
|
return &LegacyStore{store, ac}
|
||||||
}
|
}
|
||||||
|
|
||||||
type LegacyStore struct {
|
type LegacyStore struct {
|
||||||
store legacy.LegacyIdentityStore
|
store legacy.LegacyIdentityStore
|
||||||
ac claims.AccessClient
|
ac authz.AccessClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LegacyStore) New() runtime.Object {
|
func (s *LegacyStore) New() runtime.Object {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
@ -44,7 +45,7 @@ type ResourceAuthorizerOptions struct {
|
|||||||
Resolver ResourceResolver
|
Resolver ResourceResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ claims.AccessClient = (*LegacyAccessClient)(nil)
|
var _ authz.AccessClient = (*LegacyAccessClient)(nil)
|
||||||
|
|
||||||
func NewLegacyAccessClient(ac AccessControl, opts ...ResourceAuthorizerOptions) *LegacyAccessClient {
|
func NewLegacyAccessClient(ac AccessControl, opts ...ResourceAuthorizerOptions) *LegacyAccessClient {
|
||||||
stored := map[string]ResourceAuthorizerOptions{}
|
stored := map[string]ResourceAuthorizerOptions{}
|
||||||
@ -82,35 +83,34 @@ type LegacyAccessClient struct {
|
|||||||
opts map[string]ResourceAuthorizerOptions
|
opts map[string]ResourceAuthorizerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasAccess implements claims.AccessClient.
|
func (c *LegacyAccessClient) Check(ctx context.Context, id claims.AuthInfo, req authz.CheckRequest) (authz.CheckResponse, error) {
|
||||||
func (c *LegacyAccessClient) HasAccess(ctx context.Context, id claims.AuthInfo, req claims.AccessRequest) (bool, error) {
|
|
||||||
ident, ok := id.(identity.Requester)
|
ident, ok := id.(identity.Requester)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, errors.New("expected identity.Requester for legacy access control")
|
return authz.CheckResponse{}, errors.New("expected identity.Requester for legacy access control")
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, ok := c.opts[req.Resource]
|
opts, ok := c.opts[req.Resource]
|
||||||
if !ok {
|
if !ok {
|
||||||
// For now we fallback to grafana admin if no options are found for resource.
|
// For now we fallback to grafana admin if no options are found for resource.
|
||||||
if ident.GetIsGrafanaAdmin() {
|
if ident.GetIsGrafanaAdmin() {
|
||||||
return true, nil
|
return authz.CheckResponse{Allowed: true}, nil
|
||||||
}
|
}
|
||||||
return false, nil
|
return authz.CheckResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
skip := opts.Unchecked[req.Verb]
|
skip := opts.Unchecked[req.Verb]
|
||||||
if skip {
|
if skip {
|
||||||
return true, nil
|
return authz.CheckResponse{Allowed: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
action, ok := opts.Mapping[req.Verb]
|
action, ok := opts.Mapping[req.Verb]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, fmt.Errorf("missing action for %s %s", req.Verb, req.Resource)
|
return authz.CheckResponse{}, fmt.Errorf("missing action for %s %s", req.Verb, req.Resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
ns, err := claims.ParseNamespace(req.Namespace)
|
ns, err := claims.ParseNamespace(req.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return authz.CheckResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var eval Evaluator
|
var eval Evaluator
|
||||||
@ -118,7 +118,7 @@ func (c *LegacyAccessClient) HasAccess(ctx context.Context, id claims.AuthInfo,
|
|||||||
if opts.Resolver != nil {
|
if opts.Resolver != nil {
|
||||||
scopes, err := opts.Resolver.Resolve(ctx, ns, req.Name)
|
scopes, err := opts.Resolver.Resolve(ctx, ns, req.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return authz.CheckResponse{}, err
|
||||||
}
|
}
|
||||||
eval = EvalPermission(action, scopes...)
|
eval = EvalPermission(action, scopes...)
|
||||||
} else {
|
} else {
|
||||||
@ -129,14 +129,18 @@ func (c *LegacyAccessClient) HasAccess(ctx context.Context, id claims.AuthInfo,
|
|||||||
eval = EvalPermission(action)
|
eval = EvalPermission(action)
|
||||||
} else {
|
} else {
|
||||||
// Assuming that all non list request should have a valid name
|
// Assuming that all non list request should have a valid name
|
||||||
return false, fmt.Errorf("unhandled authorization: %s %s", req.Group, req.Verb)
|
return authz.CheckResponse{}, fmt.Errorf("unhandled authorization: %s %s", req.Group, req.Verb)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.ac.Evaluate(ctx, ident, eval)
|
allowed, err := c.ac.Evaluate(ctx, ident, eval)
|
||||||
|
if err != nil {
|
||||||
|
return authz.CheckResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return authz.CheckResponse{Allowed: allowed}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile implements claims.AccessClient.
|
func (c *LegacyAccessClient) Compile(ctx context.Context, id claims.AuthInfo, req authz.ListRequest) (authz.ItemChecker, error) {
|
||||||
func (c *LegacyAccessClient) Compile(ctx context.Context, id claims.AuthInfo, req claims.AccessRequest) (claims.AccessChecker, error) {
|
|
||||||
ident, ok := id.(identity.Requester)
|
ident, ok := id.(identity.Requester)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("expected identity.Requester for legacy access control")
|
return nil, errors.New("expected identity.Requester for legacy access control")
|
||||||
@ -147,13 +151,13 @@ func (c *LegacyAccessClient) Compile(ctx context.Context, id claims.AuthInfo, re
|
|||||||
return nil, fmt.Errorf("unsupported resource: %s", req.Resource)
|
return nil, fmt.Errorf("unsupported resource: %s", req.Resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
action, ok := opts.Mapping[req.Verb]
|
action, ok := opts.Mapping[utils.VerbList]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing action for %s %s", req.Verb, req.Resource)
|
return nil, fmt.Errorf("missing action for %s %s", utils.VerbList, req.Resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
check := Checker(ident, action)
|
check := Checker(ident, action)
|
||||||
return func(_, name string) bool {
|
return func(_, name, _ string) bool {
|
||||||
return check(fmt.Sprintf("%s:%s:%s", opts.Resource, opts.Attr, name))
|
return check(fmt.Sprintf("%s:%s:%s", opts.Resource, opts.Attr, name))
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||||
@ -14,20 +14,20 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
func TestLegacyAccessClient_Check(t *testing.T) {
|
||||||
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
|
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
|
||||||
|
|
||||||
t.Run("should reject when when no configuration for resource exist", func(t *testing.T) {
|
t.Run("should reject when when no configuration for resource exist", func(t *testing.T) {
|
||||||
a := accesscontrol.NewLegacyAccessClient(ac)
|
a := accesscontrol.NewLegacyAccessClient(ac)
|
||||||
|
|
||||||
ok, err := a.HasAccess(context.Background(), &identity.StaticRequester{}, claims.AccessRequest{
|
res, err := a.Check(context.Background(), &identity.StaticRequester{}, authz.CheckRequest{
|
||||||
Verb: "get",
|
Verb: "get",
|
||||||
Resource: "dashboards",
|
Resource: "dashboards",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Name: "1",
|
Name: "1",
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, false, ok)
|
assert.Equal(t, false, res.Allowed)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should reject when user don't have correct scope", func(t *testing.T) {
|
t.Run("should reject when user don't have correct scope", func(t *testing.T) {
|
||||||
@ -43,7 +43,7 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
accesscontrol.Permission{Action: "dashboards:read", Scope: "dashboards:uid:2"},
|
accesscontrol.Permission{Action: "dashboards:read", Scope: "dashboards:uid:2"},
|
||||||
)
|
)
|
||||||
|
|
||||||
ok, err := a.HasAccess(context.Background(), ident, claims.AccessRequest{
|
res, err := a.Check(context.Background(), ident, authz.CheckRequest{
|
||||||
Verb: "get",
|
Verb: "get",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Resource: "dashboards",
|
Resource: "dashboards",
|
||||||
@ -51,7 +51,7 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, false, ok)
|
assert.Equal(t, false, res.Allowed)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should just check action for list requests", func(t *testing.T) {
|
t.Run("should just check action for list requests", func(t *testing.T) {
|
||||||
@ -67,14 +67,14 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
accesscontrol.Permission{Action: "dashboards:read"},
|
accesscontrol.Permission{Action: "dashboards:read"},
|
||||||
)
|
)
|
||||||
|
|
||||||
ok, err := a.HasAccess(context.Background(), ident, claims.AccessRequest{
|
res, err := a.Check(context.Background(), ident, authz.CheckRequest{
|
||||||
Verb: "list",
|
Verb: "list",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Resource: "dashboards",
|
Resource: "dashboards",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, true, ok)
|
assert.Equal(t, true, res.Allowed)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should allow when user have correct scope", func(t *testing.T) {
|
t.Run("should allow when user have correct scope", func(t *testing.T) {
|
||||||
@ -90,7 +90,7 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
accesscontrol.Permission{Action: "dashboards:read", Scope: "dashboards:uid:1"},
|
accesscontrol.Permission{Action: "dashboards:read", Scope: "dashboards:uid:1"},
|
||||||
)
|
)
|
||||||
|
|
||||||
ok, err := a.HasAccess(context.Background(), ident, claims.AccessRequest{
|
res, err := a.Check(context.Background(), ident, authz.CheckRequest{
|
||||||
Verb: "get",
|
Verb: "get",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Resource: "dashboards",
|
Resource: "dashboards",
|
||||||
@ -98,7 +98,7 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, true, ok)
|
assert.Equal(t, true, res.Allowed)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should skip authorization for configured verb", func(t *testing.T) {
|
t.Run("should skip authorization for configured verb", func(t *testing.T) {
|
||||||
@ -115,7 +115,7 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
|
|
||||||
ident := newIdent(accesscontrol.Permission{})
|
ident := newIdent(accesscontrol.Permission{})
|
||||||
|
|
||||||
ok, err := a.HasAccess(context.Background(), ident, claims.AccessRequest{
|
res, err := a.Check(context.Background(), ident, authz.CheckRequest{
|
||||||
Verb: "get",
|
Verb: "get",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Resource: "dashboards",
|
Resource: "dashboards",
|
||||||
@ -123,9 +123,9 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, true, ok)
|
assert.Equal(t, true, res.Allowed)
|
||||||
|
|
||||||
ok, err = a.HasAccess(context.Background(), ident, claims.AccessRequest{
|
res, err = a.Check(context.Background(), ident, authz.CheckRequest{
|
||||||
Verb: "create",
|
Verb: "create",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Resource: "dashboards",
|
Resource: "dashboards",
|
||||||
@ -133,7 +133,7 @@ func TestLegacyAccessClient_HasAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, false, ok)
|
assert.Equal(t, false, res.Allowed)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,17 +4,18 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/grafana/authlib/authz"
|
||||||
"github.com/grafana/authlib/claims"
|
"github.com/grafana/authlib/claims"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewResourceAuthorizer(c claims.AccessClient) authorizer.Authorizer {
|
func NewResourceAuthorizer(c authz.AccessClient) authorizer.Authorizer {
|
||||||
return ResourceAuthorizer{c}
|
return ResourceAuthorizer{c}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceAuthorizer is used to translate authorizer.Authorizer calls to claims.AccessClient calls
|
// ResourceAuthorizer is used to translate authorizer.Authorizer calls to claims.AccessClient calls
|
||||||
type ResourceAuthorizer struct {
|
type ResourceAuthorizer struct {
|
||||||
c claims.AccessClient
|
c authz.AccessClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r ResourceAuthorizer) Authorize(ctx context.Context, attr authorizer.Attributes) (authorizer.Decision, string, error) {
|
func (r ResourceAuthorizer) Authorize(ctx context.Context, attr authorizer.Attributes) (authorizer.Decision, string, error) {
|
||||||
@ -27,7 +28,7 @@ func (r ResourceAuthorizer) Authorize(ctx context.Context, attr authorizer.Attri
|
|||||||
return authorizer.DecisionDeny, "", errors.New("no identity found for request")
|
return authorizer.DecisionDeny, "", errors.New("no identity found for request")
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, err := r.c.HasAccess(ctx, ident, claims.AccessRequest{
|
res, err := r.c.Check(ctx, ident, authz.CheckRequest{
|
||||||
Verb: attr.GetVerb(),
|
Verb: attr.GetVerb(),
|
||||||
Group: attr.GetAPIGroup(),
|
Group: attr.GetAPIGroup(),
|
||||||
Resource: attr.GetResource(),
|
Resource: attr.GetResource(),
|
||||||
@ -41,7 +42,7 @@ func (r ResourceAuthorizer) Authorize(ctx context.Context, attr authorizer.Attri
|
|||||||
return authorizer.DecisionDeny, "", err
|
return authorizer.DecisionDeny, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !res.Allowed {
|
||||||
return authorizer.DecisionDeny, "unauthorized request", nil
|
return authorizer.DecisionDeny, "unauthorized request", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
const authzServiceAudience = "authzService"
|
const authzServiceAudience = "authzService"
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
authzlib.Client
|
authzlib.AccessChecker
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProvideAuthZClient provides an AuthZ client and creates the AuthZ service.
|
// ProvideAuthZClient provides an AuthZ client and creates the AuthZ service.
|
||||||
@ -40,7 +40,7 @@ func ProvideAuthZClient(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var client authzlib.Client
|
var client Client
|
||||||
|
|
||||||
// Register the server
|
// Register the server
|
||||||
server, err := newLegacyServer(acSvc, features, grpcServer, tracer, authCfg)
|
server, err := newLegacyServer(acSvc, features, grpcServer, tracer, authCfg)
|
||||||
@ -86,7 +86,7 @@ func ProvideStandaloneAuthZClient(
|
|||||||
return newGrpcLegacyClient(authCfg.remoteAddress)
|
return newGrpcLegacyClient(authCfg.remoteAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInProcLegacyClient(server *legacyServer) (authzlib.Client, error) {
|
func newInProcLegacyClient(server *legacyServer) (authzlib.AccessChecker, error) {
|
||||||
noAuth := func(ctx context.Context) (context.Context, error) {
|
noAuth := func(ctx context.Context) (context.Context, error) {
|
||||||
return ctx, nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
@ -101,14 +101,14 @@ func newInProcLegacyClient(server *legacyServer) (authzlib.Client, error) {
|
|||||||
server,
|
server,
|
||||||
)
|
)
|
||||||
|
|
||||||
return authzlib.NewLegacyClient(
|
return authzlib.NewClient(
|
||||||
&authzlib.ClientConfig{},
|
&authzlib.ClientConfig{},
|
||||||
authzlib.WithGrpcConnectionLCOption(channel),
|
authzlib.WithGrpcConnectionClientOption(channel),
|
||||||
authzlib.WithDisableAccessTokenLCOption(),
|
authzlib.WithDisableAccessTokenClientOption(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGrpcLegacyClient(address string) (authzlib.Client, error) {
|
func newGrpcLegacyClient(address string) (authzlib.AccessChecker, error) {
|
||||||
// This client interceptor is a noop, as we don't send an access token
|
// This client interceptor is a noop, as we don't send an access token
|
||||||
grpcClientConfig := authnlib.GrpcClientConfig{}
|
grpcClientConfig := authnlib.GrpcClientConfig{}
|
||||||
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(&grpcClientConfig,
|
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(&grpcClientConfig,
|
||||||
@ -119,15 +119,15 @@ func newGrpcLegacyClient(address string) (authzlib.Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg := authzlib.ClientConfig{RemoteAddress: address}
|
cfg := authzlib.ClientConfig{RemoteAddress: address}
|
||||||
client, err := authzlib.NewLegacyClient(&cfg,
|
client, err := authzlib.NewClient(&cfg,
|
||||||
// TODO(drclau): make this configurable (e.g. allow to use insecure connections)
|
// TODO(drclau): make this configurable (e.g. allow to use insecure connections)
|
||||||
authzlib.WithGrpcDialOptionsLCOption(
|
authzlib.WithGrpcDialOptionsClientOption(
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
||||||
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
||||||
),
|
),
|
||||||
// TODO(drclau): remove this once we have access token support on-prem
|
// TODO(drclau): remove this once we have access token support on-prem
|
||||||
authzlib.WithDisableAccessTokenLCOption(),
|
authzlib.WithDisableAccessTokenClientOption(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -136,7 +136,7 @@ func newGrpcLegacyClient(address string) (authzlib.Client, error) {
|
|||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCloudLegacyClient(authCfg *Cfg) (authzlib.Client, error) {
|
func newCloudLegacyClient(authCfg *Cfg) (authzlib.AccessChecker, error) {
|
||||||
grpcClientConfig := authnlib.GrpcClientConfig{
|
grpcClientConfig := authnlib.GrpcClientConfig{
|
||||||
TokenClientConfig: &authnlib.TokenExchangeConfig{
|
TokenClientConfig: &authnlib.TokenExchangeConfig{
|
||||||
Token: authCfg.token,
|
Token: authCfg.token,
|
||||||
@ -154,9 +154,9 @@ func newCloudLegacyClient(authCfg *Cfg) (authzlib.Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clientCfg := authzlib.ClientConfig{RemoteAddress: authCfg.remoteAddress}
|
clientCfg := authzlib.ClientConfig{RemoteAddress: authCfg.remoteAddress}
|
||||||
client, err := authzlib.NewLegacyClient(&clientCfg,
|
client, err := authzlib.NewClient(&clientCfg,
|
||||||
// TODO(drclau): make this configurable (e.g. allow to use insecure connections)
|
// TODO(drclau): make this configurable (e.g. allow to use insecure connections)
|
||||||
authzlib.WithGrpcDialOptionsLCOption(
|
authzlib.WithGrpcDialOptionsClientOption(
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
||||||
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
||||||
|
@ -2,10 +2,9 @@ package authz
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
|
|
||||||
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
||||||
"github.com/grafana/authlib/claims"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
@ -16,14 +15,6 @@ import (
|
|||||||
|
|
||||||
var _ authzv1.AuthzServiceServer = (*legacyServer)(nil)
|
var _ authzv1.AuthzServiceServer = (*legacyServer)(nil)
|
||||||
|
|
||||||
type legacyServer struct {
|
|
||||||
authzv1.UnimplementedAuthzServiceServer
|
|
||||||
|
|
||||||
acSvc accesscontrol.Service
|
|
||||||
logger log.Logger
|
|
||||||
tracer tracing.Tracer
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLegacyServer(
|
func newLegacyServer(
|
||||||
acSvc accesscontrol.Service, features featuremgmt.FeatureToggles,
|
acSvc accesscontrol.Service, features featuremgmt.FeatureToggles,
|
||||||
grpcServer grpcserver.Provider, tracer tracing.Tracer, cfg *Cfg,
|
grpcServer grpcserver.Provider, tracer tracing.Tracer, cfg *Cfg,
|
||||||
@ -45,40 +36,15 @@ func newLegacyServer(
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *legacyServer) Read(ctx context.Context, req *authzv1.ReadRequest) (*authzv1.ReadResponse, error) {
|
type legacyServer struct {
|
||||||
ctx, span := s.tracer.Start(ctx, "authz.grpc.Read")
|
authzv1.UnimplementedAuthzServiceServer
|
||||||
defer span.End()
|
|
||||||
|
|
||||||
// FIXME: once we have access tokens, we need to do namespace validation here
|
acSvc accesscontrol.Service
|
||||||
|
logger log.Logger
|
||||||
action := req.GetAction()
|
tracer tracing.Tracer
|
||||||
subject := req.GetSubject()
|
}
|
||||||
namespace := req.GetNamespace() // TODO can we consider the stackID as the orgID?
|
|
||||||
|
func (l *legacyServer) Check(context.Context, *authzv1.CheckRequest) (*authzv1.CheckResponse, error) {
|
||||||
info, err := claims.ParseNamespace(namespace)
|
// FIXME: implement for legacy access control
|
||||||
if err != nil || info.OrgID == 0 {
|
return nil, errors.New("unimplemented")
|
||||||
return nil, fmt.Errorf("invalid namespace: %s", namespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxLogger := s.logger.FromContext(ctx)
|
|
||||||
ctxLogger.Debug("Read", "action", action, "subject", subject, "namespace", namespace)
|
|
||||||
|
|
||||||
permissions, err := s.acSvc.SearchUserPermissions(
|
|
||||||
ctx,
|
|
||||||
info.OrgID,
|
|
||||||
accesscontrol.SearchOptions{Action: action, TypedID: subject},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
ctxLogger.Error("failed to search user permissions", "error", err)
|
|
||||||
return nil, tracing.Errorf(span, "failed to search user permissions: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data := make([]*authzv1.ReadResponse_Data, 0, len(permissions))
|
|
||||||
for _, perm := range permissions {
|
|
||||||
data = append(data, &authzv1.ReadResponse_Data{Scope: perm.Scope})
|
|
||||||
}
|
|
||||||
return &authzv1.ReadResponse{
|
|
||||||
Data: data,
|
|
||||||
Found: len(data) > 0,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user