1. Granular API Permissions with Keycloak OpenID Client Authorization


    To set up granular API permissions using Keycloak's OpenID Client Authorization, you would typically follow these steps:

    1. Define Resources: Resources represent the objects your policies will apply to. In Keycloak, resources can be anything, such as APIs or individual endpoints within an API.

    2. Define Scopes: Scopes are used to limit permissions to certain actions or pieces of data. For an API, you might have scopes like read, write, or delete.

    3. Create Policies: Policies are the rules that enforce access control. They can be based on Keycloak roles, groups, or even custom JavaScript rules.

    4. Associate Permissions: Permissions tie everything together by associating policies with specific resources and scopes to define who can do what.

    Now, let's write a Pulumi Python program to manage Keycloak OpenID Client Authorization for granular API permissions. The following program will:

    • Create a Keycloak OpenID Client.
    • Define a Resource within that client.
    • Define a Scope for that resource.
    • Create a Policy based on user roles.
    • Create a Permission that associates the policy with the resource and scope.
    import pulumi import pulumi_keycloak as keycloak # Replace these variables with actual values from your Keycloak setup keycloak_realm = "your-realm" resource_server_id = "your-resource-server-client-id" # Create a new OpenID client openid_client = keycloak.openid.Client("api-client", realm_id=keycloak_realm, client_id="api-client-id", name="API Client", enabled=True, access_type="CONFIDENTIAL", # This should be set to "confidential" for clients that are capable of keeping a secret valid_redirect_uris=["http://localhost/callback"], web_origins=["http://localhost"], description="Client for API access" ) # Define a resource for the API endpoint api_resource = keycloak.openid.ClientAuthorizationResource("api-resource", realm_id=keycloak_realm, resource_server_id=openid_client.id, name="API Resource", uris=["/api/*"] # Assuming all API endpoints are under /api ) # Define a scope for the resource api_scope = keycloak.openid.ClientAuthorizationScope("api-scope", realm_id=keycloak_realm, resource_server_id=openid_client.id, name="write" ) # Create a user role policy (Assuming the role "api_writer" exists in Keycloak) role_policy = keycloak.openid.ClientRolePolicy("api-write-policy", realm_id=keycloak_realm, resource_server_id=openid_client.id, name="API Write Policy", roles=[{"id": "api_writer-role-id"}] ) # Create a permission that connects the resource, scope, and policy api_write_permission = keycloak.openid.ClientAuthorizationPermission("api-write-permission", realm_id=keycloak_realm, resource_server_id=openid_client.id, name="API Write Permission", resources=[api_resource.id], scopes=[api_scope.id], policies=[role_policy.id] ) # Expose the client ID and secret, this would be needed to configure your API server for example pulumi.export('client_id', openid_client.client_id) pulumi.export('client_secret', openid_client.client_secret)

    In this program:

    • openid_client will be your Keycloak OpenID Client, typically representing an application that users or services can authenticate against.
    • api_resource represents the API or individual endpoints you wish to secure.
    • api_scope defines the type of access allowed, in this case 'write' access as a common operation.
    • role_policy creates a policy that grants access to the API based on user roles.
    • api_write_permission ties together the resource, scope, and policy to enforce that only users with the api_writer role can perform 'write' operations on the API.

    To execute this code:

    1. Ensure you have Pulumi installed and configured to interact with your Keycloak server.
    2. Replace placeholder strings like your-realm and other variables with actual values corresponding to your setup.
    3. Run pulumi up to launch the provisioning of resources defined in this program.