Skip to content

Commit c9a212b

Browse files
committed
feat(api,dashboard): self-host enrollment expiry, atomic rotation, and org settings UI (#1169)
Synced from sferarc/pgbeam@31cb990
1 parent bd5c78f commit c9a212b

8 files changed

Lines changed: 197 additions & 7 deletions

openapi.json

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3136,6 +3136,66 @@
31363136
}
31373137
}
31383138
},
3139+
"/v1/organizations/{org_id}/self-host-enrollments/{enrollment_id}/rotate": {
3140+
"parameters": [
3141+
{
3142+
"$ref": "#/components/parameters/OrgId"
3143+
},
3144+
{
3145+
"name": "enrollment_id",
3146+
"in": "path",
3147+
"required": true,
3148+
"description": "Unique enrollment identifier.",
3149+
"schema": {
3150+
"type": "string",
3151+
"pattern": "^[a-zA-Z0-9_.-]+$",
3152+
"example": "she_01h455vb4pex5vsknk084sn02q"
3153+
}
3154+
}
3155+
],
3156+
"post": {
3157+
"operationId": "rotateSelfHostEnrollment",
3158+
"summary": "Rotate a self-host enrollment token",
3159+
"description": "Mints a new enrollment token in place, keeping the same enrollment id, metadata, and expiry. The swap is atomic: the old token stops authenticating new proxy connections the moment this call returns. An already-connected proxy keeps its existing gRPC streams until it disconnects, then must present the new token to reconnect. The new token is returned once and cannot be retrieved again.",
3160+
"tags": [
3161+
"Platform"
3162+
],
3163+
"responses": {
3164+
"200": {
3165+
"description": "Token rotated. New token shown once.",
3166+
"content": {
3167+
"application/json": {
3168+
"schema": {
3169+
"$ref": "#/components/schemas/SelfHostEnrollmentSecret"
3170+
}
3171+
}
3172+
}
3173+
},
3174+
"400": {
3175+
"$ref": "#/components/responses/BadRequest"
3176+
},
3177+
"401": {
3178+
"$ref": "#/components/responses/Unauthorized"
3179+
},
3180+
"403": {
3181+
"$ref": "#/components/responses/Forbidden"
3182+
},
3183+
"404": {
3184+
"$ref": "#/components/responses/NotFound"
3185+
},
3186+
"409": {
3187+
"description": "The enrollment is revoked and cannot be rotated.",
3188+
"content": {
3189+
"application/json": {
3190+
"schema": {
3191+
"$ref": "#/components/schemas/Error"
3192+
}
3193+
}
3194+
}
3195+
}
3196+
}
3197+
}
3198+
},
31393199
"/v1/organizations/{org_id}/support/cases": {
31403200
"parameters": [
31413201
{
@@ -8163,12 +8223,18 @@
81638223
"format": "date-time",
81648224
"nullable": true,
81658225
"description": "When the enrollment was revoked. Null means active."
8226+
},
8227+
"expires_at": {
8228+
"type": "string",
8229+
"format": "date-time",
8230+
"nullable": true,
8231+
"description": "When the enrollment token expires and stops authenticating new proxy connections. Null means it never expires. Enforcement is fail-closed at the gRPC auth gate the instant this time passes."
81668232
}
81678233
}
81688234
},
81698235
"SelfHostEnrollmentSecret": {
81708236
"type": "object",
8171-
"description": "Response returned once when an enrollment is created. The token is shown a single time and cannot be retrieved again; set it as GRPC_AUTH_TOKEN on the self-hosted proxy.\n",
8237+
"description": "Response returned once when an enrollment is created or its token is rotated. The token is shown a single time and cannot be retrieved again; set it as GRPC_AUTH_TOKEN on the self-hosted proxy.\n",
81728238
"required": [
81738239
"enrollment",
81748240
"token"
@@ -8201,6 +8267,12 @@
82018267
"maxLength": 500,
82028268
"pattern": "^[^\\x00]*$",
82038269
"example": "prod cluster"
8270+
},
8271+
"expires_at": {
8272+
"type": "string",
8273+
"format": "date-time",
8274+
"nullable": true,
8275+
"description": "Optional expiry. When set, the enrollment token stops authenticating new proxy connections at this time (must be in the future). Omit or set null for a token that never expires."
82048276
}
82058277
}
82068278
},

