Configuration of JWT in URL for authentication

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
opensearchproject/opensearch-dashboards:2.7.0
opensearchproject/opensearch:2.7.0

Describe the issue:
After reading the OpenSearch documentation for configuring the use of JWT in the URL for authentication, I still cannot get it to work. The http response I get is always {“statusCode”:401,“error”:“Unauthorized”,“message”:“Authentication Exception”}, which tells me little as to the root cause. It would help if a working example was provide with the appropriate configuration details.

Configuration:
In the opensearch-dashboards helm values.yaml file:
config:
opensearch_dashboards.yml:
opensearch_security.auth.type: “jwt”
opensearch_security.jwt.url_param: “jwt_token”

# removes "first certificate" validation error
# per https://github.com/opensearch-project/security-dashboards-plugin/issues/872
opensearch.ssl.verificationMode: none
opensearch.username: "admin"
opensearch.password: "admin"
opensearch.requestHeadersWhitelist: [ authorization,securitytenant ]

# per https://forum.opensearch.org/t/error-401-authorization-required/11589
opensearch_security.cookie.secure: false
opensearch_security.session.keepalive: false
# server.ssl.enabled: false

opensearch.logQueries: true
logging.verbose: true

In the opensearch helm values.yaml file:
opensearch.yml:
cluster.name: opensearch-cluster

# Bind to all interfaces because we don't know what IP address Docker will assign to us.
network.host: 0.0.0.0

logger.level: "DEBUG"

# Setting network.host to a non-loopback address enables the annoying bootstrap checks. "Single-node" mode disables them again.
# Implicitly done if ".singleNode" is set to "true".
# discovery.type: single-node

# Start OpenSearch Security Demo Configuration
# WARNING: revise all the lines below before you go into production
plugins:
  security:
    ssl:
      transport:
        pemcert_filepath: esnode.pem
        pemkey_filepath: esnode-key.pem
        pemtrustedcas_filepath: root-ca.pem
        enforce_hostname_verification: false
      http:
        enabled: true
        pemcert_filepath: esnode.pem
        pemkey_filepath: esnode-key.pem
        pemtrustedcas_filepath: root-ca.pem
    allow_unsafe_democertificates: true
    allow_default_init_securityindex: true
    authcz:
      admin_dn:
        - CN=kirk,OU=client,O=client,L=test,C=de
    audit.type: internal_opensearch
    enable_snapshot_restore_privilege: true
    check_snapshot_restore_write_privileges: true
    restapi:
      roles_enabled: ["all_access", "security_rest_api_access"]
    system_indices:
      enabled: true
      indices:
        [
          ".opendistro-alerting-config",
          ".opendistro-alerting-alert*",
          ".opendistro-anomaly-results*",
          ".opendistro-anomaly-detector*",
          ".opendistro-anomaly-checkpoints",
          ".opendistro-anomaly-detection-state",
          ".opendistro-reports-*",
          ".opendistro-notifications-*",
          ".opendistro-notebooks",
          ".opendistro-asynchronous-search-response*",
        ]
######## End OpenSearch Security Demo Configuration ########

