Skip to content

Commit 226dafb

Browse files
gaudic-ovhbenchbzh
andauthored
Hosted Private Cloud / Bare Metal Pod - adding snc_iam_manage guide (#9331)
* Add IAM rights management guide for Bare Metal Pod SecNumCloud New documentation guide explaining how to manage user access rights on the Bare Metal Pod SecNumCloud platform via Keycloak, covering: - Centralized authentication architecture (Keycloak as single entry point) - Role hierarchy (default access vs pod_operator) - OpenStack project attribute configuration (user & group level) - Step-by-step service account setup for the Keycloak API - Python script using Keycloak evaluate-scopes API to get a consolidated view of effective OpenStack permissions across all active users Available in French (fr-fr) and English (en-gb). * FR/EN - Update - index Add IAM rights management guide entry for Bare Metal Pod SecNumCloud * FR/EN - Update - snc_iam_manage Remove admin OpenStack role: highest assignable role is member * EN - Update - snc_iam_manage Remove `jq` requirement from IAM management guide * proofreading, index & index translations update * minor update --------- Co-authored-by: benchbzh <benoit.chuchla@ovhcloud.com>
1 parent d2f1ec9 commit 226dafb

11 files changed

Lines changed: 657 additions & 0 deletions
Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
---
2+
title: "IAM Rights Management - Bare Metal Pod SecNumCloud"
3+
excerpt: "Find out how to manage users, configure their access rights, and assign OpenStack roles on your Bare Metal Pod SecNumCloud via Keycloak"
4+
updated: 2026-04-28
5+
---
6+
7+
## Objective
8+
9+
This guide explains how to manage Identity and Access Management (IAM) on your **Bare Metal Pod SecNumCloud**.
10+
11+
All authentication is centralised in **Keycloak**, which acts as the single entry point for:
12+
13+
- Access to the **Dashboard** (unified service portal)
14+
- Access to the **OpenStack Horizon** graphical interface
15+
- Access to the **OpenStack APIs** (Keystone, Nova, Neutron, Glance, Ironic...)
16+
17+
## Requirements
18+
19+
- A **Bare Metal Pod SecNumCloud** delivered and operational
20+
- Access to the Keycloak interface with an account holding the `pod_operator` role or higher
21+
- Having read the [Getting started with your Bare Metal Pod SecNumCloud](/pages/hosted_private_cloud/baremetal_pod/snc_getting_started) guide
22+
23+
## Instructions
24+
25+
### Authentication architecture
26+
27+
All **Bare Metal Pod** authentication is centralised in **Keycloak**. A single Keycloak user account grants access to all pod services: dashboard, OpenStack Horizon, and OpenStack APIs.
28+
29+
### Role hierarchy
30+
31+
The IAM model of the **Bare Metal Pod SecNumCloud** is based on two access levels.
32+
33+
#### Default access
34+
35+
Any user registered in Keycloak, without a specific role assigned, has default access allowing them to:
36+
37+
- Log in to the **Dashboard** and manage their own Keycloak account settings
38+
- Access **OpenStack** and the projects for which a `pod_operator` has granted them rights via project attributes
39+
40+
> [!primary]
41+
>
42+
> A user without any project attribute configured will be able to log in to the dashboard but will have no access to any OpenStack project until a `pod_operator` assigns them rights.
43+
>
44+
45+
#### `pod_operator` role
46+
47+
The `pod_operator` role is assigned by OVHcloud to the first platform access account upon service delivery. This initial account can then freely assign the role to any other users within the pod realm.
48+
49+
It provides the following additional capabilities:
50+
51+
- Manage users, groups, and roles within the pod realm (create accounts, assign OpenStack rights via project attributes)
52+
- Request node delegation from OVHcloud support (required for specific configurations such as LACP or software RAID)
53+
54+
### Access matrix
55+
56+
The table below summarises the access each level has across integrated applications.
57+
58+
**Legend**: ✅ Allowed | ❌ Not allowed | 🟡 Partial (depends on project attributes)
59+
60+
| Application | Permission | Default | `pod_operator` |
61+
|-------------|------------|:-------:|:--------------:|
62+
| **Keycloak** | View account settings |||
63+
| **Keycloak** | Manage Keycloak users |||
64+
| **OpenStack** | view | 🟡 | 🟡 |
65+
| **OpenStack** | member (edit) | 🟡 | 🟡 |
66+
| **Dashboard** | OpenStack iframe |||
67+
| **Grafana** | view |||
68+
| **Prometheus** | view |||
69+
| **Dashboard** | Grafana iframe |||
70+
| **Dashboard** | Prometheus iframe |||
71+
72+
> [!primary]
73+
>
74+
> OpenStack accesses marked 🟡 require **project attributes** to be configured on the user or their group in Keycloak. Without a project attribute, the user will not be able to access OpenStack resources.
75+
>
76+
77+
### Configuring OpenStack rights via Keycloak attributes
78+
79+
OpenStack project access rights are defined directly as **user attributes** (or group attributes) in Keycloak. This allows you to specify which OpenStack project(s) a user can operate on and with which role(s).
80+
81+
#### Adding a project attribute to a user
82+
83+
In the Keycloak interface, navigate to the relevant user and open the **Attributes** tab.
84+
85+
Add a new attribute with the following values:
86+
87+
- **Key**: `project`
88+
- **Value**: a JSON object describing the project and the roles to assign
89+
90+
```json
91+
{
92+
"domain": {
93+
"name": "Default"
94+
},
95+
"name": "project-name",
96+
"roles": [
97+
{
98+
"name": "member"
99+
},
100+
{
101+
"name": "reader"
102+
}
103+
]
104+
}
105+
```
106+
107+
Available OpenStack roles are:
108+
109+
| OpenStack role | Description |
110+
|----------------|-------------|
111+
| `member` | Edit rights on the project |
112+
| `reader` | Read-only access to the project |
113+
114+
> [!primary]
115+
>
116+
> If an OpenStack project with the specified name does not yet exist, it will be **created automatically** when the user first logs in.
117+
>
118+
119+
#### Assigning multiple projects to a user
120+
121+
You can add multiple `project` attributes to the same user or group. Keycloak automatically merges them into a single `projects` attribute in the token passed to Keystone.
122+
123+
Example for a user accessing two projects:
124+
125+
**Attribute 1** (key: `project`):
126+
127+
```json
128+
{
129+
"domain": {
130+
"name": "Default"
131+
},
132+
"name": "production-project",
133+
"roles": [
134+
{
135+
"name": "member"
136+
}
137+
]
138+
}
139+
```
140+
141+
**Attribute 2** (key: `project`):
142+
143+
```json
144+
{
145+
"domain": {
146+
"name": "Default"
147+
},
148+
"name": "staging-project",
149+
"roles": [
150+
{
151+
"name": "member"
152+
},
153+
{
154+
"name": "reader"
155+
}
156+
]
157+
}
158+
```
159+
160+
#### Configuring attributes on a group
161+
162+
You can apply the same configuration to a **Keycloak group** — all members automatically inherit the project attributes defined on it.
163+
164+
In Keycloak, navigate to **Groups**, select the target group, and fill in the `project` attributes in the same way as for an individual user.
165+
166+
> [!primary]
167+
>
168+
> Attributes defined on a group and those defined directly on a user are merged. A user can therefore benefit from projects coming from multiple groups in addition to their own attributes.
169+
>
170+
171+
### Listing all access rights
172+
173+
#### Via the OpenStack CLI
174+
175+
To list active role assignments in OpenStack:
176+
177+
```bash
178+
openstack role assignment list --names
179+
```
180+
181+
To list roles available on the platform:
182+
183+
```bash
184+
openstack role list
185+
```
186+
187+
> [!warning]
188+
>
189+
> These commands only return users who have **already authenticated** at least once through OpenStack. Users present in Keycloak but who have never logged into OpenStack will not appear in these results.
190+
>
191+
192+
#### Via the Keycloak API (complete view)
193+
194+
For an exhaustive view of rights — including Keycloak users who have never logged into OpenStack — query the Keycloak API directly and consolidate project attributes manually.
195+
196+
The script uses a **service account** in Keycloak, which avoids any dependency on user credentials or OTP. Follow the steps below to set it up before running the script.
197+
198+
##### Creating the service account in Keycloak
199+
200+
**1. Create a new client**
201+
202+
In the Keycloak interface, select your pod realm and navigate to **Clients** > **Create client**.
203+
204+
Fill in the following fields:
205+
206+
- **Client type**: `OpenID Connect`
207+
- **Client ID**: choose a descriptive name, for example `iam-audit`
208+
209+
Click **Next**.
210+
211+
**2. Enable the Service Account**
212+
213+
On the **Capability config** screen, enable only:
214+
215+
- **Service accounts roles**: `On`
216+
217+
Disable **Standard flow** and **Direct access grants** if they are enabled. Click **Save**.
218+
219+
**3. Retrieve the Client Secret**
220+
221+
In your newly created client, open the **Credentials** tab. Copy the value of the **Client secret** field — this is the value to use for `CLIENT_SECRET` in the script.
222+
223+
**4. Assign the `view-users` role**
224+
225+
Open the **Service accounts roles** tab of your client, then click **Assign role**.
226+
227+
In the filter, select **Filter by clients** and search for `realm-management`. Assign the **view-users** role.
228+
229+
> [!primary]
230+
>
231+
> The `view-users` role from the `realm-management` client allows the service account to list realm users without granting any modification rights.
232+
>
233+
234+
##### Prerequisite: install the required libraries
235+
236+
Make sure Python 3 is installed, then install the required libraries:
237+
238+
```bash
239+
pip install python-keycloak requests
240+
```
241+
242+
##### Rights retrieval script
243+
244+
A user's OpenStack rights can come from multiple sources: attributes defined directly on their account, inherited from groups, parent groups, or roles. This combination can make it difficult to read effective permissions from the administration interface.
245+
246+
To check the rights of a specific user, you can use the Keycloak web interface directly: **Clients** > select the `keystone` client (OpenStack client) > **Client scopes** > **Evaluate** > select the user > **Generate access token**.
247+
248+
The script below is an example of using the Keycloak API to retrieve this same information programmatically. By querying Keycloak the same way Keystone would, it provides a **clear and consolidated view of effective permissions** across all active users in the realm in a single run.
249+
250+
This script uses the same mechanism as the **Generate access token** button in the Keycloak interface, via the scope evaluation endpoint. This is the ground truth: groups, subgroups, and user attributes are all merged by Keycloak itself.
251+
252+
```python
253+
import json
254+
import requests
255+
from keycloak import KeycloakAdmin
256+
257+
KEYCLOAK_URL = "https://<your-keycloak>"
258+
REALM = "pod"
259+
CLIENT_ID = "<client-id>"
260+
CLIENT_SECRET = "<client-secret>"
261+
262+
kc = KeycloakAdmin(
263+
server_url=KEYCLOAK_URL,
264+
realm_name=REALM,
265+
client_id=CLIENT_ID,
266+
client_secret_key=CLIENT_SECRET
267+
)
268+
269+
# Obtain the service account token
270+
admin_token = requests.post(
271+
f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/token",
272+
data={
273+
"grant_type": "client_credentials",
274+
"client_id": CLIENT_ID,
275+
"client_secret": CLIENT_SECRET,
276+
}
277+
).json()['access_token']
278+
279+
# Retrieve the keystone client UUID
280+
keystone_uuid = kc.get_client_id("keystone")
281+
282+
# For each active user, evaluate the token and display effective projects
283+
for user in kc.get_users():
284+
if not user.get('enabled'):
285+
continue
286+
try:
287+
resp = requests.get(
288+
f"{KEYCLOAK_URL}/admin/realms/{REALM}/clients/{keystone_uuid}"
289+
f"/evaluate-scopes/generate-example-access-token",
290+
params={"userId": user['id'], "scope": "openid"},
291+
headers={"Authorization": f"Bearer {admin_token}"}
292+
)
293+
if not resp.ok:
294+
print(f"[DEBUG] status={resp.status_code} body={resp.text}")
295+
resp.raise_for_status()
296+
claims = resp.json()
297+
# projects can be a JSON string or a list depending on the Keycloak version
298+
projects_raw = (
299+
claims.get('projects')
300+
or claims.get('otherClaims', {}).get('projects', [])
301+
)
302+
if isinstance(projects_raw, str):
303+
projects_raw = json.loads(projects_raw)
304+
print(json.dumps({
305+
"username": user['username'],
306+
"effective_projects": projects_raw
307+
}, indent=2))
308+
except Exception as e:
309+
print(f"[!] {user['username']}: {e}")
310+
```
311+
312+
This script displays for each user the `projects` claim **exactly as Keystone will receive it**, including own attributes, inherited from direct groups, and all parent groups.
313+
314+
> [!primary]
315+
>
316+
> A no-script alternative is available directly in the Keycloak interface: **Clients** > select the `keystone` client (OpenStack client) > **Client scopes** > **Evaluate** > select a user > **Generate access token**. This shows the exact token that will be sent to Keystone for that user.
317+
>
318+
319+
## Go further
320+
321+
For training or technical assistance with implementing our solutions, contact your sales representative or visit our [Professional Services](/links/professional-services) page to request a quote and a custom project analysis from our experts.
322+
323+
Join our [community of users](/links/community).

0 commit comments

Comments
 (0)