Skip to content
Latest (currently 2026.7.0) has the newest features, bug fixes, and CVE patches of Solo Enterprise for agentregistry.

Restrict registry access

Page as Markdown

Create access policies with specific permissions and map IdP groups to those policies to control what users can do in the registry.

Solo Enterprise for agentregistry lets you restrict what individual users or groups can do in the registry by creating AccessPolicy resources and mapping them to JWT group claims from your OIDC provider. For a conceptual overview of how AccessPolicy works across all access control layers, see About access control.

Before you begin

Follow one of the quickstart guides to install Solo Enterprise for agentregistry and deploy your first agent. The quickstart also sets up Keycloak as an OIDC provider and creates an admin user that you use to create AccessPolicies in this guide.

Step 1: Create a Keycloak group and user

Use the Keycloak Admin REST API to create a developers group and a user who belongs to it.

  1. Get an admin token for the Keycloak Admin REST API.

    export KEYCLOAK_ADMIN_TOKEN=$(curl -s \
      -d "client_id=admin-cli" -d "username=admin" -d "password=admin" \
      -d "grant_type=password" \
      "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
      | jq -r .access_token)
  2. Create the developers group.

    curl -s -X POST \
      -H "Authorization: Bearer ${KEYCLOAK_ADMIN_TOKEN}" \
      -H "Content-Type: application/json" \
      "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/groups" \
      -d '{"name": "developers"}'
  3. Create a dev-user account and assign it to the developers group.

    curl -s -X POST \
      -H "Authorization: Bearer ${KEYCLOAK_ADMIN_TOKEN}" \
      -H "Content-Type: application/json" \
      "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users" \
      -d '{
        "username": "dev-user",
        "email": "dev-user@example.com",
        "firstName": "Dev",
        "lastName": "User",
        "enabled": true,
        "credentials": [{"type": "password", "value": "password", "temporary": false}]
      }'
    
    export DEV_USER_ID=$(curl -s \
      -H "Authorization: Bearer ${KEYCLOAK_ADMIN_TOKEN}" \
      "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users?username=dev-user" \
      | jq -r '.[0].id')
    
    export DEVELOPERS_GROUP_ID=$(curl -s \
      -H "Authorization: Bearer ${KEYCLOAK_ADMIN_TOKEN}" \
      "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/groups?search=developers" \
      | jq -r '.[0].id')
    
    curl -s -X PUT \
      -H "Authorization: Bearer ${KEYCLOAK_ADMIN_TOKEN}" \
      "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/${DEV_USER_ID}/groups/${DEVELOPERS_GROUP_ID}"

Step 2: Create an access policy

Create an AccessPolicy resource that defines the operations that users from the developers group can perform. In this example, you allow read access to all agents and MCP servers.

  1. Log in to Solo Enterprise for agentregistry as an admin user (admin-user/password). The admin user has the permission to create AccessPolicies.

    export OIDC_ISSUER=$KEYCLOAK_ISSUER
    export OIDC_CLIENT_ID=ar-cli-interactive
    arctl user login
  2. Create the AccessPolicy. The following example creates a read-only policy for the developers group that allows listing and viewing all agents and MCP servers, but does not permit publishing or deploying them.

    cat <<EOF | arctl apply -f -
    apiVersion: ar.dev/v1alpha1
    kind: AccessPolicy
    metadata:
      name: developers
    spec:
      description: "Read-only access to all artifacts"
      principals:
        - kind: Role
          name: developers
      rules:
        - actions:
            - "registry:read"
          resources:
            - kind: server
              name: "*"
            - kind: agent
              name: "*"
    EOF

    Example output:

    ✓ AccessPolicy/developers created
    
  3. Verify that the policy is created.

    arctl get accesspolicies

    Example output:

    NAME         DESCRIPTION
    developers   Read-only access to all artifacts
    