config.yml:
dynamic:
http:
anonymous_auth_enabled: false
authc:
# basic_internal_auth_domain:
# description: “Authenticate via HTTP Basic against internal users database”
# http_enabled: true
# transport_enabled: true
# order: 4
# http_authenticator:
# type: basic
# challenge: true
# authentication_backend:
# type: intern
jwt_auth_domain:
description: “Authenticate via Json Web Token”
http_enabled: true
transport_enabled: true
order: 0
http_authenticator:
type: jwt
challenge: false
config:
signing_key: |
-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAl5sENm/wwncxJ6RwPOjb\nY7aE/X6h3aJi5XdFdm4XUOx7dc9qqhkNctX8js1AkqFnm1NvVETE3q1QpoCUd03z\nmKAz167GkFwkrvn6Khe/aWANWSLfMlnnpTCoZbCqesrNtIbROrLuDgwOwENHpAHS\n016KKR+pBjsqbay/ITCJSlzyu7uK0bz/2GzvwIt/74yemYbYKsrDaBkA2Qf687CR\nK0Q0WKMIzQi8Ykdd6HBuY7GXLz2yB7yI84bGCzadv6Mv0qMLoW05jZxzinatDoiZ\nGAes6pWqF7JUaWpZJnqKFizFhF4RdNo2T0k4ouyxbsbZIT65RN5FhoSm226uqQVS\nUbGWH/9Hj27RLtzuw6zHsccvAYdTDWYiqJp7mVYe71jYSVGpM819QTlERLUWNcv3\nTUwEduKcIgBGPoW3yS03VaxkZNlLcM1yWGiwv8Ze613iWzovI6j/Vk5neJP0na+P\nG68bz95AQsYkLabCbaEzzWEUqxc8mkBON7/HRjNG50kLnLBt5xucgWQFCwFOtPWA\nROxic/BbgWYBVKo9dFZoWpO51AYBd5if/VQ6YesM/WNCcpTMkQKbtvVXjLGuPyzG\n8ZnYzXBrCmuvIhcOznbjvk6H3t5k8iwS+7Ro1+VS+Z9F8QdetW1Rj9BwKGIHo056\nZUsyNA2guF8TGg2w8BclEo0CAwEAAQ==
-----END PUBLIC KEY-----
# jwt_header: “Authorization”
jwt_url_parameter: “jwt_token”
jwt_clock_skew_tolerance_seconds: 30
roles_key: scope
subject_key: sub
authentication_backend:
type: noop

Relevant Logs or Screenshots:

In my typescript web app, I invoke opensearch-dashboards with the following code:
const url = http://localhost:5601/app/home?jwt_token=${token}
window.open(url, ‘_blank’, ‘noreferrer’)

A new browser tab opens at the above URL with the following:
{“statusCode”:401,“error”:“Unauthorized”,“message”:“Authentication Exception”}

