IAM: Add added and omit permissions list to role definition (#117389)

* add added and omit permissions list to role definition

* Update cue properties according to comments

* Update comment

* rework the the permissionsOmit

* regenerate iam files

* update historian file for tests

* add more generated files

* Update IAM app openAPI spec

---------

Co-authored-by: Gabriel Mabille <gabriel.mabille@grafana.com>
This commit is contained in:
linoman 2026-02-18 15:38:17 +01:00 committed by GitHub
parent 883b6e9417
commit 6939440dcd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 385 additions and 22 deletions

View file

@ -7,13 +7,28 @@ RoleSpec: {
// RBAC scope (e.g: "dashboards:uid:dash1")
scope: string
}
#RoleRef: {
// Kind of role being referenced (for now only GlobalRole is supported)
kind: string
// Name of the role being referenced
name: string
}
// Display name of the role
title: string
description: string
group: string
// Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.
permissions: [...#Permission]
// Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only
permissionsOmitted: [...#Permission] | *[]
// Roles to take permissions from (for now the list should be of size 1)
roleRefs?: [...#RoleRef]
// TODO:
// delegatable?: bool
// created?

View file

@ -20,23 +20,47 @@ func (CoreRolespecPermission) OpenAPIModelName() string {
return "com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.CoreRolespecPermission"
}
// +k8s:openapi-gen=true
type CoreRolespecRoleRef struct {
// Kind of role being referenced (for now only GlobalRole is supported)
Kind string `json:"kind"`
// Name of the role being referenced
Name string `json:"name"`
}
// NewCoreRolespecRoleRef creates a new CoreRolespecRoleRef object.
func NewCoreRolespecRoleRef() *CoreRolespecRoleRef {
return &CoreRolespecRoleRef{}
}
// OpenAPIModelName returns the OpenAPI model name for CoreRolespecRoleRef.
func (CoreRolespecRoleRef) OpenAPIModelName() string {
return "com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.CoreRolespecRoleRef"
}
// +k8s:openapi-gen=true
type CoreRoleSpec struct {
// Display name of the role
Title string `json:"title"`
Description string `json:"description"`
Group string `json:"group"`
// Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.
Permissions []CoreRolespecPermission `json:"permissions"`
// Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only
PermissionsOmitted []CoreRolespecPermission `json:"permissionsOmitted"`
// Roles to take permissions from (for now the list should be of size 1)
// TODO:
// delegatable?: bool
// created?
// updated?
Permissions []CoreRolespecPermission `json:"permissions"`
RoleRefs []CoreRolespecRoleRef `json:"roleRefs,omitempty"`
}
// NewCoreRoleSpec creates a new CoreRoleSpec object.
func NewCoreRoleSpec() *CoreRoleSpec {
return &CoreRoleSpec{
Permissions: []CoreRolespecPermission{},
Permissions: []CoreRolespecPermission{},
PermissionsOmitted: []CoreRolespecPermission{},
}
}

View file

@ -20,23 +20,47 @@ func (GlobalRolespecPermission) OpenAPIModelName() string {
return "com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.GlobalRolespecPermission"
}
// +k8s:openapi-gen=true
type GlobalRolespecRoleRef struct {
// Kind of role being referenced (for now only GlobalRole is supported)
Kind string `json:"kind"`
// Name of the role being referenced
Name string `json:"name"`
}
// NewGlobalRolespecRoleRef creates a new GlobalRolespecRoleRef object.
func NewGlobalRolespecRoleRef() *GlobalRolespecRoleRef {
return &GlobalRolespecRoleRef{}
}
// OpenAPIModelName returns the OpenAPI model name for GlobalRolespecRoleRef.
func (GlobalRolespecRoleRef) OpenAPIModelName() string {
return "com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.GlobalRolespecRoleRef"
}
// +k8s:openapi-gen=true
type GlobalRoleSpec struct {
// Display name of the role
Title string `json:"title"`
Description string `json:"description"`
Group string `json:"group"`
// Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.
Permissions []GlobalRolespecPermission `json:"permissions"`
// Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only
PermissionsOmitted []GlobalRolespecPermission `json:"permissionsOmitted"`
// Roles to take permissions from (for now the list should be of size 1)
// TODO:
// delegatable?: bool
// created?
// updated?
Permissions []GlobalRolespecPermission `json:"permissions"`
RoleRefs []GlobalRolespecRoleRef `json:"roleRefs,omitempty"`
}
// NewGlobalRoleSpec creates a new GlobalRoleSpec object.
func NewGlobalRoleSpec() *GlobalRoleSpec {
return &GlobalRoleSpec{
Permissions: []GlobalRolespecPermission{},
Permissions: []GlobalRolespecPermission{},
PermissionsOmitted: []GlobalRolespecPermission{},
}
}

View file

@ -20,23 +20,47 @@ func (RolespecPermission) OpenAPIModelName() string {
return "com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.RolespecPermission"
}
// +k8s:openapi-gen=true
type RolespecRoleRef struct {
// Kind of role being referenced (for now only GlobalRole is supported)
Kind string `json:"kind"`
// Name of the role being referenced
Name string `json:"name"`
}
// NewRolespecRoleRef creates a new RolespecRoleRef object.
func NewRolespecRoleRef() *RolespecRoleRef {
return &RolespecRoleRef{}
}
// OpenAPIModelName returns the OpenAPI model name for RolespecRoleRef.
func (RolespecRoleRef) OpenAPIModelName() string {
return "com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.RolespecRoleRef"
}
// +k8s:openapi-gen=true
type RoleSpec struct {
// Display name of the role
Title string `json:"title"`
Description string `json:"description"`
Group string `json:"group"`
// Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.
Permissions []RolespecPermission `json:"permissions"`
// Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only
PermissionsOmitted []RolespecPermission `json:"permissionsOmitted"`
// Roles to take permissions from (for now the list should be of size 1)
// TODO:
// delegatable?: bool
// created?
// updated?
Permissions []RolespecPermission `json:"permissions"`
RoleRefs []RolespecRoleRef `json:"roleRefs,omitempty"`
}
// NewRoleSpec creates a new RoleSpec object.
func NewRoleSpec() *RoleSpec {
return &RoleSpec{
Permissions: []RolespecPermission{},
Permissions: []RolespecPermission{},
PermissionsOmitted: []RolespecPermission{},
}
}

View file

@ -13,6 +13,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
CoreRoleSpec{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRoleStatus": schema_pkg_apis_iam_v0alpha1_CoreRoleStatus(ref),
CoreRolespecPermission{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_CoreRolespecPermission(ref),
CoreRolespecRoleRef{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_CoreRolespecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.CoreRolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_CoreRolestatusOperatorState(ref),
ExternalGroupMapping{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_ExternalGroupMapping(ref),
ExternalGroupMappingList{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingList(ref),
@ -44,6 +45,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
GlobalRoleSpec{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleStatus": schema_pkg_apis_iam_v0alpha1_GlobalRoleStatus(ref),
GlobalRolespecPermission{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_GlobalRolespecPermission(ref),
GlobalRolespecRoleRef{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_GlobalRolespecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_GlobalRolestatusOperatorState(ref),
ResourcePermission{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_ResourcePermission(ref),
ResourcePermissionList{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_ResourcePermissionList(ref),
@ -64,6 +66,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
RoleSpec{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_RoleSpec(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleStatus": schema_pkg_apis_iam_v0alpha1_RoleStatus(ref),
RolespecPermission{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_RolespecPermission(ref),
RolespecRoleRef{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_RolespecRoleRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_RolestatusOperatorState(ref),
ServiceAccount{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_ServiceAccount(ref),
ServiceAccountList{}.OpenAPIModelName(): schema_pkg_apis_iam_v0alpha1_ServiceAccountList(ref),
@ -212,7 +215,7 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
},
"permissions": {
SchemaProps: spec.SchemaProps{
Description: "delegatable?: bool created? updated?",
Description: "Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@ -224,12 +227,40 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
},
},
},
"permissionsOmitted": {
SchemaProps: spec.SchemaProps{
Description: "Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(CoreRolespecPermission{}.OpenAPIModelName()),
},
},
},
},
},
"roleRefs": {
SchemaProps: spec.SchemaProps{
Description: "Roles to take permissions from (for now the list should be of size 1) delegatable?: bool created? updated?",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(CoreRolespecRoleRef{}.OpenAPIModelName()),
},
},
},
},
},
},
Required: []string{"title", "description", "group", "permissions"},
Required: []string{"title", "description", "group", "permissions", "permissionsOmitted"},
},
},
Dependencies: []string{
CoreRolespecPermission{}.OpenAPIModelName()},
CoreRolespecPermission{}.OpenAPIModelName(), CoreRolespecRoleRef{}.OpenAPIModelName()},
}
}
@ -306,6 +337,35 @@ func schema_pkg_apis_iam_v0alpha1_CoreRolespecPermission(ref common.ReferenceCal
}
}
func schema_pkg_apis_iam_v0alpha1_CoreRolespecRoleRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind of role being referenced (for now only GlobalRole is supported)",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"name": {
SchemaProps: spec.SchemaProps{
Description: "Name of the role being referenced",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"kind", "name"},
},
},
}
}
func schema_pkg_apis_iam_v0alpha1_CoreRolestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@ -1518,7 +1578,7 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
},
"permissions": {
SchemaProps: spec.SchemaProps{
Description: "delegatable?: bool created? updated?",
Description: "Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@ -1530,12 +1590,40 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
},
},
},
"permissionsOmitted": {
SchemaProps: spec.SchemaProps{
Description: "Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(GlobalRolespecPermission{}.OpenAPIModelName()),
},
},
},
},
},
"roleRefs": {
SchemaProps: spec.SchemaProps{
Description: "Roles to take permissions from (for now the list should be of size 1) delegatable?: bool created? updated?",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(GlobalRolespecRoleRef{}.OpenAPIModelName()),
},
},
},
},
},
},
Required: []string{"title", "description", "group", "permissions"},
Required: []string{"title", "description", "group", "permissions", "permissionsOmitted"},
},
},
Dependencies: []string{
GlobalRolespecPermission{}.OpenAPIModelName()},
GlobalRolespecPermission{}.OpenAPIModelName(), GlobalRolespecRoleRef{}.OpenAPIModelName()},
}
}
@ -1612,6 +1700,35 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRolespecPermission(ref common.ReferenceC
}
}
func schema_pkg_apis_iam_v0alpha1_GlobalRolespecRoleRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind of role being referenced (for now only GlobalRole is supported)",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"name": {
SchemaProps: spec.SchemaProps{
Description: "Name of the role being referenced",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"kind", "name"},
},
},
}
}
func schema_pkg_apis_iam_v0alpha1_GlobalRolestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@ -2353,7 +2470,7 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
},
"permissions": {
SchemaProps: spec.SchemaProps{
Description: "delegatable?: bool created? updated?",
Description: "Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
@ -2365,12 +2482,40 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
},
},
},
"permissionsOmitted": {
SchemaProps: spec.SchemaProps{
Description: "Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(RolespecPermission{}.OpenAPIModelName()),
},
},
},
},
},
"roleRefs": {
SchemaProps: spec.SchemaProps{
Description: "Roles to take permissions from (for now the list should be of size 1) delegatable?: bool created? updated?",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(RolespecRoleRef{}.OpenAPIModelName()),
},
},
},
},
},
},
Required: []string{"title", "description", "group", "permissions"},
Required: []string{"title", "description", "group", "permissions", "permissionsOmitted"},
},
},
Dependencies: []string{
RolespecPermission{}.OpenAPIModelName()},
RolespecPermission{}.OpenAPIModelName(), RolespecRoleRef{}.OpenAPIModelName()},
}
}
@ -2447,6 +2592,35 @@ func schema_pkg_apis_iam_v0alpha1_RolespecPermission(ref common.ReferenceCallbac
}
}
func schema_pkg_apis_iam_v0alpha1_RolespecRoleRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind of role being referenced (for now only GlobalRole is supported)",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"name": {
SchemaProps: spec.SchemaProps{
Description: "Name of the role being referenced",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"kind", "name"},
},
},
}
}
func schema_pkg_apis_iam_v0alpha1_RolestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{

View file

@ -4983,7 +4983,8 @@
"title",
"description",
"group",
"permissions"
"permissions",
"permissionsOmitted"
],
"properties": {
"description": {
@ -4995,7 +4996,21 @@
"default": ""
},
"permissions": {
"description": "delegatable?: bool created? updated?",
"description": "Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.",
"type": "array",
"items": {
"default": {}
}
},
"permissionsOmitted": {
"description": "Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only",
"type": "array",
"items": {
"default": {}
}
},
"roleRefs": {
"description": "Roles to take permissions from (for now the list should be of size 1) delegatable?: bool created? updated?",
"type": "array",
"items": {
"default": {}
@ -5027,6 +5042,25 @@
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.CoreRolespecRoleRef": {
"type": "object",
"required": [
"kind",
"name"
],
"properties": {
"kind": {
"description": "Kind of role being referenced (for now only GlobalRole is supported)",
"type": "string",
"default": ""
},
"name": {
"description": "Name of the role being referenced",
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.ExternalGroupMapping": {
"type": "object",
"required": [
@ -5706,7 +5740,8 @@
"title",
"description",
"group",
"permissions"
"permissions",
"permissionsOmitted"
],
"properties": {
"description": {
@ -5718,7 +5753,21 @@
"default": ""
},
"permissions": {
"description": "delegatable?: bool created? updated?",
"description": "Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.",
"type": "array",
"items": {
"default": {}
}
},
"permissionsOmitted": {
"description": "Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only",
"type": "array",
"items": {
"default": {}
}
},
"roleRefs": {
"description": "Roles to take permissions from (for now the list should be of size 1) delegatable?: bool created? updated?",
"type": "array",
"items": {
"default": {}
@ -5750,6 +5799,25 @@
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.GlobalRolespecRoleRef": {
"type": "object",
"required": [
"kind",
"name"
],
"properties": {
"kind": {
"description": "Kind of role being referenced (for now only GlobalRole is supported)",
"type": "string",
"default": ""
},
"name": {
"description": "Name of the role being referenced",
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.ResourcePermission": {
"type": "object",
"required": [
@ -6030,7 +6098,8 @@
"title",
"description",
"group",
"permissions"
"permissions",
"permissionsOmitted"
],
"properties": {
"description": {
@ -6042,7 +6111,21 @@
"default": ""
},
"permissions": {
"description": "delegatable?: bool created? updated?",
"description": "Added permissions (permissions in actual role but NOT in seed) - for basic roles only. For custom roles, this contains all permissions.",
"type": "array",
"items": {
"default": {}
}
},
"permissionsOmitted": {
"description": "Permissions that exist in seed but NOT in actual role (missing/omitted permissions) - used for basic roles only",
"type": "array",
"items": {
"default": {}
}
},
"roleRefs": {
"description": "Roles to take permissions from (for now the list should be of size 1) delegatable?: bool created? updated?",
"type": "array",
"items": {
"default": {}
@ -6074,6 +6157,25 @@
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.RolespecRoleRef": {
"type": "object",
"required": [
"kind",
"name"
],
"properties": {
"kind": {
"description": "Kind of role being referenced (for now only GlobalRole is supported)",
"type": "string",
"default": ""
},
"name": {
"description": "Name of the role being referenced",
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.ServiceAccount": {
"type": "object",
"required": [