mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
K8s: Refactor authorization initialization (#79670)
This commit is contained in:
parent
ba69d32fa5
commit
33d2d0a12d
@ -179,31 +179,3 @@ The following toggles require explicitly setting Grafana's [app mode]({{< relref
|
|||||||
| `externalServiceAccounts` | Automatic service account and token setup for plugins |
|
| `externalServiceAccounts` | Automatic service account and token setup for plugins |
|
||||||
| `panelTitleSearchInV1` | Enable searching for dashboards using panel title in search v1 |
|
| `panelTitleSearchInV1` | Enable searching for dashboards using panel title in search v1 |
|
||||||
| `ssoSettingsApi` | Enables the SSO settings API |
|
| `ssoSettingsApi` | Enables the SSO settings API |
|
||||||
|
|
||||||
## Configure feature management
|
|
||||||
|
|
||||||
**Feature toggles** is an Administration page that allows authorized users to view and toggle the feature flags available in their Grafana instance. For more information, refer to [Feature toggles](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/administration/feature-toggles/).
|
|
||||||
|
|
||||||
By default, feature toggles are in read-only mode.
|
|
||||||
Granting admin users the ability to alter the states of feature toggles requires configuring Grafana with the optional [`allow_editing`](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#allow_editing), [`update_webhook`](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#update_webhook) and [`update_webhook_token`](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#update_webhook_token) settings.
|
|
||||||
|
|
||||||
Those configurations allow the Grafana operator to set up a webhook that Grafana must call to propagate the configuration change.
|
|
||||||
|
|
||||||
**Example request**:
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST $update_webhook
|
|
||||||
Accept: application/json
|
|
||||||
Content-Type: application/json
|
|
||||||
Authorization: Bearer $update_webhook_token
|
|
||||||
|
|
||||||
{
|
|
||||||
"feature_toggles": [
|
|
||||||
{
|
|
||||||
"featureToggle1": "true",
|
|
||||||
"featureToggle2": "false",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"user": "admin@example.test",
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package example
|
package example
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
@ -19,6 +21,7 @@ import (
|
|||||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||||
|
|
||||||
example "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
example "github.com/grafana/grafana/pkg/apis/example/v0alpha1"
|
||||||
|
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||||
)
|
)
|
||||||
@ -195,3 +198,20 @@ func (b *TestingAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *TestingAPIBuilder) GetAuthorizer() authorizer.Authorizer {
|
||||||
|
return authorizer.AuthorizerFunc(
|
||||||
|
func(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
|
if !attr.IsResourceRequest() {
|
||||||
|
return authorizer.DecisionNoOpinion, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// require a user
|
||||||
|
_, err = appcontext.User(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return authorizer.DecisionDeny, "valid user is required", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizer.DecisionNoOpinion, "", err // fallback to org/role logic
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
@ -130,3 +131,7 @@ func (b *PlaylistAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinition
|
|||||||
func (b *PlaylistAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes {
|
func (b *PlaylistAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes {
|
||||||
return nil // no custom API routes
|
return nil // no custom API routes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *PlaylistAPIBuilder) GetAuthorizer() authorizer.Authorizer {
|
||||||
|
return nil // default authorizer is fine
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package impersonation
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -6,12 +6,12 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ authorizer.Authorizer = (*ImpersonationAuthorizer)(nil)
|
var _ authorizer.Authorizer = (*impersonationAuthorizer)(nil)
|
||||||
|
|
||||||
// ImpersonationAuthorizer denies all impersonation requests.
|
// ImpersonationAuthorizer denies all impersonation requests.
|
||||||
type ImpersonationAuthorizer struct{}
|
type impersonationAuthorizer struct{}
|
||||||
|
|
||||||
func (auth ImpersonationAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
func (auth impersonationAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
if a.GetVerb() == "impersonate" {
|
if a.GetVerb() == "impersonate" {
|
||||||
return authorizer.DecisionDeny, "user impersonation is not supported", nil
|
return authorizer.DecisionDeny, "user impersonation is not supported", nil
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package impersonation_test
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -6,12 +6,10 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer/impersonation"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestImpersonationAuthorizer_Authorize(t *testing.T) {
|
func TestImpersonationAuthorizer_Authorize(t *testing.T) {
|
||||||
auth := impersonation.ImpersonationAuthorizer{}
|
auth := impersonationAuthorizer{}
|
||||||
|
|
||||||
t.Run("impersonate verb", func(t *testing.T) {
|
t.Run("impersonate verb", func(t *testing.T) {
|
||||||
attrs := &fakeAttributes{
|
attrs := &fakeAttributes{
|
@ -1,8 +0,0 @@
|
|||||||
package org
|
|
||||||
|
|
||||||
import "github.com/google/wire"
|
|
||||||
|
|
||||||
var WireSet = wire.NewSet(
|
|
||||||
ProvideOrgIDAuthorizer,
|
|
||||||
ProvideOrgRoleAuthorizer,
|
|
||||||
)
|
|
@ -1,4 +1,4 @@
|
|||||||
package org
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -12,21 +12,21 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ authorizer.Authorizer = &OrgIDAuthorizer{}
|
var _ authorizer.Authorizer = &orgIDAuthorizer{}
|
||||||
|
|
||||||
type OrgIDAuthorizer struct {
|
type orgIDAuthorizer struct {
|
||||||
log log.Logger
|
log log.Logger
|
||||||
org org.Service
|
org org.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideOrgIDAuthorizer(orgService org.Service) *OrgIDAuthorizer {
|
func newOrgIDAuthorizer(orgService org.Service) *orgIDAuthorizer {
|
||||||
return &OrgIDAuthorizer{
|
return &orgIDAuthorizer{
|
||||||
log: log.New("grafana-apiserver.authorizer.orgid"),
|
log: log.New("grafana-apiserver.authorizer.orgid"),
|
||||||
org: orgService,
|
org: orgService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (auth OrgIDAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
func (auth orgIDAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
signedInUser, err := appcontext.User(ctx)
|
signedInUser, err := appcontext.User(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authorizer.DecisionDeny, fmt.Sprintf("error getting signed in user: %v", err), nil
|
return authorizer.DecisionDeny, fmt.Sprintf("error getting signed in user: %v", err), nil
|
@ -1,4 +1,4 @@
|
|||||||
package org
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -11,17 +11,17 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ authorizer.Authorizer = &OrgIDAuthorizer{}
|
var _ authorizer.Authorizer = &orgRoleAuthorizer{}
|
||||||
|
|
||||||
type OrgRoleAuthorizer struct {
|
type orgRoleAuthorizer struct {
|
||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideOrgRoleAuthorizer(orgService org.Service) *OrgRoleAuthorizer {
|
func newOrgRoleAuthorizer(orgService org.Service) *orgRoleAuthorizer {
|
||||||
return &OrgRoleAuthorizer{log: log.New("grafana-apiserver.authorizer.orgrole")}
|
return &orgRoleAuthorizer{log: log.New("grafana-apiserver.authorizer.orgrole")}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (auth OrgRoleAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
func (auth orgRoleAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
signedInUser, err := appcontext.User(ctx)
|
signedInUser, err := appcontext.User(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authorizer.DecisionDeny, fmt.Sprintf("error getting signed in user: %v", err), nil
|
return authorizer.DecisionDeny, fmt.Sprintf("error getting signed in user: %v", err), nil
|
@ -1,34 +1,65 @@
|
|||||||
package authorizer
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/authorization/union"
|
"k8s.io/apiserver/pkg/authorization/union"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer/impersonation"
|
orgsvc "github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer/org"
|
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer/stack"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideAuthorizer(
|
var _ authorizer.Authorizer = (*GrafanaAuthorizer)(nil)
|
||||||
orgIDAuthorizer *org.OrgIDAuthorizer,
|
|
||||||
orgRoleAuthorizer *org.OrgRoleAuthorizer,
|
type GrafanaAuthorizer struct {
|
||||||
stackIDAuthorizer *stack.StackIDAuthorizer,
|
apis map[string]authorizer.Authorizer
|
||||||
cfg *setting.Cfg,
|
auth authorizer.Authorizer
|
||||||
) authorizer.Authorizer {
|
}
|
||||||
|
|
||||||
|
func NewGrafanaAuthorizer(cfg *setting.Cfg, orgService orgsvc.Service) *GrafanaAuthorizer {
|
||||||
authorizers := []authorizer.Authorizer{
|
authorizers := []authorizer.Authorizer{
|
||||||
&impersonation.ImpersonationAuthorizer{},
|
&impersonationAuthorizer{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Hosted grafana, the StackID replaces the orgID as a valid namespace
|
// In Hosted grafana, the StackID replaces the orgID as a valid namespace
|
||||||
if cfg.StackID != "" {
|
if cfg.StackID != "" {
|
||||||
authorizers = append(authorizers, stackIDAuthorizer)
|
authorizers = append(authorizers, newStackIDAuthorizer(cfg))
|
||||||
} else {
|
} else {
|
||||||
authorizers = append(authorizers, orgIDAuthorizer)
|
authorizers = append(authorizers, newOrgIDAuthorizer(orgService))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Individual services may have explicit implementations
|
||||||
|
apis := make(map[string]authorizer.Authorizer)
|
||||||
|
authorizers = append(authorizers, &authorizerForAPI{apis})
|
||||||
|
|
||||||
// org role is last -- and will return allow for verbs that match expectations
|
// org role is last -- and will return allow for verbs that match expectations
|
||||||
// Ideally FGAC happens earlier and returns an explicit answer
|
// The apiVersion flavors will run first and can return early when FGAC has appropriate rules
|
||||||
authorizers = append(authorizers, orgRoleAuthorizer)
|
authorizers = append(authorizers, newOrgRoleAuthorizer(orgService))
|
||||||
return union.New(authorizers...)
|
return &GrafanaAuthorizer{
|
||||||
|
apis: apis,
|
||||||
|
auth: union.New(authorizers...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GrafanaAuthorizer) Register(gv schema.GroupVersion, fn authorizer.Authorizer) {
|
||||||
|
a.apis[gv.String()] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authorize implements authorizer.Authorizer.
|
||||||
|
func (a *GrafanaAuthorizer) Authorize(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
|
return a.auth.Authorize(ctx, attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
type authorizerForAPI struct {
|
||||||
|
apis map[string]authorizer.Authorizer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *authorizerForAPI) Authorize(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
|
auth, ok := a.apis[attr.GetAPIGroup()+"/"+attr.GetAPIVersion()]
|
||||||
|
if ok {
|
||||||
|
return auth.Authorize(ctx, attr)
|
||||||
|
}
|
||||||
|
return authorizer.DecisionNoOpinion, "", nil
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package stack
|
|
||||||
|
|
||||||
import "github.com/google/wire"
|
|
||||||
|
|
||||||
var WireSet = wire.NewSet(
|
|
||||||
ProvideStackIDAuthorizer,
|
|
||||||
)
|
|
@ -1,4 +1,4 @@
|
|||||||
package stack
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -12,21 +12,21 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ authorizer.Authorizer = &StackIDAuthorizer{}
|
var _ authorizer.Authorizer = &stackIDAuthorizer{}
|
||||||
|
|
||||||
type StackIDAuthorizer struct {
|
type stackIDAuthorizer struct {
|
||||||
log log.Logger
|
log log.Logger
|
||||||
stackID string
|
stackID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideStackIDAuthorizer(cfg *setting.Cfg) *StackIDAuthorizer {
|
func newStackIDAuthorizer(cfg *setting.Cfg) *stackIDAuthorizer {
|
||||||
return &StackIDAuthorizer{
|
return &stackIDAuthorizer{
|
||||||
log: log.New("grafana-apiserver.authorizer.stackid"),
|
log: log.New("grafana-apiserver.authorizer.stackid"),
|
||||||
stackID: cfg.StackID, // this lets a single tenant grafana validate stack id (rather than orgs)
|
stackID: cfg.StackID, // this lets a single tenant grafana validate stack id (rather than orgs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (auth StackIDAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
func (auth stackIDAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||||
signedInUser, err := appcontext.User(ctx)
|
signedInUser, err := appcontext.User(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authorizer.DecisionDeny, fmt.Sprintf("error getting signed in user: %v", err), nil
|
return authorizer.DecisionDeny, fmt.Sprintf("error getting signed in user: %v", err), nil
|
@ -1,14 +0,0 @@
|
|||||||
package authorizer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/google/wire"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer/org"
|
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer/stack"
|
|
||||||
)
|
|
||||||
|
|
||||||
var WireSet = wire.NewSet(
|
|
||||||
org.WireSet,
|
|
||||||
stack.WireSet,
|
|
||||||
ProvideAuthorizer,
|
|
||||||
)
|
|
@ -6,6 +6,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/kube-openapi/pkg/common"
|
"k8s.io/kube-openapi/pkg/common"
|
||||||
@ -33,6 +34,11 @@ type APIGroupBuilder interface {
|
|||||||
|
|
||||||
// Get the API routes for each version
|
// Get the API routes for each version
|
||||||
GetAPIRoutes() *APIRoutes
|
GetAPIRoutes() *APIRoutes
|
||||||
|
|
||||||
|
// Optionally add an authorization hook
|
||||||
|
// Standard namespace checking will happen before this is called, specifically
|
||||||
|
// the namespace must matches an org|stack that the user belongs to
|
||||||
|
GetAuthorizer() authorizer.Authorizer
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used to implement dynamic sub-resources like pods/x/logs
|
// This is used to implement dynamic sub-resources like pods/x/logs
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
|
||||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||||
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
@ -34,7 +33,9 @@ import (
|
|||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer"
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/utils"
|
"github.com/grafana/grafana/pkg/services/grafana-apiserver/utils"
|
||||||
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/api/routing"
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||||
@ -129,14 +130,14 @@ type service struct {
|
|||||||
|
|
||||||
tracing *tracing.TracingService
|
tracing *tracing.TracingService
|
||||||
|
|
||||||
authorizer authorizer.Authorizer
|
authorizer *authorizer.GrafanaAuthorizer
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideService(
|
func ProvideService(
|
||||||
cfg *setting.Cfg,
|
cfg *setting.Cfg,
|
||||||
features featuremgmt.FeatureToggles,
|
features featuremgmt.FeatureToggles,
|
||||||
rr routing.RouteRegister,
|
rr routing.RouteRegister,
|
||||||
authz authorizer.Authorizer,
|
orgService org.Service,
|
||||||
tracing *tracing.TracingService,
|
tracing *tracing.TracingService,
|
||||||
db db.DB,
|
db db.DB,
|
||||||
) (*service, error) {
|
) (*service, error) {
|
||||||
@ -147,7 +148,7 @@ func ProvideService(
|
|||||||
rr: rr,
|
rr: rr,
|
||||||
stopCh: make(chan struct{}),
|
stopCh: make(chan struct{}),
|
||||||
builders: []APIGroupBuilder{},
|
builders: []APIGroupBuilder{},
|
||||||
authorizer: authz,
|
authorizer: authorizer.NewGrafanaAuthorizer(cfg, orgService),
|
||||||
tracing: tracing,
|
tracing: tracing,
|
||||||
db: db, // For Unified storage
|
db: db, // For Unified storage
|
||||||
}
|
}
|
||||||
@ -227,6 +228,12 @@ func (s *service) start(ctx context.Context) error {
|
|||||||
if err := b.InstallSchema(Scheme); err != nil {
|
if err := b.InstallSchema(Scheme); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optionally register a custom authorizer
|
||||||
|
auth := b.GetAuthorizer()
|
||||||
|
if auth != nil {
|
||||||
|
s.authorizer.Register(b.GetGroupVersion(), auth)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
o := options.NewRecommendedOptions("/registry/grafana.app", Codecs.LegacyCodec(groupVersions...))
|
o := options.NewRecommendedOptions("/registry/grafana.app", Codecs.LegacyCodec(groupVersions...))
|
||||||
|
@ -2,8 +2,6 @@ package grafanaapiserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/auth/authorizer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var WireSet = wire.NewSet(
|
var WireSet = wire.NewSet(
|
||||||
@ -12,5 +10,4 @@ var WireSet = wire.NewSet(
|
|||||||
wire.Bind(new(Service), new(*service)),
|
wire.Bind(new(Service), new(*service)),
|
||||||
wire.Bind(new(APIRegistrar), new(*service)),
|
wire.Bind(new(APIRegistrar), new(*service)),
|
||||||
wire.Bind(new(DirectRestConfigProvider), new(*service)),
|
wire.Bind(new(DirectRestConfigProvider), new(*service)),
|
||||||
authorizer.WireSet,
|
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user