openapi.yaml

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,48 @@ paths:
20062006
$ref: '#/components/responses/Forbidden'
20072007
'404':
20082008
$ref: '#/components/responses/NotFound'
2009+
/v1/organizations/{org_id}/self-host-enrollments/{enrollment_id}/rotate:
2010+
parameters:
2011+
- $ref: '#/components/parameters/OrgId'
2012+
- name: enrollment_id
2013+
in: path
2014+
required: true
2015+
description: Unique enrollment identifier.
2016+
schema:
2017+
type: string
2018+
pattern: ^[a-zA-Z0-9_.-]+$
2019+
example: she_01h455vb4pex5vsknk084sn02q
2020+
post:
2021+
operationId: rotateSelfHostEnrollment
2022+
summary: Rotate a self-host enrollment token
2023+
description: >-
2024+
Mints a new enrollment token in place, keeping the same enrollment id, metadata, and expiry. The swap is atomic:
2025+
the old token stops authenticating new proxy connections the moment this call returns. An already-connected
2026+
proxy keeps its existing gRPC streams until it disconnects, then must present the new token to reconnect. The
2027+
new token is returned once and cannot be retrieved again.
2028+
tags:
2029+
- Platform
2030+
responses:
2031+
'200':
2032+
description: Token rotated. New token shown once.
2033+
content:
2034+
application/json:
2035+
schema:
2036+
$ref: '#/components/schemas/SelfHostEnrollmentSecret'
2037+
'400':
2038+
$ref: '#/components/responses/BadRequest'
2039+
'401':
2040+
$ref: '#/components/responses/Unauthorized'
2041+
'403':
2042+
$ref: '#/components/responses/Forbidden'
2043+
'404':
2044+
$ref: '#/components/responses/NotFound'
2045+
'409':
2046+
description: The enrollment is revoked and cannot be rotated.
2047+
content:
2048+
application/json:
2049+
schema:
2050+
$ref: '#/components/schemas/Error'
20092051
/v1/organizations/{org_id}/support/cases:
20102052
parameters:
20112053
- $ref: '#/components/parameters/OrgId'
@@ -5894,11 +5936,18 @@ components:
58945936
format: date-time
58955937
nullable: true
58965938
description: When the enrollment was revoked. Null means active.
5939+
expires_at:
5940+
type: string
5941+
format: date-time
5942+
nullable: true
5943+
description: >-
5944+
When the enrollment token expires and stops authenticating new proxy connections. Null means it never
5945+
expires. Enforcement is fail-closed at the gRPC auth gate the instant this time passes.
58975946
SelfHostEnrollmentSecret:
58985947
type: object
58995948
description: >
5900-
Response returned once when an enrollment is created. The token is shown a single time and cannot be retrieved
5901-
again; set it as GRPC_AUTH_TOKEN on the self-hosted proxy.
5949+
Response returned once when an enrollment is created or its token is rotated. The token is shown a single time
5950+
and cannot be retrieved again; set it as GRPC_AUTH_TOKEN on the self-hosted proxy.
59025951
required:
59035952
- enrollment
59045953
- token
@@ -5925,6 +5974,13 @@ components:
59255974
maxLength: 500
59265975
pattern: ^[^\x00]*$
59275976
example: prod cluster
5977+
expires_at:
5978+
type: string
5979+
format: date-time
5980+
nullable: true
5981+
description: >-
5982+
Optional expiry. When set, the enrollment token stops authenticating new proxy connections at this time
5983+
(must be in the future). Omit or set null for a token that never expires.
59285984
ListSelfHostEnrollmentsResponse:
59295985
type: object
59305986
description: List of self-host enrollments for an organization.

