wip
This commit is contained in:
@@ -57,6 +57,8 @@ func newIAMAuthorizer(
|
||||
resourceAuthorizer[iamv0.TeamResourceInfo.GetName()] = authorizer
|
||||
resourceAuthorizer["searchUsers"] = serviceAuthorizer
|
||||
resourceAuthorizer["searchTeams"] = serviceAuthorizer
|
||||
// TODO: Implement fine-grained authorization for external group mapping search on the search level
|
||||
resourceAuthorizer["searchExternalGroupMappings"] = allowAuthorizer
|
||||
|
||||
return &iamAuthorizer{resourceAuthorizer: resourceAuthorizer}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package externalgroupmapping
|
||||
|
||||
import "k8s.io/apiserver/pkg/registry/rest"
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
)
|
||||
|
||||
type TeamGroupsHandler interface {
|
||||
rest.Storage
|
||||
@@ -8,3 +12,7 @@ type TeamGroupsHandler interface {
|
||||
rest.StorageMetadata
|
||||
rest.Connecter
|
||||
}
|
||||
|
||||
type SearchHandler interface {
|
||||
GetAPIRoutes(defs map[string]common.OpenAPIDefinition) *builder.APIRoutes
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
package externalgroupmapping
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
iamv0 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
"github.com/grafana/grafana/pkg/util/errhttp"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
var _ SearchHandler = (*NoopSearchREST)(nil)
|
||||
|
||||
type NoopSearchREST struct{}
|
||||
|
||||
func ProvideNoopSearchREST() *NoopSearchREST {
|
||||
return &NoopSearchREST{}
|
||||
}
|
||||
|
||||
func (n *NoopSearchREST) GetAPIRoutes(defs map[string]common.OpenAPIDefinition) *builder.APIRoutes {
|
||||
searchResults := defs["github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingList"].Schema
|
||||
return &builder.APIRoutes{
|
||||
Namespace: []builder.APIRouteHandler{
|
||||
{
|
||||
Path: "searchExternalGroupMappings",
|
||||
Spec: &spec3.PathProps{
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Description: "External Group Mapping search",
|
||||
Tags: []string{"Search"},
|
||||
OperationId: "searchExternalGroupMappings",
|
||||
Parameters: []*spec3.Parameter{
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "namespace",
|
||||
In: "path",
|
||||
Required: true,
|
||||
Example: "default",
|
||||
Description: "workspace",
|
||||
Schema: spec.StringProperty(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "externalGroup",
|
||||
In: "query",
|
||||
Required: false,
|
||||
Description: "External group name",
|
||||
Schema: spec.StringProperty(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "teamName",
|
||||
In: "query",
|
||||
Required: false,
|
||||
Description: "Team name",
|
||||
Schema: spec.StringProperty(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "limit",
|
||||
In: "query",
|
||||
Description: "number of results to return",
|
||||
Example: 30,
|
||||
Required: false,
|
||||
Schema: spec.Int64Property(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "page",
|
||||
In: "query",
|
||||
Description: "page number (starting from 1)",
|
||||
Example: 1,
|
||||
Required: false,
|
||||
Schema: spec.Int64Property(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "offset",
|
||||
In: "query",
|
||||
Description: "number of results to skip",
|
||||
Example: 0,
|
||||
Required: false,
|
||||
Schema: spec.Int64Property(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "sort",
|
||||
In: "query",
|
||||
Description: "sortable field",
|
||||
Example: "",
|
||||
Examples: map[string]*spec3.Example{
|
||||
"externalGroup": {
|
||||
ExampleProps: spec3.ExampleProps{
|
||||
Summary: "externalGroup ascending",
|
||||
Value: "externalGroup",
|
||||
},
|
||||
},
|
||||
"-externalGroup": {
|
||||
ExampleProps: spec3.ExampleProps{
|
||||
Summary: "externalGroup descending",
|
||||
Value: "-externalGroup",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: false,
|
||||
Schema: spec.StringProperty(),
|
||||
},
|
||||
},
|
||||
},
|
||||
Responses: &spec3.Responses{
|
||||
ResponsesProps: spec3.ResponsesProps{
|
||||
Default: &spec3.Response{
|
||||
ResponseProps: spec3.ResponseProps{
|
||||
Description: "Default OK response",
|
||||
Content: map[string]*spec3.MediaType{
|
||||
"application/json": {
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: &searchResults,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Handler: n.doSearch,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NoopSearchREST) doSearch(w http.ResponseWriter, r *http.Request) {
|
||||
errhttp.Write(r.Context(), errors.NewForbidden(iamv0.ExternalGroupMappingResourceInfo.GroupResource(), "", fmt.Errorf("functionality not available")), w)
|
||||
}
|
||||
@@ -82,11 +82,12 @@ type IdentityAccessManagementAPIBuilder struct {
|
||||
reg prometheus.Registerer
|
||||
logger log.Logger
|
||||
|
||||
dual dualwrite.Service
|
||||
unified resource.ResourceClient
|
||||
userSearchClient resourcepb.ResourceIndexClient
|
||||
userSearchHandler *user.SearchHandler
|
||||
teamSearch *TeamSearchHandler
|
||||
dual dualwrite.Service
|
||||
unified resource.ResourceClient
|
||||
userSearchClient resourcepb.ResourceIndexClient
|
||||
userSearchHandler *user.SearchHandler
|
||||
teamSearch *TeamSearchHandler
|
||||
externalGroupMappingSearchHandler externalgroupmapping.SearchHandler
|
||||
|
||||
teamGroupsHandler externalgroupmapping.TeamGroupsHandler
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ func RegisterAPIService(
|
||||
roleBindingsStorage RoleBindingStorageBackend,
|
||||
externalGroupMappingStorageBackend ExternalGroupMappingStorageBackend,
|
||||
teamGroupsHandlerImpl externalgroupmapping.TeamGroupsHandler,
|
||||
externalGroupMappingSearchHandler externalgroupmapping.SearchHandler,
|
||||
dual dualwrite.Service,
|
||||
unified resource.ResourceClient,
|
||||
orgService org.Service,
|
||||
@@ -101,31 +102,32 @@ func RegisterAPIService(
|
||||
)
|
||||
|
||||
builder := &IdentityAccessManagementAPIBuilder{
|
||||
store: store,
|
||||
userLegacyStore: user.NewLegacyStore(store, accessClient, enableAuthnMutation, tracing),
|
||||
saLegacyStore: serviceaccount.NewLegacyStore(store, accessClient, enableAuthnMutation, tracing),
|
||||
legacyTeamStore: team.NewLegacyStore(store, accessClient, enableAuthnMutation, tracing),
|
||||
teamBindingLegacyStore: teambinding.NewLegacyBindingStore(store, enableAuthnMutation, tracing),
|
||||
ssoLegacyStore: sso.NewLegacyStore(ssoService, tracing),
|
||||
coreRolesStorage: coreRolesStorage,
|
||||
roleApiInstaller: roleApiInstaller,
|
||||
resourcePermissionsStorage: resourcepermission.ProvideStorageBackend(dbProvider),
|
||||
roleBindingsStorage: roleBindingsStorage,
|
||||
externalGroupMappingStorage: externalGroupMappingStorageBackend,
|
||||
teamGroupsHandler: teamGroupsHandlerImpl,
|
||||
sso: ssoService,
|
||||
resourceParentProvider: resourceParentProvider,
|
||||
authorizer: authorizer,
|
||||
legacyAccessClient: legacyAccessClient,
|
||||
accessClient: accessClient,
|
||||
zClient: zClient,
|
||||
zTickets: make(chan bool, MaxConcurrentZanzanaWrites),
|
||||
display: user.NewLegacyDisplayREST(store),
|
||||
reg: reg,
|
||||
logger: log.New("iam.apis"),
|
||||
features: features,
|
||||
dual: dual,
|
||||
unified: unified,
|
||||
store: store,
|
||||
userLegacyStore: user.NewLegacyStore(store, accessClient, enableAuthnMutation, tracing),
|
||||
saLegacyStore: serviceaccount.NewLegacyStore(store, accessClient, enableAuthnMutation, tracing),
|
||||
legacyTeamStore: team.NewLegacyStore(store, accessClient, enableAuthnMutation, tracing),
|
||||
teamBindingLegacyStore: teambinding.NewLegacyBindingStore(store, enableAuthnMutation, tracing),
|
||||
ssoLegacyStore: sso.NewLegacyStore(ssoService, tracing),
|
||||
coreRolesStorage: coreRolesStorage,
|
||||
roleApiInstaller: roleApiInstaller,
|
||||
resourcePermissionsStorage: resourcepermission.ProvideStorageBackend(dbProvider),
|
||||
roleBindingsStorage: roleBindingsStorage,
|
||||
externalGroupMappingStorage: externalGroupMappingStorageBackend,
|
||||
teamGroupsHandler: teamGroupsHandlerImpl,
|
||||
externalGroupMappingSearchHandler: externalGroupMappingSearchHandler,
|
||||
sso: ssoService,
|
||||
resourceParentProvider: resourceParentProvider,
|
||||
authorizer: authorizer,
|
||||
legacyAccessClient: legacyAccessClient,
|
||||
accessClient: accessClient,
|
||||
zClient: zClient,
|
||||
zTickets: make(chan bool, MaxConcurrentZanzanaWrites),
|
||||
display: user.NewLegacyDisplayREST(store),
|
||||
reg: reg,
|
||||
logger: log.New("iam.apis"),
|
||||
features: features,
|
||||
dual: dual,
|
||||
unified: unified,
|
||||
userSearchClient: resource.NewSearchClient(dualwrite.NewSearchAdapter(dual), iamv0.UserResourceInfo.GroupResource(),
|
||||
unified, user.NewUserLegacySearchClient(orgService, tracing, cfg), features),
|
||||
teamSearch: NewTeamSearchHandler(tracing, dual, team.NewLegacyTeamSearchClient(teamService), unified, features),
|
||||
@@ -617,7 +619,7 @@ func (b *IdentityAccessManagementAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenA
|
||||
func (b *IdentityAccessManagementAPIBuilder) GetAPIRoutes(gv schema.GroupVersion) *builder.APIRoutes {
|
||||
defs := b.GetOpenAPIDefinitions()(func(path string) spec.Ref { return spec.Ref{} })
|
||||
|
||||
searchRoutes := make([]*builder.APIRoutes, 0, 2)
|
||||
searchRoutes := make([]*builder.APIRoutes, 0, 3)
|
||||
if b.userSearchHandler != nil {
|
||||
searchRoutes = append(searchRoutes, b.userSearchHandler.GetAPIRoutes(defs))
|
||||
}
|
||||
@@ -626,6 +628,10 @@ func (b *IdentityAccessManagementAPIBuilder) GetAPIRoutes(gv schema.GroupVersion
|
||||
searchRoutes = append(searchRoutes, b.teamSearch.GetAPIRoutes(defs))
|
||||
}
|
||||
|
||||
if b.externalGroupMappingSearchHandler != nil {
|
||||
searchRoutes = append(searchRoutes, b.externalGroupMappingSearchHandler.GetAPIRoutes(defs))
|
||||
}
|
||||
|
||||
routes := []*builder.APIRoutes{b.display.GetAPIRoutes(defs)}
|
||||
routes = append(routes, searchRoutes...)
|
||||
return mergeAPIRoutes(routes...)
|
||||
|
||||
@@ -35,6 +35,9 @@ var WireSetExts = wire.NewSet(
|
||||
externalgroupmapping.ProvideNoopTeamGroupsREST,
|
||||
wire.Bind(new(externalgroupmapping.TeamGroupsHandler), new(*externalgroupmapping.NoopTeamGroupsREST)),
|
||||
|
||||
externalgroupmapping.ProvideNoopSearchREST,
|
||||
wire.Bind(new(externalgroupmapping.SearchHandler), new(*externalgroupmapping.NoopSearchREST)),
|
||||
|
||||
// Auditing Options
|
||||
auditing.ProvideNoopBackend,
|
||||
auditing.ProvideNoopPolicyRuleProvider,
|
||||
|
||||
Generated
+4
-2
@@ -883,7 +883,8 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
|
||||
storageBackendImpl := noopstorage.ProvideStorageBackend()
|
||||
roleApiInstaller := iam.ProvideNoopRoleApiInstaller()
|
||||
noopTeamGroupsREST := externalgroupmapping.ProvideNoopTeamGroupsREST()
|
||||
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(cfg, featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, roleApiInstaller, tracingService, storageBackendImpl, storageBackendImpl, noopTeamGroupsREST, dualwriteService, resourceClient, orgService, userService, teamService, eventualRestConfigProvider)
|
||||
noopSearchREST := externalgroupmapping.ProvideNoopSearchREST()
|
||||
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(cfg, featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, roleApiInstaller, tracingService, storageBackendImpl, storageBackendImpl, noopTeamGroupsREST, noopSearchREST, dualwriteService, resourceClient, orgService, userService, teamService, eventualRestConfigProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1551,7 +1552,8 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
storageBackendImpl := noopstorage.ProvideStorageBackend()
|
||||
roleApiInstaller := iam.ProvideNoopRoleApiInstaller()
|
||||
noopTeamGroupsREST := externalgroupmapping.ProvideNoopTeamGroupsREST()
|
||||
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(cfg, featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, roleApiInstaller, tracingService, storageBackendImpl, storageBackendImpl, noopTeamGroupsREST, dualwriteService, resourceClient, orgService, userService, teamService, eventualRestConfigProvider)
|
||||
noopSearchREST := externalgroupmapping.ProvideNoopSearchREST()
|
||||
identityAccessManagementAPIBuilder, err := iam.RegisterAPIService(cfg, featureToggles, apiserverService, ssosettingsimplService, sqlStore, accessControl, accessClient, zanzanaClient, registerer, storageBackendImpl, roleApiInstaller, tracingService, storageBackendImpl, storageBackendImpl, noopTeamGroupsREST, noopSearchREST, dualwriteService, resourceClient, orgService, userService, teamService, eventualRestConfigProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user