Skip to content

Certificate Admin Role - API

This guide walks through creating a custom RBAC role in F5 Distributed Cloud that grants permission to manage SSL/TLS certificates and certificate chains used by HTTP Load Balancers. For a UI-based approach, see the simplified console guide.

F5 XC uses a three-tier permission model:

api_group_element (read-only, system-defined)
api_group (read-only, system-defined)
role (full CRUD — this is what you create)
  1. api_group_element — Defines a regex path and HTTP methods (e.g., POST /api/config/.*/certificates). System-managed; you cannot create, modify, or delete these.

  2. api_group — A named collection of api_group_element references, organized by functional area. System-managed; you cannot create, modify, or delete these. Groups use naming conventions like ves-io-proxy-read or f5xc-waap-standard-admin.

  3. role — References api_group names in an array. This is the only tier you create. Use the custom role endpoints to attach specific api_groups to a role.

Certificate operations for HTTP Load Balancers are bundled into the ves-io-proxy-* api_groups alongside other proxy-related resources (HTTP Load Balancers, routes, origins, etc.). There are no standalone certificate-only api_groups — the platform organizes permissions by functional area, not by individual resource type.

The ves-io-proxy-read and ves-io-proxy-write api_groups grant access to all proxy-related resources, not just certificates. A user assigned this role can also manage HTTP Load Balancers, origins, routes, and other proxy-scoped objects.

Certificate-only RBAC is not possible on F5 XC. Both api_group and api_group_element are system-defined, read-only objects — the API only exposes GET endpoints for these. Roles can only reference existing api_group names, and there is no api_group scoped exclusively to certificates.

Mitigation — namespace isolation: Create a dedicated namespace for certificate resources and assign the example-cert-admin role scoped to that namespace only. The user retains proxy-level permissions but cannot access resources in other namespaces, limiting the blast radius of the broader api_group scope.

  • An F5 XC API token with admin privileges
  • curl and jq installed

Set your environment variables:

Terminal window
export F5XC_TENANT="your-tenant"
export F5XC_API_URL="https://${F5XC_TENANT}.console.ves.volterra.io"
export F5XC_API_TOKEN="your-api-token"

List all system-defined api_group objects and filter for proxy-related entries (which include certificate permissions):

Terminal window
curl -s \
-H "Authorization: APIToken ${F5XC_API_TOKEN}" \
"${F5XC_API_URL}/api/web/namespaces/shared/api_groups" \
| jq '[.items[] | select(.name | test("ves-io-proxy")) | .name] | sort'

Expected output:

[
"ves-io-proxy-app-firewall-read",
"ves-io-proxy-app-firewall-write",
"ves-io-proxy-monitor-read",
"ves-io-proxy-monitor-write",
"ves-io-proxy-read",
"ves-io-proxy-security-read",
"ves-io-proxy-security-write",
"ves-io-proxy-waf-read",
"ves-io-proxy-waf-write",
"ves-io-proxy-write"
]

For certificate management, the relevant groups are:

API GroupGrants
ves-io-proxy-readRead access to proxy resources including certificates
ves-io-proxy-writeWrite access to proxy resources including certificates

Use the custom role creation endpoint. The api_groups array references the system-defined api_group names discovered in Step 1.

Create the custom role with read and write access to proxy resources (including certificates and certificate chains):

Terminal window
curl -s -X POST \
-H "Authorization: APIToken ${F5XC_API_TOKEN}" \
-H "Content-Type: application/json" \
"${F5XC_API_URL}/api/web/custom/namespaces/system/roles" \
-d '{
"metadata": {
"name": "example-cert-admin",
"namespace": "system"
},
"spec": {},
"api_groups": [
"ves-io-proxy-read",
"ves-io-proxy-write"
]
}'

Retrieve the role using the custom GET endpoint to confirm the api_groups are attached:

