mirror of https://github.com/grafana/grafana.git
K8s/IAM: Use raw handler for display (not rest.Connector) (#99898)
This commit is contained in:
parent
2aa78139c4
commit
b636b81b16
|
|
@ -33,16 +33,17 @@ type Display struct {
|
|||
// AvatarURL is the url where we can get the avatar for identity
|
||||
AvatarURL string `json:"avatarURL,omitempty"`
|
||||
|
||||
// InternalID is the legacy numreric id for identity, this is deprecated and should be phased out
|
||||
// InternalID is the legacy numeric id for identity,
|
||||
// Deprecated: use the identityRef where possible
|
||||
InternalID int64 `json:"internalId,omitempty"`
|
||||
}
|
||||
|
||||
type IdentityRef struct {
|
||||
// Type of identity e.g. "user".
|
||||
// For a full list see https://github.com/grafana/authlib/blob/2f8d13a83ca3e82da08b53726de1697ee5b5b4cc/claims/type.go#L15-L24
|
||||
// For a full list see https://github.com/grafana/authlib/blob/d6737a7dc8f55e9d42834adb83b5da607ceed293/types/type.go#L15
|
||||
Type claims.IdentityType `json:"type"`
|
||||
|
||||
// Name is the unique identifier for identity, guaranteed jo be a unique value for the type within a namespace.
|
||||
// Name is the unique identifier for identity, guaranteed to be a unique value for the type within a namespace.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func schema_pkg_apis_iam_v0alpha1_Display(ref common.ReferenceCallback) common.O
|
|||
},
|
||||
"internalId": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "InternalID is the legacy numreric id for identity, this is deprecated and should be phased out",
|
||||
Description: "InternalID is the legacy numeric id for identity, Deprecated: use the identityRef where possible",
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
|
|
@ -188,7 +188,7 @@ func schema_pkg_apis_iam_v0alpha1_IdentityRef(ref common.ReferenceCallback) comm
|
|||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type of identity e.g. \"user\". For a full list see https://github.com/grafana/authlib/blob/2f8d13a83ca3e82da08b53726de1697ee5b5b4cc/claims/type.go#L15-L24",
|
||||
Description: "Type of identity e.g. \"user\". For a full list see https://github.com/grafana/authlib/blob/d6737a7dc8f55e9d42834adb83b5da607ceed293/types/type.go#L15",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
|
|
@ -196,7 +196,7 @@ func schema_pkg_apis_iam_v0alpha1_IdentityRef(ref common.ReferenceCallback) comm
|
|||
},
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Name is the unique identifier for identity, guaranteed jo be a unique value for the type within a namespace.",
|
||||
Description: "Name is the unique identifier for identity, guaranteed to be a unique value for the type within a namespace.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
|
|
@ -763,7 +763,7 @@ func schema_pkg_apis_iam_v0alpha1_TeamMember(ref common.ReferenceCallback) commo
|
|||
},
|
||||
"internalId": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "InternalID is the legacy numreric id for identity, this is deprecated and should be phased out",
|
||||
Description: "InternalID is the legacy numeric id for identity, Deprecated: use the identityRef where possible",
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
common "k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
|
||||
"github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
|
|
@ -34,6 +35,9 @@ type IdentityAccessManagementAPIBuilder struct {
|
|||
authorizer authorizer.Authorizer
|
||||
accessClient types.AccessClient
|
||||
|
||||
// non-k8s api route
|
||||
display *user.LegacyDisplayREST
|
||||
|
||||
// Not set for multi-tenant deployment for now
|
||||
sso ssosettings.Service
|
||||
}
|
||||
|
|
@ -52,6 +56,7 @@ func RegisterAPIService(
|
|||
sso: ssoService,
|
||||
authorizer: authorizer,
|
||||
accessClient: client,
|
||||
display: user.NewLegacyDisplayREST(store),
|
||||
}
|
||||
apiregistration.RegisterAPI(builder)
|
||||
|
||||
|
|
@ -61,6 +66,7 @@ func RegisterAPIService(
|
|||
func NewAPIService(store legacy.LegacyIdentityStore) *IdentityAccessManagementAPIBuilder {
|
||||
return &IdentityAccessManagementAPIBuilder{
|
||||
store: store,
|
||||
display: user.NewLegacyDisplayREST(store),
|
||||
authorizer: authorizer.AuthorizerFunc(
|
||||
func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
|
||||
user, err := identity.GetRequester(ctx)
|
||||
|
|
@ -114,9 +120,6 @@ func (b *IdentityAccessManagementAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *ge
|
|||
storage[ssoResource.StoragePath()] = sso.NewLegacyStore(b.sso)
|
||||
}
|
||||
|
||||
// The display endpoint -- NOTE, this uses a rewrite hack to allow requests without a name parameter
|
||||
storage["display"] = user.NewLegacyDisplayREST(b.store)
|
||||
|
||||
apiGroupInfo.VersionedResourcesStorageMap[iamv0.VERSION] = storage
|
||||
return nil
|
||||
}
|
||||
|
|
@ -125,6 +128,11 @@ func (b *IdentityAccessManagementAPIBuilder) GetOpenAPIDefinitions() common.GetO
|
|||
return iamv0.GetOpenAPIDefinitions
|
||||
}
|
||||
|
||||
func (b *IdentityAccessManagementAPIBuilder) GetAPIRoutes() *builder.APIRoutes {
|
||||
defs := b.GetOpenAPIDefinitions()(func(path string) spec.Ref { return spec.Ref{} })
|
||||
return b.display.GetAPIRoutes(defs)
|
||||
}
|
||||
|
||||
func (b *IdentityAccessManagementAPIBuilder) GetAuthorizer() authorizer.Authorizer {
|
||||
return b.authorizer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,85 +1,115 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
errorsK8s "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
apierrors "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"
|
||||
|
||||
claims "github.com/grafana/authlib/types"
|
||||
authlib "github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||
iam "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/iam/legacy"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util/errhttp"
|
||||
)
|
||||
|
||||
type LegacyDisplayREST struct {
|
||||
store legacy.LegacyIdentityStore
|
||||
}
|
||||
|
||||
var (
|
||||
_ rest.Storage = (*LegacyDisplayREST)(nil)
|
||||
_ rest.SingularNameProvider = (*LegacyDisplayREST)(nil)
|
||||
_ rest.Connecter = (*LegacyDisplayREST)(nil)
|
||||
_ rest.Scoper = (*LegacyDisplayREST)(nil)
|
||||
_ rest.StorageMetadata = (*LegacyDisplayREST)(nil)
|
||||
)
|
||||
|
||||
func NewLegacyDisplayREST(store legacy.LegacyIdentityStore) *LegacyDisplayREST {
|
||||
return &LegacyDisplayREST{store}
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) New() runtime.Object {
|
||||
return &iamv0.DisplayList{}
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) Destroy() {}
|
||||
|
||||
func (r *LegacyDisplayREST) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) GetSingularName() string {
|
||||
return "display"
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) ProducesMIMETypes(verb string) []string {
|
||||
return []string{"application/json"}
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) ProducesObject(verb string) any {
|
||||
return &iamv0.DisplayList{}
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) ConnectMethods() []string {
|
||||
return []string{http.MethodGet}
|
||||
}
|
||||
|
||||
func (r *LegacyDisplayREST) NewConnectOptions() (runtime.Object, bool, string) {
|
||||
return nil, false, "" // true means you can use the trailing path as a variable
|
||||
func (r *LegacyDisplayREST) GetAPIRoutes(defs map[string]common.OpenAPIDefinition) *builder.APIRoutes {
|
||||
listSchema := defs["github.com/grafana/grafana/pkg/apis/iam/v0alpha1.DisplayList"].Schema
|
||||
displaySchema := defs["github.com/grafana/grafana/pkg/apis/iam/v0alpha1.Display"].Schema
|
||||
identitySchema := defs["github.com/grafana/grafana/pkg/apis/iam/v0alpha1.IdentityRef"].Schema
|
||||
listSchema.Properties["display"].Items.Schema = &displaySchema // not sure why this is lost
|
||||
displaySchema.Properties["identity"] = identitySchema // not sure why this is lost
|
||||
return &builder.APIRoutes{
|
||||
Namespace: []builder.APIRouteHandler{
|
||||
{
|
||||
Path: "display",
|
||||
Spec: &spec3.PathProps{
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
OperationId: "getDisplayMapping", // This is used by RTK client generator
|
||||
Tags: []string{"Display"},
|
||||
Description: "Show user display information",
|
||||
Parameters: []*spec3.Parameter{
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "namespace",
|
||||
In: "path",
|
||||
Required: true,
|
||||
Example: "default",
|
||||
Description: "workspace",
|
||||
Schema: spec.StringProperty(),
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "key",
|
||||
In: "query",
|
||||
Description: "Display keys",
|
||||
Required: true,
|
||||
Example: "user:u000000001",
|
||||
Schema: spec.ArrayProperty(spec.StringProperty()),
|
||||
// Style: "form",
|
||||
Explode: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Responses: &spec3.Responses{
|
||||
ResponsesProps: spec3.ResponsesProps{
|
||||
StatusCodeResponses: map[int]*spec3.Response{
|
||||
200: {
|
||||
ResponseProps: spec3.ResponseProps{
|
||||
Content: map[string]*spec3.MediaType{
|
||||
"application/json": {
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: &listSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Handler: r.handleDisplay,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// This will always have an empty app url
|
||||
var fakeCfgForGravatar = &setting.Cfg{}
|
||||
|
||||
func (r *LegacyDisplayREST) Connect(ctx context.Context, name string, _ runtime.Object, responder rest.Responder) (http.Handler, error) {
|
||||
// See: /pkg/services/apiserver/builder/helper.go#L34
|
||||
// The name is set with a rewriter hack
|
||||
if name != "name" {
|
||||
return nil, errorsK8s.NewNotFound(schema.GroupResource{}, name)
|
||||
}
|
||||
ns, err := request.NamespaceInfoFrom(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (r *LegacyDisplayREST) handleDisplay(w http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
user, ok := authlib.AuthInfoFrom(ctx)
|
||||
if !ok {
|
||||
errhttp.Write(ctx, apierrors.NewUnauthorized("missing auth info"), w)
|
||||
return
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
ns, err := authlib.ParseNamespace(user.GetNamespace())
|
||||
if err != nil {
|
||||
errhttp.Write(ctx, err, w)
|
||||
return
|
||||
}
|
||||
keys := parseKeys(req.URL.Query()["key"])
|
||||
users, err := r.store.ListDisplay(ctx, ns, legacy.ListDisplayQuery{
|
||||
OrgID: ns.OrgID,
|
||||
|
|
@ -87,26 +117,26 @@ func (r *LegacyDisplayREST) Connect(ctx context.Context, name string, _ runtime.
|
|||
IDs: keys.ids,
|
||||
})
|
||||
if err != nil {
|
||||
responder.Error(err)
|
||||
errhttp.Write(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
rsp := &iamv0.DisplayList{
|
||||
rsp := &iam.DisplayList{
|
||||
Keys: keys.keys,
|
||||
InvalidKeys: keys.invalid,
|
||||
Items: make([]iamv0.Display, 0, len(users.Users)+len(keys.disp)+1),
|
||||
Items: make([]iam.Display, 0, len(users.Users)+len(keys.disp)+1),
|
||||
}
|
||||
for _, user := range users.Users {
|
||||
disp := iamv0.Display{
|
||||
Identity: iamv0.IdentityRef{
|
||||
Type: claims.TypeUser,
|
||||
disp := iam.Display{
|
||||
Identity: iam.IdentityRef{
|
||||
Type: authlib.TypeUser,
|
||||
Name: user.UID,
|
||||
},
|
||||
DisplayName: user.NameOrFallback(),
|
||||
InternalID: user.ID,
|
||||
InternalID: user.ID, // nolint:staticcheck
|
||||
}
|
||||
if user.IsServiceAccount {
|
||||
disp.Identity.Type = claims.TypeServiceAccount
|
||||
disp.Identity.Type = authlib.TypeServiceAccount
|
||||
}
|
||||
disp.AvatarURL = dtos.GetGravatarUrlWithDefault(fakeCfgForGravatar, user.Email, disp.DisplayName)
|
||||
rsp.Items = append(rsp.Items, disp)
|
||||
|
|
@ -116,8 +146,9 @@ func (r *LegacyDisplayREST) Connect(ctx context.Context, name string, _ runtime.
|
|||
if len(keys.disp) > 0 {
|
||||
rsp.Items = append(rsp.Items, keys.disp...)
|
||||
}
|
||||
responder.Object(200, rsp)
|
||||
}), nil
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(rsp)
|
||||
}
|
||||
|
||||
type dispKeys struct {
|
||||
|
|
@ -127,7 +158,7 @@ type dispKeys struct {
|
|||
invalid []string
|
||||
|
||||
// For terminal keys, this is a constant
|
||||
disp []iamv0.Display
|
||||
disp []iam.Display
|
||||
}
|
||||
|
||||
func parseKeys(req []string) dispKeys {
|
||||
|
|
@ -139,7 +170,7 @@ func parseKeys(req []string) dispKeys {
|
|||
for _, key := range req {
|
||||
idx := strings.Index(key, ":")
|
||||
if idx > 0 {
|
||||
t, err := claims.ParseType(key[0:idx])
|
||||
t, err := authlib.ParseType(key[0:idx])
|
||||
if err != nil {
|
||||
keys.invalid = append(keys.invalid, key)
|
||||
continue
|
||||
|
|
@ -147,18 +178,18 @@ func parseKeys(req []string) dispKeys {
|
|||
key = key[idx+1:]
|
||||
|
||||
switch t {
|
||||
case claims.TypeAnonymous:
|
||||
keys.disp = append(keys.disp, iamv0.Display{
|
||||
Identity: iamv0.IdentityRef{
|
||||
case authlib.TypeAnonymous:
|
||||
keys.disp = append(keys.disp, iam.Display{
|
||||
Identity: iam.IdentityRef{
|
||||
Type: t,
|
||||
},
|
||||
DisplayName: "Anonymous",
|
||||
AvatarURL: dtos.GetGravatarUrl(fakeCfgForGravatar, string(t)),
|
||||
})
|
||||
continue
|
||||
case claims.TypeAPIKey:
|
||||
keys.disp = append(keys.disp, iamv0.Display{
|
||||
Identity: iamv0.IdentityRef{
|
||||
case authlib.TypeAPIKey:
|
||||
keys.disp = append(keys.disp, iam.Display{
|
||||
Identity: iam.IdentityRef{
|
||||
Type: t,
|
||||
Name: key,
|
||||
},
|
||||
|
|
@ -166,9 +197,9 @@ func parseKeys(req []string) dispKeys {
|
|||
AvatarURL: dtos.GetGravatarUrl(fakeCfgForGravatar, string(t)),
|
||||
})
|
||||
continue
|
||||
case claims.TypeProvisioning:
|
||||
keys.disp = append(keys.disp, iamv0.Display{
|
||||
Identity: iamv0.IdentityRef{
|
||||
case authlib.TypeProvisioning:
|
||||
keys.disp = append(keys.disp, iam.Display{
|
||||
Identity: iam.IdentityRef{
|
||||
Type: t,
|
||||
},
|
||||
DisplayName: "Provisioning",
|
||||
|
|
@ -184,9 +215,9 @@ func parseKeys(req []string) dispKeys {
|
|||
id, err := strconv.ParseInt(key, 10, 64)
|
||||
if err == nil {
|
||||
if id == 0 {
|
||||
keys.disp = append(keys.disp, iamv0.Display{
|
||||
Identity: iamv0.IdentityRef{
|
||||
Type: claims.TypeUser,
|
||||
keys.disp = append(keys.disp, iam.Display{
|
||||
Identity: iam.IdentityRef{
|
||||
Type: authlib.TypeUser,
|
||||
Name: key,
|
||||
},
|
||||
DisplayName: "System admin",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import (
|
|||
|
||||
var (
|
||||
_ rest.Storage = (*LegacyUserTeamREST)(nil)
|
||||
_ rest.Scoper = (*LegacyUserTeamREST)(nil)
|
||||
_ rest.StorageMetadata = (*LegacyUserTeamREST)(nil)
|
||||
_ rest.Connecter = (*LegacyUserTeamREST)(nil)
|
||||
)
|
||||
|
|
@ -36,11 +35,6 @@ func (s *LegacyUserTeamREST) New() runtime.Object {
|
|||
// Destroy implements rest.Storage.
|
||||
func (s *LegacyUserTeamREST) Destroy() {}
|
||||
|
||||
// NamespaceScoped implements rest.Scoper.
|
||||
func (s *LegacyUserTeamREST) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ProducesMIMETypes implements rest.StorageMetadata.
|
||||
func (s *LegacyUserTeamREST) ProducesMIMETypes(verb string) []string {
|
||||
return []string{"application/json"}
|
||||
|
|
|
|||
|
|
@ -52,12 +52,6 @@ var PathRewriters = []filters.PathRewriter{
|
|||
return matches[1] + "/name" // connector requires a name
|
||||
},
|
||||
},
|
||||
{
|
||||
Pattern: regexp.MustCompile(`(/apis/iam.grafana.app/v0alpha1/namespaces/.*/display$)`),
|
||||
ReplaceFunc: func(matches []string) string {
|
||||
return matches[1] + "/name" // connector requires a name
|
||||
},
|
||||
},
|
||||
{
|
||||
Pattern: regexp.MustCompile(`(/apis/.*/v0alpha1/namespaces/.*/queryconvert$)`),
|
||||
ReplaceFunc: func(matches []string) string {
|
||||
|
|
|
|||
|
|
@ -35,54 +35,133 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/apis/iam.grafana.app/v0alpha1/namespaces/{namespace}/display/{name}": {
|
||||
"/apis/iam.grafana.app/v0alpha1/namespaces/{namespace}/display": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"DisplayList"
|
||||
"Display"
|
||||
],
|
||||
"description": "connect GET requests to DisplayList",
|
||||
"operationId": "getDisplayList",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"*/*": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.iam.v0alpha1.DisplayList"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-kubernetes-action": "connect",
|
||||
"x-kubernetes-group-version-kind": {
|
||||
"group": "iam.grafana.app",
|
||||
"version": "v0alpha1",
|
||||
"kind": "DisplayList"
|
||||
}
|
||||
},
|
||||
"description": "Show user display information",
|
||||
"operationId": "getDisplayMapping",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"in": "path",
|
||||
"description": "name of the DisplayList",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "namespace",
|
||||
"in": "path",
|
||||
"description": "object name and auth scope, such as for teams and projects",
|
||||
"description": "workspace",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"example": "default"
|
||||
},
|
||||
{
|
||||
"name": "key",
|
||||
"in": "query",
|
||||
"description": "Display keys",
|
||||
"required": true,
|
||||
"explode": true,
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": "user:u000000001"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"keys",
|
||||
"display"
|
||||
],
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"display": {
|
||||
"description": "Matching items (the caller may need to remap from keys to results)",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identity",
|
||||
"displayName"
|
||||
],
|
||||
"properties": {
|
||||
"avatarURL": {
|
||||
"description": "AvatarURL is the url where we can get the avatar for identity",
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"description": "Display name for identity.",
|
||||
"type": "string",
|
||||
"uniqueItems": true
|
||||
"default": ""
|
||||
},
|
||||
"identity": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name is the unique identifier for identity, guaranteed to be a unique value for the type within a namespace.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"type": {
|
||||
"description": "Type of identity e.g. \"user\". For a full list see https://github.com/grafana/authlib/blob/d6737a7dc8f55e9d42834adb83b5da607ceed293/types/type.go#L15",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"internalId": {
|
||||
"description": "InternalID is the legacy numeric id for identity, Deprecated: use the identityRef where possible",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"invalidKeys": {
|
||||
"description": "Input keys that were not useable",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"x-kubernetes-list-type": "set"
|
||||
},
|
||||
"keys": {
|
||||
"description": "Request keys used to lookup the display value",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"x-kubernetes-list-type": "set"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"default": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"/apis/iam.grafana.app/v0alpha1/namespaces/{namespace}/serviceaccounts": {
|
||||
"get": {
|
||||
|
|
@ -2432,105 +2511,6 @@
|
|||
"additionalProperties": true,
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.iam.v0alpha1.Display": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identity",
|
||||
"displayName"
|
||||
],
|
||||
"properties": {
|
||||
"avatarURL": {
|
||||
"description": "AvatarURL is the url where we can get the avatar for identity",
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"description": "Display name for identity.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"identity": {
|
||||
"default": {},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.iam.v0alpha1.IdentityRef"
|
||||
}
|
||||
]
|
||||
},
|
||||
"internalId": {
|
||||
"description": "InternalID is the legacy numreric id for identity, this is deprecated and should be phased out",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.iam.v0alpha1.DisplayList": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"keys",
|
||||
"display"
|
||||
],
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"display": {
|
||||
"description": "Matching items (the caller may need to remap from keys to results)",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"default": {},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.iam.v0alpha1.Display"
|
||||
}
|
||||
]
|
||||
},
|
||||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"invalidKeys": {
|
||||
"description": "Input keys that were not useable",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"x-kubernetes-list-type": "set"
|
||||
},
|
||||
"keys": {
|
||||
"description": "Request keys used to lookup the display value",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"x-kubernetes-list-type": "set"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"default": {},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"x-kubernetes-group-version-kind": [
|
||||
{
|
||||
"group": "iam.grafana.app",
|
||||
"kind": "DisplayList",
|
||||
"version": "__internal"
|
||||
},
|
||||
{
|
||||
"group": "iam.grafana.app",
|
||||
"kind": "DisplayList",
|
||||
"version": "v0alpha1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"com.github.grafana.grafana.pkg.apis.iam.v0alpha1.IdentityRef": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
|
@ -2539,12 +2519,12 @@
|
|||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name is the unique identifier for identity, guaranteed jo be a unique value for the type within a namespace.",
|
||||
"description": "Name is the unique identifier for identity, guaranteed to be a unique value for the type within a namespace.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"type": {
|
||||
"description": "Type of identity e.g. \"user\". For a full list see https://github.com/grafana/authlib/blob/2f8d13a83ca3e82da08b53726de1697ee5b5b4cc/claims/type.go#L15-L24",
|
||||
"description": "Type of identity e.g. \"user\". For a full list see https://github.com/grafana/authlib/blob/d6737a7dc8f55e9d42834adb83b5da607ceed293/types/type.go#L15",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
|
|
@ -2977,7 +2957,7 @@
|
|||
]
|
||||
},
|
||||
"internalId": {
|
||||
"description": "InternalID is the legacy numreric id for identity, this is deprecated and should be phased out",
|
||||
"description": "InternalID is the legacy numeric id for identity, Deprecated: use the identityRef where possible",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue