🌊 Streams: Add streams feature privilege (#218966)

This PR adds a new feature for streams to control whether the UI and API
is available.

Changes:
* Add the feature with two privileges (`show` and `manage_assets`)
* Can be configured with the classic `none`/`read`/`all` so it's
automatically aligned with serverless editor/viewer permissions
* None also means the app is not shown - to do this, the existing
`status$` observable also looks for at least the `streams.show`
capability
* Only guards changes to the linked dashboards - changes to the
Elasticsearch level are still delegated to the Elasticsearch-level
permissions of the user
* This happens on the UI level (disabled button and dashboard selection
on the dashboard page)
* and on the API level (all endpoints that can change linked dashboards
require the permission)


# Questions

* Not sure about the name `manage_assets` - maybe it should be something
else
* Not sure about how the queries stuff should work - @kdelemme anything
we should do in this area?

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Joe Reuter 2025-04-28 11:50:05 +02:00 committed by GitHub
parent 47736b2129
commit b1d85aa6a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 310 additions and 265 deletions

View file

@ -46891,7 +46891,7 @@
}, },
"/api/streams": { "/api/streams": {
"get": { "get": {
"description": "Fetches list of all streams", "description": "Fetches list of all streams<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams", "operationId": "get-streams",
"parameters": [], "parameters": [],
"requestBody": { "requestBody": {
@ -46928,7 +46928,7 @@
}, },
"/api/streams/_disable": { "/api/streams/_disable": {
"post": { "post": {
"description": "Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved.", "description": "Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-disable", "operationId": "post-streams-disable",
"parameters": [ "parameters": [
{ {
@ -46976,7 +46976,7 @@
}, },
"/api/streams/_enable": { "/api/streams/_enable": {
"post": { "post": {
"description": "Enables wired streams", "description": "Enables wired streams<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-enable", "operationId": "post-streams-enable",
"parameters": [ "parameters": [
{ {
@ -47024,7 +47024,7 @@
}, },
"/api/streams/_resync": { "/api/streams/_resync": {
"post": { "post": {
"description": "Resyncs all streams, making sure that Elasticsearch assets are up to date", "description": "Resyncs all streams, making sure that Elasticsearch assets are up to date<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-resync", "operationId": "post-streams-resync",
"parameters": [ "parameters": [
{ {
@ -47072,7 +47072,7 @@
}, },
"/api/streams/{name}": { "/api/streams/{name}": {
"delete": { "delete": {
"description": "Deletes a stream definition and the underlying data stream", "description": "Deletes a stream definition and the underlying data stream<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "delete-streams-name", "operationId": "delete-streams-name",
"parameters": [ "parameters": [
{ {
@ -47126,7 +47126,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"get": { "get": {
"description": "Fetches a stream definition and associated dashboards", "description": "Fetches a stream definition and associated dashboards<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name", "operationId": "get-streams-name",
"parameters": [ "parameters": [
{ {
@ -47170,7 +47170,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Creates or updates a stream definition. Classic streams can not be created through this API, only updated", "description": "Creates or updates a stream definition. Classic streams can not be created through this API, only updated<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name", "operationId": "put-streams-name",
"parameters": [ "parameters": [
{ {
@ -50598,7 +50598,7 @@
}, },
"/api/streams/{name}/_fork": { "/api/streams/{name}/_fork": {
"post": { "post": {
"description": "Forks a wired stream and creates a child stream", "description": "Forks a wired stream and creates a child stream<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-fork", "operationId": "post-streams-name-fork",
"parameters": [ "parameters": [
{ {
@ -50783,7 +50783,7 @@
}, },
"/api/streams/{name}/_group": { "/api/streams/{name}/_group": {
"get": { "get": {
"description": "Fetches the group settings of a group stream definition", "description": "Fetches the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-group", "operationId": "get-streams-name-group",
"parameters": [ "parameters": [
{ {
@ -50827,7 +50827,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Upserts the group settings of a group stream definition", "description": "Upserts the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-group", "operationId": "put-streams-name-group",
"parameters": [ "parameters": [
{ {
@ -50893,7 +50893,7 @@
}, },
"/api/streams/{name}/_ingest": { "/api/streams/{name}/_ingest": {
"get": { "get": {
"description": "Fetches the ingest settings of an ingest stream definition", "description": "Fetches the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-ingest", "operationId": "get-streams-name-ingest",
"parameters": [ "parameters": [
{ {
@ -50937,7 +50937,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Upserts the ingest settings of an ingest stream definition", "description": "Upserts the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-ingest", "operationId": "put-streams-name-ingest",
"parameters": [ "parameters": [
{ {
@ -54114,7 +54114,7 @@
}, },
"/api/streams/{name}/content/export": { "/api/streams/{name}/content/export": {
"post": { "post": {
"description": "Exports the content associated to a stream.", "description": "Exports the content associated to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-content-export", "operationId": "post-streams-name-content-export",
"parameters": [ "parameters": [
{ {
@ -54221,7 +54221,7 @@
}, },
"/api/streams/{name}/content/import": { "/api/streams/{name}/content/import": {
"post": { "post": {
"description": "Links content objects to a stream.", "description": "Links content objects to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-content-import", "operationId": "post-streams-name-content-import",
"parameters": [ "parameters": [
{ {
@ -54272,7 +54272,7 @@
}, },
"/api/streams/{name}/dashboards": { "/api/streams/{name}/dashboards": {
"get": { "get": {
"description": "Fetches all dashboards linked to a stream that are visible to the current user in the current space.", "description": "Fetches all dashboards linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-dashboards", "operationId": "get-streams-name-dashboards",
"parameters": [ "parameters": [
{ {
@ -54318,7 +54318,7 @@
}, },
"/api/streams/{name}/dashboards/_bulk": { "/api/streams/{name}/dashboards/_bulk": {
"post": { "post": {
"description": "Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones.", "description": "Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-dashboards-bulk", "operationId": "post-streams-name-dashboards-bulk",
"parameters": [ "parameters": [
{ {
@ -54414,7 +54414,7 @@
}, },
"/api/streams/{name}/dashboards/{dashboardId}": { "/api/streams/{name}/dashboards/{dashboardId}": {
"delete": { "delete": {
"description": "Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream.", "description": "Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "delete-streams-name-dashboards-dashboardid", "operationId": "delete-streams-name-dashboards-dashboardid",
"parameters": [ "parameters": [
{ {
@ -54476,7 +54476,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Links a dashboard to a stream. Noop if the dashboard is already linked to the stream.", "description": "Links a dashboard to a stream. Noop if the dashboard is already linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-dashboards-dashboardid", "operationId": "put-streams-name-dashboards-dashboardid",
"parameters": [ "parameters": [
{ {
@ -54540,7 +54540,7 @@
}, },
"/api/streams/{name}/queries": { "/api/streams/{name}/queries": {
"get": { "get": {
"description": "Fetches all queries linked to a stream that are visible to the current user in the current space.", "description": "Fetches all queries linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-queries", "operationId": "get-streams-name-queries",
"parameters": [ "parameters": [
{ {
@ -54586,7 +54586,7 @@
}, },
"/api/streams/{name}/queries/_bulk": { "/api/streams/{name}/queries/_bulk": {
"post": { "post": {
"description": "Bulk update queries of a stream. Can add new queries and delete existing ones.", "description": "Bulk update queries of a stream. Can add new queries and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-queries-bulk", "operationId": "post-streams-name-queries-bulk",
"parameters": [ "parameters": [
{ {
@ -54712,7 +54712,7 @@
}, },
"/api/streams/{name}/queries/{queryId}": { "/api/streams/{name}/queries/{queryId}": {
"delete": { "delete": {
"description": "Remove a query from a stream. Noop if the query is not found on the stream.", "description": "Remove a query from a stream. Noop if the query is not found on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "delete-streams-name-queries-queryid", "operationId": "delete-streams-name-queries-queryid",
"parameters": [ "parameters": [
{ {
@ -54774,7 +54774,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Adds a query to a stream. Noop if the query is already present on the stream.", "description": "Adds a query to a stream. Noop if the query is already present on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-queries-queryid", "operationId": "put-streams-name-queries-queryid",
"parameters": [ "parameters": [
{ {
@ -54847,7 +54847,7 @@
}, },
"/api/streams/{name}/significant_events": { "/api/streams/{name}/significant_events": {
"get": { "get": {
"description": "Read the significant events", "description": "Read the significant events<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-significant-events", "operationId": "get-streams-name-significant-events",
"parameters": [ "parameters": [
{ {

View file

@ -46482,7 +46482,7 @@
}, },
"/api/streams": { "/api/streams": {
"get": { "get": {
"description": "Fetches list of all streams", "description": "Fetches list of all streams<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams", "operationId": "get-streams",
"parameters": [], "parameters": [],
"requestBody": { "requestBody": {
@ -46519,7 +46519,7 @@
}, },
"/api/streams/_disable": { "/api/streams/_disable": {
"post": { "post": {
"description": "Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved.", "description": "Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-disable", "operationId": "post-streams-disable",
"parameters": [ "parameters": [
{ {
@ -46567,7 +46567,7 @@
}, },
"/api/streams/_enable": { "/api/streams/_enable": {
"post": { "post": {
"description": "Enables wired streams", "description": "Enables wired streams<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-enable", "operationId": "post-streams-enable",
"parameters": [ "parameters": [
{ {
@ -46615,7 +46615,7 @@
}, },
"/api/streams/_resync": { "/api/streams/_resync": {
"post": { "post": {
"description": "Resyncs all streams, making sure that Elasticsearch assets are up to date", "description": "Resyncs all streams, making sure that Elasticsearch assets are up to date<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-resync", "operationId": "post-streams-resync",
"parameters": [ "parameters": [
{ {
@ -46663,7 +46663,7 @@
}, },
"/api/streams/{name}": { "/api/streams/{name}": {
"delete": { "delete": {
"description": "Deletes a stream definition and the underlying data stream", "description": "Deletes a stream definition and the underlying data stream<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "delete-streams-name", "operationId": "delete-streams-name",
"parameters": [ "parameters": [
{ {
@ -46717,7 +46717,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"get": { "get": {
"description": "Fetches a stream definition and associated dashboards", "description": "Fetches a stream definition and associated dashboards<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name", "operationId": "get-streams-name",
"parameters": [ "parameters": [
{ {
@ -46761,7 +46761,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Creates or updates a stream definition. Classic streams can not be created through this API, only updated", "description": "Creates or updates a stream definition. Classic streams can not be created through this API, only updated<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name", "operationId": "put-streams-name",
"parameters": [ "parameters": [
{ {
@ -50189,7 +50189,7 @@
}, },
"/api/streams/{name}/_fork": { "/api/streams/{name}/_fork": {
"post": { "post": {
"description": "Forks a wired stream and creates a child stream", "description": "Forks a wired stream and creates a child stream<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-fork", "operationId": "post-streams-name-fork",
"parameters": [ "parameters": [
{ {
@ -50374,7 +50374,7 @@
}, },
"/api/streams/{name}/_group": { "/api/streams/{name}/_group": {
"get": { "get": {
"description": "Fetches the group settings of a group stream definition", "description": "Fetches the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-group", "operationId": "get-streams-name-group",
"parameters": [ "parameters": [
{ {
@ -50418,7 +50418,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Upserts the group settings of a group stream definition", "description": "Upserts the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-group", "operationId": "put-streams-name-group",
"parameters": [ "parameters": [
{ {
@ -50484,7 +50484,7 @@
}, },
"/api/streams/{name}/_ingest": { "/api/streams/{name}/_ingest": {
"get": { "get": {
"description": "Fetches the ingest settings of an ingest stream definition", "description": "Fetches the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-ingest", "operationId": "get-streams-name-ingest",
"parameters": [ "parameters": [
{ {
@ -50528,7 +50528,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Upserts the ingest settings of an ingest stream definition", "description": "Upserts the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-ingest", "operationId": "put-streams-name-ingest",
"parameters": [ "parameters": [
{ {
@ -53705,7 +53705,7 @@
}, },
"/api/streams/{name}/content/export": { "/api/streams/{name}/content/export": {
"post": { "post": {
"description": "Exports the content associated to a stream.", "description": "Exports the content associated to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-content-export", "operationId": "post-streams-name-content-export",
"parameters": [ "parameters": [
{ {
@ -53812,7 +53812,7 @@
}, },
"/api/streams/{name}/content/import": { "/api/streams/{name}/content/import": {
"post": { "post": {
"description": "Links content objects to a stream.", "description": "Links content objects to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-content-import", "operationId": "post-streams-name-content-import",
"parameters": [ "parameters": [
{ {
@ -53863,7 +53863,7 @@
}, },
"/api/streams/{name}/dashboards": { "/api/streams/{name}/dashboards": {
"get": { "get": {
"description": "Fetches all dashboards linked to a stream that are visible to the current user in the current space.", "description": "Fetches all dashboards linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-dashboards", "operationId": "get-streams-name-dashboards",
"parameters": [ "parameters": [
{ {
@ -53909,7 +53909,7 @@
}, },
"/api/streams/{name}/dashboards/_bulk": { "/api/streams/{name}/dashboards/_bulk": {
"post": { "post": {
"description": "Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones.", "description": "Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-dashboards-bulk", "operationId": "post-streams-name-dashboards-bulk",
"parameters": [ "parameters": [
{ {
@ -54005,7 +54005,7 @@
}, },
"/api/streams/{name}/dashboards/{dashboardId}": { "/api/streams/{name}/dashboards/{dashboardId}": {
"delete": { "delete": {
"description": "Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream.", "description": "Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "delete-streams-name-dashboards-dashboardid", "operationId": "delete-streams-name-dashboards-dashboardid",
"parameters": [ "parameters": [
{ {
@ -54067,7 +54067,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Links a dashboard to a stream. Noop if the dashboard is already linked to the stream.", "description": "Links a dashboard to a stream. Noop if the dashboard is already linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-dashboards-dashboardid", "operationId": "put-streams-name-dashboards-dashboardid",
"parameters": [ "parameters": [
{ {
@ -54131,7 +54131,7 @@
}, },
"/api/streams/{name}/queries": { "/api/streams/{name}/queries": {
"get": { "get": {
"description": "Fetches all queries linked to a stream that are visible to the current user in the current space.", "description": "Fetches all queries linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-queries", "operationId": "get-streams-name-queries",
"parameters": [ "parameters": [
{ {
@ -54177,7 +54177,7 @@
}, },
"/api/streams/{name}/queries/_bulk": { "/api/streams/{name}/queries/_bulk": {
"post": { "post": {
"description": "Bulk update queries of a stream. Can add new queries and delete existing ones.", "description": "Bulk update queries of a stream. Can add new queries and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "post-streams-name-queries-bulk", "operationId": "post-streams-name-queries-bulk",
"parameters": [ "parameters": [
{ {
@ -54303,7 +54303,7 @@
}, },
"/api/streams/{name}/queries/{queryId}": { "/api/streams/{name}/queries/{queryId}": {
"delete": { "delete": {
"description": "Remove a query from a stream. Noop if the query is not found on the stream.", "description": "Remove a query from a stream. Noop if the query is not found on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "delete-streams-name-queries-queryid", "operationId": "delete-streams-name-queries-queryid",
"parameters": [ "parameters": [
{ {
@ -54365,7 +54365,7 @@
"x-state": "Technical Preview" "x-state": "Technical Preview"
}, },
"put": { "put": {
"description": "Adds a query to a stream. Noop if the query is already present on the stream.", "description": "Adds a query to a stream. Noop if the query is already present on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.",
"operationId": "put-streams-name-queries-queryid", "operationId": "put-streams-name-queries-queryid",
"parameters": [ "parameters": [
{ {
@ -54438,7 +54438,7 @@
}, },
"/api/streams/{name}/significant_events": { "/api/streams/{name}/significant_events": {
"get": { "get": {
"description": "Read the significant events", "description": "Read the significant events<br/><br/>[Required authorization] Route required privileges: read_stream.",
"operationId": "get-streams-name-significant-events", "operationId": "get-streams-name-significant-events",
"parameters": [ "parameters": [
{ {

View file

@ -44091,7 +44091,7 @@ paths:
- system - system
/api/streams: /api/streams:
get: get:
description: Fetches list of all streams description: 'Fetches list of all streams<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams operationId: get-streams
parameters: [] parameters: []
requestBody: requestBody:
@ -44113,7 +44113,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/_disable: /api/streams/_disable:
post: post:
description: Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved. description: 'Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-disable operationId: post-streams-disable
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -44142,7 +44142,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/_enable: /api/streams/_enable:
post: post:
description: Enables wired streams description: 'Enables wired streams<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-enable operationId: post-streams-enable
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -44171,7 +44171,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/_resync: /api/streams/_resync:
post: post:
description: Resyncs all streams, making sure that Elasticsearch assets are up to date description: 'Resyncs all streams, making sure that Elasticsearch assets are up to date<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-resync operationId: post-streams-resync
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -44200,7 +44200,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}: /api/streams/{name}:
delete: delete:
description: Deletes a stream definition and the underlying data stream description: 'Deletes a stream definition and the underlying data stream<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: delete-streams-name operationId: delete-streams-name
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -44233,7 +44233,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
get: get:
description: Fetches a stream definition and associated dashboards description: 'Fetches a stream definition and associated dashboards<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name operationId: get-streams-name
parameters: parameters:
- in: path - in: path
@ -44259,7 +44259,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Creates or updates a stream definition. Classic streams can not be created through this API, only updated description: 'Creates or updates a stream definition. Classic streams can not be created through this API, only updated<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name operationId: put-streams-name
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -46380,7 +46380,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/_fork: /api/streams/{name}/_fork:
post: post:
description: Forks a wired stream and creates a child stream description: 'Forks a wired stream and creates a child stream<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-fork operationId: post-streams-name-fork
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -46498,7 +46498,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/_group: /api/streams/{name}/_group:
get: get:
description: Fetches the group settings of a group stream definition description: 'Fetches the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-group operationId: get-streams-name-group
parameters: parameters:
- in: path - in: path
@ -46524,7 +46524,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Upserts the group settings of a group stream definition description: 'Upserts the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-group operationId: put-streams-name-group
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -46568,7 +46568,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/_ingest: /api/streams/{name}/_ingest:
get: get:
description: Fetches the ingest settings of an ingest stream definition description: 'Fetches the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-ingest operationId: get-streams-name-ingest
parameters: parameters:
- in: path - in: path
@ -46594,7 +46594,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Upserts the ingest settings of an ingest stream definition description: 'Upserts the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-ingest operationId: put-streams-name-ingest
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48564,7 +48564,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/content/export: /api/streams/{name}/content/export:
post: post:
description: Exports the content associated to a stream. description: 'Exports the content associated to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-content-export operationId: post-streams-name-content-export
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48634,7 +48634,7 @@ paths:
- streams - streams
/api/streams/{name}/content/import: /api/streams/{name}/content/import:
post: post:
description: Links content objects to a stream. description: 'Links content objects to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-content-import operationId: post-streams-name-content-import
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48668,7 +48668,7 @@ paths:
- streams - streams
/api/streams/{name}/dashboards: /api/streams/{name}/dashboards:
get: get:
description: Fetches all dashboards linked to a stream that are visible to the current user in the current space. description: 'Fetches all dashboards linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-dashboards operationId: get-streams-name-dashboards
parameters: parameters:
- in: path - in: path
@ -48695,7 +48695,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/dashboards/_bulk: /api/streams/{name}/dashboards/_bulk:
post: post:
description: Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones. description: 'Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-dashboards-bulk operationId: post-streams-name-dashboards-bulk
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48756,7 +48756,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/dashboards/{dashboardId}: /api/streams/{name}/dashboards/{dashboardId}:
delete: delete:
description: Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream. description: 'Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: delete-streams-name-dashboards-dashboardid operationId: delete-streams-name-dashboards-dashboardid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48794,7 +48794,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Links a dashboard to a stream. Noop if the dashboard is already linked to the stream. description: 'Links a dashboard to a stream. Noop if the dashboard is already linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-dashboards-dashboardid operationId: put-streams-name-dashboards-dashboardid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48833,7 +48833,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/queries: /api/streams/{name}/queries:
get: get:
description: Fetches all queries linked to a stream that are visible to the current user in the current space. description: 'Fetches all queries linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-queries operationId: get-streams-name-queries
parameters: parameters:
- in: path - in: path
@ -48860,7 +48860,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/queries/_bulk: /api/streams/{name}/queries/_bulk:
post: post:
description: Bulk update queries of a stream. Can add new queries and delete existing ones. description: 'Bulk update queries of a stream. Can add new queries and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-queries-bulk operationId: post-streams-name-queries-bulk
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48939,7 +48939,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/queries/{queryId}: /api/streams/{name}/queries/{queryId}:
delete: delete:
description: Remove a query from a stream. Noop if the query is not found on the stream. description: 'Remove a query from a stream. Noop if the query is not found on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: delete-streams-name-queries-queryid operationId: delete-streams-name-queries-queryid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -48977,7 +48977,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Adds a query to a stream. Noop if the query is already present on the stream. description: 'Adds a query to a stream. Noop if the query is already present on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-queries-queryid operationId: put-streams-name-queries-queryid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -49026,7 +49026,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/significant_events: /api/streams/{name}/significant_events:
get: get:
description: Read the significant events description: 'Read the significant events<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-significant-events operationId: get-streams-name-significant-events
parameters: parameters:
- in: path - in: path

View file

@ -47613,7 +47613,7 @@ paths:
- system - system
/api/streams: /api/streams:
get: get:
description: Fetches list of all streams description: 'Fetches list of all streams<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams operationId: get-streams
parameters: [] parameters: []
requestBody: requestBody:
@ -47635,7 +47635,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/_disable: /api/streams/_disable:
post: post:
description: Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved. description: 'Disables wired streams and deletes all existing stream definitions. The data of wired streams is deleted, but the data of classic streams is preserved.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-disable operationId: post-streams-disable
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -47664,7 +47664,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/_enable: /api/streams/_enable:
post: post:
description: Enables wired streams description: 'Enables wired streams<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-enable operationId: post-streams-enable
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -47693,7 +47693,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/_resync: /api/streams/_resync:
post: post:
description: Resyncs all streams, making sure that Elasticsearch assets are up to date description: 'Resyncs all streams, making sure that Elasticsearch assets are up to date<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-resync operationId: post-streams-resync
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -47722,7 +47722,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}: /api/streams/{name}:
delete: delete:
description: Deletes a stream definition and the underlying data stream description: 'Deletes a stream definition and the underlying data stream<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: delete-streams-name operationId: delete-streams-name
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -47755,7 +47755,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
get: get:
description: Fetches a stream definition and associated dashboards description: 'Fetches a stream definition and associated dashboards<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name operationId: get-streams-name
parameters: parameters:
- in: path - in: path
@ -47781,7 +47781,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Creates or updates a stream definition. Classic streams can not be created through this API, only updated description: 'Creates or updates a stream definition. Classic streams can not be created through this API, only updated<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name operationId: put-streams-name
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -49902,7 +49902,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/_fork: /api/streams/{name}/_fork:
post: post:
description: Forks a wired stream and creates a child stream description: 'Forks a wired stream and creates a child stream<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-fork operationId: post-streams-name-fork
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -50020,7 +50020,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/_group: /api/streams/{name}/_group:
get: get:
description: Fetches the group settings of a group stream definition description: 'Fetches the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-group operationId: get-streams-name-group
parameters: parameters:
- in: path - in: path
@ -50046,7 +50046,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Upserts the group settings of a group stream definition description: 'Upserts the group settings of a group stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-group operationId: put-streams-name-group
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -50090,7 +50090,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/_ingest: /api/streams/{name}/_ingest:
get: get:
description: Fetches the ingest settings of an ingest stream definition description: 'Fetches the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-ingest operationId: get-streams-name-ingest
parameters: parameters:
- in: path - in: path
@ -50116,7 +50116,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Upserts the ingest settings of an ingest stream definition description: 'Upserts the ingest settings of an ingest stream definition<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-ingest operationId: put-streams-name-ingest
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52086,7 +52086,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/content/export: /api/streams/{name}/content/export:
post: post:
description: Exports the content associated to a stream. description: 'Exports the content associated to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-content-export operationId: post-streams-name-content-export
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52156,7 +52156,7 @@ paths:
- streams - streams
/api/streams/{name}/content/import: /api/streams/{name}/content/import:
post: post:
description: Links content objects to a stream. description: 'Links content objects to a stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-content-import operationId: post-streams-name-content-import
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52190,7 +52190,7 @@ paths:
- streams - streams
/api/streams/{name}/dashboards: /api/streams/{name}/dashboards:
get: get:
description: Fetches all dashboards linked to a stream that are visible to the current user in the current space. description: 'Fetches all dashboards linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-dashboards operationId: get-streams-name-dashboards
parameters: parameters:
- in: path - in: path
@ -52217,7 +52217,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/dashboards/_bulk: /api/streams/{name}/dashboards/_bulk:
post: post:
description: Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones. description: 'Bulk update dashboards linked to a stream. Can link new dashboards and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-dashboards-bulk operationId: post-streams-name-dashboards-bulk
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52278,7 +52278,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/dashboards/{dashboardId}: /api/streams/{name}/dashboards/{dashboardId}:
delete: delete:
description: Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream. description: 'Unlinks a dashboard from a stream. Noop if the dashboard is not linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: delete-streams-name-dashboards-dashboardid operationId: delete-streams-name-dashboards-dashboardid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52316,7 +52316,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Links a dashboard to a stream. Noop if the dashboard is already linked to the stream. description: 'Links a dashboard to a stream. Noop if the dashboard is already linked to the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-dashboards-dashboardid operationId: put-streams-name-dashboards-dashboardid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52355,7 +52355,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/queries: /api/streams/{name}/queries:
get: get:
description: Fetches all queries linked to a stream that are visible to the current user in the current space. description: 'Fetches all queries linked to a stream that are visible to the current user in the current space.<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-queries operationId: get-streams-name-queries
parameters: parameters:
- in: path - in: path
@ -52382,7 +52382,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/queries/_bulk: /api/streams/{name}/queries/_bulk:
post: post:
description: Bulk update queries of a stream. Can add new queries and delete existing ones. description: 'Bulk update queries of a stream. Can add new queries and delete existing ones.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: post-streams-name-queries-bulk operationId: post-streams-name-queries-bulk
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52461,7 +52461,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/queries/{queryId}: /api/streams/{name}/queries/{queryId}:
delete: delete:
description: Remove a query from a stream. Noop if the query is not found on the stream. description: 'Remove a query from a stream. Noop if the query is not found on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: delete-streams-name-queries-queryid operationId: delete-streams-name-queries-queryid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52499,7 +52499,7 @@ paths:
- streams - streams
x-state: Technical Preview x-state: Technical Preview
put: put:
description: Adds a query to a stream. Noop if the query is already present on the stream. description: 'Adds a query to a stream. Noop if the query is already present on the stream.<br/><br/>[Required authorization] Route required privileges: manage_stream.'
operationId: put-streams-name-queries-queryid operationId: put-streams-name-queries-queryid
parameters: parameters:
- description: A required header to protect against CSRF attacks - description: A required header to protect against CSRF attacks
@ -52548,7 +52548,7 @@ paths:
x-state: Technical Preview x-state: Technical Preview
/api/streams/{name}/significant_events: /api/streams/{name}/significant_events:
get: get:
description: Read the significant events description: 'Read the significant events<br/><br/>[Required authorization] Route required privileges: read_stream.'
operationId: get-streams-name-significant-events operationId: get-streams-name-significant-events
parameters: parameters:
- in: path - in: path

View file

@ -6,3 +6,13 @@
*/ */
export const ASSET_VERSION = 1; export const ASSET_VERSION = 1;
export const STREAMS_API_PRIVILEGES = {
read: 'read_stream',
manage: 'manage_stream',
} as const;
export const STREAMS_UI_PRIVILEGES = {
manage: 'manage',
show: 'show',
} as const;

View file

@ -18,7 +18,8 @@
"licensing", "licensing",
"taskManager", "taskManager",
"alerting", "alerting",
"inference" "inference",
"features",
], ],
"optionalPlugins": [ "optionalPlugins": [
"cloud", "cloud",

View file

@ -11,6 +11,8 @@ import { StreamsPluginSetup, StreamsPluginStart } from './types';
export type { StreamsPluginSetup, StreamsPluginStart }; export type { StreamsPluginSetup, StreamsPluginStart };
export { STREAMS_API_PRIVILEGES, STREAMS_UI_PRIVILEGES } from '../common/constants';
export const plugin: PluginInitializer<StreamsPluginSetup, StreamsPluginStart> = ( export const plugin: PluginInitializer<StreamsPluginSetup, StreamsPluginStart> = (
context: PluginInitializerContext context: PluginInitializerContext
) => { ) => {

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { CoreSetup, CoreStart, PluginInitializerContext } from '@kbn/core/public'; import { ApplicationStart, CoreSetup, CoreStart, PluginInitializerContext } from '@kbn/core/public';
import { Logger } from '@kbn/logging'; import { Logger } from '@kbn/logging';
import { createRepositoryClient } from '@kbn/server-route-repository-client'; import { createRepositoryClient } from '@kbn/server-route-repository-client';
@ -35,15 +35,18 @@ export class Plugin implements StreamsPluginClass {
setup(core: CoreSetup, pluginSetup: StreamsPluginSetupDependencies): StreamsPluginSetup { setup(core: CoreSetup, pluginSetup: StreamsPluginSetupDependencies): StreamsPluginSetup {
this.repositoryClient = createRepositoryClient(core); this.repositoryClient = createRepositoryClient(core);
return { return {};
status$: createStreamsStatusObservable(pluginSetup, this.repositoryClient, this.logger),
};
} }
start(core: CoreStart, pluginsStart: StreamsPluginStartDependencies): StreamsPluginStart { start(core: CoreStart, pluginsStart: StreamsPluginStartDependencies): StreamsPluginStart {
return { return {
streamsRepositoryClient: this.repositoryClient, streamsRepositoryClient: this.repositoryClient,
status$: createStreamsStatusObservable(pluginsStart, this.repositoryClient, this.logger), status$: createStreamsStatusObservable(
pluginsStart,
core.application,
this.repositoryClient,
this.logger
),
}; };
} }
@ -57,12 +60,19 @@ const UNKNOWN_STATUS: StreamsStatus = { status: 'unknown' };
const createStreamsStatusObservable = once( const createStreamsStatusObservable = once(
( (
deps: StreamsPluginSetupDependencies | StreamsPluginStartDependencies, deps: StreamsPluginSetupDependencies | StreamsPluginStartDependencies,
application: ApplicationStart,
repositoryClient: StreamsRepositoryClient, repositoryClient: StreamsRepositoryClient,
logger: Logger logger: Logger
): Observable<StreamsStatus> => { ): Observable<StreamsStatus> => {
const isObservabilityServerless = const isObservabilityServerless =
deps.cloud?.isServerlessEnabled && deps.cloud?.serverless.projectType === 'observability'; deps.cloud?.isServerlessEnabled && deps.cloud?.serverless.projectType === 'observability';
const hasCapabilities = application.capabilities?.streams?.show;
if (!hasCapabilities) {
return from([DISABLED_STATUS]);
}
if (isObservabilityServerless) { if (isObservabilityServerless) {
return from([ENABLED_STATUS]); return from([ENABLED_STATUS]);
} }

View file

@ -14,9 +14,8 @@ export interface StreamsStatus {
status: 'unknown' | 'enabled' | 'disabled'; status: 'unknown' | 'enabled' | 'disabled';
} }
export interface StreamsPluginSetup { // eslint-disable-next-line @typescript-eslint/no-empty-interface
status$: Observable<StreamsStatus>; export interface StreamsPluginSetup {}
}
export interface StreamsPluginStart { export interface StreamsPluginStart {
streamsRepositoryClient: StreamsRepositoryClient; streamsRepositoryClient: StreamsRepositoryClient;

View file

@ -8,6 +8,7 @@
import { import {
CoreSetup, CoreSetup,
CoreStart, CoreStart,
DEFAULT_APP_CATEGORIES,
KibanaRequest, KibanaRequest,
Logger, Logger,
Plugin, Plugin,
@ -15,6 +16,8 @@ import {
PluginInitializerContext, PluginInitializerContext,
} from '@kbn/core/server'; } from '@kbn/core/server';
import { registerRoutes } from '@kbn/server-route-repository'; import { registerRoutes } from '@kbn/server-route-repository';
import { KibanaFeatureScope } from '@kbn/features-plugin/common';
import { i18n } from '@kbn/i18n';
import { StreamsConfig, configSchema, exposeToBrowserConfig } from '../common/config'; import { StreamsConfig, configSchema, exposeToBrowserConfig } from '../common/config';
import { streamsRouteRepository } from './routes'; import { streamsRouteRepository } from './routes';
import { import {
@ -26,6 +29,7 @@ import { AssetService } from './lib/streams/assets/asset_service';
import { RouteHandlerScopedClients } from './routes/types'; import { RouteHandlerScopedClients } from './routes/types';
import { StreamsService } from './lib/streams/service'; import { StreamsService } from './lib/streams/service';
import { StreamsTelemetryService } from './lib/telemetry/service'; import { StreamsTelemetryService } from './lib/telemetry/service';
import { STREAMS_API_PRIVILEGES, STREAMS_UI_PRIVILEGES } from '../common/constants';
// eslint-disable-next-line @typescript-eslint/no-empty-interface // eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface StreamsPluginSetup {} export interface StreamsPluginSetup {}
@ -72,6 +76,37 @@ export class StreamsPlugin
const assetService = new AssetService(core, this.logger); const assetService = new AssetService(core, this.logger);
const streamsService = new StreamsService(core, this.logger, this.isDev); const streamsService = new StreamsService(core, this.logger, this.isDev);
plugins.features.registerKibanaFeature({
id: 'streams',
name: i18n.translate('xpack.streams.featureRegistry.streamsFeatureName', {
defaultMessage: 'Streams',
}),
order: 600,
category: DEFAULT_APP_CATEGORIES.observability,
scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security],
app: ['streams'],
privileges: {
all: {
app: ['streams'],
savedObject: {
all: [],
read: [],
},
api: [STREAMS_API_PRIVILEGES.read, STREAMS_API_PRIVILEGES.manage],
ui: [STREAMS_UI_PRIVILEGES.show, STREAMS_UI_PRIVILEGES.manage],
},
read: {
app: ['streams'],
savedObject: {
all: [],
read: [],
},
api: [STREAMS_API_PRIVILEGES.read],
ui: [STREAMS_UI_PRIVILEGES.show],
},
},
});
registerRoutes({ registerRoutes({
repository: streamsRouteRepository, repository: streamsRouteRepository,
dependencies: { dependencies: {

View file

@ -14,6 +14,7 @@ import {
contentPackIncludedObjectsSchema, contentPackIncludedObjectsSchema,
isIncludeAll, isIncludeAll,
} from '@kbn/content-packs-schema'; } from '@kbn/content-packs-schema';
import { STREAMS_API_PRIVILEGES } from '../../../common/constants';
import { Asset } from '../../../common'; import { Asset } from '../../../common';
import { DashboardAsset, DashboardLink } from '../../../common/assets'; import { DashboardAsset, DashboardLink } from '../../../common/assets';
import { createServerRoute } from '../create_server_route'; import { createServerRoute } from '../create_server_route';
@ -50,9 +51,7 @@ const exportContentRoute = createServerRoute({
}), }),
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
async handler({ params, request, response, getScopedClients, context }) { async handler({ params, request, response, getScopedClients, context }) {
@ -134,9 +133,7 @@ const importContentRoute = createServerRoute({
}), }),
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
async handler({ params, request, getScopedClients, context }) { async handler({ params, request, getScopedClients, context }) {
@ -210,8 +207,7 @@ const previewContentRoute = createServerRoute({
}), }),
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason: 'This API does not use any user credentials.',
}, },
}, },
async handler({ params }) { async handler({ params }) {

View file

@ -8,6 +8,7 @@
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { ErrorCause } from '@elastic/elasticsearch/lib/api/types'; import { ErrorCause } from '@elastic/elasticsearch/lib/api/types';
import { internal } from '@hapi/boom'; import { internal } from '@hapi/boom';
import { STREAMS_API_PRIVILEGES } from '../../../common/constants';
import { Asset, DashboardAsset } from '../../../common/assets'; import { Asset, DashboardAsset } from '../../../common/assets';
import { createServerRoute } from '../create_server_route'; import { createServerRoute } from '../create_server_route';
import { ASSET_ID, ASSET_TYPE } from '../../lib/streams/assets/fields'; import { ASSET_ID, ASSET_TYPE } from '../../lib/streams/assets/fields';
@ -66,9 +67,7 @@ const listDashboardsRoute = createServerRoute({
}), }),
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
async handler({ params, request, getScopedClients }): Promise<ListDashboardsResponse> { async handler({ params, request, getScopedClients }): Promise<ListDashboardsResponse> {
@ -104,9 +103,7 @@ const linkDashboardRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -147,9 +144,7 @@ const unlinkDashboardRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -185,9 +180,7 @@ const suggestDashboardsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -244,9 +237,7 @@ const bulkDashboardsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -6,6 +6,7 @@
*/ */
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { DashboardAsset } from '../../../../common/assets'; import { DashboardAsset } from '../../../../common/assets';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
import { SanitizedDashboardAsset } from '../../dashboards/route'; import { SanitizedDashboardAsset } from '../../dashboards/route';
@ -30,9 +31,7 @@ const suggestDashboardsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -8,6 +8,7 @@
import { UnparsedEsqlResponse, createTracedEsClient } from '@kbn/traced-es-client'; import { UnparsedEsqlResponse, createTracedEsClient } from '@kbn/traced-es-client';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { isNumber } from 'lodash'; import { isNumber } from 'lodash';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
import { excludeFrozenQuery, kqlQuery, rangeQuery } from './query_helpers'; import { excludeFrozenQuery, kqlQuery, rangeQuery } from './query_helpers';
@ -18,9 +19,7 @@ export const executeEsqlRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -10,6 +10,7 @@ import { StreamDefinition, isGroupStreamDefinition } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { estypes } from '@elastic/elasticsearch'; import { estypes } from '@elastic/elasticsearch';
import { UnwiredIngestStreamEffectiveLifecycle } from '@kbn/streams-schema'; import { UnwiredIngestStreamEffectiveLifecycle } from '@kbn/streams-schema';
import { STREAMS_API_PRIVILEGES } from '../../../../../common/constants';
import { createServerRoute } from '../../../create_server_route'; import { createServerRoute } from '../../../create_server_route';
import { getDataStreamLifecycle } from '../../../../lib/streams/stream_crud'; import { getDataStreamLifecycle } from '../../../../lib/streams/stream_crud';
@ -27,9 +28,7 @@ export const listStreamsRoute = createServerRoute({
params: z.object({}), params: z.object({}),
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
handler: async ({ request, getScopedClients }): Promise<{ streams: ListStreamDetail[] }> => { handler: async ({ request, getScopedClients }): Promise<{ streams: ListStreamDetail[] }> => {
@ -66,9 +65,7 @@ export const streamDetailRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -118,9 +115,7 @@ export const resolveIndexRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -7,6 +7,7 @@
import { isIlmLifecycle, isIngestStreamDefinition } from '@kbn/streams-schema'; import { isIlmLifecycle, isIngestStreamDefinition } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../../common/constants';
import { createServerRoute } from '../../../create_server_route'; import { createServerRoute } from '../../../create_server_route';
import { ilmPhases } from '../../../../lib/streams/lifecycle/ilm_phases'; import { ilmPhases } from '../../../../lib/streams/lifecycle/ilm_phases';
import { getEffectiveLifecycle } from '../../../../lib/streams/lifecycle/get_effective_lifecycle'; import { getEffectiveLifecycle } from '../../../../lib/streams/lifecycle/get_effective_lifecycle';
@ -19,9 +20,7 @@ const lifecycleStatsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -62,9 +61,7 @@ const lifecycleIlmExplainRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -13,6 +13,7 @@ import {
isUnwiredStreamDefinition, isUnwiredStreamDefinition,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../../common/constants';
import { SecurityError } from '../../../../lib/streams/errors/security_error'; import { SecurityError } from '../../../../lib/streams/errors/security_error';
import { WrongStreamTypeError } from '../../../../lib/streams/errors/wrong_stream_type_error'; import { WrongStreamTypeError } from '../../../../lib/streams/errors/wrong_stream_type_error';
import { import {
@ -29,9 +30,7 @@ export const sampleStreamRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -111,9 +110,7 @@ export const unmanagedAssetDetailsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -12,6 +12,7 @@ import {
processorWithIdDefinitionSchema, processorWithIdDefinitionSchema,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../../common/constants';
import { SecurityError } from '../../../../lib/streams/errors/security_error'; import { SecurityError } from '../../../../lib/streams/errors/security_error';
import { checkAccess } from '../../../../lib/streams/stream_crud'; import { checkAccess } from '../../../../lib/streams/stream_crud';
import { createServerRoute } from '../../../create_server_route'; import { createServerRoute } from '../../../create_server_route';
@ -34,9 +35,7 @@ export const simulateProcessorRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: paramsSchema, params: paramsSchema,
@ -76,9 +75,7 @@ export const processingSuggestionRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: suggestionsParamsSchema, params: suggestionsParamsSchema,

View file

@ -11,6 +11,7 @@ import {
isWiredStreamDefinition, isWiredStreamDefinition,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../../common/constants';
import { SecurityError } from '../../../../lib/streams/errors/security_error'; import { SecurityError } from '../../../../lib/streams/errors/security_error';
import { checkAccess } from '../../../../lib/streams/stream_crud'; import { checkAccess } from '../../../../lib/streams/stream_crud';
import { createServerRoute } from '../../../create_server_route'; import { createServerRoute } from '../../../create_server_route';
@ -24,9 +25,7 @@ export const unmappedFieldsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -91,9 +90,7 @@ export const schemaFieldsSimulationRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -13,6 +13,7 @@ import {
upsertStreamQueryRequestSchema, upsertStreamQueryRequestSchema,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../common/constants';
import { ASSET_ID, ASSET_TYPE } from '../../lib/streams/assets/fields'; import { ASSET_ID, ASSET_TYPE } from '../../lib/streams/assets/fields';
import { createServerRoute } from '../create_server_route'; import { createServerRoute } from '../create_server_route';
export interface ListQueriesResponse { export interface ListQueriesResponse {
@ -47,9 +48,7 @@ const listQueriesRoute = createServerRoute({
}), }),
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
async handler({ params, request, getScopedClients }): Promise<ListQueriesResponse> { async handler({ params, request, getScopedClients }): Promise<ListQueriesResponse> {
@ -80,12 +79,9 @@ const upsertQueryRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
path: z.object({ path: z.object({
name: z.string(), name: z.string(),
@ -132,9 +128,7 @@ const deleteQueryRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -175,9 +169,7 @@ const bulkQueriesRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -13,6 +13,7 @@ import {
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { badData } from '@hapi/boom'; import { badData } from '@hapi/boom';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { UpsertStreamResponse } from '../../../lib/streams/client'; import { UpsertStreamResponse } from '../../../lib/streams/client';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
import { readStream } from './read_stream'; import { readStream } from './read_stream';
@ -29,9 +30,7 @@ export const readStreamRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -65,9 +64,7 @@ export const listStreamsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({}), params: z.object({}),
@ -92,9 +89,7 @@ export const editStreamRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -130,9 +125,7 @@ export const deleteStreamRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -7,6 +7,7 @@
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { conflict } from '@hapi/boom'; import { conflict } from '@hapi/boom';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { NameTakenError } from '../../../lib/streams/errors/name_taken_error'; import { NameTakenError } from '../../../lib/streams/errors/name_taken_error';
import { DisableStreamsResponse, EnableStreamsResponse } from '../../../lib/streams/client'; import { DisableStreamsResponse, EnableStreamsResponse } from '../../../lib/streams/client';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
@ -24,9 +25,7 @@ export const enableStreamsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
handler: async ({ request, getScopedClients }): Promise<EnableStreamsResponse> => { handler: async ({ request, getScopedClients }): Promise<EnableStreamsResponse> => {
@ -60,9 +59,7 @@ export const disableStreamsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
handler: async ({ request, getScopedClients }): Promise<DisableStreamsResponse> => { handler: async ({ request, getScopedClients }): Promise<DisableStreamsResponse> => {

View file

@ -13,6 +13,7 @@ import {
GroupStreamUpsertRequest, GroupStreamUpsertRequest,
isGroupStreamDefinition, isGroupStreamDefinition,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
import { ASSET_TYPE, ASSET_UUID } from '../../../lib/streams/assets/fields'; import { ASSET_TYPE, ASSET_UUID } from '../../../lib/streams/assets/fields';
import { QueryAsset } from '../../../../common/assets'; import { QueryAsset } from '../../../../common/assets';
@ -29,9 +30,7 @@ const readGroupRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions',
}, },
}, },
params: z.object({ params: z.object({
@ -66,9 +65,7 @@ const upsertGroupRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -14,6 +14,7 @@ import {
isWiredStreamDefinition, isWiredStreamDefinition,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
import { ASSET_ID, ASSET_TYPE } from '../../../lib/streams/assets/fields'; import { ASSET_ID, ASSET_TYPE } from '../../../lib/streams/assets/fields';
import { QueryAsset } from '../../../../common/assets'; import { QueryAsset } from '../../../../common/assets';
@ -30,9 +31,7 @@ const readIngestRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -71,9 +70,7 @@ const upsertIngestRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({

View file

@ -7,6 +7,7 @@
import { conditionSchema } from '@kbn/streams-schema'; import { conditionSchema } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { ResyncStreamsResponse } from '../../../lib/streams/client'; import { ResyncStreamsResponse } from '../../../lib/streams/client';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
@ -22,9 +23,7 @@ export const forkStreamsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({ params: z.object({
@ -58,9 +57,7 @@ export const resyncStreamsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.manage],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
params: z.object({}), params: z.object({}),
@ -78,9 +75,7 @@ export const getStreamsStatusRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
handler: async ({ request, getScopedClients }): Promise<{ enabled: boolean }> => { handler: async ({ request, getScopedClients }): Promise<{ enabled: boolean }> => {

View file

@ -8,6 +8,7 @@
import { badRequest } from '@hapi/boom'; import { badRequest } from '@hapi/boom';
import { SignificantEventsGetResponse } from '@kbn/streams-schema'; import { SignificantEventsGetResponse } from '@kbn/streams-schema';
import { z } from '@kbn/zod'; import { z } from '@kbn/zod';
import { STREAMS_API_PRIVILEGES } from '../../../../common/constants';
import { createServerRoute } from '../../create_server_route'; import { createServerRoute } from '../../create_server_route';
import { readSignificantEvents } from './read_significant_events'; import { readSignificantEvents } from './read_significant_events';
@ -28,9 +29,7 @@ export const readSignificantEventsRoute = createServerRoute({
}, },
security: { security: {
authz: { authz: {
enabled: false, requiredPrivileges: [STREAMS_API_PRIVILEGES.read],
reason:
'This API delegates security to the currently logged in user and their Elasticsearch permissions.',
}, },
}, },
handler: async ({ params, request, getScopedClients }): Promise<SignificantEventsGetResponse> => { handler: async ({ params, request, getScopedClients }): Promise<SignificantEventsGetResponse> => {

View file

@ -18,6 +18,7 @@ import type {
} from '@kbn/task-manager-plugin/server'; } from '@kbn/task-manager-plugin/server';
import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { AlertingServerSetup, AlertingServerStart } from '@kbn/alerting-plugin/server';
import type { InferenceServerStart } from '@kbn/inference-plugin/server'; import type { InferenceServerStart } from '@kbn/inference-plugin/server';
import { FeaturesPluginSetup } from '@kbn/features-plugin/server';
import type { StreamsConfig } from '../common/config'; import type { StreamsConfig } from '../common/config';
export interface StreamsServer { export interface StreamsServer {
core: CoreStart; core: CoreStart;
@ -37,6 +38,7 @@ export interface StreamsPluginSetupDependencies {
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
taskManager: TaskManagerSetupContract; taskManager: TaskManagerSetupContract;
alerting: AlertingServerSetup; alerting: AlertingServerSetup;
features: FeaturesPluginSetup;
} }
export interface StreamsPluginStartDependencies { export interface StreamsPluginStartDependencies {

View file

@ -45,6 +45,8 @@
"@kbn/fleet-plugin", "@kbn/fleet-plugin",
"@kbn/content-packs-schema", "@kbn/content-packs-schema",
"@kbn/cloud-plugin", "@kbn/cloud-plugin",
"@kbn/es-types" "@kbn/es-types",
"@kbn/features-plugin",
"@kbn/i18n"
] ]
} }

View file

@ -18,6 +18,7 @@ import { i18n } from '@kbn/i18n';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import type { SanitizedDashboardAsset } from '@kbn/streams-plugin/server/routes/dashboards/route'; import type { SanitizedDashboardAsset } from '@kbn/streams-plugin/server/routes/dashboards/route';
import { IngestStreamGetResponse } from '@kbn/streams-schema'; import { IngestStreamGetResponse } from '@kbn/streams-schema';
import { STREAMS_UI_PRIVILEGES } from '@kbn/streams-plugin/public';
import { AddDashboardFlyout } from './add_dashboard_flyout'; import { AddDashboardFlyout } from './add_dashboard_flyout';
import { DashboardsTable } from './dashboard_table'; import { DashboardsTable } from './dashboard_table';
import { useDashboardsApi } from '../../hooks/use_dashboards_api'; import { useDashboardsApi } from '../../hooks/use_dashboards_api';
@ -56,7 +57,14 @@ export function StreamDetailDashboardsView({
const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const { const {
core: { featureFlags }, core: {
featureFlags,
application: {
capabilities: {
streams: { [STREAMS_UI_PRIVILEGES.manage]: canLinkAssets },
},
},
},
} = useKibana(); } = useKibana();
const renderContentPackItems = featureFlags.getBooleanValue( const renderContentPackItems = featureFlags.getBooleanValue(
@ -124,6 +132,7 @@ export function StreamDetailDashboardsView({
iconType="importAction" iconType="importAction"
iconSide="left" iconSide="left"
color="primary" color="primary"
disabled={!canLinkAssets}
onClick={() => setIsPopoverOpen(true)} onClick={() => setIsPopoverOpen(true)}
> >
{i18n.translate( {i18n.translate(
@ -182,6 +191,7 @@ export function StreamDetailDashboardsView({
<EuiButton <EuiButton
data-test-subj="streamsAppStreamDetailAddDashboardButton" data-test-subj="streamsAppStreamDetailAddDashboardButton"
iconType="plusInCircle" iconType="plusInCircle"
disabled={!canLinkAssets}
onClick={() => { onClick={() => {
setIsAddDashboardFlyoutOpen(true); setIsAddDashboardFlyoutOpen(true);
}} }}
@ -199,7 +209,7 @@ export function StreamDetailDashboardsView({
dashboards={filteredDashboards} dashboards={filteredDashboards}
loading={dashboardsFetch.loading} loading={dashboardsFetch.loading}
selectedDashboards={selectedDashboards} selectedDashboards={selectedDashboards}
setSelectedDashboards={setSelectedDashboards} setSelectedDashboards={canLinkAssets ? setSelectedDashboards : undefined}
/> />
{definition && isAddDashboardFlyoutOpen ? ( {definition && isAddDashboardFlyoutOpen ? (
<AddDashboardFlyout <AddDashboardFlyout

View file

@ -13,7 +13,9 @@ import {
isUnwiredStreamGetResponse, isUnwiredStreamGetResponse,
} from '@kbn/streams-schema'; } from '@kbn/streams-schema';
import { EuiFlexGroup, EuiLoadingSpinner } from '@elastic/eui'; import { EuiFlexGroup, EuiLoadingSpinner } from '@elastic/eui';
import { STREAMS_UI_PRIVILEGES } from '@kbn/streams-plugin/public';
import { useStreamsAppFetch } from './use_streams_app_fetch'; import { useStreamsAppFetch } from './use_streams_app_fetch';
import { useKibana } from './use_kibana';
export interface StreamDetailContextProviderProps { export interface StreamDetailContextProviderProps {
name: string; name: string;
@ -33,6 +35,15 @@ export function StreamDetailContextProvider({
streamsRepositoryClient, streamsRepositoryClient,
children, children,
}: React.PropsWithChildren<StreamDetailContextProviderProps>) { }: React.PropsWithChildren<StreamDetailContextProviderProps>) {
const {
core: {
application: {
capabilities: {
streams: { [STREAMS_UI_PRIVILEGES.manage]: canManage },
},
},
},
} = useKibana();
const { const {
value: definition, value: definition,
loading, loading,
@ -50,13 +61,21 @@ export function StreamDetailContextProvider({
}) })
.then((response) => { .then((response) => {
if (isWiredStreamGetResponse(response) || isUnwiredStreamGetResponse(response)) { if (isWiredStreamGetResponse(response) || isUnwiredStreamGetResponse(response)) {
return response; return {
...response,
privileges: {
...response.privileges,
// restrict the manage privilege by the Elasticsearch-level data-stream specific privilege and the Kibana-level UI privilege
// the UI should only enable manage features if the user has privileges on both levels for the current stream
manage: response.privileges.manage && canManage,
},
};
} }
throw new Error('Stream detail only supports IngestStreams.'); throw new Error('Stream detail only supports IngestStreams.');
}); });
}, },
[streamsRepositoryClient, name] [streamsRepositoryClient, name, canManage]
); );
const context = React.useMemo( const context = React.useMemo(

View file

@ -27,7 +27,7 @@ import {
} from '@kbn/observability-ai-assistant-plugin/public'; } from '@kbn/observability-ai-assistant-plugin/public';
import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public'; import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public';
import type { SharePublicSetup, SharePublicStart } from '@kbn/share-plugin/public/plugin'; import type { SharePublicSetup, SharePublicStart } from '@kbn/share-plugin/public/plugin';
import type { StreamsPluginSetup, StreamsPluginStart } from '@kbn/streams-plugin/public'; import type { StreamsPluginStart } from '@kbn/streams-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
/* eslint-disable @typescript-eslint/no-empty-interface*/ /* eslint-disable @typescript-eslint/no-empty-interface*/
@ -46,7 +46,6 @@ export interface StreamsAppSetupDependencies {
discoverShared: DiscoverSharedPublicSetup; discoverShared: DiscoverSharedPublicSetup;
observabilityAIAssistant: ObservabilityAIAssistantPublicSetup; observabilityAIAssistant: ObservabilityAIAssistantPublicSetup;
share: SharePublicSetup; share: SharePublicSetup;
streams: StreamsPluginSetup;
unifiedSearch: {}; unifiedSearch: {};
} }

View file

@ -120,6 +120,7 @@ export default function ({ getService }: FtrProviderContext) {
'ml', 'ml',
'apm', 'apm',
'stackAlerts', 'stackAlerts',
'streams',
'canvas', 'canvas',
'generalCasesV3', 'generalCasesV3',
'infrastructure', 'infrastructure',
@ -179,6 +180,7 @@ export default function ({ getService }: FtrProviderContext) {
'ml', 'ml',
'apm', 'apm',
'stackAlerts', 'stackAlerts',
'streams',
'canvas', 'canvas',
'generalCasesV3', 'generalCasesV3',
'infrastructure', 'infrastructure',

View file

@ -6,7 +6,7 @@
*/ */
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { map } from 'rxjs'; import { from, map, switchMap } from 'rxjs';
import { import {
AppUpdater, AppUpdater,
CoreSetup, CoreSetup,
@ -85,8 +85,12 @@ export class ObservabilityStreamsWrapperPlugin
>, >,
pluginsSetup: ObservabilityStreamsWrapperSetupDependencies pluginsSetup: ObservabilityStreamsWrapperSetupDependencies
): ObservabilityStreamsWrapperPublicSetup { ): ObservabilityStreamsWrapperPublicSetup {
const startServicesPromise = coreSetup.getStartServices();
pluginsSetup.observabilityShared.navigation.registerSections( pluginsSetup.observabilityShared.navigation.registerSections(
pluginsSetup.streams.status$.pipe( from(startServicesPromise).pipe(
switchMap(([_, pluginsStart]) =>
pluginsStart.streams.status$.pipe(
map(({ status }) => { map(({ status }) => {
if (status !== 'enabled') { if (status !== 'enabled') {
return []; return [];
@ -113,6 +117,8 @@ export class ObservabilityStreamsWrapperPlugin
]; ];
}) })
) )
)
)
); );
coreSetup.application.register({ coreSetup.application.register({
@ -124,7 +130,9 @@ export class ObservabilityStreamsWrapperPlugin
appRoute: '/app/streams', appRoute: '/app/streams',
category: DEFAULT_APP_CATEGORIES.observability, category: DEFAULT_APP_CATEGORIES.observability,
order: 8001, order: 8001,
updater$: pluginsSetup.streams.status$.pipe( updater$: from(startServicesPromise).pipe(
switchMap(([_, pluginsStart]) =>
pluginsStart.streams.status$.pipe(
map(({ status }): AppUpdater => { map(({ status }): AppUpdater => {
return (app) => { return (app) => {
if (status !== 'enabled') { if (status !== 'enabled') {
@ -138,6 +146,8 @@ export class ObservabilityStreamsWrapperPlugin
}; };
}; };
}) })
)
)
), ),
mount: async (appMountParameters: AppMountParameters<unknown>) => { mount: async (appMountParameters: AppMountParameters<unknown>) => {
// Load application bundle and Get start services // Load application bundle and Get start services

View file

@ -13,7 +13,7 @@ import type {
ObservabilitySharedPluginSetup, ObservabilitySharedPluginSetup,
ObservabilitySharedPluginStart, ObservabilitySharedPluginStart,
} from '@kbn/observability-shared-plugin/public'; } from '@kbn/observability-shared-plugin/public';
import type { StreamsPluginSetup, StreamsPluginStart } from '@kbn/streams-plugin/public'; import type { StreamsPluginStart } from '@kbn/streams-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { SharePublicSetup, SharePublicStart } from '@kbn/share-plugin/public/plugin'; import type { SharePublicSetup, SharePublicStart } from '@kbn/share-plugin/public/plugin';
import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public'; import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public';
@ -29,7 +29,6 @@ import { StreamsAppPublicSetup, StreamsAppPublicStart } from '@kbn/streams-app-p
export interface ConfigSchema {} export interface ConfigSchema {}
export interface ObservabilityStreamsWrapperSetupDependencies { export interface ObservabilityStreamsWrapperSetupDependencies {
streams: StreamsPluginSetup;
streamsApp: StreamsAppPublicSetup; streamsApp: StreamsAppPublicSetup;
dataViews: DataViewsPublicPluginSetup; dataViews: DataViewsPublicPluginSetup;
observabilityShared: ObservabilitySharedPluginSetup; observabilityShared: ObservabilitySharedPluginSetup;

View file

@ -280,6 +280,7 @@ export default function ({ getService }: FtrProviderContext) {
'readFlappingSettings', 'readFlappingSettings',
], ],
maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'], maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'],
streams: ['all', 'read', 'minimal_all', 'minimal_read'],
guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'], guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'],
aiAssistantManagementSelection: ['all', 'read', 'minimal_all', 'minimal_read'], aiAssistantManagementSelection: ['all', 'read', 'minimal_all', 'minimal_read'],
inventory: ['all', 'read', 'minimal_all', 'minimal_read'], inventory: ['all', 'read', 'minimal_all', 'minimal_read'],

View file

@ -75,6 +75,7 @@ export default function ({ getService }: FtrProviderContext) {
filesSharedImage: ['all', 'read', 'minimal_all', 'minimal_read'], filesSharedImage: ['all', 'read', 'minimal_all', 'minimal_read'],
rulesSettings: ['all', 'read', 'minimal_all', 'minimal_read'], rulesSettings: ['all', 'read', 'minimal_all', 'minimal_read'],
maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'], maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'],
streams: ['all', 'read', 'minimal_all', 'minimal_read'],
guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'], guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'],
aiAssistantManagementSelection: ['all', 'read', 'minimal_all', 'minimal_read'], aiAssistantManagementSelection: ['all', 'read', 'minimal_all', 'minimal_read'],
inventory: ['all', 'read', 'minimal_all', 'minimal_read'], inventory: ['all', 'read', 'minimal_all', 'minimal_read'],
@ -380,6 +381,7 @@ export default function ({ getService }: FtrProviderContext) {
'readFlappingSettings', 'readFlappingSettings',
], ],
maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'], maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'],
streams: ['all', 'read', 'minimal_all', 'minimal_read'],
guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'], guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'],
aiAssistantManagementSelection: ['all', 'read', 'minimal_all', 'minimal_read'], aiAssistantManagementSelection: ['all', 'read', 'minimal_all', 'minimal_read'],
inventory: ['all', 'read', 'minimal_all', 'minimal_read'], inventory: ['all', 'read', 'minimal_all', 'minimal_read'],

View file

@ -102,6 +102,7 @@ export function createTestSuiteFactory({ getService }: DeploymentAgnosticFtrProv
'siem', 'siem',
'siemV2', 'siemV2',
'slo', 'slo',
'streams',
'uptime', 'uptime',
], ],
solution: 'es', solution: 'es',

View file

@ -106,6 +106,7 @@ export function getTestSuiteFactory(context: DeploymentAgnosticFtrProviderContex
'siem', 'siem',
'siemV2', 'siemV2',
'slo', 'slo',
'streams',
'uptime', 'uptime',
], ],
}), }),

View file

@ -94,6 +94,7 @@ const ALL_SPACE_RESULTS: Space[] = [
'siem', 'siem',
'siemV2', 'siemV2',
'slo', 'slo',
'streams',
'uptime', 'uptime',
], ],
solution: 'es', solution: 'es',

View file

@ -65,6 +65,7 @@ export default function ({ getService }: FtrProviderContext) {
rulesSettings: 0, rulesSettings: 0,
maintenanceWindow: 0, maintenanceWindow: 0,
stackAlerts: 0, stackAlerts: 0,
streams: 0,
generalCases: 0, generalCases: 0,
generalCasesV2: 0, generalCasesV2: 0,
generalCasesV3: 0, generalCasesV3: 0,