spec/components/schemas/CreateSelfHostEnrollmentRequest.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ properties:
1313
maxLength: 500
1414
pattern: ^[^\x00]*$
1515
example: prod cluster
16+
expires_at:
17+
type: string
18+
format: date-time
19+
nullable: true
20+
description: >-
21+
Optional expiry. When set, the enrollment token stops authenticating new
22+
proxy connections at this time (must be in the future). Omit or set null
23+
for a token that never expires.

spec/components/schemas/SelfHostEnrollment.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,11 @@ properties:
4242
format: date-time
4343
nullable: true
4444
description: When the enrollment was revoked. Null means active.
45+
expires_at:
46+
type: string
47+
format: date-time
48+
nullable: true
49+
description: >-
50+
When the enrollment token expires and stops authenticating new proxy
51+
connections. Null means it never expires. Enforcement is fail-closed at
52+
the gRPC auth gate the instant this time passes.

spec/components/schemas/SelfHostEnrollmentSecret.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
type: object
22
description: >
3-
Response returned once when an enrollment is created. The token is shown a
4-
single time and cannot be retrieved again; set it as GRPC_AUTH_TOKEN on the
5-
self-hosted proxy.
3+
Response returned once when an enrollment is created or its token is rotated.
4+
The token is shown a single time and cannot be retrieved again; set it as
5+
GRPC_AUTH_TOKEN on the self-hosted proxy.
66
required:
77
- enrollment
88
- token

spec/openapi.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ paths:
161161
$ref: paths/v1_organizations_{org_id}_self-host-enrollments.yaml
162162
/v1/organizations/{org_id}/self-host-enrollments/{enrollment_id}:
163163
$ref: paths/v1_organizations_{org_id}_self-host-enrollments_{enrollment_id}.yaml
164+
/v1/organizations/{org_id}/self-host-enrollments/{enrollment_id}/rotate:
165+
$ref: >-
166+
paths/v1_organizations_{org_id}_self-host-enrollments_{enrollment_id}_rotate.yaml
164167
/v1/organizations/{org_id}/support/cases:
165168
$ref: paths/v1_organizations_{org_id}_support_cases.yaml
166169
/v1/organizations/{org_id}/support/cases/{case_id}:
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
parameters:
2+
- $ref: ../components/parameters/OrgId.yaml
3+
- name: enrollment_id
4+
in: path
5+
required: true
6+
description: Unique enrollment identifier.
7+
schema:
8+
type: string
9+
pattern: ^[a-zA-Z0-9_.-]+$
10+
example: she_01h455vb4pex5vsknk084sn02q
11+
post:
12+
operationId: rotateSelfHostEnrollment
13+
summary: Rotate a self-host enrollment token
14+
description: >-
15+
Mints a new enrollment token in place, keeping the same enrollment id,
16+
metadata, and expiry. The swap is atomic: the old token stops authenticating
17+
new proxy connections the moment this call returns. An already-connected
18+
proxy keeps its existing gRPC streams until it disconnects, then must
19+
present the new token to reconnect. The new token is returned once and
20+
cannot be retrieved again.
21+
tags:
22+
- Platform
23+
responses:
24+
'200':
25+
description: Token rotated. New token shown once.
26+
content:
27+
application/json:
28+
schema:
29+
$ref: ../components/schemas/SelfHostEnrollmentSecret.yaml
30+
'400':
31+
$ref: ../components/responses/BadRequest.yaml
32+
'401':
33+
$ref: ../components/responses/Unauthorized.yaml
34+
'403':
35+
$ref: ../components/responses/Forbidden.yaml
36+
'404':
37+
$ref: ../components/responses/NotFound.yaml
38+
'409':
39+
description: The enrollment is revoked and cannot be rotated.
40+
content:
41+
application/json:
42+
schema:
43+
$ref: ../components/schemas/Error.yaml

src/spec.gen.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)