mirror of https://github.com/grafana/grafana
Advisor: Implement authorizer (#99440)
parent
a540c2fe7c
commit
3993d691f4
@ -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 |
||||
}) |
||||
} |
@ -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
|
Loading…
Reference in new issue