Terminal window
curl -s \
-H "Authorization: APIToken ${F5XC_API_TOKEN}" \
"${F5XC_API_URL}/api/web/custom/namespaces/system/roles/example-cert-admin" \
| jq '{name: .object.metadata.name, api_groups: .api_groups}'

Expected output:

{
"name": "example-cert-admin",
"api_groups": [
"ves-io-proxy-read",
"ves-io-proxy-write"
]
}

To add or remove api_groups from an existing role, use the custom PUT endpoint:

Terminal window
curl -s -X PUT \
-H "Authorization: APIToken ${F5XC_API_TOKEN}" \
-H "Content-Type: application/json" \
"${F5XC_API_URL}/api/web/custom/namespaces/system/roles/example-cert-admin" \
-d '{
"name": "example-cert-admin",
"namespace": "system",
"spec": {},
"api_groups": [
"ves-io-proxy-read"
]
}'

This example downgrades the role to read-only access by removing ves-io-proxy-write.

Delete uses the standard role endpoint:

Terminal window
curl -s -X DELETE \
-H "Authorization: APIToken ${F5XC_API_TOKEN}" \
"${F5XC_API_URL}/api/web/namespaces/system/roles/example-cert-admin"

Role Endpoints (Custom — includes api_groups)

Section titled “Role Endpoints (Custom — includes api_groups)”

Roles are always in the system namespace.

MethodPathDescription
POST/api/web/custom/namespaces/system/rolesCreate a custom role
GET/api/web/custom/namespaces/system/rolesList custom roles
GET/api/web/custom/namespaces/system/roles/{name}Get a custom role
PUT/api/web/custom/namespaces/system/roles/{name}Replace a custom role
MethodPathDescription
DELETE/api/web/namespaces/system/roles/{name}Delete a role
GET/api/web/namespaces/system/roles/{name}Get a role
GET/api/web/namespaces/system/rolesList roles

Discovery uses the shared namespace.

MethodPathDescription
GET/api/web/namespaces/shared/api_groupsList all api_groups
GET/api/web/namespaces/shared/api_group_elementsList all api_group_elements

Certificate Endpoints (What the Role Grants Access To)

Section titled “Certificate Endpoints (What the Role Grants Access To)”

Replace {namespace} with the namespace where your certificates are managed.

MethodPathDescription
POST/api/config/namespaces/{namespace}/certificatesCreate a certificate
GET/api/config/namespaces/{namespace}/certificatesList certificates
GET/api/config/namespaces/{namespace}/certificates/{name}Get a certificate
PUT/api/config/namespaces/{namespace}/certificates/{name}Replace a certificate
DELETE/api/config/namespaces/{namespace}/certificates/{name}Delete a certificate
POST/api/config/namespaces/{namespace}/certificate_chainsCreate a certificate chain
GET/api/config/namespaces/{namespace}/certificate_chainsList certificate chains
GET/api/config/namespaces/{namespace}/certificate_chains/{name}Get a certificate chain
PUT/api/config/namespaces/{namespace}/certificate_chains/{name}Replace a certificate chain
DELETE/api/config/namespaces/{namespace}/certificate_chains/{name}Delete a certificate chain

Why api_group and api_group_element Are Read-Only

Section titled “Why api_group and api_group_element Are Read-Only”

These objects are system-defined by F5 XC. The platform pre-creates api_group_element entries for every API path and groups them into api_group objects organized by functional area.

You do not need to create these — they already exist for every resource in the system. Your job is to discover the relevant group names (Step 1) and reference them in your custom role (Step 2).

To see which individual API paths an api_group covers, list the api_group_elements endpoint and look for elements related to your resource:

Terminal window
curl -s \
-H "Authorization: APIToken ${F5XC_API_TOKEN}" \
"${F5XC_API_URL}/api/web/namespaces/shared/api_group_elements" \
| jq '[.items[] | select(.name | test("ves-io-schema-certificate")) | .name]'