mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Update plugin schema with service registration info (#70692)
This commit is contained in:
committed by
GitHub
parent
e03f61fe26
commit
025465e611
@@ -477,6 +477,68 @@
|
|||||||
"tracing": {
|
"tracing": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "For data source plugins, if the plugin supports tracing. Used for example to link logs (e.g. Loki logs) with tracing plugins."
|
"description": "For data source plugins, if the plugin supports tracing. Used for example to link logs (e.g. Loki logs) with tracing plugins."
|
||||||
|
},
|
||||||
|
"externalServiceRegistration": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Oauth App Service Registration.",
|
||||||
|
"properties": {
|
||||||
|
"impersonation": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Impersonation describes the permissions that the external service will have on behalf of the user.",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enabled allows the service to request access tokens to impersonate users using the jwtbearer grant"
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Groups allows the service to list the impersonated user's teams."
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Permissions are the permissions that the external service needs when impersonating a user. The intersection of this set with the impersonated user's permission guarantees that the client will not gain more privileges than the impersonated user has.",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"self": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Self describes the permissions that the external service will have on behalf of itself",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enabled allows the service to request access tokens for itself using the client_credentials grant"
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Permissions are the permissions that the external service needs its associated service account to have",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins/config"
|
"github.com/grafana/grafana/pkg/plugins/config"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||||
"github.com/grafana/grafana/pkg/plugins/oauth"
|
"github.com/grafana/grafana/pkg/plugins/oauth"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
@@ -312,7 +313,7 @@ func TestInitializer_oauthEnvVars(t *testing.T) {
|
|||||||
p := &plugins.Plugin{
|
p := &plugins.Plugin{
|
||||||
JSONData: plugins.JSONData{
|
JSONData: plugins.JSONData{
|
||||||
ID: "test",
|
ID: "test",
|
||||||
ExternalServiceRegistration: &oauth.ExternalServiceRegistration{},
|
ExternalServiceRegistration: &plugindef.ExternalServiceRegistration{},
|
||||||
},
|
},
|
||||||
ExternalService: &oauth.ExternalService{
|
ExternalService: &oauth.ExternalService{
|
||||||
ClientID: "clientID",
|
ClientID: "clientID",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||||
"github.com/grafana/grafana/pkg/plugins/log"
|
"github.com/grafana/grafana/pkg/plugins/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins/oauth"
|
"github.com/grafana/grafana/pkg/plugins/oauth"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
"github.com/grafana/grafana/pkg/plugins/repo"
|
"github.com/grafana/grafana/pkg/plugins/repo"
|
||||||
"github.com/grafana/grafana/pkg/plugins/storage"
|
"github.com/grafana/grafana/pkg/plugins/storage"
|
||||||
)
|
)
|
||||||
@@ -428,6 +429,6 @@ type FakeOauthService struct {
|
|||||||
Result *oauth.ExternalService
|
Result *oauth.ExternalService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeOauthService) RegisterExternalService(ctx context.Context, name string, svc *oauth.ExternalServiceRegistration) (*oauth.ExternalService, error) {
|
func (f *FakeOauthService) RegisterExternalService(ctx context.Context, name string, svc *plugindef.ExternalServiceRegistration) (*oauth.ExternalService, error) {
|
||||||
return f.Result, nil
|
return f.Result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,29 +3,9 @@ package oauth
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SelfCfg is a subset of oauthserver.SelfCfg making some fields optional
|
|
||||||
type SelfCfg struct {
|
|
||||||
Enabled *bool `json:"enabled,omitempty"`
|
|
||||||
Permissions []accesscontrol.Permission `json:"permissions,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImpersonationCfg is a subset of oauthserver.ImpersonationCfg making some fields optional
|
|
||||||
type ImpersonationCfg struct {
|
|
||||||
Enabled *bool `json:"enabled,omitempty"`
|
|
||||||
Groups *bool `json:"groups,omitempty"`
|
|
||||||
Permissions []accesscontrol.Permission `json:"permissions,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginExternalServiceRegistration is a subset of oauthserver.ExternalServiceRegistration
|
|
||||||
// simplified for the plugin use case.
|
|
||||||
type ExternalServiceRegistration struct {
|
|
||||||
Impersonation *ImpersonationCfg `json:"impersonation,omitempty"`
|
|
||||||
Self *SelfCfg `json:"self,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExternalService struct {
|
type ExternalService struct {
|
||||||
ClientID string `json:"clientId"`
|
ClientID string `json:"clientId"`
|
||||||
ClientSecret string `json:"clientSecret"`
|
ClientSecret string `json:"clientSecret"`
|
||||||
@@ -33,5 +13,5 @@ type ExternalService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ExternalServiceRegistry interface {
|
type ExternalServiceRegistry interface {
|
||||||
RegisterExternalService(ctx context.Context, name string, svc *ExternalServiceRegistration) (*ExternalService, error)
|
RegisterExternalService(ctx context.Context, name string, svc *plugindef.ExternalServiceRegistration) (*ExternalService, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,6 +405,37 @@ schemas: [{
|
|||||||
// Parameters for the JWT token authentication request.
|
// Parameters for the JWT token authentication request.
|
||||||
params: [string]: string
|
params: [string]: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// External service registration information
|
||||||
|
externalServiceRegistration: #ExternalServiceRegistration
|
||||||
|
|
||||||
|
#ExternalServiceRegistration: {
|
||||||
|
// Impersonation describes the permissions that the external service will have on behalf of the user
|
||||||
|
impersonation?: #Impersonation
|
||||||
|
// Self describes the permissions that the external service will have on behalf of itself
|
||||||
|
self?: #Self
|
||||||
|
}
|
||||||
|
|
||||||
|
#Impersonation: {
|
||||||
|
// Enabled allows the service to request access tokens to impersonate users using the jwtbearer grant
|
||||||
|
// Defaults to true.
|
||||||
|
enabled?: bool
|
||||||
|
// Groups allows the service to list the impersonated user's teams.
|
||||||
|
// Defaults to true.
|
||||||
|
groups?: bool
|
||||||
|
// Permissions are the permissions that the external service needs when impersonating a user.
|
||||||
|
// The intersection of this set with the impersonated user's permission guarantees that the client will not
|
||||||
|
// gain more privileges than the impersonated user has.
|
||||||
|
permissions?: [...#Permission]
|
||||||
|
}
|
||||||
|
|
||||||
|
#Self: {
|
||||||
|
// Enabled allows the service to request access tokens for itself using the client_credentials grant
|
||||||
|
// Defaults to true.
|
||||||
|
enabled?: bool
|
||||||
|
// Permissions are the permissions that the external service needs its associated service account to have.
|
||||||
|
permissions?: [...#Permission]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
lenses: []
|
lenses: []
|
||||||
|
|||||||
@@ -122,6 +122,12 @@ type Dependency struct {
|
|||||||
// DependencyType defines model for Dependency.Type.
|
// DependencyType defines model for Dependency.Type.
|
||||||
type DependencyType string
|
type DependencyType string
|
||||||
|
|
||||||
|
// ExternalServiceRegistration defines model for ExternalServiceRegistration.
|
||||||
|
type ExternalServiceRegistration struct {
|
||||||
|
Impersonation *Impersonation `json:"impersonation,omitempty"`
|
||||||
|
Self *Self `json:"self,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Header describes an HTTP header that is forwarded with a proxied request for
|
// Header describes an HTTP header that is forwarded with a proxied request for
|
||||||
// a plugin route.
|
// a plugin route.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
@@ -129,6 +135,22 @@ type Header struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Impersonation defines model for Impersonation.
|
||||||
|
type Impersonation struct {
|
||||||
|
// Enabled allows the service to request access tokens to impersonate users using the jwtbearer grant
|
||||||
|
// Defaults to true.
|
||||||
|
Enabled *bool `json:"enabled,omitempty"`
|
||||||
|
|
||||||
|
// Groups allows the service to list the impersonated user's teams.
|
||||||
|
// Defaults to true.
|
||||||
|
Groups *bool `json:"groups,omitempty"`
|
||||||
|
|
||||||
|
// Permissions are the permissions that the external service needs when impersonating a user.
|
||||||
|
// The intersection of this set with the impersonated user's permission guarantees that the client will not
|
||||||
|
// gain more privileges than the impersonated user has.
|
||||||
|
Permissions []Permission `json:"permissions,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// A resource to be included in a plugin.
|
// A resource to be included in a plugin.
|
||||||
type Include struct {
|
type Include struct {
|
||||||
// RBAC action the user must have to access the route
|
// RBAC action the user must have to access the route
|
||||||
@@ -288,7 +310,8 @@ type PluginDef struct {
|
|||||||
// $GOARCH><.exe for Windows>`, e.g. `plugin_linux_amd64`.
|
// $GOARCH><.exe for Windows>`, e.g. `plugin_linux_amd64`.
|
||||||
// Combination of $GOOS and $GOARCH can be found here:
|
// Combination of $GOOS and $GOARCH can be found here:
|
||||||
// https://golang.org/doc/install/source#environment.
|
// https://golang.org/doc/install/source#environment.
|
||||||
Executable *string `json:"executable,omitempty"`
|
Executable *string `json:"executable,omitempty"`
|
||||||
|
ExternalServiceRegistration ExternalServiceRegistration `json:"externalServiceRegistration"`
|
||||||
|
|
||||||
// [internal only] Excludes the plugin from listings in Grafana's UI. Only
|
// [internal only] Excludes the plugin from listings in Grafana's UI. Only
|
||||||
// allowed for `builtIn` plugins.
|
// allowed for `builtIn` plugins.
|
||||||
@@ -445,6 +468,16 @@ type Route struct {
|
|||||||
UrlParams []URLParam `json:"urlParams,omitempty"`
|
UrlParams []URLParam `json:"urlParams,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Self defines model for Self.
|
||||||
|
type Self struct {
|
||||||
|
// Enabled allows the service to request access tokens for itself using the client_credentials grant
|
||||||
|
// Defaults to true.
|
||||||
|
Enabled *bool `json:"enabled,omitempty"`
|
||||||
|
|
||||||
|
// Permissions are the permissions that the external service needs its associated service account to have.
|
||||||
|
Permissions []Permission `json:"permissions,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// TODO docs
|
// TODO docs
|
||||||
type TokenAuth struct {
|
type TokenAuth struct {
|
||||||
// Parameters for the token authentication request.
|
// Parameters for the token authentication request.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||||
"github.com/grafana/grafana/pkg/plugins/log"
|
"github.com/grafana/grafana/pkg/plugins/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins/oauth"
|
"github.com/grafana/grafana/pkg/plugins/oauth"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
@@ -155,7 +156,7 @@ type JSONData struct {
|
|||||||
Executable string `json:"executable,omitempty"`
|
Executable string `json:"executable,omitempty"`
|
||||||
|
|
||||||
// Oauth App Service Registration
|
// Oauth App Service Registration
|
||||||
ExternalServiceRegistration *oauth.ExternalServiceRegistration `json:"externalServiceRegistration,omitempty"`
|
ExternalServiceRegistration *plugindef.ExternalServiceRegistration `json:"externalServiceRegistration,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadPluginJSON(reader io.Reader) (JSONData, error) {
|
func ReadPluginJSON(reader io.Reader) (JSONData, error) {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/oauth"
|
"github.com/grafana/grafana/pkg/plugins/oauth"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/oauthserver"
|
"github.com/grafana/grafana/pkg/services/oauthserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,10 +21,10 @@ func ProvideService(os oauthserver.OAuth2Server) *Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RegisterExternalService is a simplified wrapper around SaveExternalService for the plugin use case.
|
// RegisterExternalService is a simplified wrapper around SaveExternalService for the plugin use case.
|
||||||
func (s *Service) RegisterExternalService(ctx context.Context, svcName string, svc *oauth.ExternalServiceRegistration) (*oauth.ExternalService, error) {
|
func (s *Service) RegisterExternalService(ctx context.Context, svcName string, svc *plugindef.ExternalServiceRegistration) (*oauth.ExternalService, error) {
|
||||||
impersonation := oauthserver.ImpersonationCfg{}
|
impersonation := oauthserver.ImpersonationCfg{}
|
||||||
if svc.Impersonation != nil {
|
if svc.Impersonation != nil {
|
||||||
impersonation.Permissions = svc.Impersonation.Permissions
|
impersonation.Permissions = toAccessControlPermissions(svc.Impersonation.Permissions)
|
||||||
if svc.Impersonation.Enabled != nil {
|
if svc.Impersonation.Enabled != nil {
|
||||||
impersonation.Enabled = *svc.Impersonation.Enabled
|
impersonation.Enabled = *svc.Impersonation.Enabled
|
||||||
} else {
|
} else {
|
||||||
@@ -37,7 +39,7 @@ func (s *Service) RegisterExternalService(ctx context.Context, svcName string, s
|
|||||||
|
|
||||||
self := oauthserver.SelfCfg{}
|
self := oauthserver.SelfCfg{}
|
||||||
if svc.Self != nil {
|
if svc.Self != nil {
|
||||||
self.Permissions = svc.Self.Permissions
|
self.Permissions = toAccessControlPermissions(svc.Self.Permissions)
|
||||||
if svc.Self.Enabled != nil {
|
if svc.Self.Enabled != nil {
|
||||||
self.Enabled = *svc.Self.Enabled
|
self.Enabled = *svc.Self.Enabled
|
||||||
} else {
|
} else {
|
||||||
@@ -60,3 +62,18 @@ func (s *Service) RegisterExternalService(ctx context.Context, svcName string, s
|
|||||||
PrivateKey: extSvc.KeyResult.PrivatePem,
|
PrivateKey: extSvc.KeyResult.PrivatePem,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toAccessControlPermissions(ps []plugindef.Permission) []accesscontrol.Permission {
|
||||||
|
res := make([]accesscontrol.Permission, 0, len(ps))
|
||||||
|
for _, p := range ps {
|
||||||
|
scope := ""
|
||||||
|
if p.Scope != nil {
|
||||||
|
scope = *p.Scope
|
||||||
|
}
|
||||||
|
res = append(res, accesscontrol.Permission{
|
||||||
|
Action: p.Action,
|
||||||
|
Scope: scope,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user