feat(auth): OpenShift RBAC fine-grained permissions - #1734
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 SummarySummary by CodeRabbit
WalkthroughThis change adds configurable fine-grained RBAC with Kubernetes permission mapping, HTTP and GraphQL enforcement, token and decision caching, endpoint annotations, OpenAPI security requirements, validation tests, agent-container networking updates, and schema-generator cleanup. ChangesFine-grained RBAC
Suggested reviewers: ✨ Finishing Touches🧪 Generate unit tests (beta)
|
|
/build_test |
|
Workflow started at 8/11/2026, 4:39:38 PM. View Actions Run. |
|
OpenAPI schema change detected: diff --git a/schema/openapi.yaml b/schema/openapi.yaml
index 17dac91..4491cbd 100644
--- a/schema/openapi.yaml
+++ b/schema/openapi.yaml
@@ -1282,105 +1282,141 @@ paths:
get:
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedHeapDumpDirectory'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List Fs Heap Dumps
tags:
- Diagnostics
/api/beta/diagnostics/fs/heapdumps/{jvmId}/{heapDumpId}:
delete:
parameters:
- in: path
name: heapDumpId
required: true
schema:
type: string
- in: path
name: jvmId
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete Heap Dump By Path
tags:
- Diagnostics
/api/beta/diagnostics/fs/threaddumps:
get:
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedThreadDumpDirectory'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List Fs Thread Dumps
tags:
- Diagnostics
/api/beta/diagnostics/fs/threaddumps/{jvmId}/{threadDumpId}:
delete:
parameters:
- in: path
name: jvmId
required: true
schema:
type: string
- in: path
name: threadDumpId
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete Thread Dump
tags:
- Diagnostics
/api/beta/diagnostics/fs/unified-logs:
get:
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedUnifiedLogDirectory'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List Fs Unified Logs
tags:
- Unified Logs
/api/beta/diagnostics/fs/unified-logs/{jvmId}/{logId}:
delete:
parameters:
- in: path
name: jvmId
required: true
schema:
type: string
- in: path
name: logId
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete Unified Log By Path
tags:
- Unified Logs
patch:
parameters:
- in: path
name: jvmId
required: true
schema:
type: string
@@ -1395,20 +1431,26 @@ paths:
schema:
$ref: '#/components/schemas/MetadataBody'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UnifiedLog'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Patch Fs Unified Log Metadata
tags:
- Unified Logs
/api/beta/diagnostics/heapdump/download/{encodedKey}:
get:
parameters:
- in: path
name: encodedKey
required: true
schema:
@@ -1416,20 +1458,26 @@ paths:
- in: query
name: filename
schema:
type: string
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Handle Heap Dumps Storage Download
tags:
- Diagnostics
/api/beta/diagnostics/heapdump/upload/{jvmId}:
post:
parameters:
- in: path
name: jvmId
required: true
schema:
@@ -1446,20 +1494,26 @@ paths:
type: string
labels:
$ref: '#/components/schemas/JsonObject'
type: object
required: true
responses:
"201":
description: Created
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Upload Heap Dump
tags:
- Diagnostics
/api/beta/diagnostics/targets/{jvmId}/heapdump/{heapDumpId}/analyze:
post:
parameters:
- in: path
name: heapDumpId
required: true
schema:
@@ -1476,20 +1530,26 @@ paths:
$ref: '#/components/schemas/HttpServerResponse'
required: true
responses:
"200":
content:
application/json:
schema: {}
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Analyze Heap Dump
tags:
- Diagnostics
/api/beta/diagnostics/targets/{jvmId}/threaddump/{threadDumpId}/analyze:
post:
parameters:
- in: path
name: jvmId
required: true
schema:
@@ -1499,38 +1559,50 @@ paths:
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ThreadDumpAnalysis'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Analyze Thread Dump
tags:
- Diagnostics
/api/beta/diagnostics/targets/{targetId}/gc:
post:
description: |
Request the remote target to perform a garbage collection. The target JVM is free to ignore this
request. This is generally equivalent to a System.gc() call made within the target JVM.
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"201":
description: Created
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Initiate a garbage collection on the specified target
tags:
- Diagnostics
/api/beta/diagnostics/targets/{targetId}/heapdump:
get:
parameters:
- in: path
name: targetId
required: true
schema:
@@ -1538,20 +1610,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/HeapDump'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get Heap Dumps
tags:
- Diagnostics
post:
description: |
Request the remote target to perform a heap dump.
parameters:
- in: path
name: targetId
required: true
@@ -1566,40 +1644,52 @@ paths:
required: true
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Initiates a heap dump on the specified target
tags:
- Diagnostics
/api/beta/diagnostics/targets/{targetId}/heapdump/{heapDumpId}:
delete:
parameters:
- in: path
name: heapDumpId
required: true
schema:
type: string
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete Heap Dump
tags:
- Diagnostics
/api/beta/diagnostics/targets/{targetId}/threaddump:
get:
parameters:
- in: path
name: targetId
required: true
schema:
@@ -1607,20 +1697,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ThreadDump'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get Thread Dumps
tags:
- Diagnostics
post:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
@@ -1638,73 +1734,97 @@ paths:
required: true
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Thread Dump
tags:
- Diagnostics
/api/beta/diagnostics/targets/{targetId}/threaddump/{threadDumpId}:
delete:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
- in: path
name: threadDumpId
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete Thread Dump
tags:
- Diagnostics
/api/beta/diagnostics/targets/{targetId}/unified-logging:
delete:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Disable Unified Logging
tags:
- Unified Logs
get:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UnifiedLogStatus'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Unified Logging Status
tags:
- Unified Logs
patch:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
@@ -1717,20 +1837,26 @@ paths:
name: what
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UnifiedLog'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Reconfigure Unified Logging
tags:
- Unified Logs
post:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
@@ -1743,39 +1869,51 @@ paths:
name: what
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UnifiedLog'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Enable Unified Logging
tags:
- Unified Logs
/api/beta/diagnostics/targets/{targetId}/unified-logging/pull:
post:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UnifiedLog'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Pull Unified Log
tags:
- Unified Logs
/api/beta/diagnostics/targets/{targetId}/unified-logs:
get:
parameters:
- in: path
name: targetId
required: true
schema:
@@ -1783,40 +1921,52 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/UnifiedLog'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List Unified Logs
tags:
- Unified Logs
/api/beta/diagnostics/targets/{targetId}/unified-logs/{logId}:
delete:
parameters:
- in: path
name: logId
required: true
schema:
type: string
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete Unified Log
tags:
- Unified Logs
get:
parameters:
- in: path
name: logId
required: true
schema:
type: string
@@ -1829,20 +1979,26 @@ paths:
- in: query
name: filename
schema:
type: string
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Download Unified Log
tags:
- Unified Logs
patch:
parameters:
- in: path
name: logId
required: true
schema:
type: string
@@ -1858,20 +2014,26 @@ paths:
schema:
$ref: '#/components/schemas/MetadataBody'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UnifiedLog'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Patch Unified Log Metadata
tags:
- Unified Logs
/api/beta/diagnostics/threaddump/download/{encodedKey}:
get:
parameters:
- in: path
name: encodedKey
required: true
schema:
@@ -1879,20 +2041,26 @@ paths:
- in: query
name: filename
schema:
type: string
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Handle Thread Dumps Storage Download
tags:
- Diagnostics
/api/beta/diagnostics/unified-logs/download/{encodedKey}:
get:
parameters:
- in: path
name: encodedKey
required: true
schema:
@@ -1900,20 +2068,26 @@ paths:
- in: query
name: filename
schema:
type: string
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Handle Unified Log Storage Download
tags:
- Unified Logs
/api/beta/discovery/credential_exists:
post:
requestBody:
content:
application/x-www-form-urlencoded:
schema:
properties:
@@ -1929,73 +2103,97 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Credential'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Check if a Credential already exists with an identical MatchExpression script.
tags:
- Discovery
/api/beta/fs/recordings:
get:
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedRecordingDirectory'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List all archived recordings grouped by target
tags:
- Archived Recordings
/api/beta/fs/recordings/{jvmId}:
get:
parameters:
- in: path
name: jvmId
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedRecordingDirectory'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List all archived recordings belonging to the specified target
tags:
- Archived Recordings
/api/beta/fs/recordings/{jvmId}/{filename}:
delete:
parameters:
- in: path
name: filename
required: true
schema:
type: string
- in: path
name: jvmId
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete an archived recording by name belonging to the specified target
tags:
- Archived Recordings
/api/beta/recording_analytics/{jvmId}/{filename}:
post:
parameters:
- in: path
name: filename
required: true
schema:
@@ -2020,60 +2218,78 @@ paths:
application/json:
schema:
items:
items:
type: string
type: array
type: array
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Execute Query
tags:
- Jfr Analytics
/api/beta/recordings/{connectUrl}/{filename}:
delete:
parameters:
- description: the connection URL associated with the target
in: path
name: connectUrl
required: true
schema:
type: string
- in: path
name: filename
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete an archived recording belonging to the specified target
tags:
- Archived Recordings
/api/beta/recordings/{jvmId}:
get:
parameters:
- in: path
name: jvmId
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedRecording'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List archived recordings belonging to the specified target
tags:
- Archived Recordings
post:
description: |
Upload a JFR binary file into the archives, associating the archived recording with a particular
target JVM. This is primarily used by the Cryostat Agent for pushing harvested recording files.
parameters:
- in: path
name: jvmId
@@ -2093,40 +2309,52 @@ paths:
recording:
format: binary
type: string
type: object
required: true
responses:
"201":
description: Created
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Upload a JFR binary file to archives, associated with a particular target
tags:
- Archived Recordings
/api/beta/targets/{jvmId}/smart_triggers/sync:
post:
parameters:
- in: path
name: jvmId
required: true
schema:
type: string
requestBody:
content:
text/plain:
schema:
type: string
required: true
responses:
"201":
description: Created
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Sync Recordings
tags:
- Smart Triggers
/api/beta/targets/{targetId}/async-profiler:
get:
parameters:
- in: path
name: targetId
required: true
schema:
@@ -2134,20 +2362,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/AsyncProfile'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List existing async-profiler profiles on the specified target
tags:
- Async Profiler
post:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
@@ -2160,59 +2394,77 @@ paths:
required: true
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Create a new async-profiler profile on the specified target
tags:
- Async Profiler
/api/beta/targets/{targetId}/async-profiler/status:
get:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/AsyncProfilerStatus'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get specified target's async-profiler status
tags:
- Async Profiler
/api/beta/targets/{targetId}/async-profiler/{profileId}:
delete:
parameters:
- in: path
name: profileId
required: true
schema:
type: string
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete an async-profiler profile from the specified target
tags:
- Async Profiler
get:
parameters:
- in: path
name: profileId
required: true
schema:
type: string
@@ -2223,20 +2475,26 @@ paths:
format: int64
type: integer
responses:
"200":
content:
application/octet-stream:
schema:
format: binary
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Download an async-profiler binary file in JFR format
tags:
- Async Profiler
/api/beta/targets/{targetId}/smart_triggers:
get:
parameters:
- in: path
name: targetId
required: true
schema:
@@ -2244,20 +2502,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/SmartTrigger'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve all currently active Smart Triggers for a target
tags:
- Smart Triggers
post:
description: |
Define a new Smart Trigger. A custom trigger definition must consist of both an expression
that defines the overall trigger condition and the name of an event template that is used
for the JFR Recording. The entire trigger expression must be enclosed in square brackets,
with the recording template name specified after a ~. For an example definition:
[ProcessCpuLoad > 0.2 ; TargetDuration > duration("30s")]~profile
@@ -2275,20 +2539,26 @@ paths:
properties:
definition:
type: string
type: object
required: true
responses:
"201":
description: Created
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Define a new Smart Trigger for a target
tags:
- Smart Triggers
/api/beta/targets/{targetId}/smart_triggers/{uuid}:
delete:
description: |
Delete an active Smart Trigger. A custom trigger definition must consist of both an expression
that defines the overall trigger condition and the name of an event template that is used
for the JFR Recording. The entire trigger expression must be enclosed in square brackets,
with the recording template name specified after a ~. For an example definition:
@@ -2301,20 +2571,26 @@ paths:
format: int64
type: integer
- in: path
name: uuid
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete a currently active Smart Trigger for a target
tags:
- Smart Triggers
/api/v4.1/metrics/reports:
get:
description: |
Retrieve the latest aggregate report data across all targets with recent automated analysis reports
scores. These are multi-dimensional metrics in Prometheus format.
parameters:
- in: query
@@ -2325,20 +2601,26 @@ paths:
type: number
responses:
"200":
content:
text/plain:
schema:
items:
type: string
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve the latest aggregate report data
tags:
- Analysis Report Aggregator
/api/v4.1/metrics/reports/{jvmId}:
get:
description: |
Retrieve the latest aggregate report data for a given target's recent automated analysis reports
scores. These are multi-dimensional metrics in Prometheus format.
parameters:
- in: path
@@ -2346,34 +2628,46 @@ paths:
required: true
schema:
type: string
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve the latest aggregate report data for the specified target
tags:
- Analysis Report Aggregator
/api/v4.1/reports_rules:
get:
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ReportRule'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List Report Rules
tags:
- Reports
/api/v4.1/targets/{targetId}/reports:
get:
description: |
Get the current cached automated analysis report for the specified target, if any. If no such
report currently exists for the specified target then the response will be an HTTP 404 Not Found,
and automated analysis report generation will not be triggered.
parameters:
@@ -2385,20 +2679,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
additionalProperties:
$ref: '#/components/schemas/AnalysisResult1'
type: object
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve current automated analysis report for a target
tags:
- Reports
post:
description: |
Composite action that 1) creates a Snapshot active recording on the specified target, 2) archives
that Snapshot immediately, 3) performs automated analysis report generation on the archived file.
The response will include a Location header pointing the client to an endpoint where the report can
be retrieved, which may require the client to wait for a Job UUID notification.
parameters:
@@ -2420,20 +2720,26 @@ paths:
$ref: '#/components/schemas/HttpServerResponse'
required: true
responses:
"200":
content:
application/json:
schema: {}
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Perform "target analysis" on the specified target
tags:
- Reports
/api/v4.2/discovery/{id}:
post:
description: |
Using its plugin ID and current token, a discovery plugin uses this endpoint to publish a JSON
request body containing a list of discovery nodes. The discovery plugin itself is a Realm node in
the overall discovery tree, so the published list of nodes here will replace the plugin Realm
node's list of children.
@@ -2476,20 +2782,26 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PluginRegistration'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Register and publish a Cryostat Agent
tags:
- Discovery
/api/v4/activedownload/{id}:
get:
description: |
Given a recording ID and a remote recording ID within that target, Cryostat will open a remote
connection to the target and pipe back a data stream containing the Flight Recording binary file
format for that recording. The client can feed this data to other tooling which ingests the JFR
binary file format.
@@ -2501,20 +2813,26 @@ paths:
format: int64
type: integer
responses:
"200":
content:
application/octet-stream:
schema:
format: binary
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Download a Flight Recording binary file
tags:
- Active Recordings Download
/api/v4/auth:
post:
description: |
In modern Cryostat deployments it is customary to deploy Cryostat behind an authenticating reverse
proxy, so authentication is not actually handled by Cryostat itself. This endpoint is used by the
Cryostat Web UI client to send an authenticated client request, including some authentication
headers, to the Cryostat server so that it can extract information about the logged-in user. The
@@ -2538,20 +2856,26 @@ paths:
and are therefore candidates for Cryostat to select this Credential.
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/CredentialMatchResult'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List information about all of the available Stored Credentials.
tags:
- Credentials
post:
description: |
Define a new Stored Credential. Requires a match expression which defines which targets require
this credential, and the username and password to use to pass authentication checks on those
targets. Stored Credentials are stored in an encrypted keyring using symmetric encryption and an
encryption key configured on the Cryostat database.
requestBody:
@@ -2569,20 +2893,26 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Credential'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Define a new Stored Credential
tags:
- Credentials
/api/v4/credentials/test/{targetId}:
post:
parameters:
- in: path
name: targetId
required: true
schema:
@@ -2601,35 +2931,47 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/CredentialTestResult'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Test if the supplied username/password are valid credentials for the specified target.
tags:
- Credentials
/api/v4/credentials/{id}:
delete:
parameters:
- in: path
name: id
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete a Stored Credential
tags:
- Credentials
get:
description: |
Get match result information about a specific Stored Credential. A match result includes the Stored
Credential's ID, its Match Expression, and a list of currently discovered Targets which match that
expression and are therefore candidates for Cryostat to select this Credential.
parameters:
- in: path
@@ -2638,38 +2980,50 @@ paths:
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/CredentialMatchResult'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get information about a Stored Credential
tags:
- Credentials
/api/v4/discovery:
get:
parameters:
- in: query
name: mergeRealms
schema:
default: false
type: boolean
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/DiscoveryNode'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve the entire discovery tree.
tags:
- Discovery
post:
description: |
Register a new discovery plugin, or refresh an existing plugin's registration and generate a new
token. New registrations require the realm and callback fields. Registration refreshers
additionally require the id and token fields, which are supplied in the response to the original
registration.
requestBody:
@@ -2680,20 +3034,26 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PluginRegistration'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Register as a new discovery plugin or refresh existing registration
tags:
- Discovery
/api/v4/discovery/{id}:
delete:
description: |
Delete the plugin's registration along with its discovery Realm node and all of its children. This
is used when a discovery plugin is shutting down.
parameters:
- in: path
@@ -2721,20 +3081,26 @@ paths:
required: true
schema:
$ref: '#/components/schemas/UUID'
- in: header
name: Cryostat-Discovery-Authentication
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Endpoint for discovery plugins to check their own registration status
tags:
- Discovery
post:
description: |
Using its plugin ID and current token, a discovery plugin uses this endpoint to publish a JSON
request body containing a list of discovery nodes. The discovery plugin itself is a Realm node in
the overall discovery tree, so the published list of nodes here will replace the plugin Realm
node's list of children.
parameters:
@@ -2774,20 +3140,26 @@ paths:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/DiscoveryPlugin_Flat'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List currently registered discovery plugins
tags:
- Discovery
/api/v4/discovery_plugins/{id}:
get:
description: |
Retrieve information about a specific discovery plugin, including its discovery Realm node and
subtree.
parameters:
- in: path
@@ -2795,20 +3167,26 @@ paths:
required: true
schema:
$ref: '#/components/schemas/UUID'
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/DiscoveryPlugin'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve a specific discovery plugin
tags:
- Discovery
/api/v4/download/{encodedKey}:
get:
description: |
Get a download URL for an archived recording. The response will be an HTTP redirect with a Location
header pointing to the location where the client can download the recording JFR binary file.
parameters:
- in: path
@@ -2819,38 +3197,50 @@ paths:
- in: query
name: filename
schema:
type: string
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get a download URL for an archived recording
tags:
- Archived Recordings
/api/v4/event_templates:
get:
description: |
Retrieve a list of templates available on this Cryostat server. These templates can be applied to
recordings started on any discovered target, but any event configurations within the template which
reference events that do not exist on the target will be ignored.
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/Template'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List server event templates
tags:
- Event Templates
post:
description: |
Upload a new custom event template to the server. This must be in OpenJDK .jfc (XML) format.
requestBody:
content:
application/x-www-form-urlencoded:
schema:
@@ -2862,57 +3252,75 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Template'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Upload a custom event template
tags:
- Event Templates
/api/v4/event_templates/{templateName}:
delete:
description: |
Delete a custom event template from the server. Only previously uploaded custom event templates can
be deleted.
parameters:
- in: path
name: templateName
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete a custom event template
tags:
- Event Templates
/api/v4/event_templates/{templateType}:
get:
parameters:
- in: path
name: templateType
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/Template'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List server event templates of the given type
tags:
- Event Templates
/api/v4/event_templates/{templateType}/{templateName}:
get:
description: |
Get the .jfc (XML) file definition for the given server event template. This is the same type of
event configuration file that ships with OpenJDK distributions.
parameters:
- in: path
@@ -2925,20 +3333,26 @@ paths:
required: true
schema:
type: string
responses:
"200":
content:
application/xml:
schema:
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get a specific event template
tags:
- Event Templates
/api/v4/grafana/{encodedKey}:
post:
description: |
Upload an archived recording to the jfr-datasource for later online analysis in the associated
Grafana dashboard.
parameters:
- in: path
@@ -2954,20 +3368,26 @@ paths:
required: true
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Upload an archived recording to Grafana for online analysis
tags:
- Archived Recordings
/api/v4/grafana_dashboard_url:
get:
description: |
Returns the URL for the associated Grafana dashboard instance. If there is an internally-accessible
(for Cryostat) URL and an externally-accessible URL (for users) URL, the externally-accessible URL
is preferred. If neither are configured then the response is an HTTP 400 Bad Request.
responses:
@@ -3020,20 +3440,26 @@ paths:
responses:
"200":
content:
application/json:
schema:
items:
additionalProperties: {}
type: object
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve a list of all currently defined Match Expressions
tags:
- Match Expressions
post:
description: |
Given a list of Target IDs, retrieve each Target instance from the database, then return the list
filtered by the Targets which satisfy the Match Expression. If a given ID does not exist in the
database then the whole request will fail. The expression must evaluate to a boolean value for each
target. The match expression will not be stored.
requestBody:
@@ -3044,39 +3470,51 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/MatchedExpression'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Test a MatchExpression against a list of Targets
tags:
- Match Expressions
/api/v4/matchExpressions/{id}:
get:
parameters:
- in: path
name: id
required: true
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/MatchedExpression'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve a single Match Expression
tags:
- Match Expressions
/api/v4/probes:
get:
responses:
"200":
content:
application/json:
schema:
@@ -3154,20 +3592,26 @@ paths:
List all archived recordings from all targets, including (re-)uploaded files.
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ArchivedRecording'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List all archived recordings
tags:
- Archived Recordings
post:
description: |
(Re-)upload a JFR binary file into the archives. This allows for the restoration of archived files
after they have been otherwise removed, or for portability across Cryostat instances or between
Cryostat version upgrades. This can also be used to upload JFR files which were not collected by
Cryostat, so that Cryostat can be used to perform online analysis of the file.
requestBody:
@@ -3185,35 +3629,47 @@ paths:
responses:
"200":
content:
application/json:
schema:
additionalProperties: {}
type: object
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Upload a JFR binary file to archives
tags:
- Archived Recordings
/api/v4/recordings/{filename}:
delete:
deprecated: true
parameters:
- in: path
name: filename
required: true
schema:
type: string
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete an archived recording by filename
tags:
- Archived Recordings
/api/v4/reports/{encodedKey}:
get:
description: |
Given an encoded key from another endpoint, request an actual automated analysis report. If the
requested report already exists in one of the tiered caching layers then the report will be
directly returned as a JSON response body. If the report does not yet exist then the response will
contain a Job UUID as a plain text response body. Cryostat will emit a WebSocket notification later
@@ -3236,34 +3692,46 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HttpServerResponse'
required: true
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get an automated analysis report
tags:
- Reports
/api/v4/rules:
get:
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/Rule'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List all Automated Rules
tags:
- Rules
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Rule'
application/x-www-form-urlencoded:
@@ -3335,56 +3803,74 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Rule'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Create a new Automated Rule
tags:
- Rules
/api/v4/rules/{name}:
delete:
parameters:
- in: path
name: name
required: true
schema:
type: string
- in: query
name: clean
schema:
default: false
type: boolean
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete an Automated Rule by name
tags:
- Rules
get:
parameters:
- in: path
name: name
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Rule'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get an Automated Rule by name
tags:
- Rules
patch:
description: |
Update Automated Rule parameters, such as whether the rule is currently active or not.
parameters:
- in: path
name: name
required: true
@@ -3401,37 +3887,49 @@ paths:
schema:
$ref: '#/components/schemas/JsonObject'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Rule'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Update an Automated Rule
tags:
- Rules
/api/v4/targets:
get:
description: |
Get a list of the currently discovered targets. These are essentialy the same as the leaf nodes of
the discovery tree. See 'GET /api/v4/discovery'.
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/Target'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List currently discovered targets
tags:
- Targets
post:
description: |
Create a target definition given a JSON request body target stub. The target stub must contain the
connectUrl and alias, and optionally contain a username and password to create a Stored Credential
associated with this target. The dryrun parameter can be used to perform this operation as a check,
to verify if such a target could be created (no connectUrl conflict and acceptable credentials).
parameters:
@@ -3477,59 +3975,77 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Target'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Create a target definition
tags:
- Custom Discovery
/api/v4/targets/{id}:
delete:
description: |
Delete the specified target by ID. Only allows deletion of targets that were defined by the same
Custom Target discovery API. Other targets must be removed by the discovery mechanisms which
discovered them.
parameters:
- in: path
name: id
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete the specified target
tags:
- Custom Discovery
get:
description: |
Get details about a particular target given its ID.
parameters:
- in: path
name: id
required: true
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Target'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get a target by ID
tags:
- Targets
/api/v4/targets/{id}/event_templates:
get:
description: |
Retrieve a list of event templates available on the given target when starting recordings on the
same target. This includes all of the server's available templates, plus the templates available
specifically from the target (ex. within /usr/lib/jvm/java/lib/jfr).
parameters:
@@ -3541,20 +4057,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/Template'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Retrieve a list of event templates available on the given target
tags:
- Target Event Templates
/api/v4/targets/{id}/event_templates/{templateType}/{templateName}:
get:
description: |
Get the .jfc (XML) file definition for the given target event template.
parameters:
- in: path
name: id
@@ -3572,20 +4094,26 @@ paths:
required: true
schema:
$ref: '#/components/schemas/TemplateType'
responses:
"200":
content:
application/xml:
schema:
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get a specific event template
tags:
- Target Event Templates
/api/v4/targets/{id}/events:
get:
description: |
Retrieve a list of JFR event types registered within the given target. This will include all
built-in JFR types emitted by the target JVM, as well as custom event types specific to that
target JVM if they are correctly registered. Custom event types, or event types emitted by plugins
and extensions, may not always appear in this list.
@@ -3602,20 +4130,26 @@ paths:
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/SerializableEventTypeInfo'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List JFR event types registered within the given target
tags:
- Events
/api/v4/targets/{id}/probes:
delete:
parameters:
- in: path
name: id
required: true
schema:
@@ -3681,20 +4215,26 @@ paths:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
additionalProperties: {}
type: object
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get the current set of options for the specified target
tags:
- Recording Options
patch:
description: |
Set default recording options for the specified target. These options will be applied to any
recordings started on this target if no override values are specified when the recording is
created.
parameters:
- in: path
@@ -3717,20 +4257,26 @@ paths:
type: object
required: true
responses:
"200":
content:
application/json:
schema:
additionalProperties: {}
type: object
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Update the recording options for the specified target
tags:
- Recording Options
/api/v4/targets/{targetId}/recordings:
get:
description: |
Retrieve a list of active recordings currently present on the specified target. This may initiate
a new remote connection to the target to update Cryostat's model of available recordings.
parameters:
- in: path
@@ -3741,20 +4287,26 @@ paths:
type: integer
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/LinkedRecordingDescriptor'
type: array
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: List active recordings on the specified target
tags:
- Active Recordings
post:
description: |
Create a new Flight Recording on the specified target. The recording will be immediately started
and begin capturing Flight Recording data.
The recording must be given a name (unique within the
target). An event specifier string must be included, which follows the format
"template={name},(type={type})". The type parameter is optional and the template name is required.
@@ -3815,20 +4367,26 @@ paths:
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/LinkedRecordingDescriptor'
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Start a new recording on the specified target
tags:
- Active Recordings
/api/v4/targets/{targetId}/recordings/{remoteId}:
delete:
description: |
Delete a recording from the specified target. This will remove it both from Cryostat's database
as well as remove the recording and release all resources in the remote target JVM.
parameters:
- in: path
@@ -3839,20 +4397,26 @@ paths:
type: integer
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"204":
description: No Content
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Delete a recording from the specified target
tags:
- Active Recordings
get:
description: |
Given a recording ID and a remote recording ID within that target, Cryostat will open a remote
connection to the target and pipe back a data stream containing the Flight Recording binary file
format for that recording. The client can feed this data to other tooling which ingests the JFR
binary file format.
parameters:
@@ -3869,20 +4433,26 @@ paths:
format: int64
type: integer
responses:
"200":
content:
application/octet-stream:
schema:
format: binary
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Download a Flight Recording binary file
tags:
- Active Recordings
patch:
description: |
Remote recordings can be stopped by sending the request body "stop", or copied to archives by
sending the request body "save". The body is case-insensitive.
parameters:
- in: path
name: remoteId
@@ -3902,20 +4472,26 @@ paths:
schema:
$ref: '#/components/schemas/HttpServerResponse'
required: true
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Update a remote recording on the specified target
tags:
- Active Recordings
/api/v4/targets/{targetId}/recordings/{remoteId}/upload:
post:
description: |
Upload the current data stream of the specified recording to the jfr-datasource for online analysis
in the associated Grafana dashboard.
parameters:
- in: path
@@ -3938,20 +4514,26 @@ paths:
required: true
responses:
"200":
content:
text/plain:
schema:
type: string
description: OK
"400":
description: Bad Request
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Upload a recording for analysis in Grafana dashboard
tags:
- Active Recordings
/api/v4/targets/{targetId}/reports/{recordingId}:
get:
description: |
Request an automated analysis report for a particular active recording on the specified target. If
such a report already exists it will be returned directly as a JSON response body. If the report
does not yet exist then an asynchronous task for it will be started, and a Job UUID will be
sent as the plaintext response body.
@@ -3978,39 +4560,51 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HttpServerResponse'
required: true
responses:
"200":
content:
application/json:
schema: {}
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Get an automated analysis report for a particular recording on the specified target
tags:
- Reports
/api/v4/targets/{targetId}/snapshot:
post:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/LinkedRecordingDescriptor'
description: OK
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Create a JFR Snapshot on the specified target
tags:
- Snapshots
/api/v4/tls/certs:
get:
description: |
In addition to the standard system/OpenJDK certificate trust store, Cryostat can be configured to
trust additional certificates which may be presented by target JVM JMX servers or by Cryostat Agent
HTTPS servers. This endpoint returns a list of local file paths to additional certificate files,
which Cryostat will have loaded into an additional trust store at startup.
No GraphQL schema changes detected. WebSocket notifications schema change detected: diff --git a/schema/notifications.yaml b/schema/notifications.yaml
index b263685..bce6681 100644
--- a/schema/notifications.yaml
+++ b/schema/notifications.yaml
@@ -1081,43 +1081,39 @@ components:
properties:
event:
type: object
properties:
kind:
type: object
description: Payload of type EventKind
serviceRef:
type: object
properties:
- id:
- type: integer
connectUrl:
type: object
description: Payload of type URI
alias:
type: string
jvmId:
type: string
labels:
type: object
additionalProperties: true
annotations:
type: object
properties:
platform:
type: object
additionalProperties: true
cryostat:
type: object
additionalProperties: true
- agent:
- type: boolean
jvmId:
type: string
required:
- meta
- message
TemplateDeleted:
name: TemplateDeleted
title: Template Deleted
summary: 'Notification: TemplateDeleted'
description: WebSocket notification for Template Deleted events
|
|
CI build: |
9ca7bb7 to
293591e
Compare
|
/build_test |
|
Workflow started at 8/11/2026, 4:57:25 PM. View Actions Run. |
|
CI build: Flaky tests:
|
|
No OpenAPI schema changes detected. No GraphQL schema changes detected. No WebSocket notifications schema changes detected. |
|
CI build: |
|
/build_test |
|
Workflow started at 8/11/2026, 5:10:45 PM. View Actions Run. |
|
No OpenAPI schema changes detected. No GraphQL schema changes detected. No WebSocket notifications schema changes detected. |
|
CI build: |
|
CI build: Flaky tests:
|
|
/build_test |
|
Workflow started at 8/11/2026, 5:51:21 PM. View Actions Run. |
|
No OpenAPI schema changes detected. No GraphQL schema changes detected. No WebSocket notifications schema changes detected. |
|
CI build: |
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (4)
src/main/java/io/cryostat/security/rbac/graphql/GraphQLSecurityInterceptor.java (1)
70-84: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winCache authorization decisions per request and permission.
SsarClientCacheonly caches Kubernetes clients; repeated checks still create separateSelfSubjectAccessReviewrequests. Add request-scoped memoization inbuildOpenshiftIdentity, includingfalseresults, while preserving fail-closed error handling.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/io/cryostat/security/rbac/graphql/GraphQLSecurityInterceptor.java` around lines 70 - 84, Update buildOpenshiftIdentity to memoize each authorization decision by request and permission, including denied (false) results, so repeated checks reuse the cached outcome instead of issuing new SelfSubjectAccessReview requests. Preserve the existing fail-closed behavior for authorization errors and keep the per-permission validation semantics unchanged.Source: Path instructions
src/main/java/io/cryostat/security/rbac/SsarClientCache.java (1)
47-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
Cacheinstead ofLoadingCachewith a throwing loader.The declared loader always throws
UnsupportedOperationException, andgetOrCreatesupplies its own mapping function. A plainCache<String, KubernetesClient>built withCaffeine.build()expresses the same behavior and removes the unreachable loader.♻️ Proposed refactor
- private final LoadingCache<String, KubernetesClient> clientCache; + private final Cache<String, KubernetesClient> clientCache;- .build( - tokenHash -> { - throw new UnsupportedOperationException( - "Use getOrCreate(rawToken)"); - }); + .build();Update the imports to
com.github.benmanes.caffeine.cache.Cache.Also applies to: 82-86
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/io/cryostat/security/rbac/SsarClientCache.java` at line 47, Replace the LoadingCache field in SsarClientCache with Cache<String, KubernetesClient>, update the Caffeine import, and build it with build() rather than a throwing loader. Remove the unreachable loader configuration while preserving getOrCreate’s existing mapping function behavior.src/test/java/io/cryostat/security/rbac/SsarClientCacheTest.java (1)
114-124: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
testHashingConsistencyduplicatestestGetOrCreateReturnsCachedClientForSameToken.Both tests call
getOrCreatetwice with the same token and assert one factory call. Either remove this test or change it to assert the property its name states, for example that two distinct tokens produce two distinct cache entries and that a token containing non-ASCII characters is hashed without error.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/io/cryostat/security/rbac/SsarClientCacheTest.java` around lines 114 - 124, Remove the duplicate testHashingConsistency coverage or rewrite it to validate hashing-specific behavior rather than repeating testGetOrCreateReturnsCachedClientForSameToken. Prefer asserting that distinct tokens create distinct cached clients and that a non-ASCII token is processed successfully, while retaining the relevant factory-call and identity assertions.src/main/java/io/cryostat/security/rbac/RbacHttpAuthenticationMechanism.java (1)
189-248: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy liftCache SSAR decisions, not only clients.
Each permission check performs one
SelfSubjectAccessReviewHTTP call to the API server. Endpoints declare multiple permissions (for example{"targets:read", "activerecordings:write", "reports:write"}inReports.analyze), so a single request produces several serial API-server round trips on the request path.SsarClientCachecaches clients only, so no decision reuse occurs.Add a short-TTL cache keyed by token hash plus
resource/subresource/verb. A TTL of a few seconds bounds staleness and removes most API-server traffic.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/io/cryostat/security/rbac/RbacHttpAuthenticationMechanism.java` around lines 189 - 248, The checkSsarPermission flow currently caches only the client, so repeated permission checks still issue SSAR requests. Add a short-TTL decision cache keyed by a hash of rawToken plus the resolved resource/subresource/verb, consult it before creating the SSAR request, and store both allowed and denied results with a TTL of a few seconds. Preserve the existing denial behavior for unmapped permissions and SSAR failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@schema/openapi.yaml`:
- Around line 1296-1297: Define the referenced
components.securitySchemes.SecurityScheme in the OpenAPI document, ensuring its
type and required authentication details match the existing security usage. Keep
the existing security reference unchanged and place the definition under
components.securitySchemes.
In `@src/main/java/io/cryostat/asyncprofiler/AsyncProfiler.java`:
- Line 101: Require all permissions in every multi-permission
`@PermissionsAllowed` declaration by setting inclusive = true, preserving each
declaration’s existing permission names. Apply this to AsyncProfiler.java at
lines 101, 113, 132, 142, and 153; UnifiedLogs.java at lines 89, 130, 182, 207,
217, 251, 278, 295, and 349; RecordingOptions.java at lines 56 and 75; and
SmartTriggers.java at lines 69, 89, 123, and 156, as well as the remaining
multi-permission declarations in these affected classes.
In `@src/main/java/io/cryostat/credentials/Credentials.java`:
- Line 105: Add the targets:read permission requirement to the target-scoped
operation in Credentials.java at lines 105-105, before testing supplied
credentials against targetId. Also add targets:read to the operation in
Events.java at lines 46-46, before retrieving event types from id; retain the
existing feature permissions.
In `@src/main/java/io/cryostat/diagnostic/Diagnostics.java`:
- Line 141: Require all permissions in every multi-value `@PermissionsAllowed`
declaration by setting inclusive = true. Update the declarations at
src/main/java/io/cryostat/diagnostic/Diagnostics.java:141-141, 162-162, 299-299,
362-362, and 423-423;
src/main/java/io/cryostat/events/TargetEventTemplates.java:60-60 and 87-87; and
src/main/java/io/cryostat/recordings/ActiveRecordings.java:82-82, 127-127, and
176-176. Apply the same change to all multi-value declarations in Reports.java,
SmartTriggers.java, UnifiedLogs.java, AsyncProfiler.java, and
RecordingOptions.java, preserving single-permission declarations.
In `@src/main/java/io/cryostat/discovery/CustomDiscovery.java`:
- Line 94: Update both CustomDiscovery handlers at
src/main/java/io/cryostat/discovery/CustomDiscovery.java lines 94-94 and 116-116
to require credentials:write when supplied credentials will be persisted, while
retaining targets:write for target creation. Apply the authorization
consistently to both doCreate and the form-request handler.
In `@src/main/java/io/cryostat/graphql/TargetNodes.java`:
- Line 227: Update the resolver governed by the `@RequiresPermission` annotation
in TargetNodes so authorization is selection-aware: require
archivedrecordings:read only when archived data is selected, and
activerecordings:read only when active data is selected. Ensure clients
selecting only recordings { active } can proceed with targets:read and
activerecordings:read without requiring archived access, while preserving
authorization for each selected resource before loading its data.
In `@src/main/java/io/cryostat/recordings/ActiveRecordings.java`:
- Line 127: Update the authorization on the handler around the save-processing
logic in ActiveRecordings to require archivedrecordings:write before creating an
archived recording, while preserving targets:read and the existing
stop-operation authorization. If the handler combines stop and save, split their
authorization or enforce the archive permission specifically for the save
branch.
In `@src/main/java/io/cryostat/recordings/Snapshots.java`:
- Line 50: Update the multi-permission authorization declarations so all listed
permissions are required together: add inclusive = true to Snapshots.java lines
50-50 and Reports.java lines 164-164, and apply the same AND semantics to other
multi-permission declarations in UnifiedLogs.java, AsyncProfiler.java, and the
`@RequiresPermission` GraphQL resolvers in TargetNodes.java. Verify
GraphQLSecurityInterceptor enforces AND semantics for permission arrays as well.
In
`@src/main/java/io/cryostat/security/rbac/RbacHttpAuthenticationMechanism.java`:
- Around line 148-172: Update the permission checker lambda in
RbacHttpAuthenticationMechanism to build the filtered action checks before
calling Uni.combine().all(). If the resulting list is empty, fall back to
checkSsarPermission(rawToken, permission.getName()); otherwise combine the
checks and require all results to be true.
In `@src/main/resources/application.properties`:
- Around line 308-321: Remove the shipped
cryostat.security.rbac.default-permission property from
src/main/resources/application.properties while leaving the property available
for explicit deployment overrides. In
src/test/java/io/cryostat/security/rbac/PermissionMapperNoDefaultTest.java,
explicitly clear the inherited default and assert that
PermissionMapper.resolve("unknown:action") returns empty.
In `@src/test/java/io/cryostat/security/rbac/SsarClientCacheTest.java`:
- Around line 73-83: Remove the cache.shutdown() call from
testInvalidateClosesClient so the subsequent verify(mockClient).close()
assertion isolates and validates the behavior of cache.invalidate("token-close")
alone.
---
Nitpick comments:
In
`@src/main/java/io/cryostat/security/rbac/graphql/GraphQLSecurityInterceptor.java`:
- Around line 70-84: Update buildOpenshiftIdentity to memoize each authorization
decision by request and permission, including denied (false) results, so
repeated checks reuse the cached outcome instead of issuing new
SelfSubjectAccessReview requests. Preserve the existing fail-closed behavior for
authorization errors and keep the per-permission validation semantics unchanged.
In
`@src/main/java/io/cryostat/security/rbac/RbacHttpAuthenticationMechanism.java`:
- Around line 189-248: The checkSsarPermission flow currently caches only the
client, so repeated permission checks still issue SSAR requests. Add a short-TTL
decision cache keyed by a hash of rawToken plus the resolved
resource/subresource/verb, consult it before creating the SSAR request, and
store both allowed and denied results with a TTL of a few seconds. Preserve the
existing denial behavior for unmapped permissions and SSAR failures.
In `@src/main/java/io/cryostat/security/rbac/SsarClientCache.java`:
- Line 47: Replace the LoadingCache field in SsarClientCache with Cache<String,
KubernetesClient>, update the Caffeine import, and build it with build() rather
than a throwing loader. Remove the unreachable loader configuration while
preserving getOrCreate’s existing mapping function behavior.
In `@src/test/java/io/cryostat/security/rbac/SsarClientCacheTest.java`:
- Around line 114-124: Remove the duplicate testHashingConsistency coverage or
rewrite it to validate hashing-specific behavior rather than repeating
testGetOrCreateReturnsCachedClientForSameToken. Prefer asserting that distinct
tokens create distinct cached clients and that a non-ASCII token is processed
successfully, while retaining the relevant factory-call and identity assertions.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Enterprise
Run ID: b8def103-b0e4-4378-bd2d-e1d3dae26b24
📒 Files selected for processing (46)
pom.xmlschema/openapi.yamlsrc/main/java/io/cryostat/asyncprofiler/AsyncProfiler.javasrc/main/java/io/cryostat/credentials/Credentials.javasrc/main/java/io/cryostat/diagnostic/Diagnostics.javasrc/main/java/io/cryostat/diagnostic/UnifiedLogs.javasrc/main/java/io/cryostat/discovery/CustomDiscovery.javasrc/main/java/io/cryostat/discovery/Discovery.javasrc/main/java/io/cryostat/events/EventTemplates.javasrc/main/java/io/cryostat/events/Events.javasrc/main/java/io/cryostat/events/TargetEventTemplates.javasrc/main/java/io/cryostat/expressions/MatchExpressions.javasrc/main/java/io/cryostat/graphql/ActiveRecordings.javasrc/main/java/io/cryostat/graphql/ArchivedRecordings.javasrc/main/java/io/cryostat/graphql/AsyncProfilerGraphQL.javasrc/main/java/io/cryostat/graphql/EnvironmentNodes.javasrc/main/java/io/cryostat/graphql/HeapDumpGraphQL.javasrc/main/java/io/cryostat/graphql/RecordingLinks.javasrc/main/java/io/cryostat/graphql/RootNode.javasrc/main/java/io/cryostat/graphql/TargetNodes.javasrc/main/java/io/cryostat/graphql/ThreadDumpGraphQL.javasrc/main/java/io/cryostat/recordings/ActiveRecordings.javasrc/main/java/io/cryostat/recordings/ActiveRecordingsDownload.javasrc/main/java/io/cryostat/recordings/ArchivedRecordings.javasrc/main/java/io/cryostat/recordings/RecordingOptions.javasrc/main/java/io/cryostat/recordings/Snapshots.javasrc/main/java/io/cryostat/recordings/analysis/JfrAnalytics.javasrc/main/java/io/cryostat/reports/AnalysisReportAggregator.javasrc/main/java/io/cryostat/reports/Reports.javasrc/main/java/io/cryostat/rules/Rules.javasrc/main/java/io/cryostat/security/SecurityContextFilter.javasrc/main/java/io/cryostat/security/rbac/PermissionMapper.javasrc/main/java/io/cryostat/security/rbac/RbacConfig.javasrc/main/java/io/cryostat/security/rbac/RbacHttpAuthenticationMechanism.javasrc/main/java/io/cryostat/security/rbac/RbacMode.javasrc/main/java/io/cryostat/security/rbac/SsarClientCache.javasrc/main/java/io/cryostat/security/rbac/SsarClientFactory.javasrc/main/java/io/cryostat/security/rbac/graphql/GraphQLSecurityInterceptor.javasrc/main/java/io/cryostat/security/rbac/graphql/RequiresPermission.javasrc/main/java/io/cryostat/targets/Targets.javasrc/main/java/io/cryostat/triggers/SmartTriggers.javasrc/main/resources/application.propertiessrc/test/java/io/cryostat/security/rbac/PermissionMapperNoDefaultTest.javasrc/test/java/io/cryostat/security/rbac/PermissionMapperTest.javasrc/test/java/io/cryostat/security/rbac/RbacHttpAuthenticationMechanismTest.javasrc/test/java/io/cryostat/security/rbac/SsarClientCacheTest.java
|
CI build: Flaky tests:
|
…ings:write permission
…drecordings:write permission
664637f to
ed24546
Compare
|
/build_test |
CI build — Schema check resultsOpenAPI schema change detected: diff --git a/schema/openapi.yaml b/schema/openapi.yaml
index b31c9382..42aa6fdd 100644
--- a/schema/openapi.yaml
+++ b/schema/openapi.yaml
@@ -2883,20 +2883,26 @@ paths:
parameters:
- in: path
name: targetId
required: true
schema:
format: int64
type: integer
responses:
"204":
description: Active recordings synchronized
+ "401":
+ description: Not Authorized
+ "403":
+ description: Not Allowed
+ security:
+ - SecurityScheme: []
summary: Resynchronize active recordings on the specified target
tags:
- Recording Sync
/api/v4/activedownload/{id}:
get:
description: |
Given a recording ID and a remote recording ID within that target, Cryostat will open a remote
connection to the target and pipe back a data stream containing the Flight Recording binary file
format for that recording. The client can feed this data to other tooling which ingests the JFR
binary file format.No GraphQL schema changes detected. WebSocket notifications schema change detected: diff --git a/schema/notifications.yaml b/schema/notifications.yaml
index 2a482aaa..3d54e68d 100644
--- a/schema/notifications.yaml
+++ b/schema/notifications.yaml
@@ -1158,43 +1158,39 @@ components:
properties:
event:
type: object
properties:
kind:
type: object
description: Payload of type EventKind
serviceRef:
type: object
properties:
- id:
- type: integer
connectUrl:
type: object
description: Payload of type URI
alias:
type: string
jvmId:
type: string
labels:
type: object
additionalProperties: true
annotations:
type: object
properties:
platform:
type: object
additionalProperties: true
cryostat:
type: object
additionalProperties: true
- agent:
- type: boolean
jvmId:
type: string
required:
- meta
- message
TemplateDeleted:
name: TemplateDeleted
title: Template Deleted
summary: 'Notification: TemplateDeleted'
description: WebSocket notification for Template Deleted events |
|
CI build: |
|
/build_test |
CI build — Schema check resultsNo OpenAPI schema changes detected. No GraphQL schema changes detected. WebSocket notifications schema change detected: diff --git a/schema/notifications.yaml b/schema/notifications.yaml
index 2a482aaa..3d54e68d 100644
--- a/schema/notifications.yaml
+++ b/schema/notifications.yaml
@@ -1158,43 +1158,39 @@ components:
properties:
event:
type: object
properties:
kind:
type: object
description: Payload of type EventKind
serviceRef:
type: object
properties:
- id:
- type: integer
connectUrl:
type: object
description: Payload of type URI
alias:
type: string
jvmId:
type: string
labels:
type: object
additionalProperties: true
annotations:
type: object
properties:
platform:
type: object
additionalProperties: true
cryostat:
type: object
additionalProperties: true
- agent:
- type: boolean
jvmId:
type: string
required:
- meta
- message
TemplateDeleted:
name: TemplateDeleted
title: Template Deleted
summary: 'Notification: TemplateDeleted'
description: WebSocket notification for Template Deleted events |
|
CI build: |
|
CI build: Flaky tests:
|
|
CI build: Flaky tests:
|
Welcome to Cryostat! 👋
Before contributing, make sure you have:
mainbranch[chore, ci, docs, feat, fix, test]To recreate commits with GPG signature
git fetch upstream && git rebase --force --gpg-sign upstream/mainFixes: #1733
Fixes #1750
Description of the change:
Reimplements the old Cryostat 2.x concept of optionally hooking in to the OpenShift cluster OAuth server to perform additional authorization checks on incoming requests. Various Cryostat API resource types are modelled such as
targets,activerecordings,archivedrecordings,heapdumps, etc., each with verbsread,write, anddelete. All REST API endpoints are annotated with an appropriate set of required permissions. All GraphQL queries and mutations are similarly annotated. When Cryostat is configured forPERMISSIVERBAC mode (the default), it simply passes all requests - the same behaviour as before (relying on the auth proxy, if there is one). When configured forBASICRBAC mode Cryostat passes all requests but asserts that the request originated from the auth proxy. When configured inOPENSHIFTRBAC mode Cryostat asserts that the request originated from the auth proxy, extracts the user's token passed back by the proxy, and uses that to perform aSelfSubjectAccessReviewagainst the cluster OAuth to check if the user is authorized to perform the requested action(s). Acryostat.security.rbac.namespaceproperty (CRYOSTAT_SECURITY_RBAC_NAMESPACEenvironment variable) is also exposed so that the Operator/Helm can control the context that the SSAR is performed in - if this property is blank then the SSAR requires the user to pass a ClusterRole check, otherwise if the property is set to a Namespace name then the user must pass a Role check scoped to that Namespace. Therefore, the Operator/Helm can set this environment variable to the Cryostat (CR) installation Namespace to retain the existing authz semantics.Motivation for the change:
See #1733
This allows for fine-grained access controls within the Cryostat API. Previously, access to Cryostat was controlled by a single check at the auth proxy (if any) - when behind an
oauth2-proxy, having valid authentication credentials implied authorization to read any data and perform any action, and when behindopenshift-oauth-proxypassing an authentication check and singlecreate pods/execrole check granted access to read any data and perform any action. This is a very broad, coarse level of authn/authz. Admins installing Cryostat may wish to set up user accounts or groups so that some users have full access, other users may only read existing data, other users may only read specific data, etc.Not handled (yet): #630 multitenancy. API endpoints may leak metadata, ex.
GET /api/v4/targetswill return a full list of all targets to a user who has thetargets:readpermission, when really it should first check that the user hastargets:readand then for each target check that the user has permission to that particular target (either a per-targettarget:readpermission, or a scopedactiverecordings:readon that target for example). This PR still assumes that the scenario is that all users given access to a Cryostat instance are part of the same team/organization and that per-namespace authorization is out of scope. This intentionally only handles the case of differing user permissions within Cryostat instance or within the set of target namespaces so that there can be ex. admin roles vs readonly roles within a team.How to manually test:
See cryostatio/cryostat-operator#1428 . Outside of an OpenShift context, ex. on other Kubernetes or in smoketest, Cryostat should behave identically to how it does prior to this PR.