When I look at the the pod logs for opensearch-dashboards pod, I only see the following related logs:
{“type”:“log”,“@timestamp”:“2023-06-05T16:42:46Z”,“tags”:[“debug”,“metrics”],“pid”:459,“message”:“Refreshing metrics”} {“type”:“log”,“@timestamp”:“2023-06-05T16:42:46Z”,“tags”:[“debug”,“opensearch”,“opendistro_security”,“query”],“pid”:459,“message”:“401\nGET /_plugins/_security/authinfo\n”} {“type”:“response”,“@timestamp”:“2023-06-05T16:42:43Z”,“tags”:,“pid”:459,“method”:“get”,“statusCode”:401,“req”:{“url”:“/app/home?jwt_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzcnBfdXNlciIsIm5hbWUiOiJzcnBfdXNlciIsImV4cCI6MTY4NTk3OTI3MSwiaWF0IjoxNjg1OTc1NjcxLCJuYmYiOjE2ODU5NzU2NzEsInJvbGVzIjpbImFsbF9hY2Nlc3MiXX0.ddAxpvKnvPGzLEBFxULLhYYVwwcnQW9C-nr1bxNZkt4wqgETaYBgUGOW0MH1MKTPyEexn3qnLfM6h9-GT-yVnBY1H2RoGSmDDjrG7PUZfuerxHUmYe1j-pUF-dArGmAz0krVJcDaaxC0ewrv1ShBccO41oSz8eObPRAGgGp8BEio_jeR8YyaZFvLcoKQz9E8Ns_YJVNTqDApKQMjmM9YMlx6Gbs3KbwGqIIZP86Xqj_XpkotHWyY8VQZe5NLpPsMAHVpqRgagIVoPbTV5an5-4sAl_Wf5QpLaTYT8Ua6p32ZQK1BEou8RPkjyKpPOIfwf24tIBk0tU2r12qMaQLwrL-DTjTUzW5bL3k5AejLBUKzIX1qQSepH6x7BL9cZUFVzMlAWZqje5npSvlXJ4WIqG4qZ_1hzUqNg-xjGTvM-Ro16HfkHM4vi-jpbt23BhWm1WpqBtNf8KQGQoT1GrxBogu0WdS3uskdZ0cCDEtw_Xl5t_PPdRxUpBGWDW441FjWeawQs4IkfaIGTlyVJiKmjlXLDvABEkdmdqZNe8jhK48EIPFXvUunmYpEBv30lida39A8N3BW9NlOnlpXkU9bk3XCHPulbT0Tszd0ZcNJjXzDvbAhvVyALY4qu6g3sD2Rv0MCLken-14U2ApXAu9IdkGK6NfSLeNqAifMjH6Xfhw”,“method”:“get”,“headers”:{“host”:“localhost:5601”,“connection”:“keep-alive”,“sec-ch-ua”:“"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"”,“sec-ch-ua-mobile”:“?0”,“sec-ch-ua-platform”:“"macOS"”,“upgrade-insecure-requests”:“1”,“user-agent”:“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36”,“accept”:“text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7”,“sec-fetch-site”:“same-site”,“sec-fetch-mode”:“navigate”,“sec-fetch-user”:“?1”,“sec-fetch-dest”:“document”,“accept-encoding”:“gzip, deflate, br”,“accept-language”:“en-US,en;q=0.9”},“remoteAddress”:“127.0.0.1”,“userAgent”:“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36”},“res”:{“statusCode”:401,“responseTime”:3504,“contentLength”:9},“message”:“GET /app/home?jwt_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzcnBfdXNlciIsIm5hbWUiOiJzcnBfdXNlciIsImV4cCI6MTY4NTk3OTI3MSwiaWF0IjoxNjg1OTc1NjcxLCJuYmYiOjE2ODU5NzU2NzEsInJvbGVzIjpbImFsbF9hY2Nlc3MiXX0.ddAxpvKnvPGzLEBFxULLhYYVwwcnQW9C-nr1bxNZkt4wqgETaYBgUGOW0MH1MKTPyEexn3qnLfM6h9-GT-yVnBY1H2RoGSmDDjrG7PUZfuerxHUmYe1j-pUF-dArGmAz0krVJcDaaxC0ewrv1ShBccO41oSz8eObPRAGgGp8BEio_jeR8YyaZFvLcoKQz9E8Ns_YJVNTqDApKQMjmM9YMlx6Gbs3KbwGqIIZP86Xqj_XpkotHWyY8VQZe5NLpPsMAHVpqRgagIVoPbTV5an5-4sAl_Wf5QpLaTYT8Ua6p32ZQK1BEou8RPkjyKpPOIfwf24tIBk0tU2r12qMaQLwrL-DTjTUzW5bL3k5AejLBUKzIX1qQSepH6x7BL9cZUFVzMlAWZqje5npSvlXJ4WIqG4qZ_1hzUqNg-xjGTvM-Ro16HfkHM4vi-jpbt23BhWm1WpqBtNf8KQGQoT1GrxBogu0WdS3uskdZ0cCDEtw_Xl5t_PPdRxUpBGWDW441FjWeawQs4IkfaIGTlyVJiKmjlXLDvABEkdmdqZNe8jhK48EIPFXvUunmYpEBv30lida39A8N3BW9NlOnlpXkU9bk3XCHPulbT0Tszd0ZcNJjXzDvbAhvVyALY4qu6g3sD2Rv0MCLken-14U2ApXAu9IdkGK6NfSLeNqAifMjH6Xfhw 401 3504ms - 9.0B”} {“type”:“log”,“@timestamp”:“2023-06-05T16:42:46Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:459,“message”:“Error: Unauthorized”} {“type”:“response”,“@timestamp”:“2023-06-05T16:42:46Z”,“tags”:,“pid”:459,“method”:“get”,“statusCode”:401,“req”:{“url”:“/favicon.ico”,“method”:“get”,“headers”:{“host”:“localhost:5601”,“connection”:“keep-alive”,“sec-ch-ua”:“"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"”,“sec-ch-ua-mobile”:“?0”,“user-agent”:“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36”,“sec-ch-ua-platform”:“"macOS"”,“accept”:“image/avif,image/webp,image/apng,image/svg+xml,image/,/;q=0.8",“sec-fetch-site”:“same-origin”,“sec-fetch-mode”:“no-cors”,“sec-fetch-dest”:“image”,“referer”:“http://localhost:5601/app/home?jwt_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzcnBfdXNlciIsIm5hbWUiOiJzcnBfdXNlciIsImV4cCI6MTY4NTk3OTI3MSwiaWF0IjoxNjg1OTc1NjcxLCJuYmYiOjE2ODU5NzU2NzEsInJvbGVzIjpbImFsbF9hY2Nlc3MiXX0.ddAxpvKnvPGzLEBFxULLhYYVwwcnQW9C-nr1bxNZkt4wqgETaYBgUGOW0MH1MKTPyEexn3qnLfM6h9-GT-yVnBY1H2RoGSmDDjrG7PUZfuerxHUmYe1j-pUF-dArGmAz0krVJcDaaxC0ewrv1ShBccO41oSz8eObPRAGgGp8BEio_jeR8YyaZFvLcoKQz9E8Ns_YJVNTqDApKQMjmM9YMlx6Gbs3KbwGqIIZP86Xqj_XpkotHWyY8VQZe5NLpPsMAHVpqRgagIVoPbTV5an5-4sAl_Wf5QpLaTYT8Ua6p32ZQK1BEou8RPkjyKpPOIfwf24tIBk0tU2r12qMaQLwrL-DTjTUzW5bL3k5AejLBUKzIX1qQSepH6x7BL9cZUFVzMlAWZqje5npSvlXJ4WIqG4qZ_1hzUqNg-xjGTvM-Ro16HfkHM4vi-jpbt23BhWm1WpqBtNf8KQGQoT1GrxBogu0WdS3uskdZ0cCDEtw_Xl5t_PPdRxUpBGWDW441FjWeawQs4IkfaIGTlyVJiKmjlXLDvABEkdmdqZNe8jhK48EIPFXvUunmYpEBv30lida39A8N3BW9NlOnlpXkU9bk3XCHPulbT0Tszd0ZcNJjXzDvbAhvVyALY4qu6g3sD2Rv0MCLken-14U2ApXAu9IdkGK6NfSLeNqAifMjH6Xfhw",“accept-encoding”:"gzip, deflate, br”,“accept-language”:“en-US,en;q=0.9”},“remoteAddress”:“127.0.0.1”,“userAgent”:“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36”,“referer”:“http://localhost:5601/app/home?jwt_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzcnBfdXNlciIsIm5hbWUiOiJzcnBfdXNlciIsImV4cCI6MTY4NTk3OTI3MSwiaWF0IjoxNjg1OTc1NjcxLCJuYmYiOjE2ODU5NzU2NzEsInJvbGVzIjpbImFsbF9hY2Nlc3MiXX0.ddAxpvKnvPGzLEBFxULLhYYVwwcnQW9C-nr1bxNZkt4wqgETaYBgUGOW0MH1MKTPyEexn3qnLfM6h9-GT-yVnBY1H2RoGSmDDjrG7PUZfuerxHUmYe1j-pUF-dArGmAz0krVJcDaaxC0ewrv1ShBccO41oSz8eObPRAGgGp8BEio_jeR8YyaZFvLcoKQz9E8Ns_YJVNTqDApKQMjmM9YMlx6Gbs3KbwGqIIZP86Xqj_XpkotHWyY8VQZe5NLpPsMAHVpqRgagIVoPbTV5an5-4sAl_Wf5QpLaTYT8Ua6p32ZQK1BEou8RPkjyKpPOIfwf24tIBk0tU2r12qMaQLwrL-DTjTUzW5bL3k5AejLBUKzIX1qQSepH6x7BL9cZUFVzMlAWZqje5npSvlXJ4WIqG4qZ_1hzUqNg-xjGTvM-Ro16HfkHM4vi-jpbt23BhWm1WpqBtNf8KQGQoT1GrxBogu0WdS3uskdZ0cCDEtw_Xl5t_PPdRxUpBGWDW441FjWeawQs4IkfaIGTlyVJiKmjlXLDvABEkdmdqZNe8jhK48EIPFXvUunmYpEBv30lida39A8N3BW9NlOnlpXkU9bk3XCHPulbT0Tszd0ZcNJjXzDvbAhvVyALY4qu6g3sD2Rv0MCLken-14U2ApXAu9IdkGK6NfSLeNqAifMjH6Xfhw"},“res”:{“statusCode”:401,“responseTime”:6,“contentLength”:9},“message”:"GET /favicon.ico 401 6ms - 9.0B”} {“type”:“log”,“@timestamp”:“2023-06-05T16:42:47Z”,“tags”:[“debug”,“opensearch”,“data”,“query”],“pid”:459,“message”:"200\nGET /_nodes?filter_path=nodes..version%2Cnodes..http.publish_address%2Cnodes..ip”}

@jbowen28

This looks like a double post from here

The config files are the same but the topic is different. In this topic, I am requesting example helm configuration values.yaml for opensearch and opensearch-dashboards.

In the other topic, I am requesting more logging levels for opensearch-dashboards.

Understood,

Unfortunately my knowledge base with helm is null. Sorry

I discovered I was missing a step to activate the security config.yml file with securityadmin.sh as indicated in Modifying the YAML files - OpenSearch documentation.

This was performed by shelling into the opensearch-master2 pod from localhost as follows:

jamesbowen@Jamess-MBP charts % kubectl exec -it opensearch-cluster-master-2 – /bin/bash
Defaulted container “opensearch” out of: opensearch, fsgroup-volume (init)
[opensearch@opensearch-cluster-master-2 ~]$
[opensearch@opensearch-cluster-master-2 ~]$
[opensearch@opensearch-cluster-master-2 ~]$ ls config
esnode-key.pem jvm.options kirk-key.pem log4j2.properties opensearch-notifications-core opensearch-performance-analyzer opensearch-security opensearch.yml
esnode.pem jvm.options.d kirk.pem opensearch-notifications opensearch-observability opensearch-reports-scheduler opensearch.keystore root-ca.pem
[opensearch@opensearch-cluster-master-2 ~]$ ls config/opensearch-security/
config.yml
[opensearch@opensearch-cluster-master-2 ~]$ ls config/…data
ls: cannot access config/…data: No such file or directory
[opensearch@opensearch-cluster-master-2 ~]$ ls -la config/opensearch-security/
total 8
drwxrwsrwt 4 root opensearch 100 Jun 6 20:38 .
drwxr-xr-x 1 opensearch opensearch 4096 Jun 6 20:39 …
drwxr-sr-x 2 root opensearch 60 Jun 6 20:38 …2023_06_06_20_38_58.2742897231
lrwxrwxrwx 1 root opensearch 32 Jun 6 20:38 …data → …2023_06_06_20_38_58.2742897231
drwxrwsrwx 2 root opensearch 4096 Jun 6 20:38 config.yml
[opensearch@opensearch-cluster-master-2 ~]$ /usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh \

-cacert config/root-ca.pem
-cert config/kirk.pem
-key config/kirk-key.pem
-f config/opensearch-security/…data/config.yml


** This tool will be deprecated in the next major release of OpenSearch **
** [DEPRECATION] Security Plugin Tools will be replaced · Issue #1755 · opensearch-project/security · GitHub **


Security Admin v7
Will connect to localhost:9200 … done
Connected as “CN=kirk,OU=client,O=client,L=test,C=de”
OpenSearch Version: 2.7.0
Contacting opensearch cluster ‘opensearch’ and wait for YELLOW clusterstate …
Clustername: opensearch-cluster
Clusterstate: YELLOW
Number of nodes: 3
Number of data nodes: 3
.opendistro_security index already exists, so we do not need to create one.
INFO: .opendistro_security index state is YELLOW, it seems you miss some replicas
Populate config from /usr/share/opensearch
Will update ‘/config’ with config/opensearch-security/…data/config.yml
SUCC: Configuration for ‘config’ created or updated
SUCC: Expected 1 config types for node {“updated_config_types”:[“config”],“updated_config_size”:1,“message”:null} is 1 ([“config”]) due to: null
SUCC: Expected 1 config types for node {“updated_config_types”:[“config”],“updated_config_size”:1,“message”:null} is 1 ([“config”]) due to: null
SUCC: Expected 1 config types for node {“updated_config_types”:[“config”],“updated_config_size”:1,“message”:null} is 1 ([“config”]) due to: null
Done with success

But I am now getting the following http response when I try to access opensearch at port 9200 from a browser window with ‘https://localhost:9200/’:
OpenSearch Security not initialized.

Apparently, there is something still not working with my security configuration.

This issue: JWT RSA Public Key - ERR: while scanning a simple key,
was a big help. Contrary to what the opensearch documentation says, you cannot have multiple lines in your signing key because the securityadmin.sh script will convert the carriage returns to ‘\n’ characters which will cause opensearch base64 decode of the public key to fail.

1 Like

After removing the ‘\n’ characters in the public key for the security plugin, I was able to successfully access the opensearch APIs using a JWT in the URL.

I also finally was able to login to opensearch-dashboard using the JWT token in the URL. So, now I can open a new browser window from my web app and have the user already logged in. Below is my opensearch_dashboard.yaml configuration. But there still remains one big issue, I cannot logout the user. I am getting a 404 http status code when the opensearch-dashboards redirects to http:/<opensearch-dashboards_IP_address>:5601/auth/logout. If I type the same URL and include the JWT token, I get a 401 http status code which means unauthorized. I am going to post another topic in this forum for this JWT logout issue.

---
# Copyright OpenSearch Contributors
# SPDX-License-Identifier: Apache-2.0

# Description:
# Default configuration for OpenSearch Dashboards

# 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: 0.0.0.0


# per https://github.com/opensearch-project/security-dashboards-plugin/issues/872
# per https://opensearch.org/docs/latest/security/authentication-backends/jwt/
opensearch_security.jwt.enabled: true
opensearch_security.auth.type: "jwt"
opensearch_security.jwt.url_param: "jwt_token"

# removes "first certificate" validation error
# per https://github.com/opensearch-project/security-dashboards-plugin/issues/872
# see near bottom
# opensearch.ssl.verificationMode: none
# opensearch.username: "admin"
# opensearch.password: "admin"
# opensearch.requestHeadersWhitelist: [ authorization,securitytenant,Authorization ]

# per https://forum.opensearch.org/t/error-401-authorization-required/11589
# see near bottom
# opensearch_security.cookie.secure: false
# opensearch_security.session.keepalive: false       


# 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.optimizedHealthcheckId: "cluster_id"

# 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

# 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 ]

# Header names and values that are sent to OpenSearch. Any custom headers cannot be overwritten
# by client-side headers, regardless of the opensearch.requestHeadersWhitelist 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: true

# 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: true

# 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 blocklist to check input graphite Url. Blocklist 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.graphiteBlockedIPs: []

# opensearchDashboards.branding:
#   logo:
#     defaultUrl: ""
#     darkModeUrl: ""
#   mark:
#     defaultUrl: ""
#     darkModeUrl: ""
#   loadingLogo:
#     defaultUrl: ""
#     darkModeUrl: ""
#   faviconUrl: ""
#   applicationTitle: ""

# Set the value of this setting to true to capture region blocked warnings and errors
# for your map rendering services.
# map.showRegionBlockedWarning: 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

# 2.4 renames 'wizard.enabled: false' to 'vis_builder.enabled: false'
# Set the value of this setting to false to disable VisBuilder
# functionality in Visualization.
# vis_builder.enabled: false

# 2.4 New Experimental Feature
# Set the value of this setting to true to enable the experimental multiple data source
# support feature. Use with caution.
# 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]

# 2.6 New ML Commons Dashboards Experimental Feature
# Set the value of this setting to true to enable the experimental ml commons dashboards
# ml_commons_dashboards.enabled: false

opensearch.hosts: [https://localhost:9200]
opensearch.ssl.verificationMode: none
opensearch.username: kibanaserver
opensearch.password: kibanaserver
opensearch.requestHeadersWhitelist: [authorization, securitytenant, Authorization]

opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: [Private, Global]
opensearch_security.readonly_mode.roles: [kibana_read_only]
# Use this setting if you are running opensearch-dashboards without https
opensearch_security.cookie.secure: false

Hey @jbowen28

If you do can you link this post to the new one. I have been following this post on you progress.
Thanks