mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Advisor: Implement authorizer (#99440)
This commit is contained in:
parent
a540c2fe7c
commit
3993d691f4
31
apps/advisor/pkg/app/authorizer.go
Normal file
31
apps/advisor/pkg/app/authorizer.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func 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
|
||||||
|
u, err := identity.GetRequester(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return authorizer.DecisionDeny, "valid user is required", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if is admin
|
||||||
|
if u.GetIsGrafanaAdmin() {
|
||||||
|
return authorizer.DecisionAllow, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorizer.DecisionDeny, "forbidden", nil
|
||||||
|
})
|
||||||
|
}
|
78
apps/advisor/pkg/app/authorizer_test.go
Normal file
78
apps/advisor/pkg/app/authorizer_test.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetAuthorizer(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ctx context.Context
|
||||||
|
attr authorizer.Attributes
|
||||||
|
expectedDecision authorizer.Decision
|
||||||
|
expectedReason string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "non-resource request",
|
||||||
|
ctx: context.TODO(),
|
||||||
|
attr: &mockAttributes{resourceRequest: false},
|
||||||
|
expectedDecision: authorizer.DecisionNoOpinion,
|
||||||
|
expectedReason: "",
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "user is admin",
|
||||||
|
ctx: identity.WithRequester(context.TODO(), &mockUser{isGrafanaAdmin: true}),
|
||||||
|
attr: &mockAttributes{resourceRequest: true},
|
||||||
|
expectedDecision: authorizer.DecisionAllow,
|
||||||
|
expectedReason: "",
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "user is not admin",
|
||||||
|
ctx: identity.WithRequester(context.TODO(), &mockUser{isGrafanaAdmin: false}),
|
||||||
|
attr: &mockAttributes{resourceRequest: true},
|
||||||
|
expectedDecision: authorizer.DecisionDeny,
|
||||||
|
expectedReason: "forbidden",
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
auth := GetAuthorizer()
|
||||||
|
decision, reason, err := auth.Authorize(tt.ctx, tt.attr)
|
||||||
|
assert.Equal(t, tt.expectedDecision, decision)
|
||||||
|
assert.Equal(t, tt.expectedReason, reason)
|
||||||
|
assert.Equal(t, tt.expectedErr, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockAttributes struct {
|
||||||
|
authorizer.Attributes
|
||||||
|
resourceRequest bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockAttributes) IsResourceRequest() bool {
|
||||||
|
return m.resourceRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement other methods of authorizer.Attributes as needed
|
||||||
|
|
||||||
|
type mockUser struct {
|
||||||
|
identity.Requester
|
||||||
|
isGrafanaAdmin bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockUser) GetIsGrafanaAdmin() bool {
|
||||||
|
return m.isGrafanaAdmin
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement other methods of identity.Requester as needed
|
2
go.mod
2
go.mod
@ -198,7 +198,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/grafana/grafana/apps/advisor v0.0.0-20250121115006-c1eac9f9973f // @grafana/plugins-platform-backend
|
github.com/grafana/grafana/apps/advisor v0.0.0-20250123151950-b066a6313173 // @grafana/plugins-platform-backend
|
||||||
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d // @grafana/alerting-backend
|
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d // @grafana/alerting-backend
|
||||||
github.com/grafana/grafana/apps/investigation v0.0.0-20250121113133-e747350fee2d // @fcjack @matryer
|
github.com/grafana/grafana/apps/investigation v0.0.0-20250121113133-e747350fee2d // @fcjack @matryer
|
||||||
github.com/grafana/grafana/apps/playlist v0.0.0-20250121113133-e747350fee2d // @grafana/grafana-app-platform-squad
|
github.com/grafana/grafana/apps/playlist v0.0.0-20250121113133-e747350fee2d // @grafana/grafana-app-platform-squad
|
||||||
|
4
go.sum
4
go.sum
@ -1532,8 +1532,8 @@ github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79
|
|||||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.262.0 h1:R2DV6lwBQE5zaogxX3PorD9Seo8CXA8YuStf84oqwkk=
|
github.com/grafana/grafana-plugin-sdk-go v0.262.0 h1:R2DV6lwBQE5zaogxX3PorD9Seo8CXA8YuStf84oqwkk=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.262.0/go.mod h1:U43Cnrj/9DNYyvFcNdeUWNjMXTKNB0jcTcQGpWKd2gw=
|
github.com/grafana/grafana-plugin-sdk-go v0.262.0/go.mod h1:U43Cnrj/9DNYyvFcNdeUWNjMXTKNB0jcTcQGpWKd2gw=
|
||||||
github.com/grafana/grafana/apps/advisor v0.0.0-20250121115006-c1eac9f9973f h1:c8IkbxPvM6+lscVOLgtbt8Gnro4Liltd+E2eqkoAeZA=
|
github.com/grafana/grafana/apps/advisor v0.0.0-20250123151950-b066a6313173 h1:uOM89HiWVVOTls0LrD4coHTckb2lA4U0sIJwCYdbhbw=
|
||||||
github.com/grafana/grafana/apps/advisor v0.0.0-20250121115006-c1eac9f9973f/go.mod h1:goSDiy3jtC2cp8wjpPZdUHRENcoSUHae1/Px/MDfddA=
|
github.com/grafana/grafana/apps/advisor v0.0.0-20250123151950-b066a6313173/go.mod h1:goSDiy3jtC2cp8wjpPZdUHRENcoSUHae1/Px/MDfddA=
|
||||||
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d h1:NRVOtiG1aUwOazBj9KM7X2o2shsM6TchqisezzoH1gw=
|
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d h1:NRVOtiG1aUwOazBj9KM7X2o2shsM6TchqisezzoH1gw=
|
||||||
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d/go.mod h1:AvleS6icyPmcBjihtx5jYEvdzLmHGBp66NuE0AMR57A=
|
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250121113133-e747350fee2d/go.mod h1:AvleS6icyPmcBjihtx5jYEvdzLmHGBp66NuE0AMR57A=
|
||||||
github.com/grafana/grafana/apps/investigation v0.0.0-20250121113133-e747350fee2d h1:oNc/aDfDucQxLbRZK25yz3Cwc+dGo1C0Xmm2LaliWUQ=
|
github.com/grafana/grafana/apps/investigation v0.0.0-20250121113133-e747350fee2d h1:oNc/aDfDucQxLbRZK25yz3Cwc+dGo1C0Xmm2LaliWUQ=
|
||||||
|
@ -21,6 +21,7 @@ func RegisterApp(
|
|||||||
appCfg := &runner.AppBuilderConfig{
|
appCfg := &runner.AppBuilderConfig{
|
||||||
OpenAPIDefGetter: advisorv0alpha1.GetOpenAPIDefinitions,
|
OpenAPIDefGetter: advisorv0alpha1.GetOpenAPIDefinitions,
|
||||||
ManagedKinds: advisorapp.GetKinds(),
|
ManagedKinds: advisorapp.GetKinds(),
|
||||||
|
Authorizer: advisorapp.GetAuthorizer(),
|
||||||
CustomConfig: any(checkRegistry),
|
CustomConfig: any(checkRegistry),
|
||||||
}
|
}
|
||||||
provider.Provider = simple.NewAppProvider(apis.LocalManifest(), appCfg, advisorapp.New)
|
provider.Provider = simple.NewAppProvider(apis.LocalManifest(), appCfg, advisorapp.New)
|
||||||
|
Loading…
Reference in New Issue
Block a user