published on Saturday, Aug 1, 2026 by Pulumi
published on Saturday, Aug 1, 2026 by Pulumi
This data source fetches an authorization scope by name from an OpenID client that has authorization enabled.
The primary use case is looking up scopes that Keycloak creates automatically — for example, the view, manage, view-members, manage-members, and manage-membership scopes that Keycloak creates on the realm-management client when Fine-Grained Admin Permissions are enabled for a group. These scopes need to be referenced by ID in keycloak.openid.ClientAuthorizationPermission, but their IDs are not known until after the permissions have been initialized. Providing a scope name directly (instead of an ID) causes plan instability because Keycloak always stores and returns scope IDs.
Example Usage
The following example demonstrates the primary use case: resolving an authorization scope by name so it can be referenced by ID in a keycloak.openid.ClientAuthorizationPermission. Using a scope name directly causes plan instability because Keycloak normalises the value to an ID on write — this data source fixes that.
import * as pulumi from "@pulumi/pulumi";
import * as keycloak from "@pulumi/keycloak";
const realm = new keycloak.Realm("realm", {realm: "my-realm"});
// An application client with authorization enabled.
const app = new keycloak.openid.Client("app", {
realmId: realm.id,
clientId: "my-app",
accessType: "CONFIDENTIAL",
serviceAccountsEnabled: true,
authorization: {
policyEnforcementMode: "ENFORCING",
},
});
// A named scope on the authorization-enabled client.
const readOrdersClientAuthorizationScope = new keycloak.openid.ClientAuthorizationScope("read_orders", {
realmId: realm.id,
resourceServerId: app.resourceServerId,
name: "read:orders",
});
// Resolve the scope ID by name — stable across plan/apply cycles.
const readOrders = keycloak.openid.getClientAuthorizationScopeOutput({
realmId: realm.id,
resourceServerId: app.resourceServerId,
name: "read:orders",
});
const orders = new keycloak.openid.ClientAuthorizationResource("orders", {
realmId: realm.id,
resourceServerId: app.resourceServerId,
name: "orders",
uris: ["/orders/*"],
});
const readOrdersClientAuthorizationPermission = new keycloak.openid.ClientAuthorizationPermission("read_orders", {
realmId: realm.id,
resourceServerId: app.resourceServerId,
name: "read-orders-permission",
type: "scope",
decisionStrategy: "UNANIMOUS",
resources: [orders.id],
scopes: [readOrders.apply(readOrders => readOrders.id)],
});
import pulumi
import pulumi_keycloak as keycloak
realm = keycloak.Realm("realm", realm="my-realm")
# An application client with authorization enabled.
app = keycloak.openid.Client("app",
realm_id=realm.id,
client_id="my-app",
access_type="CONFIDENTIAL",
service_accounts_enabled=True,
authorization={
"policy_enforcement_mode": "ENFORCING",
})
# A named scope on the authorization-enabled client.
read_orders_client_authorization_scope = keycloak.openid.ClientAuthorizationScope("read_orders",
realm_id=realm.id,
resource_server_id=app.resource_server_id,
name="read:orders")
# Resolve the scope ID by name — stable across plan/apply cycles.
read_orders = keycloak.openid.get_client_authorization_scope_output(realm_id=realm.id,
resource_server_id=app.resource_server_id,
name="read:orders")
orders = keycloak.openid.ClientAuthorizationResource("orders",
realm_id=realm.id,
resource_server_id=app.resource_server_id,
name="orders",
uris=["/orders/*"])
read_orders_client_authorization_permission = keycloak.openid.ClientAuthorizationPermission("read_orders",
realm_id=realm.id,
resource_server_id=app.resource_server_id,
name="read-orders-permission",
type="scope",
decision_strategy="UNANIMOUS",
resources=[orders.id],
scopes=[read_orders.id])
package main
import (
"github.com/pulumi/pulumi-keycloak/sdk/v6/go/keycloak"
"github.com/pulumi/pulumi-keycloak/sdk/v6/go/keycloak/openid"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
realm, err := keycloak.NewRealm(ctx, "realm", &keycloak.RealmArgs{
Realm: pulumi.String("my-realm"),
})
if err != nil {
return err
}
// An application client with authorization enabled.
app, err := openid.NewClient(ctx, "app", &openid.ClientArgs{
RealmId: realm.ID(),
ClientId: pulumi.String("my-app"),
AccessType: pulumi.String("CONFIDENTIAL"),
ServiceAccountsEnabled: pulumi.Bool(true),
Authorization: &openid.ClientAuthorizationArgs{
PolicyEnforcementMode: pulumi.String("ENFORCING"),
},
})
if err != nil {
return err
}
// A named scope on the authorization-enabled client.
_, err = openid.NewClientAuthorizationScope(ctx, "read_orders", &openid.ClientAuthorizationScopeArgs{
RealmId: realm.ID(),
ResourceServerId: app.ResourceServerId,
Name: pulumi.String("read:orders"),
})
if err != nil {
return err
}
// Resolve the scope ID by name — stable across plan/apply cycles.
readOrders := openid.LookupClientAuthorizationScopeOutput(ctx, openid.GetClientAuthorizationScopeOutputArgs{
RealmId: realm.ID(),
ResourceServerId: app.ResourceServerId,
Name: pulumi.String("read:orders"),
}, nil)
orders, err := openid.NewClientAuthorizationResource(ctx, "orders", &openid.ClientAuthorizationResourceArgs{
RealmId: realm.ID(),
ResourceServerId: app.ResourceServerId,
Name: pulumi.String("orders"),
Uris: pulumi.StringArray{
pulumi.String("/orders/*"),
},
})
if err != nil {
return err
}
_, err = openid.NewClientAuthorizationPermission(ctx, "read_orders", &openid.ClientAuthorizationPermissionArgs{
RealmId: realm.ID(),
ResourceServerId: app.ResourceServerId,
Name: pulumi.String("read-orders-permission"),
Type: pulumi.String("scope"),
DecisionStrategy: pulumi.String("UNANIMOUS"),
Resources: pulumi.StringArray{
orders.ID(),
},
Scopes: pulumi.StringArray{
pulumi.String(readOrders.ApplyT(func(readOrders openid.GetClientAuthorizationScopeResult) (*string, error) {
return readOrders.Id, nil
}).(pulumi.StringPtrOutput)),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Keycloak = Pulumi.Keycloak;
return await Deployment.RunAsync(() =>
{
var realm = new Keycloak.Realm("realm", new()
{
RealmName = "my-realm",
});
// An application client with authorization enabled.
var app = new Keycloak.OpenId.Client("app", new()
{
RealmId = realm.Id,
ClientId = "my-app",
AccessType = "CONFIDENTIAL",
ServiceAccountsEnabled = true,
Authorization = new Keycloak.OpenId.Inputs.ClientAuthorizationArgs
{
PolicyEnforcementMode = "ENFORCING",
},
});
// A named scope on the authorization-enabled client.
var readOrdersClientAuthorizationScope = new Keycloak.OpenId.ClientAuthorizationScope("read_orders", new()
{
RealmId = realm.Id,
ResourceServerId = app.ResourceServerId,
Name = "read:orders",
});
// Resolve the scope ID by name — stable across plan/apply cycles.
var readOrders = Keycloak.OpenId.GetClientAuthorizationScope.Invoke(new()
{
RealmId = realm.Id,
ResourceServerId = app.ResourceServerId,
Name = "read:orders",
});
var orders = new Keycloak.OpenId.ClientAuthorizationResource("orders", new()
{
RealmId = realm.Id,
ResourceServerId = app.ResourceServerId,
Name = "orders",
Uris = new[]
{
"/orders/*",
},
});
var readOrdersClientAuthorizationPermission = new Keycloak.OpenId.ClientAuthorizationPermission("read_orders", new()
{
RealmId = realm.Id,
ResourceServerId = app.ResourceServerId,
Name = "read-orders-permission",
Type = "scope",
DecisionStrategy = "UNANIMOUS",
Resources = new[]
{
orders.Id,
},
Scopes = new[]
{
readOrders.Apply(getClientAuthorizationScopeResult => getClientAuthorizationScopeResult.Id),
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.keycloak.Realm;
import com.pulumi.keycloak.RealmArgs;
import com.pulumi.keycloak.openid.Client;
import com.pulumi.keycloak.openid.ClientArgs;
import com.pulumi.keycloak.openid.inputs.ClientAuthorizationArgs;
import com.pulumi.keycloak.openid.ClientAuthorizationScope;
import com.pulumi.keycloak.openid.ClientAuthorizationScopeArgs;
import com.pulumi.keycloak.openid.OpenidFunctions;
import com.pulumi.keycloak.openid.inputs.GetClientAuthorizationScopeArgs;
import com.pulumi.keycloak.openid.ClientAuthorizationResource;
import com.pulumi.keycloak.openid.ClientAuthorizationResourceArgs;
import com.pulumi.keycloak.openid.ClientAuthorizationPermission;
import com.pulumi.keycloak.openid.ClientAuthorizationPermissionArgs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var realm = new Realm("realm", RealmArgs.builder()
.realm("my-realm")
.build());
// An application client with authorization enabled.
var app = new Client("app", ClientArgs.builder()
.realmId(realm.id())
.clientId("my-app")
.accessType("CONFIDENTIAL")
.serviceAccountsEnabled(true)
.authorization(ClientAuthorizationArgs.builder()
.policyEnforcementMode("ENFORCING")
.build())
.build());
// A named scope on the authorization-enabled client.
var readOrdersClientAuthorizationScope = new ClientAuthorizationScope("readOrdersClientAuthorizationScope", ClientAuthorizationScopeArgs.builder()
.realmId(realm.id())
.resourceServerId(app.resourceServerId())
.name("read:orders")
.build());
// Resolve the scope ID by name — stable across plan/apply cycles.
final var readOrders = OpenidFunctions.getClientAuthorizationScope(GetClientAuthorizationScopeArgs.builder()
.realmId(realm.id())
.resourceServerId(app.resourceServerId())
.name("read:orders")
.build());
var orders = new ClientAuthorizationResource("orders", ClientAuthorizationResourceArgs.builder()
.realmId(realm.id())
.resourceServerId(app.resourceServerId())
.name("orders")
.uris("/orders/*")
.build());
var readOrdersClientAuthorizationPermission = new ClientAuthorizationPermission("readOrdersClientAuthorizationPermission", ClientAuthorizationPermissionArgs.builder()
.realmId(realm.id())
.resourceServerId(app.resourceServerId())
.name("read-orders-permission")
.type("scope")
.decisionStrategy("UNANIMOUS")
.resources(orders.id())
.scopes(readOrders.applyValue(_readOrders -> _readOrders.id()))
.build());
}
}
resources:
realm:
type: keycloak:Realm
properties:
realm: my-realm
# An application client with authorization enabled.
app:
type: keycloak:openid:Client
properties:
realmId: ${realm.id}
clientId: my-app
accessType: CONFIDENTIAL
serviceAccountsEnabled: true
authorization:
policyEnforcementMode: ENFORCING
# A named scope on the authorization-enabled client.
readOrdersClientAuthorizationScope:
type: keycloak:openid:ClientAuthorizationScope
name: read_orders
properties:
realmId: ${realm.id}
resourceServerId: ${app.resourceServerId}
name: read:orders
orders:
type: keycloak:openid:ClientAuthorizationResource
properties:
realmId: ${realm.id}
resourceServerId: ${app.resourceServerId}
name: orders
uris:
- /orders/*
readOrdersClientAuthorizationPermission:
type: keycloak:openid:ClientAuthorizationPermission
name: read_orders
properties:
realmId: ${realm.id}
resourceServerId: ${app.resourceServerId}
name: read-orders-permission
type: scope
decisionStrategy: UNANIMOUS
resources:
- ${orders.id}
scopes:
- ${readOrders.id}
variables:
# Resolve the scope ID by name — stable across plan/apply cycles.
readOrders:
fn::invoke:
function: keycloak:openid:getClientAuthorizationScope
arguments:
realmId: ${realm.id}
resourceServerId: ${app.resourceServerId}
name: read:orders
pulumi {
required_providers {
keycloak = {
source = "pulumi/keycloak"
}
}
}
data "keycloak_openid_getclientauthorizationscope" "readOrders" {
realm_id = keycloak_realm.realm.id
resource_server_id = keycloak_openid_client.app.resource_server_id
name = "read:orders"
}
resource "keycloak_realm" "realm" {
realm = "my-realm"
}
# An application client with authorization enabled.
resource "keycloak_openid_client" "app" {
realm_id = keycloak_realm.realm.id
client_id = "my-app"
access_type = "CONFIDENTIAL"
service_accounts_enabled = true
authorization = {
policy_enforcement_mode = "ENFORCING"
}
}
# A named scope on the authorization-enabled client.
resource "keycloak_openid_clientauthorizationscope" "read_orders" {
realm_id = keycloak_realm.realm.id
resource_server_id = keycloak_openid_client.app.resource_server_id
name = "read:orders"
}
resource "keycloak_openid_clientauthorizationresource" "orders" {
realm_id = keycloak_realm.realm.id
resource_server_id = keycloak_openid_client.app.resource_server_id
name = "orders"
uris = ["/orders/*"]
}
resource "keycloak_openid_clientauthorizationpermission" "read_orders" {
realm_id = keycloak_realm.realm.id
resource_server_id = keycloak_openid_client.app.resource_server_id
name = "read-orders-permission"
type = "scope"
decision_strategy = "UNANIMOUS"
resources = [keycloak_openid_clientauthorizationresource.orders.id]
scopes = [data.keycloak_openid_getclientauthorizationscope.readOrders.id]
}
# Resolve the scope ID by name — stable across plan/apply cycles.
FGAPv2 example: role-based map-role permission
The following shows how to use FGAPv2 (admin-fine-grained-authz:v2) to grant members of an hr-managers group permission to map an hr-viewer role. The map-role scope lives on the admin-permissions resource server; this data source resolves its ID for use in a custom scope-based permission alongside the one managed by keycloak.RoleAdminPermissions.
import * as pulumi from "@pulumi/pulumi";
import * as keycloak from "@pulumi/keycloak";
const realm = new keycloak.Realm("realm", {
realm: "my-realm",
adminPermissionsEnabled: true,
});
const adminPermissions = keycloak.openid.getClientOutput({
realmId: realm.id,
clientId: "admin-permissions",
});
const hrViewer = new keycloak.Role("hr_viewer", {
realmId: realm.id,
name: "hr-viewer",
});
const hrViewerRoleAdminPermissions = new keycloak.RoleAdminPermissions("hr_viewer", {
realmId: realm.id,
name: "map-role-hr-viewer",
roleIds: [hrViewer.id],
scopes: ["map-role"],
});
// Resolve the map-role scope by name for use in a custom permission.
const mapRole = keycloak.openid.getClientAuthorizationScopeOutput({
realmId: realm.id,
resourceServerId: adminPermissions.apply(adminPermissions => adminPermissions.id),
name: "map-role",
});
const hrManagers = new keycloak.Group("hr_managers", {
realmId: realm.id,
name: "hr-managers",
});
const hrManagersClientGroupPolicy = new keycloak.openid.ClientGroupPolicy("hr_managers", {
realmId: realm.id,
resourceServerId: adminPermissions.apply(adminPermissions => adminPermissions.id),
name: "policy-hr-managers",
decisionStrategy: "UNANIMOUS",
logic: "POSITIVE",
groups: [{
id: hrManagers.id,
path: hrManagers.path,
extendChildren: false,
}],
});
const hrManagersMapRole = new keycloak.openid.ClientAuthorizationPermission("hr_managers_map_role", {
realmId: realm.id,
resourceServerId: adminPermissions.apply(adminPermissions => adminPermissions.id),
name: "hr-managers-map-hr-viewer-role",
type: "scope",
decisionStrategy: "UNANIMOUS",
resources: [hrViewer.id],
scopes: [mapRole.apply(mapRole => mapRole.id)],
policies: [hrManagersClientGroupPolicy.id],
});
import pulumi
import pulumi_keycloak as keycloak
realm = keycloak.Realm("realm",
realm="my-realm",
admin_permissions_enabled=True)
admin_permissions = keycloak.openid.get_client_output(realm_id=realm.id,
client_id="admin-permissions")
hr_viewer = keycloak.Role("hr_viewer",
realm_id=realm.id,
name="hr-viewer")
hr_viewer_role_admin_permissions = keycloak.RoleAdminPermissions("hr_viewer",
realm_id=realm.id,
name="map-role-hr-viewer",
role_ids=[hr_viewer.id],
scopes=["map-role"])
# Resolve the map-role scope by name for use in a custom permission.
map_role = keycloak.openid.get_client_authorization_scope_output(realm_id=realm.id,
resource_server_id=admin_permissions.id,
name="map-role")
hr_managers = keycloak.Group("hr_managers",
realm_id=realm.id,
name="hr-managers")
hr_managers_client_group_policy = keycloak.openid.ClientGroupPolicy("hr_managers",
realm_id=realm.id,
resource_server_id=admin_permissions.id,
name="policy-hr-managers",
decision_strategy="UNANIMOUS",
logic="POSITIVE",
groups=[{
"id": hr_managers.id,
"path": hr_managers.path,
"extend_children": False,
}])
hr_managers_map_role = keycloak.openid.ClientAuthorizationPermission("hr_managers_map_role",
realm_id=realm.id,
resource_server_id=admin_permissions.id,
name="hr-managers-map-hr-viewer-role",
type="scope",
decision_strategy="UNANIMOUS",
resources=[hr_viewer.id],
scopes=[map_role.id],
policies=[hr_managers_client_group_policy.id])
package main
import (
"github.com/pulumi/pulumi-keycloak/sdk/v6/go/keycloak"
"github.com/pulumi/pulumi-keycloak/sdk/v6/go/keycloak/openid"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
realm, err := keycloak.NewRealm(ctx, "realm", &keycloak.RealmArgs{
Realm: pulumi.String("my-realm"),
AdminPermissionsEnabled: pulumi.Bool(true),
})
if err != nil {
return err
}
adminPermissions := openid.LookupClientOutput(ctx, openid.GetClientOutputArgs{
RealmId: realm.ID(),
ClientId: pulumi.String("admin-permissions"),
}, nil)
hrViewer, err := keycloak.NewRole(ctx, "hr_viewer", &keycloak.RoleArgs{
RealmId: realm.ID(),
Name: pulumi.String("hr-viewer"),
})
if err != nil {
return err
}
_, err = keycloak.NewRoleAdminPermissions(ctx, "hr_viewer", &keycloak.RoleAdminPermissionsArgs{
RealmId: realm.ID(),
Name: pulumi.String("map-role-hr-viewer"),
RoleIds: pulumi.StringArray{
hrViewer.ID(),
},
Scopes: pulumi.StringArray{
pulumi.String("map-role"),
},
})
if err != nil {
return err
}
// Resolve the map-role scope by name for use in a custom permission.
mapRole := openid.LookupClientAuthorizationScopeOutput(ctx, openid.GetClientAuthorizationScopeOutputArgs{
RealmId: realm.ID(),
ResourceServerId: adminPermissions.ApplyT(func(adminPermissions openid.GetClientResult) (*string, error) {
return adminPermissions.Id, nil
}).(pulumi.StringPtrOutput),
Name: pulumi.String("map-role"),
}, nil)
hrManagers, err := keycloak.NewGroup(ctx, "hr_managers", &keycloak.GroupArgs{
RealmId: realm.ID(),
Name: pulumi.String("hr-managers"),
})
if err != nil {
return err
}
hrManagersClientGroupPolicy, err := openid.NewClientGroupPolicy(ctx, "hr_managers", &openid.ClientGroupPolicyArgs{
RealmId: realm.ID(),
ResourceServerId: pulumi.String(adminPermissions.ApplyT(func(adminPermissions openid.GetClientResult) (*string, error) {
return adminPermissions.Id, nil
}).(pulumi.StringPtrOutput)),
Name: pulumi.String("policy-hr-managers"),
DecisionStrategy: pulumi.String("UNANIMOUS"),
Logic: pulumi.String("POSITIVE"),
Groups: openid.ClientGroupPolicyGroupArray{
&openid.ClientGroupPolicyGroupArgs{
Id: hrManagers.ID(),
Path: hrManagers.Path,
ExtendChildren: pulumi.Bool(false),
},
},
})
if err != nil {
return err
}
_, err = openid.NewClientAuthorizationPermission(ctx, "hr_managers_map_role", &openid.ClientAuthorizationPermissionArgs{
RealmId: realm.ID(),
ResourceServerId: pulumi.String(adminPermissions.ApplyT(func(adminPermissions openid.GetClientResult) (*string, error) {
return adminPermissions.Id, nil
}).(pulumi.StringPtrOutput)),
Name: pulumi.String("hr-managers-map-hr-viewer-role"),
Type: pulumi.String("scope"),
DecisionStrategy: pulumi.String("UNANIMOUS"),
Resources: pulumi.StringArray{
hrViewer.ID(),
},
Scopes: pulumi.StringArray{
pulumi.String(mapRole.ApplyT(func(mapRole openid.GetClientAuthorizationScopeResult) (*string, error) {
return mapRole.Id, nil
}).(pulumi.StringPtrOutput)),
},
Policies: pulumi.StringArray{
hrManagersClientGroupPolicy.ID(),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Keycloak = Pulumi.Keycloak;
return await Deployment.RunAsync(() =>
{
var realm = new Keycloak.Realm("realm", new()
{
RealmName = "my-realm",
AdminPermissionsEnabled = true,
});
var adminPermissions = Keycloak.OpenId.GetClient.Invoke(new()
{
RealmId = realm.Id,
ClientId = "admin-permissions",
});
var hrViewer = new Keycloak.Role("hr_viewer", new()
{
RealmId = realm.Id,
Name = "hr-viewer",
});
var hrViewerRoleAdminPermissions = new Keycloak.RoleAdminPermissions("hr_viewer", new()
{
RealmId = realm.Id,
Name = "map-role-hr-viewer",
RoleIds = new[]
{
hrViewer.Id,
},
Scopes = new[]
{
"map-role",
},
});
// Resolve the map-role scope by name for use in a custom permission.
var mapRole = Keycloak.OpenId.GetClientAuthorizationScope.Invoke(new()
{
RealmId = realm.Id,
ResourceServerId = adminPermissions.Apply(getClientResult => getClientResult.Id),
Name = "map-role",
});
var hrManagers = new Keycloak.Group("hr_managers", new()
{
RealmId = realm.Id,
Name = "hr-managers",
});
var hrManagersClientGroupPolicy = new Keycloak.OpenId.ClientGroupPolicy("hr_managers", new()
{
RealmId = realm.Id,
ResourceServerId = adminPermissions.Apply(getClientResult => getClientResult.Id),
Name = "policy-hr-managers",
DecisionStrategy = "UNANIMOUS",
Logic = "POSITIVE",
Groups = new[]
{
new Keycloak.OpenId.Inputs.ClientGroupPolicyGroupArgs
{
Id = hrManagers.Id,
Path = hrManagers.Path,
ExtendChildren = false,
},
},
});
var hrManagersMapRole = new Keycloak.OpenId.ClientAuthorizationPermission("hr_managers_map_role", new()
{
RealmId = realm.Id,
ResourceServerId = adminPermissions.Apply(getClientResult => getClientResult.Id),
Name = "hr-managers-map-hr-viewer-role",
Type = "scope",
DecisionStrategy = "UNANIMOUS",
Resources = new[]
{
hrViewer.Id,
},
Scopes = new[]
{
mapRole.Apply(getClientAuthorizationScopeResult => getClientAuthorizationScopeResult.Id),
},
Policies = new[]
{
hrManagersClientGroupPolicy.Id,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.keycloak.Realm;
import com.pulumi.keycloak.RealmArgs;
import com.pulumi.keycloak.openid.OpenidFunctions;
import com.pulumi.keycloak.openid.inputs.GetClientArgs;
import com.pulumi.keycloak.Role;
import com.pulumi.keycloak.RoleArgs;
import com.pulumi.keycloak.RoleAdminPermissions;
import com.pulumi.keycloak.RoleAdminPermissionsArgs;
import com.pulumi.keycloak.openid.inputs.GetClientAuthorizationScopeArgs;
import com.pulumi.keycloak.Group;
import com.pulumi.keycloak.GroupArgs;
import com.pulumi.keycloak.openid.ClientGroupPolicy;
import com.pulumi.keycloak.openid.ClientGroupPolicyArgs;
import com.pulumi.keycloak.openid.inputs.ClientGroupPolicyGroupArgs;
import com.pulumi.keycloak.openid.ClientAuthorizationPermission;
import com.pulumi.keycloak.openid.ClientAuthorizationPermissionArgs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var realm = new Realm("realm", RealmArgs.builder()
.realm("my-realm")
.adminPermissionsEnabled(true)
.build());
final var adminPermissions = OpenidFunctions.getClient(GetClientArgs.builder()
.realmId(realm.id())
.clientId("admin-permissions")
.build());
var hrViewer = new Role("hrViewer", RoleArgs.builder()
.realmId(realm.id())
.name("hr-viewer")
.build());
var hrViewerRoleAdminPermissions = new RoleAdminPermissions("hrViewerRoleAdminPermissions", RoleAdminPermissionsArgs.builder()
.realmId(realm.id())
.name("map-role-hr-viewer")
.roleIds(hrViewer.id())
.scopes("map-role")
.build());
// Resolve the map-role scope by name for use in a custom permission.
final var mapRole = OpenidFunctions.getClientAuthorizationScope(GetClientAuthorizationScopeArgs.builder()
.realmId(realm.id())
.resourceServerId(adminPermissions.applyValue(_adminPermissions -> _adminPermissions.id()))
.name("map-role")
.build());
var hrManagers = new Group("hrManagers", GroupArgs.builder()
.realmId(realm.id())
.name("hr-managers")
.build());
var hrManagersClientGroupPolicy = new ClientGroupPolicy("hrManagersClientGroupPolicy", ClientGroupPolicyArgs.builder()
.realmId(realm.id())
.resourceServerId(adminPermissions.applyValue(_adminPermissions -> _adminPermissions.id()))
.name("policy-hr-managers")
.decisionStrategy("UNANIMOUS")
.logic("POSITIVE")
.groups(ClientGroupPolicyGroupArgs.builder()
.id(hrManagers.id())
.path(hrManagers.path())
.extendChildren(false)
.build())
.build());
var hrManagersMapRole = new ClientAuthorizationPermission("hrManagersMapRole", ClientAuthorizationPermissionArgs.builder()
.realmId(realm.id())
.resourceServerId(adminPermissions.applyValue(_adminPermissions -> _adminPermissions.id()))
.name("hr-managers-map-hr-viewer-role")
.type("scope")
.decisionStrategy("UNANIMOUS")
.resources(hrViewer.id())
.scopes(mapRole.applyValue(_mapRole -> _mapRole.id()))
.policies(hrManagersClientGroupPolicy.id())
.build());
}
}
resources:
realm:
type: keycloak:Realm
properties:
realm: my-realm
adminPermissionsEnabled: true
hrViewer:
type: keycloak:Role
name: hr_viewer
properties:
realmId: ${realm.id}
name: hr-viewer
hrViewerRoleAdminPermissions:
type: keycloak:RoleAdminPermissions
name: hr_viewer
properties:
realmId: ${realm.id}
name: map-role-hr-viewer
roleIds:
- ${hrViewer.id}
scopes:
- map-role
hrManagers:
type: keycloak:Group
name: hr_managers
properties:
realmId: ${realm.id}
name: hr-managers
hrManagersClientGroupPolicy:
type: keycloak:openid:ClientGroupPolicy
name: hr_managers
properties:
realmId: ${realm.id}
resourceServerId: ${adminPermissions.id}
name: policy-hr-managers
decisionStrategy: UNANIMOUS
logic: POSITIVE
groups:
- id: ${hrManagers.id}
path: ${hrManagers.path}
extendChildren: false
hrManagersMapRole:
type: keycloak:openid:ClientAuthorizationPermission
name: hr_managers_map_role
properties:
realmId: ${realm.id}
resourceServerId: ${adminPermissions.id}
name: hr-managers-map-hr-viewer-role
type: scope
decisionStrategy: UNANIMOUS
resources:
- ${hrViewer.id}
scopes:
- ${mapRole.id}
policies:
- ${hrManagersClientGroupPolicy.id}
variables:
adminPermissions:
fn::invoke:
function: keycloak:openid:getClient
arguments:
realmId: ${realm.id}
clientId: admin-permissions
# Resolve the map-role scope by name for use in a custom permission.
mapRole:
fn::invoke:
function: keycloak:openid:getClientAuthorizationScope
arguments:
realmId: ${realm.id}
resourceServerId: ${adminPermissions.id}
name: map-role
pulumi {
required_providers {
keycloak = {
source = "pulumi/keycloak"
}
}
}
data "keycloak_openid_getclient" "adminPermissions" {
realm_id = keycloak_realm.realm.id
client_id = "admin-permissions"
}
data "keycloak_openid_getclientauthorizationscope" "mapRole" {
realm_id = keycloak_realm.realm.id
resource_server_id = data.keycloak_openid_getclient.adminPermissions.id
name = "map-role"
}
resource "keycloak_realm" "realm" {
realm = "my-realm"
admin_permissions_enabled = true
}
resource "keycloak_role" "hr_viewer" {
realm_id = keycloak_realm.realm.id
name = "hr-viewer"
}
resource "keycloak_roleadminpermissions" "hr_viewer" {
realm_id = keycloak_realm.realm.id
name = "map-role-hr-viewer"
role_ids = [keycloak_role.hr_viewer.id]
scopes = ["map-role"]
}
resource "keycloak_group" "hr_managers" {
realm_id = keycloak_realm.realm.id
name = "hr-managers"
}
resource "keycloak_openid_clientgrouppolicy" "hr_managers" {
realm_id = keycloak_realm.realm.id
resource_server_id = data.keycloak_openid_getclient.adminPermissions.id
name = "policy-hr-managers"
decision_strategy = "UNANIMOUS"
logic = "POSITIVE"
groups {
id = keycloak_group.hr_managers.id
path = keycloak_group.hr_managers.path
extend_children = false
}
}
resource "keycloak_openid_clientauthorizationpermission" "hr_managers_map_role" {
realm_id = keycloak_realm.realm.id
resource_server_id = data.keycloak_openid_getclient.adminPermissions.id
name = "hr-managers-map-hr-viewer-role"
type = "scope"
decision_strategy = "UNANIMOUS"
resources = [keycloak_role.hr_viewer.id]
scopes = [data.keycloak_openid_getclientauthorizationscope.mapRole.id]
policies = [keycloak_openid_clientgrouppolicy.hr_managers.id]
}
# Resolve the map-role scope by name for use in a custom permission.
Using getClientAuthorizationScope
Two invocation forms are available. The direct form accepts plain arguments and either blocks until the result value is available, or returns a Promise-wrapped result. The output form accepts Input-wrapped arguments and returns an Output-wrapped result.
function getClientAuthorizationScope(args: GetClientAuthorizationScopeArgs, opts?: InvokeOptions): Promise<GetClientAuthorizationScopeResult>
function getClientAuthorizationScopeOutput(args: GetClientAuthorizationScopeOutputArgs, opts?: InvokeOutputOptions): Output<GetClientAuthorizationScopeResult>def get_client_authorization_scope(name: Optional[str] = None,
realm_id: Optional[str] = None,
resource_server_id: Optional[str] = None,
opts: Optional[InvokeOptions] = None) -> GetClientAuthorizationScopeResult
def get_client_authorization_scope_output(name: pulumi.Input[Optional[str]] = None,
realm_id: pulumi.Input[Optional[str]] = None,
resource_server_id: pulumi.Input[Optional[str]] = None,
opts: Optional[InvokeOutputOptions] = None) -> Output[GetClientAuthorizationScopeResult]func LookupClientAuthorizationScope(ctx *Context, args *LookupClientAuthorizationScopeArgs, opts ...InvokeOption) (*LookupClientAuthorizationScopeResult, error)
func LookupClientAuthorizationScopeOutput(ctx *Context, args *LookupClientAuthorizationScopeOutputArgs, opts ...InvokeOption) LookupClientAuthorizationScopeResultOutput> Note: This function is named LookupClientAuthorizationScope in the Go SDK.
public static class GetClientAuthorizationScope
{
public static Task<GetClientAuthorizationScopeResult> InvokeAsync(GetClientAuthorizationScopeArgs args, InvokeOptions? opts = null)
public static Output<GetClientAuthorizationScopeResult> Invoke(GetClientAuthorizationScopeInvokeArgs args, InvokeOptions? opts = null)
public static Output<GetClientAuthorizationScopeResult> Invoke(GetClientAuthorizationScopeInvokeArgs args, InvokeOutputOptions opts)
}public static CompletableFuture<GetClientAuthorizationScopeResult> getClientAuthorizationScope(GetClientAuthorizationScopeArgs args, InvokeOptions options)
public static Output<GetClientAuthorizationScopeResult> getClientAuthorizationScope(GetClientAuthorizationScopeArgs args, InvokeOptions options)
public static Output<GetClientAuthorizationScopeResult> getClientAuthorizationScope(GetClientAuthorizationScopeArgs args, InvokeOutputOptions options)
fn::invoke:
function: keycloak:openid/getClientAuthorizationScope:getClientAuthorizationScope
arguments:
# arguments dictionarydata "keycloak_openid_get_client_authorization_scope" "name" {
# arguments
}The following arguments are supported:
- Name string
- The name of the authorization scope to look up.
- Realm
Id string - The realm this authorization scope exists within.
- Resource
Server stringId - The ID of the resource server (client) this authorization scope belongs to.
- Name string
- The name of the authorization scope to look up.
- Realm
Id string - The realm this authorization scope exists within.
- Resource
Server stringId - The ID of the resource server (client) this authorization scope belongs to.
- name string
- The name of the authorization scope to look up.
- realm_
id string - The realm this authorization scope exists within.
- resource_
server_ stringid - The ID of the resource server (client) this authorization scope belongs to.
- name String
- The name of the authorization scope to look up.
- realm
Id String - The realm this authorization scope exists within.
- resource
Server StringId - The ID of the resource server (client) this authorization scope belongs to.
- name string
- The name of the authorization scope to look up.
- realm
Id string - The realm this authorization scope exists within.
- resource
Server stringId - The ID of the resource server (client) this authorization scope belongs to.
- name str
- The name of the authorization scope to look up.
- realm_
id str - The realm this authorization scope exists within.
- resource_
server_ strid - The ID of the resource server (client) this authorization scope belongs to.
- name String
- The name of the authorization scope to look up.
- realm
Id String - The realm this authorization scope exists within.
- resource
Server StringId - The ID of the resource server (client) this authorization scope belongs to.
getClientAuthorizationScope Result
The following output properties are available:
- Display
Name string - (Computed) The display name of the scope.
- Icon
Uri string - (Computed) The icon URI of the scope.
- Id string
- The provider-assigned unique ID for this managed resource.
- Name string
- Realm
Id string - Resource
Server stringId
- Display
Name string - (Computed) The display name of the scope.
- Icon
Uri string - (Computed) The icon URI of the scope.
- Id string
- The provider-assigned unique ID for this managed resource.
- Name string
- Realm
Id string - Resource
Server stringId
- display_
name string - (Computed) The display name of the scope.
- icon_
uri string - (Computed) The icon URI of the scope.
- id string
- The provider-assigned unique ID for this managed resource.
- name string
- realm_
id string - resource_
server_ stringid
- display
Name String - (Computed) The display name of the scope.
- icon
Uri String - (Computed) The icon URI of the scope.
- id String
- The provider-assigned unique ID for this managed resource.
- name String
- realm
Id String - resource
Server StringId
- display
Name string - (Computed) The display name of the scope.
- icon
Uri string - (Computed) The icon URI of the scope.
- id string
- The provider-assigned unique ID for this managed resource.
- name string
- realm
Id string - resource
Server stringId
- display_
name str - (Computed) The display name of the scope.
- icon_
uri str - (Computed) The icon URI of the scope.
- id str
- The provider-assigned unique ID for this managed resource.
- name str
- realm_
id str - resource_
server_ strid
- display
Name String - (Computed) The display name of the scope.
- icon
Uri String - (Computed) The icon URI of the scope.
- id String
- The provider-assigned unique ID for this managed resource.
- name String
- realm
Id String - resource
Server StringId
Package Details
- Repository
- Keycloak pulumi/pulumi-keycloak
- License
- Apache-2.0
- Notes
- This Pulumi package is based on the
keycloakTerraform Provider.
published on Saturday, Aug 1, 2026 by Pulumi