Step 3: Verify access as the new user

  1. Log out of the current CLI session.

    arctl user logout
  2. Complete the device authorization in your browser by using the URL and code that is shown in your CLI output. Log in with the dev-user username and password password.

    arctl user login
  3. Inspect the JWT that is returned by Keycloak to confirm that the developers group claim is in the token.

    arctl user info --show-tokens \
      | jq -r '.access_token | split(".") | .[1] | @base64d | fromjson | {sub, email, Groups}'

    Example output:

    {
      "sub": "fbb5e028-4ef7-41de-8a6b-88365c26287d",
      "email": "dev-user@example.com",
      "Groups": [
        "developers"
      ]
    }
    
  4. Verify the user’s identity. In your CLI output, verify that the developers role has a status of configured. This setting means that the registry controller found a corresponding AccessPolicy for users with the developers claim value.

    arctl user whoami

    Example output:

    FIELD       VALUE
    Subject     fbb5e028-...
    Email       dev-user@example.com
    Issuer      http://172.18.0.15:8080/realms/agentregistry
    Superuser   false
    
    ROLE         STATUS
    developers   configured
    
  5. Confirm that the dev-user can list agents in the catalog.

    arctl get agents

    Example output:

    NAME      TAG      FRAMEWORK   LANGUAGE   PROVIDER   MODEL
    myagent   latest   adk         python     gemini     gemini-2.5-flash
    
  6. Confirm that the dev-user user cannot publish an agent.

    arctl apply -f - <<EOF
    apiVersion: ar.dev/v1alpha1
    kind: Agent
    metadata:
      name: test-agent
    spec:
      description: Test agent
      language: python
      framework: adk
      modelProvider: gemini
      modelName: gemini-2.5-flash
      source:
        image: localhost:5001/myagent:latest
    EOF

    Example output:

    ✗ Agent/test-agent failed: forbidden: forbidden
    Error: one or more resources failed to apply
    
  7. Confirm that the dev-user user cannot create a deployment.

    arctl apply -f - <<EOF
    apiVersion: ar.dev/v1alpha1
    kind: Deployment
    metadata:
      name: test-agent
    spec:
      targetRef:
        kind: Agent
        name: myagent
        tag: "latest"
      runtimeRef:
        kind: Runtime
        name: local
    EOF

    Expected output:

    ✗ Deployment/test-agent failed: forbidden: forbidden
    Error: one or more resources failed to apply
    

Example access policies

The following examples show common permission configurations.

Read and deploy, but not publish or delete:

cat <<EOF | arctl apply -f -
apiVersion: ar.dev/v1alpha1
kind: AccessPolicy
metadata:
  name: deployers
spec:
  principals:
    - kind: Role
      name: deployers
  rules:
    - actions:
        - "registry:read"
        - "registry:deploy"
      resources:
        - kind: agent
          name: "*"
        - kind: server
          name: "*"
EOF

Full access except delete:

cat <<EOF | arctl apply -f -
apiVersion: ar.dev/v1alpha1
kind: AccessPolicy
metadata:
  name: publishers
spec:
  principals:
    - kind: Role
      name: publishers
  rules:
    - actions:
        - "registry:read"
        - "registry:publish"
        - "registry:edit"
        - "registry:deploy"
      resources:
        - kind: agent
          name: "*"
        - kind: server
          name: "*"
EOF

Full access including delete:

cat <<EOF | arctl apply -f -
apiVersion: ar.dev/v1alpha1
kind: AccessPolicy
metadata:
  name: admins
spec:
  principals:
    - kind: Role
      name: admins
  rules:
    - actions:
        - "registry:*"
      resources:
        - kind: agent
          name: "*"
        - kind: server
          name: "*"
EOF

Scoped access to a specific agent: Use this pattern when a team owns a particular agent and needs full publish rights for it, but needs only read access to everything else.

cat <<EOF | arctl apply -f -
apiVersion: ar.dev/v1alpha1
kind: AccessPolicy
metadata:
  name: myagent-owners
spec:
  principals:
    - kind: Role
      name: myagent-team
  rules:
    - actions:
        - "registry:read"
        - "registry:publish"
        - "registry:edit"
        - "registry:deploy"
      resources:
        - kind: agent
          name: myagent
    - actions:
        - "registry:read"
      resources:
        - kind: agent
          name: "*"
        - kind: server
          name: "*"
EOF

Read access to the catalog and chat invocation: Use this pattern for users who need to browse the catalog and chat with agents through the UI, but do not need to publish or deploy.

cat <<EOF | arctl apply -f -
apiVersion: ar.dev/v1alpha1
kind: AccessPolicy
metadata:
  name: catalog-viewers
spec:
  principals:
    - kind: Role
      name: viewers
  rules:
    - actions:
        - "registry:read"
      resources:
        - kind: agent
          name: "*"
        - kind: server
          name: "*"
    - actions:
        - "runtime:*"
      resources:
        - kind: agent
          name: "*"
EOF