@@ -13,7 +13,21 @@ section_menu_id: guides
1313# Integrating an External Console with the KubeDB Platform
1414
1515This guide is for ** Cloud Service Providers (CSPs)** and ISVs who already operate their
16- own web console and want to embed the KubeDB Platform console for their end users.
16+ own web console and want to embed the KubeDB Platform console for their end users, so that
17+ a user who signs in to the CSP console is transparently signed in to the KubeDB console
18+ hosted on a subdomain — with no second login prompt.
19+
20+ All endpoints referenced here are documented in the
21+ [ KubeDB Platform API Reference] ( ../../../api/ ) . The most relevant pages are:
22+
23+ - [ Administrative-Org Admin] ( ../../../api/administration/admin-org.md ) — the admin user
24+ APIs used to provision and maintain the mirrored user.
25+ - [ Public & Basic-auth User APIs] ( ../../../api/users-settings/public-user-apis.md ) — the
26+ public ` POST /user/signin ` endpoint that establishes the browser session.
27+ - [ Authenticated User APIs] ( ../../../api/users-settings/authenticated-user.md ) — `GET
28+ /user/signout` and other session-scoped calls.
29+ - [ Client Organizations] ( ../../../api/client-organizations/overview.md ) — the
30+ managed-service-provider model for granting each user scoped access to clusters.
1731
1832## 1. Goal
1933
@@ -27,16 +41,16 @@ the CSP's console**, for example:
2741| KubeDB Platform console ** and** API server (per-CSP deployment) | ` https://db.acme.com ` |
2842
2943The requirement: ** when a user logs into the CSP console, the CSP backend should
30- seamlessly log that same user into the KubeDB console** — no second username/password
31- prompt. The user's identity of record lives in the CSP console; the KubeDB Platform holds a
32- * mirror * of that identity that the CSP backend controls.
44+ seamlessly log that same user into the KubeDB console. ** The user's identity of record
45+ lives in the CSP console; the KubeDB Platform holds a * mirror * of that identity that the
46+ CSP backend controls.
3347
3448This is achieved with two flows:
3549
36501 . ** Provisioning (once per user)** — the CSP backend creates a mirrored KubeDB user
37- using an ** admin bearer token** . The CSP generates and stores that user's KubeDB
38- password; the end user never sees or types it.
39- 2 . ** Session handoff (every CSP login)** — the CSP backend performs a server-side login
51+ with the admin API, authenticating with a site-admin ** personal access token** . The CSP
52+ generates and stores that user's KubeDB password; the end user never sees or types it.
53+ 2 . ** Session handoff (every CSP login)** — the CSP backend performs a server-side sign-in
4054 to the KubeDB Platform on the user's behalf, captures the resulting session cookies, and
4155 hands them to the user's browser scoped to the KubeDB subdomain.
4256
@@ -49,116 +63,160 @@ Because both consoles share the registrable domain `acme.com`, the browser treat
4963
5064- A per-CSP KubeDB Platform deployment reachable at the subdomain (` https://db.acme.com ` ),
5165 serving both the web console and the ` /api/v1 ` REST API.
52- - An ** admin personal access token** (bearer token) issued to the CSP, held ** only** by
53- the CSP backend — never shipped to a browser. Used for ` /api/v1/admin/* ` calls.
66+ - A site-admin ** personal access token** issued to the CSP, held ** only** by the CSP
67+ backend — never shipped to a browser. It is sent as an ` Authorization: token <TOKEN> `
68+ header and authorizes the ` /api/v1/admin/* ` calls (which require the
69+ ` admin_of_administrative_org ` relation). See
70+ [ Administrative-Org Admin] ( ../../../api/administration/admin-org.md ) .
71+ - The administrative organization slug (e.g. ` appscode ` ) to pass as the ` ?org= ` context on
72+ admin calls.
5473- TLS on both hosts. All calls below assume ` https:// ` .
55- - The mirrored KubeDB users must ** not** have 2FA enabled — the password login endpoint
56- rejects 2FA-enrolled users ( HTTP 405) . Since the CSP console is the identity provider,
74+ - The mirrored KubeDB users must ** not** have 2FA enabled — ` POST /user/signin ` rejects
75+ 2FA-enrolled accounts with HTTP ` 405 ` . Since the CSP console is the identity provider,
5776 leave 2FA off on the mirror and enforce MFA in the CSP console instead.
5877
59- Throughout, replace:
78+ Throughout, replace the placeholders :
6079
61- - ` db.acme.com ` → your KubeDB Platform subdomain
62- - ` 2ed08ee9a855b8ff614ef1505b33c75a8836d55d ` → your admin bearer token
80+ - ` db.acme.com ` → your KubeDB Platform subdomain (shown as ` <akp-host> ` in the API reference)
81+ - ` $AKP_TOKEN ` → your site-admin token
82+ - ` appscode ` → your administrative-org slug
6383
6484---
6585
6686## 3. Phase 1 — Provision the mirrored user (once, at CSP signup)
6787
6888When a customer signs up (or is first granted database access) on the CSP console, the
6989CSP backend creates the corresponding user in the KubeDB Platform. Do ** not** use the public
70- signup API — user creation is an admin operation.
90+ signup flow — user creation is an admin operation.
7191
7292The CSP backend generates a strong random password for the KubeDB identity and ** stores
7393it** (encrypted) alongside the CSP user record. This password is an internal credential
7494used only for the server-side handoff in Phase 2; the end user never learns it.
7595
76- ** Create user** — ` POST /api/v1/admin/users ` :
96+ ### 3.1 Create the user
97+
98+ ` POST /api/v1/admin/users?org=<slug> ` — body is a ` CreateUserOption `
99+ ([ reference] ( ../../../api/administration/admin-org.md ) ):
77100
78101``` bash
79- curl -X POST ' https://db.acme.com/api/v1/admin/users' \
80- -H ' Authorization: Bearer 2ed08ee9a855b8ff614ef1505b33c75a8836d55d ' \
102+ curl -X POST ' https://db.acme.com/api/v1/admin/users?org=appscode ' \
103+ -H " Authorization: token $AKP_TOKEN " \
81104 -H ' Content-Type: application/json' \
82105 --data-raw ' {
83106 "username": "acme-user-42",
84- "full_name": "Jane Doe",
85107 "email": "jane@customer.example.com",
86108 "password": "<STRONG_RANDOM_PASSWORD_GENERATED_AND_STORED_BY_CSP>",
109+ "full_name": "Jane Doe",
87110 "must_change_password": false,
88111 "send_notify": false
89112 }'
90113```
91114
92- Notes:
115+ | Field | Type | Required | Notes for CSP integration |
116+ | -------| ------| ----------| ---------------------------|
117+ | ` username ` | string | yes | Stable, collision-free (e.g. prefix with your tenant slug). |
118+ | ` email ` | string | yes | The user's email. |
119+ | ` password ` | string | yes | CSP-generated random secret; store it encrypted. |
120+ | ` full_name ` | string | no | Display name. |
121+ | ` must_change_password ` | boolean | no | ** Set ` false ` ** — a forced change breaks the automated handoff. |
122+ | ` send_notify ` | boolean | no | ** Set ` false ` ** — the CSP owns all user communication. |
93123
94- - Set ` must_change_password: false ` — a forced password change would break the automated
95- login handoff.
96- - Set ` send_notify: false ` — the KubeDB Platform should not email the user; the CSP owns all
97- user communication.
98- - Pick a stable, collision-free ` username ` (e.g. prefix with your tenant slug). Persist the
99- mapping ` CSP user ↔ KubeDB username ` in the CSP database.
124+ ** Response:** ` 201 Created ` — the created ` User ` . Persist the mapping
125+ ` CSP user ↔ KubeDB username ` in the CSP database.
100126
101- ** Keep profile in sync (optional)** — when the user edits their name/email in the CSP
102- console, mirror it with ` POST /api/v1/admin/users/{username}/update ` :
127+ ### 3.2 Keep the profile in sync (optional)
128+
129+ When the user edits their name/email in the CSP console, mirror it with `POST
130+ /api/v1/admin/users/{username}/update?org=<slug >` — body is a ` Profile`
131+ ([ reference] ( ../../../api/administration/admin-org.md ) ):
103132
104133``` bash
105- curl -X POST ' https://db.acme.com/api/v1/admin/users/acme-user-42/update' \
106- -H ' Authorization: Bearer 2ed08ee9a855b8ff614ef1505b33c75a8836d55d ' \
134+ curl -X POST ' https://db.acme.com/api/v1/admin/users/acme-user-42/update?org=appscode ' \
135+ -H " Authorization: token $AKP_TOKEN " \
107136 -H ' Content-Type: application/json' \
108137 --data-raw ' {
109138 "name": "acme-user-42",
110139 "full_name": "Jane A. Doe",
111140 "email": "jane@customer.example.com",
112141 "keep_email_private": false,
113- "language": "en",
142+ "language": "en-US ",
114143 "description": "Mirrored from CSP console"
115144 }'
116145```
117146
118- ** Rotate the password (optional)** — if the CSP rotates the stored KubeDB credential,
119- push the new value with ` POST /api/v1/admin/users/{username}/change-password ` :
147+ ### 3.3 Rotate the password (optional)
148+
149+ If the CSP rotates the stored KubeDB credential, push the new value with `POST
150+ /api/v1/admin/users/{username}/change-password?org=<slug >` — body is an
151+ ` UpdatePasswordParams `
152+ ([ reference] ( ../../../api/administration/admin-org.md ) ):
120153
121154``` bash
122- curl -X POST ' https://db.acme.com/api/v1/admin/users/acme-user-42/change-password' \
123- -H ' Authorization: Bearer 2ed08ee9a855b8ff614ef1505b33c75a8836d55d ' \
155+ curl -X POST ' https://db.acme.com/api/v1/admin/users/acme-user-42/change-password?org=appscode ' \
156+ -H " Authorization: token $AKP_TOKEN " \
124157 -H ' Content-Type: application/json' \
125- --data-raw ' { "password": "<NEW_STRONG_RANDOM_PASSWORD>" }'
158+ --data-raw ' { "password": "<NEW_STRONG_RANDOM_PASSWORD>", "retype": "<NEW_STRONG_RANDOM_PASSWORD>" }'
126159```
127160
161+ ### 3.4 Deprovision (on CSP account deletion)
162+
163+ When a CSP user is disabled or deleted, revoke KubeDB access with `DELETE
164+ /api/v1/admin/users/{username}?org=<slug >` (or ` PATCH` the user with ` active: false ` /
165+ ` prohibit_login:true ` to keep the record). See
166+ [ Edit / Delete user] ( ../../../api/administration/admin-org.md ) .
167+
128168![ Provisioning the mirrored user] ( ../images/csp-provisioning.svg )
129169
130170---
131171
132172## 4. Phase 2 — Session handoff (every time the user opens the KubeDB console)
133173
134- The KubeDB Platform's login endpoint sets a ** session cookie** plus a ` _csrf ` cookie. The
135- trick is that these cookies are obtained by the CSP backend server-to-server, then delivered
136- to the user's browser so it holds a valid ` db.acme.com ` session.
137-
138- ### 4.1 The login call
174+ The public sign-in endpoint ** ` POST /api/v1/user/signin ` ** authenticates a username +
175+ password and, on success, ** sets the session, CSRF (` _csrf ` ), and NATS cookies** — the same
176+ cookies the web console relies on
177+ ([ reference] ( ../../../api/users-settings/public-user-apis.md ) ). The trick is
178+ that these cookies are obtained by the CSP backend server-to-server, then delivered to the
179+ user's browser so it holds a valid ` db.acme.com ` session.
139180
140- ``` bash
141- curl -X POST ' https://db.acme.com/accounts/user/login' \
142- -H ' content-type: application/x-www-form-urlencoded' \
143- --data-raw ' user_name=acme-user-42&password=<STORED_KUBEDB_PASSWORD>&remember=on' \
144- -c cookie.txt -D headers.txt
145- ```
181+ ### 4.1 The sign-in call
146182
147- The response's ` Set-Cookie ` headers (captured above in ` headers.txt ` , cookies jarred in
148- ` cookie.txt ` ) contain the session cookie and the ` _csrf ` cookie. Any ** subsequent
149- server-side API call** made with these cookies must also send the ` _csrf ` value in the
150- ` X-Csrf-Token ` header:
183+ ` POST /api/v1/user/signin ` — body is a ` SignInParams ` :
151184
152185``` bash
153- curl -X GET ' https://db.acme.com/api/v1/user/settings/profile ' \
186+ curl -X POST ' https://db.acme.com/api/v1/user/signin ' \
154187 -H ' Content-Type: application/json' \
155- -H ' X-Csrf-Token: <VALUE_OF__csrf_COOKIE>' \
156- -b cookie.txt
188+ --data-raw ' {
189+ "username": "acme-user-42",
190+ "password": "<STORED_KUBEDB_PASSWORD>",
191+ "remember": true
192+ }' \
193+ -c cookie.txt -D headers.txt
157194```
158195
196+ | Field | Type | Required | Description |
197+ | -------| ------| ----------| -------------|
198+ | ` username ` | string | yes | The mirrored KubeDB username. |
199+ | ` password ` | string | yes | The CSP-stored password for that user. |
200+ | ` remember ` | boolean | no | Persist the session across browser restarts. |
201+
202+ ** Response:** ` 200 OK ` with no body. The ` Set-Cookie ` headers (captured in ` headers.txt ` ,
203+ jarred in ` cookie.txt ` ) carry the session, ` _csrf ` , and NATS cookies. Non-200 statuses:
204+ ` 404 ` (no such user), ` 405 ` (login prohibited / inactive / 2FA enrolled), ` 422 `
205+ (validation error).
206+
207+ > ** CSRF on later calls.** Any subsequent ** state-changing** API call made server-side with
208+ > these cookies must echo the ` _csrf ` cookie value in an ` X-Csrf-Token ` header, e.g.:
209+ >
210+ > ``` bash
211+ > curl -X POST ' https://db.acme.com/api/v1/user/settings/profile' \
212+ > -H ' Content-Type: application/json' \
213+ > -H " X-Csrf-Token: <VALUE_OF__csrf_COOKIE>" \
214+ > -b cookie.txt --data-raw ' { ... }'
215+ > ` ` `
216+
159217# ## 4.2 Delivering the cookies to the browser
160218
161- The CSP backend can log in, but a backend cannot set cookies in the browser for a domain
219+ The CSP backend can sign in, but a backend cannot set cookies in the browser for a domain
162220other than the one that served the response. So the piece that ** re-emits** the captured
163221cookies must run on the KubeDB host itself. Host a small ** launch endpoint on the KubeDB
164222subdomain** , e.g. ` https://db.acme.com/csp-sso/launch` , in one of two ways:
@@ -177,8 +235,8 @@ The end-to-end handoff:
177235 TTL) identifying the CSP user, and redirects the browser to
178236 ` https://db.acme.com/csp-sso/launch? ticket=< handoff-token> ` .
1792373. The launch endpoint validates the ticket, looks up the mapped KubeDB username +
180- stored password, and performs the ** server-side login ** (§4.1).
181- 4 . The launch endpoint copies the login response's ` Set-Cookie ` headers onto its ** own
238+ stored password, and performs the ** server-side sign-in ** (§4.1).
239+ 4. The launch endpoint copies the sign-in response' s `Set-Cookie` headers onto its **own
182240 redirect response** to the browser, then `302`s to `https://db.acme.com/`.
1832415. The browser now holds a valid KubeDB session cookie for `db.acme.com` and loads the
184242 KubeDB console fully authenticated — no login prompt.
@@ -197,40 +255,69 @@ safe default.
197255
198256---
199257
200- ## 5. Logout
258+ ## 5. Granting database access (Client Organizations)
259+
260+ Provisioning a mirrored user establishes an identity, but that user still needs **access to
261+ clusters and databases**. The KubeDB Platform' s managed-service-provider model — ** Client
262+ Organizations** — is designed exactly for CSPs. As a site admin, the CSP:
263+
264+ 1. Creates a client organization and imports spoke clusters into it —
265+ ` POST /api/v1/user/client/create` and
266+ ` POST /api/v1/user/client/{orgname}/add-cluster`
267+ ([Client Org Management](../../../api/client-organizations/management.md)).
268+ 2. Creates a per-cluster user with scoped permissions and (optionally) fetches a kubeconfig
269+ for them —
270+ ` POST /api/v1/clusters/{owner}/{cluster}/permission/user/create` and
271+ ` GET /api/v1/clusters/{owner}/{cluster}/permission/user/{id}/kubeconfig`
272+ ([Cluster User Permissions](../../../api/client-organizations/cluster-user-permissions.md)).
273+
274+ Map each CSP customer to a client organization and each mirrored user to that org' s
275+ per-cluster permission set, so that when the user lands on the KubeDB console (via the
276+ handoff above) they see exactly the clusters and databases they are entitled to. The
277+ equivalent UI walkthrough is in the
278+ [Client Organization guide](../../client-organization/create-client-organization.md).
279+
280+ ---
281+
282+ ## 6. Logout
201283
202284When the user logs out of the CSP console, also terminate the KubeDB session so a shared
203- browser can't keep the console open. Call the logout route with the user's cookies and CSRF
204- token:
285+ browser can' t keep the console open. Call ` GET /api/v1/user/signout ` with the user' s cookies
286+ and CSRF token ([reference](../../../api/users-settings/authenticated-user.md)) :
205287
206288```bash
207- curl -X GET ' https://db.acme.com/accounts/user/logout' \
208- -H ' Content-Type: application/json' \
209- -H ' X-Csrf-Token: <VALUE_OF__csrf_COOKIE>' \
289+ curl -X GET ' https://db.acme.com/api/v1/user/signout' \
290+ -H "X-Csrf-Token: <VALUE_OF__csrf_COOKIE>" \
210291 -b cookie.txt
211292```
212293
213294If you use shared-domain SSO (§4.3), clear the `.acme.com` cookie on logout as well.
214295
215296---
216297
217- ## 6 . API summary
298+ ## 7 . API summary
218299
219300| Step | When | Method & path | Auth |
220301|------|------|---------------|------|
221- | Create mirrored user | CSP signup (once) | ` POST /api/v1/admin/users ` | Admin bearer token |
222- | Sync profile | On CSP profile edit | ` POST /api/v1/admin/users/{username}/update ` | Admin bearer token |
223- | Rotate password | On credential rotation | ` POST /api/v1/admin/users/{username}/change-password ` | Admin bearer token |
224- | Server-side login | Each console open | ` POST /accounts/user/login ` (form-encoded) | Mirror user password → sets cookies |
302+ | Create mirrored user | CSP signup (once) | `POST /api/v1/admin/users?org=<slug>` | `Authorization: token` (site admin) |
303+ | Sync profile | On CSP profile edit | `POST /api/v1/admin/users/{username}/update?org=<slug>` | `Authorization: token` (site admin) |
304+ | Rotate password | On credential rotation | `POST /api/v1/admin/users/{username}/change-password?org=<slug>` | `Authorization: token` (site admin) |
305+ | Deprovision | On CSP account deletion | `DELETE /api/v1/admin/users/{username}?org=<slug>` | `Authorization: token` (site admin) |
306+ | Grant cluster access | On entitlement change | Client-org + permission APIs (§5) | `Authorization: token` (site admin / org admin) |
307+ | Server-side sign-in | Each console open | `POST /api/v1/user/signin` | Mirror user password → sets cookies |
225308| Authenticated API call | As needed | any `/api/v1/...` | Session cookie + `X-Csrf-Token: <_csrf>` |
226- | Logout | On CSP logout | ` GET /accounts/user/logout ` | Session cookie + ` X-Csrf-Token: <_csrf> ` |
309+ | Logout | On CSP logout | `GET /api/v1/user/signout` | Session cookie + `X-Csrf-Token: <_csrf>` |
310+
311+ Explore any of these interactively in the
312+ [Interactive API Reference](../../../api/reference/).
227313
228314---
229315
230- ## 7 . Security checklist
316+ ## 8 . Security checklist
231317
232- - ** Admin bearer token** stays server-side, in a secret manager. Rotate periodically. Its
233- compromise means full control of every mirrored user.
318+ - **Site-admin token** stays server-side, in a secret manager. Rotate it periodically. Its
319+ compromise means full control of every mirrored user. Generate/manage tokens via the
320+ [access-token APIs](../../../api/users-settings/public-user-apis.md).
234321- **Stored KubeDB passwords** are internal credentials: generate them randomly (high
235322 entropy), encrypt at rest, and never expose them to the browser or the end user.
236323- **Handoff ticket** must be short-lived (seconds), single-use, signed/encrypted, and bound
@@ -241,7 +328,6 @@ If you use shared-domain SSO (§4.3), clear the `.acme.com` cookie on logout as
241328 is same-site and the handoff is a top-level navigation).
242329- **TLS everywhere**.
243330- **No 2FA on mirrors** (see §2); enforce MFA in the CSP console instead.
244- - ** Logout propagation** (§5 ) so a KubeDB session never outlives the CSP session on a shared
331+ - **Logout propagation** (§6 ) so a KubeDB session never outlives the CSP session on a shared
245332 device.
246- - ** Deprovisioning** : when a CSP user is disabled/deleted, disable or delete the mirrored
247- KubeDB user via the admin API so access is revoked in both places.
333+ - **Deprovisioning** (§3.4) so access is revoked in both consoles together.
0 commit comments