From b5fd84b6067568ef9af201bbedd5ed2846f61068 Mon Sep 17 00:00:00 2001 From: jakubp-eliatra Date: Wed, 5 Jul 2023 14:38:29 +0200 Subject: [PATCH 01/12] merge conflict resolved Signed-off-by: jakubp-eliatra --- config/opensearch_dashboards.yml | 266 ------------------ src/core/types/capabilities.ts | 2 +- .../server/capabilities_provider.ts | 1 + src/plugins/console/server/plugin.ts | 1 + .../dashboard/server/capabilities_provider.ts | 1 + .../index_patterns/capabilities_provider.ts | 1 + .../discover/server/capabilities_provider.ts | 1 + .../server/capabilities_provider.ts | 1 + .../visualize/server/capabilities_provider.ts | 1 + 9 files changed, 8 insertions(+), 267 deletions(-) delete mode 100644 config/opensearch_dashboards.yml diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml deleted file mode 100644 index d7e0d390b0fc..000000000000 --- a/config/opensearch_dashboards.yml +++ /dev/null @@ -1,266 +0,0 @@ -# OpenSearch Dashboards is served by a back end server. This setting specifies the port to use. -#server.port: 5601 - -# Specifies the address to which the OpenSearch Dashboards server will bind. IP addresses and host names are both valid values. -# The default is 'localhost', which usually means remote machines will not be able to connect. -# To allow connections from remote users, set this parameter to a non-loopback address. -#server.host: "localhost" - -# Enables you to specify a path to mount OpenSearch Dashboards at if you are running behind a proxy. -# Use the `server.rewriteBasePath` setting to tell OpenSearch Dashboards if it should remove the basePath -# from requests it receives, and to prevent a deprecation warning at startup. -# This setting cannot end in a slash. -#server.basePath: "" - -# Specifies whether OpenSearch Dashboards should rewrite requests that are prefixed with -# `server.basePath` or require that they are rewritten by your reverse proxy. -#server.rewriteBasePath: false - -# The maximum payload size in bytes for incoming server requests. -#server.maxPayloadBytes: 1048576 - -# The OpenSearch Dashboards server's name. This is used for display purposes. -#server.name: "your-hostname" - -# The URLs of the OpenSearch instances to use for all your queries. -#opensearch.hosts: ["http://localhost:9200"] - -# OpenSearch Dashboards uses an index in OpenSearch to store saved searches, visualizations and -# dashboards. OpenSearch Dashboards creates a new index if the index doesn't already exist. -#opensearchDashboards.index: ".opensearch_dashboards" - -# The default application to load. -#opensearchDashboards.defaultAppId: "home" - -# Setting for an optimized healthcheck that only uses the local OpenSearch node to do Dashboards healthcheck. -# This settings should be used for large clusters or for clusters with ingest heavy nodes. -# It allows Dashboards to only healthcheck using the local OpenSearch node rather than fan out requests across all nodes. -# -# It requires the user to create an OpenSearch node attribute with the same name as the value used in the setting -# This node attribute should assign all nodes of the same cluster an integer value that increments with each new cluster that is spun up -# e.g. in opensearch.yml file you would set the value to a setting using node.attr.cluster_id: -# Should only be enabled if there is a corresponding node attribute created in your OpenSearch config that matches the value here -#opensearch.optimizedHealthcheck.id: "cluster_id" -#opensearch.optimizedHealthcheck.filters: { -# attribute_key: "attribute_value", -#} - -# If your OpenSearch is protected with basic authentication, these settings provide -# the username and password that the OpenSearch Dashboards server uses to perform maintenance on the OpenSearch Dashboards -# index at startup. Your OpenSearch Dashboards users still need to authenticate with OpenSearch, which -# is proxied through the OpenSearch Dashboards server. -#opensearch.username: "opensearch_dashboards_system" -#opensearch.password: "pass" - -# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively. -# These settings enable SSL for outgoing requests from the OpenSearch Dashboards server to the browser. -#server.ssl.enabled: false -#server.ssl.certificate: /path/to/your/server.crt -#server.ssl.key: /path/to/your/server.key - -# Optional settings that provide the paths to the PEM-format SSL certificate and key files. -# These files are used to verify the identity of OpenSearch Dashboards to OpenSearch and are required when -# xpack.security.http.ssl.client_authentication in OpenSearch is set to required. -#opensearch.ssl.certificate: /path/to/your/client.crt -#opensearch.ssl.key: /path/to/your/client.key - -# Optional setting that enables you to specify a path to the PEM file for the certificate -# authority for your OpenSearch instance. -#opensearch.ssl.certificateAuthorities: [ "/path/to/your/CA.pem" ] - -# To disregard the validity of SSL certificates, change this setting's value to 'none'. -#opensearch.ssl.verificationMode: full - -# Time in milliseconds to wait for OpenSearch to respond to pings. Defaults to the value of -# the opensearch.requestTimeout setting. -#opensearch.pingTimeout: 1500 - -# Time in milliseconds to wait for responses from the back end or OpenSearch. This value -# must be a positive integer. -#opensearch.requestTimeout: 30000 - -# Enables the memory circuit breaker that prevents heap out of memory errors for large query responses. -# If enabled, we will provide additional check to prevent potential out of memory error in @openserach-project/opensearch. -# The default threshold is based on the `max-old-space-size` of NodeJS. It is configurable by tuning `opensearch.memoryCircuitBreaker.maxPercentage`. -#opensearch.memoryCircuitBreaker.enabled: false - -# The pecentage of maximum heap allowed for processing response. The default value of the pecentage is `1.0`. The valid input range should be [0, 1] inclusively. -# For reference, the `threshold of memoryCircuitBreaker` = `max-old-space-size of NodeJS` * `opensearch.memoryCircuitBreaker.maxPercentage` -#opensearch.memoryCircuitBreaker.maxPercentage: 1.0 - -# DEPRECATED: Use opensearch.requestHeadersAllowlist -# List of OpenSearch Dashboards client-side headers to send to OpenSearch. To send *no* client-side -# headers, set this value to [] (an empty list). -#opensearch.requestHeadersWhitelist: [ authorization ] - -# List of OpenSearch Dashboards client-side headers to send to OpenSearch. To send *no* client-side -# headers, set this value to [] (an empty list). -#opensearch.requestHeadersAllowlist: [ authorization ] - -# Header names and values that are sent to OpenSearch. Any custom headers cannot be overwritten -# by client-side headers, regardless of the opensearch.requestHeadersAllowlist configuration. -#opensearch.customHeaders: {} - -# Time in milliseconds for OpenSearch to wait for responses from shards. Set to 0 to disable. -#opensearch.shardTimeout: 30000 - -# Logs queries sent to OpenSearch. Requires logging.verbose set to true. -#opensearch.logQueries: false - -# Disables errors from the OpenSearch JS client and enables you to utilize protected words such as: 'boolean', 'proto', 'constructor'. -# within cluster. By default, OpenSearch Dashboards and the client will protect you against prototype poisoning attacks. -# WARNING: Index patterns are user-supplied data. Disabling this will place the expectation that you are handling the data safely. -#opensearch.disablePrototypePoisoningProtection: false - -# Specifies the path where OpenSearch Dashboards creates the process ID file. -#pid.file: /var/run/opensearchDashboards.pid - -# Enables you to specify a file where OpenSearch Dashboards stores log output. -#logging.dest: stdout - -# Set the value of this setting to true to suppress all logging output. -#logging.silent: false - -# Set the value of this setting to true to suppress all logging output other than error messages. -#logging.quiet: false - -# Set the value of this setting to true to log all events, including system usage information -# and all requests. -#logging.verbose: false - -# Set the interval in milliseconds to sample system and process performance -# metrics. Minimum is 100ms. Defaults to 5000. -#ops.interval: 5000 - -# Specifies locale to be used for all localizable strings, dates and number formats. -# Supported languages are the following: English - en , by default , Chinese - zh-CN . -#i18n.locale: "en" - -# Set the allowlist to check input graphite Url. Allowlist is the default check list. -#vis_type_timeline.graphiteAllowedUrls: ['https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite'] - -# Set the denylist to check input graphite Url. Denylist is an IP list. -# Below is an example for reference - -# vis_type_timeline.graphiteBlockedIPs: [ -# //Loopback -# '127.0.0.0/8', -# '::1/128', -# //Link-local Address for IPv6 -# 'fe80::/10', -# //Private IP address for IPv4 -# '10.0.0.0/8', -# '172.16.0.0/12', -# '192.168.0.0/16', -# //Unique local address (ULA) -# 'fc00::/7', -# //Reserved IP address -# '0.0.0.0/8', -# '100.64.0.0/10', -# '192.0.0.0/24', -# '192.0.2.0/24', -# '198.18.0.0/15', -# '192.88.99.0/24', -# '198.51.100.0/24', -# '203.0.113.0/24', -# '224.0.0.0/4', -# '240.0.0.0/4', -# '255.255.255.255/32', -# '::/128', -# '2001:db8::/32', -# 'ff00::/8', -# ] - -# vis_type_timeline.graphiteDeniedIPs: [] - -# vis_type_timeline.graphiteDeniedIPs: [ -# //Loopback -# '127.0.0.0/8', -# '::1/128', -# //Link-local Address for IPv6 -# 'fe80::/10', -# //Private IP address for IPv4 -# '10.0.0.0/8', -# '172.16.0.0/12', -# '192.168.0.0/16', -# //Unique local address (ULA) -# 'fc00::/7', -# //Reserved IP address -# '0.0.0.0/8', -# '100.64.0.0/10', -# '192.0.0.0/24', -# '192.0.2.0/24', -# '198.18.0.0/15', -# '192.88.99.0/24', -# '198.51.100.0/24', -# '203.0.113.0/24', -# '224.0.0.0/4', -# '240.0.0.0/4', -# '255.255.255.255/32', -# '::/128', -# '2001:db8::/32', -# 'ff00::/8', -# ] - -# opensearchDashboards.branding: -# logo: -# defaultUrl: "" -# darkModeUrl: "" -# mark: -# defaultUrl: "" -# darkModeUrl: "" -# loadingLogo: -# defaultUrl: "" -# darkModeUrl: "" -# faviconUrl: "" -# applicationTitle: "" -# useExpandedHeader: false - -# Set the value of this setting to true to capture region denied warnings and errors -# for your map rendering services. - -# map.showRegionDeniedWarning: false - -# Set the value of this setting to false to suppress search usage telemetry -# for reducing the load of OpenSearch cluster. -# data.search.usageTelemetry.enabled: false - -# Set the value of this setting to false to disable VisBuilder -# functionality in Visualization. -# vis_builder.enabled: false - -# Set the value of this setting to true to enable multiple data source feature. -#data_source.enabled: false -# Set the value of these settings to customize crypto materials to encryption saved credentials -# in data sources. -#data_source.encryption.wrappingKeyName: 'changeme' -#data_source.encryption.wrappingKeyNamespace: 'changeme' -#data_source.encryption.wrappingKey: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - -#data_source.endpointDeniedIPs: [ -# '127.0.0.0/8', -# '::1/128', -# '169.254.0.0/16', -# 'fe80::/10', -# '10.0.0.0/8', -# '172.16.0.0/12', -# '192.168.0.0/16', -# 'fc00::/7', -# '0.0.0.0/8', -# '100.64.0.0/10', -# '192.0.0.0/24', -# '192.0.2.0/24', -# '198.18.0.0/15', -# '192.88.99.0/24', -# '198.51.100.0/24', -# '203.0.113.0/24', -# '224.0.0.0/4', -# '240.0.0.0/4', -# '255.255.255.255/32', -# '::/128', -# '2001:db8::/32', -# 'ff00::/8', -# ] - -# Set the value of this setting to false to hide the help menu link to the OpenSearch Dashboards user survey -# opensearchDashboards.survey.url: "https://survey.opensearch.org" diff --git a/src/core/types/capabilities.ts b/src/core/types/capabilities.ts index a4d4b59b2a4e..f8bb43c61738 100644 --- a/src/core/types/capabilities.ts +++ b/src/core/types/capabilities.ts @@ -48,5 +48,5 @@ export interface Capabilities { catalogue: Record; /** Custom capabilities, registered by plugins. */ - [key: string]: Record>; + [key: string]: Record>; } diff --git a/src/plugins/advanced_settings/server/capabilities_provider.ts b/src/plugins/advanced_settings/server/capabilities_provider.ts index be87d687d4b9..198ba0f6d3d2 100644 --- a/src/plugins/advanced_settings/server/capabilities_provider.ts +++ b/src/plugins/advanced_settings/server/capabilities_provider.ts @@ -32,5 +32,6 @@ export const capabilitiesProvider = () => ({ advancedSettings: { show: true, save: true, + hide_for_read_only: ['save'], }, }); diff --git a/src/plugins/console/server/plugin.ts b/src/plugins/console/server/plugin.ts index 4c33bc1d6060..11b5bf7baed5 100644 --- a/src/plugins/console/server/plugin.ts +++ b/src/plugins/console/server/plugin.ts @@ -55,6 +55,7 @@ export class ConsoleServerPlugin implements Plugin { dev_tools: { show: true, save: true, + hide_for_read_only: ['save'], }, })); diff --git a/src/plugins/dashboard/server/capabilities_provider.ts b/src/plugins/dashboard/server/capabilities_provider.ts index e0ae2a183c47..93062bb143f0 100644 --- a/src/plugins/dashboard/server/capabilities_provider.ts +++ b/src/plugins/dashboard/server/capabilities_provider.ts @@ -34,5 +34,6 @@ export const capabilitiesProvider = () => ({ show: true, showWriteControls: true, saveQuery: true, + hide_for_read_only: ['createNew', 'showWriteControls', 'saveQuery'], }, }); diff --git a/src/plugins/data/server/index_patterns/capabilities_provider.ts b/src/plugins/data/server/index_patterns/capabilities_provider.ts index 0f040faccceb..8da03f14a1da 100644 --- a/src/plugins/data/server/index_patterns/capabilities_provider.ts +++ b/src/plugins/data/server/index_patterns/capabilities_provider.ts @@ -31,5 +31,6 @@ export const capabilitiesProvider = () => ({ indexPatterns: { save: true, + hide_for_read_only: ['save'], }, }); diff --git a/src/plugins/discover/server/capabilities_provider.ts b/src/plugins/discover/server/capabilities_provider.ts index ecbefd8f4bb8..0f75f7a18650 100644 --- a/src/plugins/discover/server/capabilities_provider.ts +++ b/src/plugins/discover/server/capabilities_provider.ts @@ -34,5 +34,6 @@ export const capabilitiesProvider = () => ({ createShortUrl: true, save: true, saveQuery: true, + hide_for_read_only: ['createShortUrl', 'save', 'saveQuery'], }, }); diff --git a/src/plugins/saved_objects_management/server/capabilities_provider.ts b/src/plugins/saved_objects_management/server/capabilities_provider.ts index c97893b0aa17..ab4f22eb04a7 100644 --- a/src/plugins/saved_objects_management/server/capabilities_provider.ts +++ b/src/plugins/saved_objects_management/server/capabilities_provider.ts @@ -33,5 +33,6 @@ export const capabilitiesProvider = () => ({ delete: true, edit: true, read: true, + hide_for_read_only: ['delete', 'edit'], }, }); diff --git a/src/plugins/visualize/server/capabilities_provider.ts b/src/plugins/visualize/server/capabilities_provider.ts index 961b2ff6ed5d..0f2be34162ae 100644 --- a/src/plugins/visualize/server/capabilities_provider.ts +++ b/src/plugins/visualize/server/capabilities_provider.ts @@ -35,5 +35,6 @@ export const capabilitiesProvider = () => ({ delete: true, save: true, saveQuery: true, + hide_for_read_only: ['createShortUrl', 'delete', 'save', 'saveQuery'], }, }); From 34b6105c2f7a760dbfbfdd13b4e8620c83bbcc91 Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Fri, 14 Jul 2023 11:19:18 +0200 Subject: [PATCH 02/12] Restore config/opensearch_dashboards.yml Signed-off-by: Kajetan Nobel --- config/opensearch_dashboards.yml | 270 +++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 config/opensearch_dashboards.yml diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml new file mode 100644 index 000000000000..73f31233a783 --- /dev/null +++ b/config/opensearch_dashboards.yml @@ -0,0 +1,270 @@ +# OpenSearch Dashboards is served by a back end server. This setting specifies the port to use. +#server.port: 5601 + +# Specifies the address to which the OpenSearch Dashboards server will bind. IP addresses and host names are both valid values. +# The default is 'localhost', which usually means remote machines will not be able to connect. +# To allow connections from remote users, set this parameter to a non-loopback address. +#server.host: "localhost" + +# Enables you to specify a path to mount OpenSearch Dashboards at if you are running behind a proxy. +# Use the `server.rewriteBasePath` setting to tell OpenSearch Dashboards if it should remove the basePath +# from requests it receives, and to prevent a deprecation warning at startup. +# This setting cannot end in a slash. +#server.basePath: "" + +# Specifies whether OpenSearch Dashboards should rewrite requests that are prefixed with +# `server.basePath` or require that they are rewritten by your reverse proxy. +#server.rewriteBasePath: false + +# The maximum payload size in bytes for incoming server requests. +#server.maxPayloadBytes: 1048576 + +# The OpenSearch Dashboards server's name. This is used for display purposes. +#server.name: "your-hostname" + +# The URLs of the OpenSearch instances to use for all your queries. +#opensearch.hosts: ["http://localhost:9200"] + +# OpenSearch Dashboards uses an index in OpenSearch to store saved searches, visualizations and +# dashboards. OpenSearch Dashboards creates a new index if the index doesn't already exist. +#opensearchDashboards.index: ".opensearch_dashboards" + +# The default application to load. +#opensearchDashboards.defaultAppId: "home" + +# Setting for an optimized healthcheck that only uses the local OpenSearch node to do Dashboards healthcheck. +# This settings should be used for large clusters or for clusters with ingest heavy nodes. +# It allows Dashboards to only healthcheck using the local OpenSearch node rather than fan out requests across all nodes. +# +# It requires the user to create an OpenSearch node attribute with the same name as the value used in the setting +# This node attribute should assign all nodes of the same cluster an integer value that increments with each new cluster that is spun up +# e.g. in opensearch.yml file you would set the value to a setting using node.attr.cluster_id: +# Should only be enabled if there is a corresponding node attribute created in your OpenSearch config that matches the value here +#opensearch.optimizedHealthcheck.id: "cluster_id" +#opensearch.optimizedHealthcheck.filters: { +# attribute_key: "attribute_value", +#} + +# If your OpenSearch is protected with basic authentication, these settings provide +# the username and password that the OpenSearch Dashboards server uses to perform maintenance on the OpenSearch Dashboards +# index at startup. Your OpenSearch Dashboards users still need to authenticate with OpenSearch, which +# is proxied through the OpenSearch Dashboards server. +#opensearch.username: "opensearch_dashboards_system" +#opensearch.password: "pass" + +# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively. +# These settings enable SSL for outgoing requests from the OpenSearch Dashboards server to the browser. +#server.ssl.enabled: false +#server.ssl.certificate: /path/to/your/server.crt +#server.ssl.key: /path/to/your/server.key + +# Optional settings that provide the paths to the PEM-format SSL certificate and key files. +# These files are used to verify the identity of OpenSearch Dashboards to OpenSearch and are required when +# xpack.security.http.ssl.client_authentication in OpenSearch is set to required. +#opensearch.ssl.certificate: /path/to/your/client.crt +#opensearch.ssl.key: /path/to/your/client.key + +# Optional setting that enables you to specify a path to the PEM file for the certificate +# authority for your OpenSearch instance. +#opensearch.ssl.certificateAuthorities: [ "/path/to/your/CA.pem" ] + +# To disregard the validity of SSL certificates, change this setting's value to 'none'. +#opensearch.ssl.verificationMode: full + +# Time in milliseconds to wait for OpenSearch to respond to pings. Defaults to the value of +# the opensearch.requestTimeout setting. +#opensearch.pingTimeout: 1500 + +# Time in milliseconds to wait for responses from the back end or OpenSearch. This value +# must be a positive integer. +#opensearch.requestTimeout: 30000 + +# Enables the memory circuit breaker that prevents heap out of memory errors for large query responses. +# If enabled, we will provide additional check to prevent potential out of memory error in @openserach-project/opensearch. +# The default threshold is based on the `max-old-space-size` of NodeJS. It is configurable by tuning `opensearch.memoryCircuitBreaker.maxPercentage`. +#opensearch.memoryCircuitBreaker.enabled: false + +# The pecentage of maximum heap allowed for processing response. The default value of the pecentage is `1.0`. The valid input range should be [0, 1] inclusively. +# For reference, the `threshold of memoryCircuitBreaker` = `max-old-space-size of NodeJS` * `opensearch.memoryCircuitBreaker.maxPercentage` +#opensearch.memoryCircuitBreaker.maxPercentage: 1.0 + +# DEPRECATED: Use opensearch.requestHeadersAllowlist +# List of OpenSearch Dashboards client-side headers to send to OpenSearch. To send *no* client-side +# headers, set this value to [] (an empty list). +#opensearch.requestHeadersWhitelist: [ authorization ] + +# List of OpenSearch Dashboards client-side headers to send to OpenSearch. To send *no* client-side +# headers, set this value to [] (an empty list). +#opensearch.requestHeadersAllowlist: [ authorization ] + +# Header names and values that are sent to OpenSearch. Any custom headers cannot be overwritten +# by client-side headers, regardless of the opensearch.requestHeadersAllowlist configuration. +#opensearch.customHeaders: {} + +# Time in milliseconds for OpenSearch to wait for responses from shards. Set to 0 to disable. +#opensearch.shardTimeout: 30000 + +# Logs queries sent to OpenSearch. Requires logging.verbose set to true. +#opensearch.logQueries: false + +# Disables errors from the OpenSearch JS client and enables you to utilize protected words such as: 'boolean', 'proto', 'constructor'. +# within cluster. By default, OpenSearch Dashboards and the client will protect you against prototype poisoning attacks. +# WARNING: Index patterns are user-supplied data. Disabling this will place the expectation that you are handling the data safely. +#opensearch.disablePrototypePoisoningProtection: false + +# Specifies the path where OpenSearch Dashboards creates the process ID file. +#pid.file: /var/run/opensearchDashboards.pid + +# Enables you to specify a file where OpenSearch Dashboards stores log output. +#logging.dest: stdout + +# Set the value of this setting to true to suppress all logging output. +#logging.silent: false + +# Set the value of this setting to true to suppress all logging output other than error messages. +#logging.quiet: false + +# Set the value of this setting to true to log all events, including system usage information +# and all requests. +#logging.verbose: false + +# Set the interval in milliseconds to sample system and process performance +# metrics. Minimum is 100ms. Defaults to 5000. +#ops.interval: 5000 + +# Specifies locale to be used for all localizable strings, dates and number formats. +# Supported languages are the following: English - en , by default , Chinese - zh-CN . +#i18n.locale: "en" + +# Set the allowlist to check input graphite Url. Allowlist is the default check list. +#vis_type_timeline.graphiteAllowedUrls: ['https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite'] + +# Set the denylist to check input graphite Url. Denylist is an IP list. +# Below is an example for reference + +# vis_type_timeline.graphiteBlockedIPs: [ +# //Loopback +# '127.0.0.0/8', +# '::1/128', +# //Link-local Address for IPv6 +# 'fe80::/10', +# //Private IP address for IPv4 +# '10.0.0.0/8', +# '172.16.0.0/12', +# '192.168.0.0/16', +# //Unique local address (ULA) +# 'fc00::/7', +# //Reserved IP address +# '0.0.0.0/8', +# '100.64.0.0/10', +# '192.0.0.0/24', +# '192.0.2.0/24', +# '198.18.0.0/15', +# '192.88.99.0/24', +# '198.51.100.0/24', +# '203.0.113.0/24', +# '224.0.0.0/4', +# '240.0.0.0/4', +# '255.255.255.255/32', +# '::/128', +# '2001:db8::/32', +# 'ff00::/8', +# ] + +# vis_type_timeline.graphiteDeniedIPs: [] + +# vis_type_timeline.graphiteDeniedIPs: [ +# //Loopback +# '127.0.0.0/8', +# '::1/128', +# //Link-local Address for IPv6 +# 'fe80::/10', +# //Private IP address for IPv4 +# '10.0.0.0/8', +# '172.16.0.0/12', +# '192.168.0.0/16', +# //Unique local address (ULA) +# 'fc00::/7', +# //Reserved IP address +# '0.0.0.0/8', +# '100.64.0.0/10', +# '192.0.0.0/24', +# '192.0.2.0/24', +# '198.18.0.0/15', +# '192.88.99.0/24', +# '198.51.100.0/24', +# '203.0.113.0/24', +# '224.0.0.0/4', +# '240.0.0.0/4', +# '255.255.255.255/32', +# '::/128', +# '2001:db8::/32', +# 'ff00::/8', +# ] + +# opensearchDashboards.branding: +# logo: +# defaultUrl: "" +# darkModeUrl: "" +# mark: +# defaultUrl: "" +# darkModeUrl: "" +# loadingLogo: +# defaultUrl: "" +# darkModeUrl: "" +# faviconUrl: "" +# applicationTitle: "" +# useExpandedHeader: false + +# Set the value of this setting to true to capture region denied warnings and errors +# for your map rendering services. + +# map.showRegionDeniedWarning: false + +# Set the value of this setting to false to suppress search usage telemetry +# for reducing the load of OpenSearch cluster. +# data.search.usageTelemetry.enabled: false + +# Set the value of this setting to false to disable VisBuilder +# functionality in Visualization. +# vis_builder.enabled: false + +# Set the value of this setting to true to enable multiple data source feature. +#data_source.enabled: false +# Set the value of these settings to customize crypto materials to encryption saved credentials +# in data sources. +#data_source.encryption.wrappingKeyName: 'changeme' +#data_source.encryption.wrappingKeyNamespace: 'changeme' +#data_source.encryption.wrappingKey: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + +#data_source.endpointDeniedIPs: [ +# '127.0.0.0/8', +# '::1/128', +# '169.254.0.0/16', +# 'fe80::/10', +# '10.0.0.0/8', +# '172.16.0.0/12', +# '192.168.0.0/16', +# 'fc00::/7', +# '0.0.0.0/8', +# '100.64.0.0/10', +# '192.0.0.0/24', +# '192.0.2.0/24', +# '198.18.0.0/15', +# '192.88.99.0/24', +# '198.51.100.0/24', +# '203.0.113.0/24', +# '224.0.0.0/4', +# '240.0.0.0/4', +# '255.255.255.255/32', +# '::/128', +# '2001:db8::/32', +# 'ff00::/8', +# ] + +# Set the value of this setting to false to hide the help menu link to the OpenSearch Dashboards user survey +# opensearchDashboards.survey.url: "https://survey.opensearch.org" + +# Set the value of this setting to true to enable plugin augmentation on Dashboard +# vis_augmenter.pluginAugmentationEnabled: true + From ad6bac06100bb57ad10e5ba9722a213f719f600c Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Fri, 14 Jul 2023 11:19:56 +0200 Subject: [PATCH 03/12] Fix capabilities tsc Signed-off-by: Kajetan Nobel --- src/core/public/application/application_service.tsx | 3 ++- src/core/types/capabilities.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index f6efbfac422e..62c13694e245 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -32,6 +32,7 @@ import React from 'react'; import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; import { map, shareReplay, takeUntil, distinctUntilChanged, filter } from 'rxjs/operators'; import { createBrowserHistory, History } from 'history'; +import { RecursiveReadonly } from '@osd/utility-types'; import { MountPoint } from '../types'; import { HttpSetup, HttpStart } from '../http'; @@ -73,7 +74,7 @@ interface StartDeps { // Mount functions with two arguments are assumed to expect deprecated `context` object. const isAppMountDeprecated = (mount: (...args: any[]) => any): mount is AppMountDeprecated => mount.length === 2; -function filterAvailable(m: Map, capabilities: Capabilities) { +function filterAvailable(m: Map, capabilities: RecursiveReadonly) { return new Map( [...m].filter( ([id]) => capabilities.navLinks[id] === undefined || capabilities.navLinks[id] === true diff --git a/src/core/types/capabilities.ts b/src/core/types/capabilities.ts index f8bb43c61738..860d788ca614 100644 --- a/src/core/types/capabilities.ts +++ b/src/core/types/capabilities.ts @@ -48,5 +48,5 @@ export interface Capabilities { catalogue: Record; /** Custom capabilities, registered by plugins. */ - [key: string]: Record>; + [key: string]: Record>; } From 3f7799a702c2a9dc15525ecaee59dbe84b99050c Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Fri, 28 Jul 2023 14:43:34 +0200 Subject: [PATCH 04/12] docs: read only tenant mode Signed-off-by: Kajetan Nobel --- DEVELOPER_GUIDE.md | 19 ++++++++ docs/capabilities/read_only_tenant_mode.md | 56 ++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 docs/capabilities/read_only_tenant_mode.md diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index ac26f4bcd8b2..29c607b14091 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -256,6 +256,25 @@ Options: $ yarn opensearch snapshot --version 2.2.0 -E cluster.name=test -E path.data=/tmp/opensearch-data --P org.opensearch.plugin:test-plugin:2.2.0.0 --P file:/home/user/opensearch-test-plugin-2.2.0.0.zip ``` +#### Read Only capabalities + +_This feature will only work if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled._ + +Whenever a plugin registers capabilities that should be limited (in other words, set to false) for read-only tenants, such capabilities should be listed in a separate capability called `hide_for_read_only` that is an array of strings, containing capabilities that are set to false whenever Dashboards Security Plugin detects a read-only tenant. + +For example: + +```js +export const capabilitiesProvider = () => ({ + indexPatterns: { + save: true, + hide_for_read_only: ['save'], + }, +}); +``` + +In this case, we might assume that a plugin relies on the `save` capability to limit saving changes somewhere in the UI. Therefore, this `save` capability is listed in the `hide_for_read_only` array and will be set to `false` whenever a read-only tenant is accessed. + ### Alternative - Run OpenSearch from tarball If you would like to run OpenSearch from the tarball, you'll need to download the minimal distribution, install it, and then run the executable. (You'll also need Java installed and the `JAVA_HOME` environmental variable set - see [OpenSearch developer guide](https://github.com/opensearch-project/OpenSearch/blob/main/DEVELOPER_GUIDE.md#install-prerequisites) for details). diff --git a/docs/capabilities/read_only_tenant_mode.md b/docs/capabilities/read_only_tenant_mode.md new file mode 100644 index 000000000000..dc58d0aa5772 --- /dev/null +++ b/docs/capabilities/read_only_tenant_mode.md @@ -0,0 +1,56 @@ +# Read Only Tenant Mode + +There are two distinct functionalities for "read-only" access in Dashboards. One of them is associated with roles and one is associated with tenants. Regarding the first one, the Dashboards Security plugin contains a feature of hiding all plugin navigation links except Dashboards and Visualizations when the logged-in user has a certain role. The second one is limiting Dashboards access rights via assigning a specific role to a tenant (therefore, making a tenant read-only). Due to past issues and the deprecation of the first functionality, using read-only tenants is now the recommended way to limit users' access to Dashboards. + +For more context, see [this group issues of problems connected with read-only roles](https://github.com/opensearch-project/security/issues/2701). + +## Read Only Tenant + +A read-only tenant looks like this: +``` +read_only_tenant_role: + tenant_permissions: + - tenant_patterns: + - "human_resources" + allowed_actions: + - "kibana_all_read" +``` + +If the `kibana_all_read` role is assigned (without `kibana_all_write`), a given tenant provides solely read-only access. + +Dashboards Security plugin recognizes the selection of read-only tenant after logging in and sets the capabilities associated with write access or showing write controls to false for a variety of plugins. This can be easily checked for example by trying to re-arrange some visualizations on Dashboards. Such action will be resulting in a 403 error due to limited read-only access. + +## Design + +Whenever a plugin registers capabilities that should be limited (in other words, set to false) for read-only tenants, such capabilities should be listed in a separate capability called `hide_for_read_only` that is an array of strings, containing capabilities that are set to false whenever Dashboards Security Plugin detects a read-only tenant. + +For example: +``` +export const capabilitiesProvider = () => ({ + indexPatterns: { + save: true, + hide_for_read_only: ['save'], + }, +}); +``` + +In this case, we might assume that a plugin relies on the `save` capability to limit saving changes somewhere in the UI. Therefore, this `save` capability is listed in the `hide_for_read_only` array and will be set to `false` whenever a read-only tenant is accessed. + +## Scope + +Affected plugins: +- `advanced_settings` (`save` capability) +- `console` (`save` capability) +- `dashboard` (`createNew`, `showWriteControls`, `saveQuery` capabilities) +- `index_patterns` (`save` capability) +- `discover` (`save` capability) +- `saved_objects_management` (`edit`, `delete` capabilities) +- `visualize` (`createShortUrl`, `delete`, `save`, `saveQuery` capabilities) + +## Requirements + +This feature will only work if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled. + +## Usage + +To set it up, you have to add Role's "Tenant permissions" a new tenant with `Read only` access. From 97ffecfa990a5ca123170c495a230c5185be367e Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Wed, 13 Sep 2023 07:25:03 +0200 Subject: [PATCH 05/12] feat: introduce security service in core and readonly service Signed-off-by: Kajetan Nobel --- src/core/server/index.ts | 3 + src/core/server/internal_types.ts | 2 + src/core/server/legacy/legacy_service.ts | 1 + src/core/server/plugins/plugin_context.ts | 1 + src/core/server/security/security_service.ts | 66 +++++++++++++++++++ src/core/server/security/types.ts | 47 +++++++++++++ src/core/server/server.ts | 9 +++ .../server/capabilities_provider.ts | 1 - .../advanced_settings/server/plugin.ts | 8 +++ src/plugins/console/server/plugin.ts | 11 +++- .../dashboard/server/capabilities_provider.ts | 1 - src/plugins/dashboard/server/plugin.ts | 9 +++ .../index_patterns/capabilities_provider.ts | 1 - .../index_patterns/index_patterns_service.ts | 7 ++ .../discover/server/capabilities_provider.ts | 1 - src/plugins/discover/server/plugin.ts | 9 +++ .../server/capabilities_provider.ts | 1 - .../saved_objects_management/server/plugin.ts | 10 ++- .../visualize/server/capabilities_provider.ts | 1 - src/plugins/visualize/server/plugin.ts | 11 ++++ 20 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 src/core/server/security/security_service.ts create mode 100644 src/core/server/security/types.ts diff --git a/src/core/server/index.ts b/src/core/server/index.ts index ca55cc8dc1d5..df272c474844 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -76,6 +76,7 @@ import { StatusServiceSetup } from './status'; import { Auditor, AuditTrailSetup, AuditTrailStart } from './audit_trail'; import { AppenderConfigType, appendersSchema, LoggingServiceSetup } from './logging'; import { CoreUsageDataStart } from './core_usage_data'; +import { SecurityServiceSetup } from './security/types'; // Because of #79265 we need to explicity import, then export these types for // scripts/telemetry_check.js to work as expected @@ -437,6 +438,8 @@ export interface CoreSetup Promise.resolve([coreStart, startDeps.plugins, {}]), + security: setupDeps.core.security, }; // eslint-disable-next-line @typescript-eslint/no-var-requires diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index ab028e169a71..39e9bef7e4f4 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -220,6 +220,7 @@ export function createPluginSetupContext( }, getStartServices: () => plugin.startDependencies, auditTrail: deps.auditTrail, + security: deps.security, }; } diff --git a/src/core/server/security/security_service.ts b/src/core/server/security/security_service.ts new file mode 100644 index 000000000000..250733bb3a08 --- /dev/null +++ b/src/core/server/security/security_service.ts @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreService } from '../../types'; +import { IReadOnlyService, InternalSecurityServiceSetup } from './types'; +import { CoreContext } from '../core_context'; +import { Logger } from '../logging'; + +export class SecurityService implements CoreService { + private logger: Logger; + private readonlyService?: IReadOnlyService; + + constructor(private readonly coreContext: CoreContext) { + this.logger = coreContext.logger.get('security-service'); + } + + public setup() { + this.logger.debug('Setting up Security service'); + + const securityService = this; + + return { + registerReadonlyService(service: IReadOnlyService) { + securityService.readonlyService = service; + }, + readonlyService() { + return securityService.readonlyService!; + }, + }; + } + + public start() { + this.logger.debug('Starting plugin'); + } + + public stop() { + this.logger.debug('Stopping plugin'); + } +} diff --git a/src/core/server/security/types.ts b/src/core/server/security/types.ts new file mode 100644 index 000000000000..955eb081adf5 --- /dev/null +++ b/src/core/server/security/types.ts @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Capabilities, OpenSearchDashboardsRequest } from '../index'; + +export interface SecurityServiceSetup { + registerReadonlyService(service: IReadOnlyService): void; + readonlyService(): IReadOnlyService; +} + +export type InternalSecurityServiceSetup = SecurityServiceSetup; + +export interface IReadOnlyService { + isReadonly(request: OpenSearchDashboardsRequest): Promise; + hideForReadonly( + request: OpenSearchDashboardsRequest, + capabilites: Capabilities, + hideCapabilities: Partial + ): Promise>; +} diff --git a/src/core/server/server.ts b/src/core/server/server.ts index d4c041725ac7..83ebbdf8938b 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -47,6 +47,7 @@ import { MetricsService, opsConfig } from './metrics'; import { CapabilitiesService } from './capabilities'; import { EnvironmentService, config as pidConfig } from './environment'; import { StatusService } from './status/status_service'; +import { SecurityService } from './security/security_service'; import { config as cspConfig } from './csp'; import { config as opensearchConfig } from './opensearch'; @@ -86,6 +87,7 @@ export class Server { private readonly coreApp: CoreApp; private readonly auditTrail: AuditTrailService; private readonly coreUsageData: CoreUsageDataService; + private readonly security: SecurityService; #pluginsInitialized?: boolean; private coreStart?: InternalCoreStart; @@ -118,6 +120,7 @@ export class Server { this.auditTrail = new AuditTrailService(core); this.logging = new LoggingService(core); this.coreUsageData = new CoreUsageDataService(core); + this.security = new SecurityService(core); } public async setup() { @@ -196,6 +199,8 @@ export class Server { loggingSystem: this.loggingSystem, }); + const securitySetup = this.security.setup(); + this.coreUsageData.setup({ metrics: metricsSetup }); const coreSetup: InternalCoreSetup = { @@ -212,6 +217,7 @@ export class Server { auditTrail: auditTrailSetup, logging: loggingSetup, metrics: metricsSetup, + security: securitySetup, }; const pluginsSetup = await this.plugins.setup(coreSetup); @@ -277,6 +283,8 @@ export class Server { await this.http.start(); + await this.security.start(); + startTransaction?.end(); return this.coreStart; } @@ -295,6 +303,7 @@ export class Server { await this.status.stop(); await this.logging.stop(); await this.auditTrail.stop(); + await this.security.stop(); } private registerCoreContext(coreSetup: InternalCoreSetup) { diff --git a/src/plugins/advanced_settings/server/capabilities_provider.ts b/src/plugins/advanced_settings/server/capabilities_provider.ts index 198ba0f6d3d2..be87d687d4b9 100644 --- a/src/plugins/advanced_settings/server/capabilities_provider.ts +++ b/src/plugins/advanced_settings/server/capabilities_provider.ts @@ -32,6 +32,5 @@ export const capabilitiesProvider = () => ({ advancedSettings: { show: true, save: true, - hide_for_read_only: ['save'], }, }); diff --git a/src/plugins/advanced_settings/server/plugin.ts b/src/plugins/advanced_settings/server/plugin.ts index 46ea4b3f8961..094d975acf91 100644 --- a/src/plugins/advanced_settings/server/plugin.ts +++ b/src/plugins/advanced_settings/server/plugin.ts @@ -49,6 +49,14 @@ export class AdvancedSettingsServerPlugin implements Plugin { core.capabilities.registerProvider(capabilitiesProvider); + core.capabilities.registerSwitcher(async (request, capabilites) => { + return await core.security.readonlyService().hideForReadonly(request, capabilites, { + advancedSettings: { + save: false, + }, + }); + }); + return {}; } diff --git a/src/plugins/console/server/plugin.ts b/src/plugins/console/server/plugin.ts index 11b5bf7baed5..fa89863198cb 100644 --- a/src/plugins/console/server/plugin.ts +++ b/src/plugins/console/server/plugin.ts @@ -50,15 +50,22 @@ export class ConsoleServerPlugin implements Plugin { this.log = this.ctx.logger.get(); } - async setup({ http, capabilities, getStartServices, opensearch }: CoreSetup) { + async setup({ http, capabilities, opensearch, security }: CoreSetup) { capabilities.registerProvider(() => ({ dev_tools: { show: true, save: true, - hide_for_read_only: ['save'], }, })); + capabilities.registerSwitcher(async (request, capabilites) => { + return await security.readonlyService().hideForReadonly(request, capabilites, { + dev_tools: { + save: false, + }, + }); + }); + const config = await this.ctx.config.create().pipe(first()).toPromise(); const globalConfig = await this.ctx.config.legacy.globalConfig$.pipe(first()).toPromise(); const proxyPathFilters = config.proxyFilter.map((str: string) => new RegExp(str)); diff --git a/src/plugins/dashboard/server/capabilities_provider.ts b/src/plugins/dashboard/server/capabilities_provider.ts index 93062bb143f0..e0ae2a183c47 100644 --- a/src/plugins/dashboard/server/capabilities_provider.ts +++ b/src/plugins/dashboard/server/capabilities_provider.ts @@ -34,6 +34,5 @@ export const capabilitiesProvider = () => ({ show: true, showWriteControls: true, saveQuery: true, - hide_for_read_only: ['createNew', 'showWriteControls', 'saveQuery'], }, }); diff --git a/src/plugins/dashboard/server/plugin.ts b/src/plugins/dashboard/server/plugin.ts index 49eb29706b04..4e377e24bbce 100644 --- a/src/plugins/dashboard/server/plugin.ts +++ b/src/plugins/dashboard/server/plugin.ts @@ -53,6 +53,15 @@ export class DashboardPlugin implements Plugin { + return await core.security.readonlyService().hideForReadonly(request, capabilites, { + dashboard: { + createNew: false, + showWriteControls: false, + saveQuery: false, + }, + }); + }); return {}; } diff --git a/src/plugins/data/server/index_patterns/capabilities_provider.ts b/src/plugins/data/server/index_patterns/capabilities_provider.ts index 8da03f14a1da..0f040faccceb 100644 --- a/src/plugins/data/server/index_patterns/capabilities_provider.ts +++ b/src/plugins/data/server/index_patterns/capabilities_provider.ts @@ -31,6 +31,5 @@ export const capabilitiesProvider = () => ({ indexPatterns: { save: true, - hide_for_read_only: ['save'], }, }); diff --git a/src/plugins/data/server/index_patterns/index_patterns_service.ts b/src/plugins/data/server/index_patterns/index_patterns_service.ts index 4917e4240f52..29021794e883 100644 --- a/src/plugins/data/server/index_patterns/index_patterns_service.ts +++ b/src/plugins/data/server/index_patterns/index_patterns_service.ts @@ -59,6 +59,13 @@ export class IndexPatternsService implements Plugin { + return await core.security.readonlyService().hideForReadonly(request, capabilites, { + indexPatterns: { + save: false, + }, + }); + }); registerRoutes(core.http); } diff --git a/src/plugins/discover/server/capabilities_provider.ts b/src/plugins/discover/server/capabilities_provider.ts index 0f75f7a18650..ecbefd8f4bb8 100644 --- a/src/plugins/discover/server/capabilities_provider.ts +++ b/src/plugins/discover/server/capabilities_provider.ts @@ -34,6 +34,5 @@ export const capabilitiesProvider = () => ({ createShortUrl: true, save: true, saveQuery: true, - hide_for_read_only: ['createShortUrl', 'save', 'saveQuery'], }, }); diff --git a/src/plugins/discover/server/plugin.ts b/src/plugins/discover/server/plugin.ts index 3c4425712d22..96b8e758fdc6 100644 --- a/src/plugins/discover/server/plugin.ts +++ b/src/plugins/discover/server/plugin.ts @@ -36,6 +36,15 @@ import { searchSavedObjectType } from './saved_objects'; export class DiscoverServerPlugin implements Plugin { public setup(core: CoreSetup) { core.capabilities.registerProvider(capabilitiesProvider); + core.capabilities.registerSwitcher(async (request, capabilites) => { + return await core.security.readonlyService().hideForReadonly(request, capabilites, { + discover: { + createShortUrl: false, + save: false, + saveQuery: false, + }, + }); + }); core.uiSettings.register(uiSettings); core.savedObjects.registerType(searchSavedObjectType); diff --git a/src/plugins/saved_objects_management/server/capabilities_provider.ts b/src/plugins/saved_objects_management/server/capabilities_provider.ts index ab4f22eb04a7..c97893b0aa17 100644 --- a/src/plugins/saved_objects_management/server/capabilities_provider.ts +++ b/src/plugins/saved_objects_management/server/capabilities_provider.ts @@ -33,6 +33,5 @@ export const capabilitiesProvider = () => ({ delete: true, edit: true, read: true, - hide_for_read_only: ['delete', 'edit'], }, }); diff --git a/src/plugins/saved_objects_management/server/plugin.ts b/src/plugins/saved_objects_management/server/plugin.ts index 4f9d183922a5..c3053884a71e 100644 --- a/src/plugins/saved_objects_management/server/plugin.ts +++ b/src/plugins/saved_objects_management/server/plugin.ts @@ -45,7 +45,7 @@ export class SavedObjectsManagementPlugin this.logger = this.context.logger.get(); } - public async setup({ http, capabilities }: CoreSetup) { + public async setup({ http, capabilities, security }: CoreSetup) { this.logger.debug('Setting up SavedObjectsManagement plugin'); registerRoutes({ http, @@ -53,6 +53,14 @@ export class SavedObjectsManagementPlugin }); capabilities.registerProvider(capabilitiesProvider); + capabilities.registerSwitcher(async (request, capabilites) => { + return await security.readonlyService().hideForReadonly(request, capabilites, { + savedObjectsManagement: { + delete: false, + edit: false, + }, + }); + }); return {}; } diff --git a/src/plugins/visualize/server/capabilities_provider.ts b/src/plugins/visualize/server/capabilities_provider.ts index 0f2be34162ae..961b2ff6ed5d 100644 --- a/src/plugins/visualize/server/capabilities_provider.ts +++ b/src/plugins/visualize/server/capabilities_provider.ts @@ -35,6 +35,5 @@ export const capabilitiesProvider = () => ({ delete: true, save: true, saveQuery: true, - hide_for_read_only: ['createShortUrl', 'delete', 'save', 'saveQuery'], }, }); diff --git a/src/plugins/visualize/server/plugin.ts b/src/plugins/visualize/server/plugin.ts index aa8359d396c7..086346e31ca9 100644 --- a/src/plugins/visualize/server/plugin.ts +++ b/src/plugins/visualize/server/plugin.ts @@ -49,6 +49,17 @@ export class VisualizeServerPlugin implements Plugin { core.capabilities.registerProvider(capabilitiesProvider); + core.capabilities.registerSwitcher(async (request, capabilites) => { + return await core.security.readonlyService().hideForReadonly(request, capabilites, { + visualize: { + createShortUrl: false, + delete: false, + save: false, + saveQuery: false, + }, + }); + }); + return {}; } From 27ae5b52b1dda192f88d5a6337d81fc76171de4e Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Wed, 13 Sep 2023 07:57:23 +0200 Subject: [PATCH 06/12] fix: adds securityServiceMock Signed-off-by: Kajetan Nobel --- src/core/server/legacy/legacy_service.test.ts | 2 + src/core/server/mocks.ts | 3 ++ .../server/security/security_service.mock.ts | 43 +++++++++++++++++++ .../server/security/security_service.test.ts | 33 ++++++++++++++ src/core/server/security/security_service.ts | 2 +- 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/core/server/security/security_service.mock.ts create mode 100644 src/core/server/security/security_service.test.ts diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index 8ad4c738df44..3dd4ce6589bd 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -60,6 +60,7 @@ import { statusServiceMock } from '../status/status_service.mock'; import { auditTrailServiceMock } from '../audit_trail/audit_trail_service.mock'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { metricsServiceMock } from '../metrics/metrics_service.mock'; +import { securityServiceMock } from '../security/security_service.mock'; const MockOsdServer: jest.Mock = OsdServer as any; @@ -108,6 +109,7 @@ beforeEach(() => { auditTrail: auditTrailServiceMock.createSetupContract(), logging: loggingServiceMock.createInternalSetupContract(), metrics: metricsServiceMock.createInternalSetupContract(), + security: securityServiceMock.createSetupContract(), }, plugins: { 'plugin-id': 'plugin-value' }, uiPlugins: { diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 3dd289669a01..c253e95245d5 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -50,6 +50,7 @@ import { environmentServiceMock } from './environment/environment_service.mock'; import { statusServiceMock } from './status/status_service.mock'; import { auditTrailServiceMock } from './audit_trail/audit_trail_service.mock'; import { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; +import { securityServiceMock } from './security/security_service.mock'; export { configServiceMock } from './config/mocks'; export { httpServerMock } from './http/http_server.mocks'; @@ -157,6 +158,7 @@ function createCoreSetupMock({ getStartServices: jest .fn, object, any]>, []>() .mockResolvedValue([createCoreStartMock(), pluginStartDeps, pluginStartContract]), + security: securityServiceMock.createSetupContract(), }; return mock; @@ -192,6 +194,7 @@ function createInternalCoreSetupMock() { auditTrail: auditTrailServiceMock.createSetupContract(), logging: loggingServiceMock.createInternalSetupContract(), metrics: metricsServiceMock.createInternalSetupContract(), + security: securityServiceMock.createSetupContract(), }; return setupDeps; } diff --git a/src/core/server/security/security_service.mock.ts b/src/core/server/security/security_service.mock.ts new file mode 100644 index 000000000000..478b29b2ecdb --- /dev/null +++ b/src/core/server/security/security_service.mock.ts @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SecurityServiceSetup } from './types'; + +const createSetupContractMock = () => { + const setupContract: jest.Mocked = { + readonlyService: jest.fn(), + registerReadonlyService: jest.fn(), + }; + return setupContract; +}; + +export const securityServiceMock = { + createSetupContract: createSetupContractMock, +}; diff --git a/src/core/server/security/security_service.test.ts b/src/core/server/security/security_service.test.ts new file mode 100644 index 000000000000..b9269f2d5038 --- /dev/null +++ b/src/core/server/security/security_service.test.ts @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +describe('SecurityService', () => { + it.todo('missing tests'); +}); diff --git a/src/core/server/security/security_service.ts b/src/core/server/security/security_service.ts index 250733bb3a08..d2e0731fd55f 100644 --- a/src/core/server/security/security_service.ts +++ b/src/core/server/security/security_service.ts @@ -37,7 +37,7 @@ export class SecurityService implements CoreService Date: Wed, 13 Sep 2023 08:47:20 +0200 Subject: [PATCH 07/12] feat: adds tests and default default readonly service Signed-off-by: Kajetan Nobel --- .../server/security/readonly_service.test.ts | 59 +++++++++++++++++++ src/core/server/security/readonly_service.ts | 47 +++++++++++++++ .../server/security/security_service.test.ts | 39 +++++++++++- src/core/server/security/security_service.ts | 6 +- 4 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 src/core/server/security/readonly_service.test.ts create mode 100644 src/core/server/security/readonly_service.ts diff --git a/src/core/server/security/readonly_service.test.ts b/src/core/server/security/readonly_service.test.ts new file mode 100644 index 000000000000..26be5b786fd8 --- /dev/null +++ b/src/core/server/security/readonly_service.test.ts @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { OpenSearchDashboardsRequest } from '../index'; +import { ReadonlyService } from './readonly_service'; +import { httpServerMock } from '../http/http_server.mocks'; + +describe('ReadonlyService', () => { + let readonlyService: ReadonlyService; + let request: OpenSearchDashboardsRequest; + + beforeEach(() => { + readonlyService = new ReadonlyService(); + request = httpServerMock.createOpenSearchDashboardsRequest(); + }); + + it('isReadonly returns false by default', () => { + expect(readonlyService.isReadonly(request)).resolves.toBeFalsy(); + }); + + it('hideForReadonly merges capabilites to hide', () => { + readonlyService.isReadonly = jest.fn(() => new Promise(() => true)); + const result = readonlyService.hideForReadonly( + request, + { foo: { show: true } }, + { foo: { show: false } } + ); + + expect(readonlyService.isReadonly).toBeCalledTimes(1); + expect(result).resolves.toEqual({ foo: { show: false } }); + }); +}); diff --git a/src/core/server/security/readonly_service.ts b/src/core/server/security/readonly_service.ts new file mode 100644 index 000000000000..9c0e83cc482f --- /dev/null +++ b/src/core/server/security/readonly_service.ts @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { merge } from 'lodash'; +import { OpenSearchDashboardsRequest, Capabilities } from '../index'; +import { IReadOnlyService } from './types'; + +export class ReadonlyService implements IReadOnlyService { + async isReadonly(request: OpenSearchDashboardsRequest): Promise { + return false; + } + + async hideForReadonly( + request: OpenSearchDashboardsRequest, + capabilites: Partial, + hideCapabilities: Partial + ): Promise> { + return (await this.isReadonly(request)) ? merge(capabilites, hideCapabilities) : capabilites; + } +} diff --git a/src/core/server/security/security_service.test.ts b/src/core/server/security/security_service.test.ts index b9269f2d5038..54697108e4ec 100644 --- a/src/core/server/security/security_service.test.ts +++ b/src/core/server/security/security_service.test.ts @@ -28,6 +28,43 @@ * under the License. */ +import { OpenSearchDashboardsRequest } from '../index'; +import { mockCoreContext } from '../core_context.mock'; +import { SecurityService } from './security_service'; +import { httpServerMock } from '../http/http_server.mocks'; +import { IReadOnlyService } from './types'; + describe('SecurityService', () => { - it.todo('missing tests'); + let securityService: SecurityService; + let request: OpenSearchDashboardsRequest; + + beforeEach(() => { + const coreContext = mockCoreContext.create(); + securityService = new SecurityService(coreContext); + request = httpServerMock.createOpenSearchDashboardsRequest(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('#readonlyService', () => { + it("uses core's readonly service by default", () => { + const setupContext = securityService.setup(); + expect(setupContext.readonlyService().isReadonly(request)).resolves.toBeFalsy(); + }); + + it('registers custom readonly service and it uses it', () => { + const setupContext = securityService.setup(); + const readonlyServiceMock: jest.Mocked = { + isReadonly: jest.fn(), + hideForReadonly: jest.fn(), + }; + + setupContext.registerReadonlyService(readonlyServiceMock); + setupContext.readonlyService().isReadonly(request); + + expect(readonlyServiceMock.isReadonly).toBeCalledTimes(1); + }); + }); }); diff --git a/src/core/server/security/security_service.ts b/src/core/server/security/security_service.ts index d2e0731fd55f..015d663f862d 100644 --- a/src/core/server/security/security_service.ts +++ b/src/core/server/security/security_service.ts @@ -32,13 +32,15 @@ import { CoreService } from '../../types'; import { IReadOnlyService, InternalSecurityServiceSetup } from './types'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; +import { ReadonlyService } from './readonly_service'; export class SecurityService implements CoreService { private logger: Logger; - private readonlyService?: IReadOnlyService; + private readonlyService: IReadOnlyService; constructor(coreContext: CoreContext) { this.logger = coreContext.logger.get('security-service'); + this.readonlyService = new ReadonlyService(); } public setup() { @@ -51,7 +53,7 @@ export class SecurityService implements CoreService Date: Wed, 13 Sep 2023 11:22:43 +0200 Subject: [PATCH 08/12] docs: fill up docs for read only tenant mode Signed-off-by: Kajetan Nobel --- DEVELOPER_GUIDE.md | 15 +--- docs/capabilities/read_only_mode.md | 80 ++++++++++++++++++++++ docs/capabilities/read_only_tenant_mode.md | 56 --------------- 3 files changed, 81 insertions(+), 70 deletions(-) create mode 100644 docs/capabilities/read_only_mode.md delete mode 100644 docs/capabilities/read_only_tenant_mode.md diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 29c607b14091..e6eb11dce8db 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -260,20 +260,7 @@ $ yarn opensearch snapshot --version 2.2.0 -E cluster.name=test -E path.data=/tm _This feature will only work if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled._ -Whenever a plugin registers capabilities that should be limited (in other words, set to false) for read-only tenants, such capabilities should be listed in a separate capability called `hide_for_read_only` that is an array of strings, containing capabilities that are set to false whenever Dashboards Security Plugin detects a read-only tenant. - -For example: - -```js -export const capabilitiesProvider = () => ({ - indexPatterns: { - save: true, - hide_for_read_only: ['save'], - }, -}); -``` - -In this case, we might assume that a plugin relies on the `save` capability to limit saving changes somewhere in the UI. Therefore, this `save` capability is listed in the `hide_for_read_only` array and will be set to `false` whenever a read-only tenant is accessed. +Please follow the design described in [the docs](https://github.com/opensearch-project/OpenSearch/blob/main/docs/capabilities/read_only_mode.md#design) ### Alternative - Run OpenSearch from tarball diff --git a/docs/capabilities/read_only_mode.md b/docs/capabilities/read_only_mode.md new file mode 100644 index 000000000000..a1e14d119cbf --- /dev/null +++ b/docs/capabilities/read_only_mode.md @@ -0,0 +1,80 @@ +# Read-only Mode + +There are two distinct functionalities for "read-only" access in Dashboards. One of them is associated with roles and one is associated with tenants. Regarding the first one, the Dashboards Security plugin contains a feature of hiding all plugin navigation links except Dashboards and Visualizations when the logged-in user has a certain role (more about it in [Read-only Role](#read-only-role)). + +The second one is limiting Dashboards access rights via assigning a specific role to a tenant (therefore, making a tenant read-only). Due to past issues and the deprecation of the first functionality, using read-only tenants is now the recommended way to limit users' access to Dashboards. + +## Design + +Whenever a plugin registers capabilities that should be limited (in other words, set to false) for read-only tenants, such capabilities should be registered through `registerSwitcher` with using method `core.security.readonlyService().hideForReadonly()` + +### Example + +```ts +public setup(core: CoreSetup) { + core.capabilities.registerProvider({ + myAwesomePlugin: { + show: true, + save: true, + delete: true, + } + }); + + core.capabilities.registerSwitcher(async (request, capabilites) => { + return await core.security.readonlyService().hideForReadonly(request, capabilites, { + myAwesomePlugin: { + save: false, + delete: false, + }, + }); + }); +} +``` + +In this case, we might assume that a plugin relies on the `save` and `delete` capabilities to limit changes somewhere in the UI. Therefore, those capabilities are processed through `registerSwitcher`, they will be set to `false` whenever a read-only tenant is accessed. + +If `registerSwitcher` will try to provide or remove capabilites when invoking the switcher will be ignored. + +*In case of a disabled / not installed `security` plugin changes will be never applied to a capabilites.* + +## Requirements + +This feature will only work if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled. + +## Read-only Role + +The role is called `kibana_read_only` by default, but the name can be changed using the dashboard config option `opensearch_security.readonly_mode.roles`. One big issue with this feature is that the backend site of a Dashboard Security plugin is completely unaware of it. Thus, users in this mode still have write access to the Dashboards saved objects via the API as the implementation effectively hides everything except the Dashboards and Visualization plugins. + +**We highly do not recommend using it!** + +For more context, see [this group issues of problems connected with read-only roles](https://github.com/opensearch-project/security/issues/2701). + +### Usage + +1. Go to `Management > Security > Internal users` +2. Create or select an already existing user +3. Add a new `Backend role` called `kibana_read_only` (or use name used in `opensearch_security.readonly_mode.roles`) +4. Save changes + +## Read-only Tenant (recommended) + +Dashboards Security plugin recognizes the selection of read-only tenant after logging in and sets the capabilities associated with write access or showing write controls to false for a variety of plugins. This can be easily checked for example by trying to re-arrange some visualizations on Dashboards. Such action will be resulting in a 403 error due to limited read-only access. + +### Usage + +1. Prepare tenant: + * Use an existing tenant or create a new one in `Management > Security > Tenants` +2. Prepare role: + * Go to `Management > Security > Roles` + * Use an existing role or create a new one + * Fill **index permissions** with: + * `indices:data/read/search` + * `indices:data/read/get` + * Add new **tenant permission** with: + * your name of the tenant + * read only +3. Assign a role to a user: + * Go to role + * Click the tab `Mapped users` + * Click `Manage mapping` + * In `Users` select the user that will be affected diff --git a/docs/capabilities/read_only_tenant_mode.md b/docs/capabilities/read_only_tenant_mode.md deleted file mode 100644 index dc58d0aa5772..000000000000 --- a/docs/capabilities/read_only_tenant_mode.md +++ /dev/null @@ -1,56 +0,0 @@ -# Read Only Tenant Mode - -There are two distinct functionalities for "read-only" access in Dashboards. One of them is associated with roles and one is associated with tenants. Regarding the first one, the Dashboards Security plugin contains a feature of hiding all plugin navigation links except Dashboards and Visualizations when the logged-in user has a certain role. The second one is limiting Dashboards access rights via assigning a specific role to a tenant (therefore, making a tenant read-only). Due to past issues and the deprecation of the first functionality, using read-only tenants is now the recommended way to limit users' access to Dashboards. - -For more context, see [this group issues of problems connected with read-only roles](https://github.com/opensearch-project/security/issues/2701). - -## Read Only Tenant - -A read-only tenant looks like this: -``` -read_only_tenant_role: - tenant_permissions: - - tenant_patterns: - - "human_resources" - allowed_actions: - - "kibana_all_read" -``` - -If the `kibana_all_read` role is assigned (without `kibana_all_write`), a given tenant provides solely read-only access. - -Dashboards Security plugin recognizes the selection of read-only tenant after logging in and sets the capabilities associated with write access or showing write controls to false for a variety of plugins. This can be easily checked for example by trying to re-arrange some visualizations on Dashboards. Such action will be resulting in a 403 error due to limited read-only access. - -## Design - -Whenever a plugin registers capabilities that should be limited (in other words, set to false) for read-only tenants, such capabilities should be listed in a separate capability called `hide_for_read_only` that is an array of strings, containing capabilities that are set to false whenever Dashboards Security Plugin detects a read-only tenant. - -For example: -``` -export const capabilitiesProvider = () => ({ - indexPatterns: { - save: true, - hide_for_read_only: ['save'], - }, -}); -``` - -In this case, we might assume that a plugin relies on the `save` capability to limit saving changes somewhere in the UI. Therefore, this `save` capability is listed in the `hide_for_read_only` array and will be set to `false` whenever a read-only tenant is accessed. - -## Scope - -Affected plugins: -- `advanced_settings` (`save` capability) -- `console` (`save` capability) -- `dashboard` (`createNew`, `showWriteControls`, `saveQuery` capabilities) -- `index_patterns` (`save` capability) -- `discover` (`save` capability) -- `saved_objects_management` (`edit`, `delete` capabilities) -- `visualize` (`createShortUrl`, `delete`, `save`, `saveQuery` capabilities) - -## Requirements - -This feature will only work if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled. - -## Usage - -To set it up, you have to add Role's "Tenant permissions" a new tenant with `Read only` access. From e55caaed0ea1f97c6ab3a6e262ca115385815a01 Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Thu, 14 Sep 2023 10:06:49 +0200 Subject: [PATCH 09/12] Update DEVELOPER_GUIDE.md Co-authored-by: Peter Nied Signed-off-by: Kajetan Nobel --- DEVELOPER_GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index e6eb11dce8db..f6b42eae3af0 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -256,7 +256,7 @@ Options: $ yarn opensearch snapshot --version 2.2.0 -E cluster.name=test -E path.data=/tmp/opensearch-data --P org.opensearch.plugin:test-plugin:2.2.0.0 --P file:/home/user/opensearch-test-plugin-2.2.0.0.zip ``` -#### Read Only capabalities +#### Read Only capabilities _This feature will only work if you have the [`security` plugin](https://github.com/opensearch-project/security) installed on your OpenSearch cluster with https/authentication enabled._ From 77d3e690c201439cdfb5a71c65ba81d4d5592d00 Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Wed, 27 Sep 2023 10:26:38 +0200 Subject: [PATCH 10/12] docs: update changelog Signed-off-by: Kajetan Nobel --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a20fd14d79..b689906061cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Adds Data explorer framework and implements Discover using it ([#4806](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4806)) - [Theme] Use themes' definitions to render the initial view ([#4936](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4936/)) - [Theme] Make `next` theme the default ([#4854](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4854/)) +- Adds support for read-only mode through tenants ([#4498](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4498)) ### 🐛 Bug Fixes From 66100c0f89f90c66a5c71a921ce2168244c35419 Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Tue, 24 Oct 2023 15:59:20 +0200 Subject: [PATCH 11/12] feat: change to correct license headers Signed-off-by: Kajetan Nobel --- .../server/security/readonly_service.test.ts | 27 +------------------ src/core/server/security/readonly_service.ts | 27 +------------------ .../server/security/security_service.mock.ts | 27 +------------------ .../server/security/security_service.test.ts | 27 +------------------ src/core/server/security/security_service.ts | 27 +------------------ src/core/server/security/types.ts | 27 +------------------ 6 files changed, 6 insertions(+), 156 deletions(-) diff --git a/src/core/server/security/readonly_service.test.ts b/src/core/server/security/readonly_service.test.ts index 26be5b786fd8..739d9e3daac3 100644 --- a/src/core/server/security/readonly_service.test.ts +++ b/src/core/server/security/readonly_service.test.ts @@ -1,31 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. */ import { OpenSearchDashboardsRequest } from '../index'; diff --git a/src/core/server/security/readonly_service.ts b/src/core/server/security/readonly_service.ts index 9c0e83cc482f..a41dc0fde3b1 100644 --- a/src/core/server/security/readonly_service.ts +++ b/src/core/server/security/readonly_service.ts @@ -1,31 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. */ import { merge } from 'lodash'; diff --git a/src/core/server/security/security_service.mock.ts b/src/core/server/security/security_service.mock.ts index 478b29b2ecdb..687509e42b5e 100644 --- a/src/core/server/security/security_service.mock.ts +++ b/src/core/server/security/security_service.mock.ts @@ -1,31 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. */ import { SecurityServiceSetup } from './types'; diff --git a/src/core/server/security/security_service.test.ts b/src/core/server/security/security_service.test.ts index 54697108e4ec..cf09b64ae36a 100644 --- a/src/core/server/security/security_service.test.ts +++ b/src/core/server/security/security_service.test.ts @@ -1,31 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. */ import { OpenSearchDashboardsRequest } from '../index'; diff --git a/src/core/server/security/security_service.ts b/src/core/server/security/security_service.ts index 015d663f862d..1916afc165dd 100644 --- a/src/core/server/security/security_service.ts +++ b/src/core/server/security/security_service.ts @@ -1,31 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. */ import { CoreService } from '../../types'; diff --git a/src/core/server/security/types.ts b/src/core/server/security/types.ts index 955eb081adf5..43a599d99625 100644 --- a/src/core/server/security/types.ts +++ b/src/core/server/security/types.ts @@ -1,31 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. */ import { Capabilities, OpenSearchDashboardsRequest } from '../index'; From 7f5ad0844766c0c091eafcf64473e9c04c14374a Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Mon, 30 Oct 2023 20:18:37 +0100 Subject: [PATCH 12/12] Update CHANGELOG.md Co-authored-by: Anan Zhuang Signed-off-by: Kajetan Nobel --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2872b8881305..236224932bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Theme] Use themes' definitions to render the initial view ([#4936](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4936)) - [Theme] Make `next` theme the default ([#4854](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4854)) - [Discover] Update embeddable for saved searches ([#5081](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5081)) -- Adds support for read-only mode through tenants ([#4498](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4498)) +- Add support for read-only mode through tenants ([#4498](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4498)) - [Workspace] Add core workspace service module to enable the implementation of workspace features within OSD plugins ([#5092](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5092)) ### 🐛 Bug Fixes