"Unable to retrieve version information from OpenSearch nodes."

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
2.19.1

Describe the issue:
I cant connect to opensearch-dashboards

Configuration:

opensearch.yml

######## Start OpenSearch Security Demo Configuration ######## 
# WARNING: revise all the lines below before you go into production 
plugins.security.ssl.transport.pemcert_filepath: certificates/elk-transport-crt.pem
plugins.security.ssl.transport.pemkey_filepath: certificates/elk-transport-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: certificates/elastic_ca.pem
plugins.security.ssl.transport.enforce_hostname_verification: false 
plugins.security.ssl.http.enabled: true 
plugins.security.ssl.http.pemcert_filepath: certificates/elk-node-crt.pem
plugins.security.ssl.http.pemkey_filepath: certificates/elk-node-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: certificates/elastic_ca.pem
plugins.security.allow_unsafe_democertificates: true 
plugins.security.allow_default_init_securityindex: true 
plugins.security.authcz.admin_dn: 
  - 'CN=CONTROL-M_EM_ES_admin,O=ChangeMe,L=ChangeMeL,ST=ChangeMeST,C=CM'

 
#plugins.security.audit.type: internal_opensearch 
plugins.security.enable_snapshot_restore_privilege: true 
plugins.security.check_snapshot_restore_write_privileges: true 
plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"] 
plugins.security.system_indices.enabled: true 
plugins.security.system_indices.indices: [".plugins-ml-model", ".plugins-ml-task", ".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".opendistro-asynchronous-search-response*", ".replication-metadata-store"] 
node.max_local_storage_nodes: 3 
######## End OpenSearch Security Demo Configuration ######## 
path.logs: C:\Program Files\BMC Software\Control-M EM\Default\log\services\workflow_insights
cluster.name: workflow_insights_cluster
network.host: 0
node.name: px-6dcf5134
node.roles: ["initial_master","data","ingest","master","remote_cluster_client"]
action.auto_create_index: false
bootstrap.memory_lock: true
http.port: 19200
transport.port: 19300
cluster.initial_master_nodes: ['px-6dcf5134']
discovery.seed_hosts: ['px-6dcf5134']
plugins.security.nodes_dn: 
  - 'CN=CONTROL-M_EM_ES_transport,O=ChangeMe,L=ChangeMeL,ST=ChangeMeST,C=CM'

opensearch_dashboards.yml

---
server.port: 15061
server.host: '0.0.0.0'
opensearch.hosts: ['https://localhost:19200']
opensearch.ssl.verificationMode: certificate
opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"]

opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: ["Global"]
opensearch_security.multitenancy.tenants.enable_private: false
opensearch_security.readonly_mode.roles: ["kibana_read_only","kibana_read"]
opensearch_security.cookie.secure: false

# Use this setting if you are running opensearch-dashboards without https
#server.rewriteBasePath: true
server.basePath: "/services-proxy/kibana"
csp.warnLegacyBrowsers: false
csp.rules:
 - "script-src 'unsafe-eval' 'self' 'unsafe-inline'"
# Options for the logging rotate feature
logging.rotate:
   enabled: true
   everyBytes: 10000000
   keepFiles: 5
   usePolling: true
   pollingInterval: 10000

#logging.quiet : true
#logging.verbose: true
opensearch.ssl.certificateAuthorities: ['C:\\Program Files\\BMC Software\\Control-M EM\\Default\\ini\\ssl\\elastic_ca.pem']
logging.dest: C:\Program Files\BMC Software\Control-M EM\Default\log\services\workflow_insights\opensearch-dashboards.log
server.ssl.enabled: true
server.ssl.key: C:\Program Files\BMC Software\Control-M EM\Default\opensearch-dashboards\config\certificates\kibana-node-key.pem
server.ssl.certificate: C:\Program Files\BMC Software\Control-M EM\Default\opensearch-dashboards\config\certificates\kibana-node-crt.pem
opensearch.ssl.key: C:\Program Files\BMC Software\Control-M EM\Default\opensearch-dashboards\config\certificates\kibana-node-key.pem
opensearch.ssl.certificate: C:\Program Files\BMC Software\Control-M EM\Default\opensearch-dashboards\config\certificates\kibana-node-crt.pem

roles.yml

_meta:
  type: "roles"
  config_version: 2

kibana_only_read:
  reserved: false
  cluster_permissions:
    - cluster_composite_ops_ro
  index_permissions:
    - index_patterns:
        - '*'
      allowed_actions:
        - 'read'
  tenant_permissions:
    - tenant_patterns:
        - 'global_tenant'
      allowed_actions:
        - 'kibana_all_write'
        

# Restrict users so they can only view visualization and dashboard on kibana
kibana_read_only:
  reserved: true

# The security REST API access role is used to assign specific users access to change the security settings through the REST API.
security_rest_api_access:
  reserved: true
 
# Allows users to view monitors, destinations and alerts
alerting_read_access:
  reserved: true
  cluster_permissions:
    - 'cluster:admin/opendistro/alerting/alerts/get'
    - 'cluster:admin/opendistro/alerting/destination/get'
    - 'cluster:admin/opendistro/alerting/monitor/get'
    - 'cluster:admin/opendistro/alerting/monitor/search'

# Allows users to view and acknowledge alerts
alerting_ack_alerts:
  reserved: true
  cluster_permissions:
    - 'cluster:admin/opendistro/alerting/alerts/*'

# Allows users to use all alerting functionality
alerting_full_access:
  reserved: true
  cluster_permissions:
    - 'cluster_monitor'
    - 'cluster:admin/opendistro/alerting/*'
  index_permissions:
    - index_patterns:
        - '*'
      allowed_actions:
        - 'indices_monitor'
        - 'indices:admin/aliases/get'
        - 'indices:admin/mappings/get'

# Allow users to read Anomaly Detection detectors and results
anomaly_read_access:
  reserved: true
  cluster_permissions:
    - 'cluster:admin/opendistro/ad/detector/info'
    - 'cluster:admin/opendistro/ad/detector/search'
    - 'cluster:admin/opendistro/ad/detectors/get'
    - 'cluster:admin/opendistro/ad/result/search'

# Allows users to use all Anomaly Detection functionality
anomaly_full_access:
  reserved: true
  cluster_permissions:
    - 'cluster_monitor'
    - 'cluster:admin/opendistro/ad/*'
  index_permissions:
    - index_patterns:
        - '*'
      allowed_actions:
        - 'indices_monitor'
        - 'indices:admin/aliases/get'
        - 'indices:admin/mappings/get'

# Allows users to read and download Reports
reports_instances_read_access:
  reserved: true
  cluster_permissions:
    - 'cluster:admin/opendistro/reports/instance/list'
    - 'cluster:admin/opendistro/reports/instance/get'
    - 'cluster:admin/opendistro/reports/menu/download'

# Allows users to read and download Reports and Report-definitions
reports_read_access:
  reserved: true
  cluster_permissions:
    - 'cluster:admin/opendistro/reports/definition/get'
    - 'cluster:admin/opendistro/reports/definition/list'
    - 'cluster:admin/opendistro/reports/instance/list'
    - 'cluster:admin/opendistro/reports/instance/get'
    - 'cluster:admin/opendistro/reports/menu/download'

# Allows users to all Reports functionality
reports_full_access:
  reserved: true
  cluster_permissions:
    - 'cluster:admin/opendistro/reports/definition/create'
    - 'cluster:admin/opendistro/reports/definition/update'
    - 'cluster:admin/opendistro/reports/definition/on_demand'
    - 'cluster:admin/opendistro/reports/definition/delete'
    - 'cluster:admin/opendistro/reports/definition/get'
    - 'cluster:admin/opendistro/reports/definition/list'
    - 'cluster:admin/opendistro/reports/instance/list'
    - 'cluster:admin/opendistro/reports/instance/get'
    - 'cluster:admin/opendistro/reports/menu/download'

roles_mapping.yml

---
# In this file users, backendroles and hosts can be mapped to Security roles.
# Permissions for OpenSearch roles are configured in roles.yml

_meta:
  type: "rolesmapping"
  config_version: 2

# Define your roles mapping here

## Demo roles mapping

all_access:
  reserved: false
  backend_roles:
  - "admin"
  description: "Maps admin to all_access"

own_index:
  reserved: false
  users:
  - "*"
  description: "Allow full access to an index named like the username"

logstash:
  reserved: false
  backend_roles:
  - "logstash"

kibana_user:
  reserved: false
  backend_roles:
  - "kibanauser"
  description: "Maps kibanauser to kibana_user"

readall:
  reserved: false
  backend_roles:
  - "readall"

manage_snapshots:
  reserved: false
  backend_roles:
  - "snapshotrestore"

kibana_server:
  reserved: true
  users:
  - "kibanaserver"

Relevant Logs or Screenshots:

opensearch-dashboards.log

{"type":"log","@timestamp":"2025-03-10T09:07:12Z","tags":["warning","config","deprecation"],"pid":408,"message":"You should set server.basePath along with server.rewriteBasePath. OpenSearch Dashboards will expect that all requests start with server.basePath rather than expecting you to rewrite the requests in your reverse proxy. Set server.rewriteBasePath to false to preserve the current behavior and silence this warning."}
{"type":"log","@timestamp":"2025-03-10T09:07:12Z","tags":["warning","config","deprecation"],"pid":408,"message":"\"opensearch.requestHeadersWhitelist\" is deprecated and has been replaced by \"opensearch.requestHeadersAllowlist\""}
{"type":"log","@timestamp":"2025-03-10T09:07:12Z","tags":["info","dynamic-config-service"],"pid":408,"message":"registering middleware to inject context to AsyncLocalStorage"}
{"type":"log","@timestamp":"2025-03-10T09:07:12Z","tags":["info","plugins-system"],"pid":408,"message":"Setting up [56] plugins: [usageCollection,opensearchDashboardsUsageCollection,opensearchDashboardsLegacy,mapsLegacy,share,opensearchUiShared,embeddable,legacyExport,expressions,data,savedObjects,queryEnhancements,home,dashboard,visualizations,tileMap,visTypeVega,visTypeTimeline,visTypeTable,visTypeMarkdown,visBuilder,visAugmenter,regionMap,inputControlVis,visualize,ganttChartDashboards,apmOss,management,indexPatternManagement,dataSourceManagement,securityAnalyticsDashboards,searchRelevanceDashboards,reportsDashboards,mlCommonsDashboards,indexManagementDashboards,flowFrameworkDashboards,customImportMapDashboards,assistantDashboards,anomalyDetectionDashboards,alertingDashboards,console,queryInsightsDashboards,notificationsDashboards,advancedSettings,dataExplorer,charts,visTypeVislib,visTypeTimeseries,visTypeTagcloud,visTypeMetric,discover,savedObjectsManagement,securityDashboards,observabilityDashboards,queryWorkbenchDashboards,bfetch]"}
{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["info","plugins","queryEnhancements"],"pid":408,"message":"queryEnhancements: Setup complete"}
{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["info","dynamic-config-service"],"pid":408,"message":"initiating start()"}
{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["info","dynamic-config-service"],"pid":408,"message":"finished start()"}
{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["info","savedobjects-service"],"pid":408,"message":"Waiting until all OpenSearch nodes are compatible with OpenSearch Dashboards before starting saved objects migrations..."}
{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["error","opensearch","data"],"pid":408,"message":"[ResponseError]: Response Error"}
{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["error","savedobjects-service"],"pid":408,"message":"Unable to retrieve version information from OpenSearch nodes."}
{"type":"log","@timestamp":"2025-03-10T09:07:16Z","tags":["error","opensearch","data"],"pid":408,"message":"[ResponseError]: Response Error"}
{"type":"log","@timestamp":"2025-03-10T09:07:18Z","tags":["error","opensearch","data"],"pid":408,"message":"[ResponseError]: Response Error"}
{"type":"log","@timestamp":"2025-03-10T09:07:21Z","tags":["error","opensearch","data"],"pid":408,"message":"[ResponseError]: Response Error"}
{"type":"log","@timestamp":"2025-03-10T09:07:23Z","tags":["error","opensearch","data"],"pid":408,"message":"[ResponseError]: Response Error"}

@nap608 As per your issue title and logs

{"type":"log","@timestamp":"2025-03-10T09:07:13Z","tags":["error","savedobjects-service"],"pid":408,"message":"Unable to retrieve version information from OpenSearch nodes."}

It means that OpenSearch Dashboards can’t connect to OpenSearch node (localhost:19200)

How did you deploy the cluster? Are OpenSearch Dashobards and OpenSearch on the same virtual machine?

Can you connect to the cluster with curl from OpenSearch Dashboards VM?

curl --insecure -u <username>:<password> -XGET https://localhost:19200

Did you test curl with this certificate and key?

curl --insecure --cert C:\Program Files\BMC Software\Control-M EM\Default\opensearch-dashboards\config\certificates\kibana-node-crt.pem --key C:\Program Files\BMC Software\Control-M EM\Default\opensearch-dashboards\config\certificates\kibana-node-key.pem -XGET https://localhost:19200

Please share your config.yml file.

“How did you deploy the cluster?”
Extracted on windows VMs (3 nodes)
“Are OpenSearch Dashobards and OpenSearch on the same virtual machine?”
Yes
“Can you connect to the cluster with curl from OpenSearch Dashboards VM?”
Yes

======================================================
curl works :backhand_index_pointing_down:t2:

curl --insecure -u  -XGET https://px-cfd24e77:19200
{
  "name" : "px-cfd24e77",
  "cluster_name" : "workflow_insights_cluster",
  "cluster_uuid" : "UM17HduLRcqLNxC0V3HPQQ",
  "version" : {
    "distribution" : "opensearch",
    "number" : "2.19.1",
    "build_type" : "zip",
    "build_hash" : "2e4741fb45d1b150aaeeadf66d41445b23ff5982",
    "build_date" : "2025-02-27T01:30:51.732081Z",
    "build_snapshot" : false,
    "lucene_version" : "9.12.1",
    "minimum_wire_compatibility_version" : "7.10.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "The OpenSearch Project: https://opensearch.org/"
}

======================================================
config.yml

---

_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    http:
      anonymous_auth_enabled: false
      xff:
        enabled: false
        internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern

    authc:
      kerberos_auth_domain:
        http_enabled: false
        transport_enabled: false
        order: 6
        http_authenticator:
          type: kerberos
          challenge: true
          config:
            # If true a lot of kerberos/security related debugging output will be logged to standard out
            krb_debug: false
            # If true then the realm will be stripped from the user name
            strip_realm_from_principal: true
        authentication_backend:
          type: noop
      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
      proxy_auth_domain:
        description: "Authenticate via proxy"
        http_enabled: false
        transport_enabled: false
        order: 3
        http_authenticator:
          type: proxy
          challenge: false
          config:
            user_header: "x-proxy-user"
            roles_header: "x-proxy-roles"
        authentication_backend:
          type: noop
      jwt_auth_domain:
        description: "Authenticate via Json Web Token"
        http_enabled: false
        transport_enabled: false
        order: 0
        http_authenticator:
          type: jwt
          challenge: false
          config:
            signing_key: "base64 encoded HMAC key or public RSA/ECDSA pem key"
            jwt_header: "Authorization"
            jwt_url_parameter: null
            jwt_clock_skew_tolerance_seconds: 30
            roles_key: null
            subject_key: null
        authentication_backend:
          type: noop
      clientcert_auth_domain:
        description: "Authenticate via SSL client certificates"
        http_enabled: true
        transport_enabled: true
        order: 1
        http_authenticator:
          type: clientcert
          config:
            username_attribute: cn #optional, if omitted DN becomes username
          challenge: false
        authentication_backend:
          type: noop
      ldap:
        description: "Authenticate via LDAP or Active Directory"
        http_enabled: false
        transport_enabled: false
        order: 5
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          # LDAP authentication backend (authenticate users against a LDAP or Active Directory)
          type: ldap
          config:
            # enable ldaps
            enable_ssl: false
            # enable start tls, enable_ssl should be false
            enable_start_tls: false
            # send client certificate
            enable_ssl_client_auth: false
            # verify ldap hostname
            verify_hostnames: true
            hosts:
            - localhost:8389
            bind_dn: null
            password: null
            userbase: 'ou=people,dc=example,dc=com'
            # Filter to search for users (currently in the whole subtree beneath userbase)
            # {0} is substituted with the username
            usersearch: '(sAMAccountName={0})'
            # Use this attribute from the user as username (if not set then DN is used)
            username_attribute: null
    authz:
      roles_from_myldap:
        description: "Authorize via LDAP or Active Directory"
        http_enabled: false
        transport_enabled: false
        authorization_backend:
          # LDAP authorization backend (gather roles from a LDAP or Active Directory, you have to configure the above LDAP authentication backend settings too)
          type: ldap
          config:
            # enable ldaps
            enable_ssl: false
            # enable start tls, enable_ssl should be false
            enable_start_tls: false
            # send client certificate
            enable_ssl_client_auth: false
            # verify ldap hostname
            verify_hostnames: true
            hosts:
            - localhost:8389
            bind_dn: null
            password: null
            rolebase: 'ou=groups,dc=example,dc=com'
            # Filter to search for roles (currently in the whole subtree beneath rolebase)
            # {0} is substituted with the DN of the user
            # {1} is substituted with the username
            # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute
            rolesearch: '(member={0})'
            # Specify the name of the attribute which value should be substituted with {2} above
            userroleattribute: null
            # Roles as an attribute of the user entry
            userrolename: disabled
            #userrolename: memberOf
            # The attribute in a role entry containing the name of that role, Default is "name".
            # Can also be "dn" to use the full DN as rolename.
            rolename: cn
            # Resolve nested roles transitive (roles which are members of other roles and so on ...)
            resolve_nested_roles: true
            userbase: 'ou=people,dc=example,dc=com'
            # Filter to search for users (currently in the whole subtree beneath userbase)
            # {0} is substituted with the username
            usersearch: '(uid={0})'
            # Skip users matching a user name, a wildcard or a regex pattern
            #skip_users:
            #  - 'cn=Michael Jackson,ou*people,o=TEST'
            #  - '/\S*/'
      roles_from_another_ldap:
        description: "Authorize via another Active Directory"
        http_enabled: false
        transport_enabled: false
        authorization_backend:
          type: ldap

@nap608 Please check my curl again. Your curl is using basic authentication.
The one I shared is using certificates that you’ve configured in OpenSearch Dashboards.

The issue is resolved, it was related to how I defined the user permissions

thanks anyway pablo.

1 Like