trombik.opensearch

trombik.opensearch

An ansible role for managing opensearch.

The role is currently in beta.

For FreeBSD Users

The example requires a custom version of opensearch-dashboards for FreeBSD, available at trombik/freebsd-ports-opensearch. It also uses trombik.opensearch_dashboards. However, it relies on www/node10, which is now end-of-life and not recommended.

For an upgrade plan, see Issue 835.

For Debian and CentOS Users

This role installs opensearch using the official tar file. This is a temporary solution until Amazon or the relevant distributions provide proper packages.

Variables related to source installation, opensearch_src_*, are intentionally not documented.

The role does not install the JDK package; it uses the bundled JDK instead.

The role imports a PGP key into the root keyring from the upstream project to verify the tar file. If you know how to verify a signed file without importing a PGP key, please share.

Some plugins may not work yet.

Modifications from the default setup include:

  • Log files are saved in /var/log/opensearch
  • The application is installed under opensearch_root_dir, defaulting to /usr/local/opensearch-dashboards
  • The application runs under the user opensearch

These modifications will be revised once an official package is available.

The role downloads the official tar archive to opensearch_src_dir, which defaults to /var/dist. This directory also holds the PGP key, signature file, and task control files for ansible.

A systemd unit file for opensearch will be installed, but the author does not claim expertise in systemd.

Requirements

By default, the role uses trombik.x509_certificate to manage X509 certificates. It is not listed as a dependency since TLS is optional.

Role Variables

Variable Description Default
opensearch_user Username for opensearch {{ __opensearch_user }}
opensearch_group Group name for opensearch {{ __opensearch_group }}
opensearch_log_dir Path to log directory {{ __opensearch_log_dir }}
opensearch_db_dir Path to data directory {{ __opensearch_db_dir }}
opensearch_scripts_dir Path to script directory {{ __opensearch_scripts_dir }}
opensearch_plugins_dir Path to plugin directory {{ __opensearch_plugins_dir }}
opensearch_plugin_command Path to opensearch-plugin command {{ __opensearch_plugin_command }}
opensearch_plugins List of plugins (see below) []
opensearch_service Service name for opensearch {{ __opensearch_service }}
opensearch_package Package name for opensearch {{ __opensearch_package }}
opensearch_conf_dir Path to the configuration directory {{ __opensearch_conf_dir }}
opensearch_jvm_options JVM options (see example playbook) ""
opensearch_conf_file Path to opensearch.yml {{ opensearch_conf_dir }}/opensearch.yml
opensearch_flags Extra flags for startup scripts ""
opensearch_config Content of opensearch.yml ""
opensearch_config_log4j2_properties Content for log4j2.properties ""
opensearch_http_host Address or hostname for opensearch; must be accessible from ansible controller localhost
opensearch_http_port Listening port for opensearch; must be accessible from ansible controller 9200
opensearch_http_url URL of HTTP interface; must be accessible from ansible controller https://{{ opensearch_http_host }}:{{ opensearch_http_port }}
opensearch_http_auth Authentication details for API access {}
opensearch_java_home JAVA_HOME environment variable {{ __opensearch_java_home }}
opensearch_extra_plugin_files List of extra files for plugins (see below) []
opensearch_include_role_x509_certificate Include trombik.x509_certificate during play yes
opensearch_x509_certificate_vars Variables for trombik.x509_certificate {}
opensearch_wait_for_cluster_status Wait for cluster status after starting service; valid values include red, yellow, green, false no
opensearch_wait_for_cluster_status_timeout Timeout when waiting for cluster status 10s
opensearch_wait_for_cluster_status_retry Number of retries while waiting for cluster status 3

opensearch_plugins

This is a list of plugins. Each element in the list is a dictionary.

Key Description Mandatory?
name Name of the plugin Yes
src Source URL of the plugin No

opensearch_extra_plugin_files

This variable is a list of files for plugins. Each element in the list is a dictionary.

Key Description Mandatory?
path Relative path to file from opensearch_plugins_dir Yes
type Either yaml or raw. If yaml, content rendered as YAML; if raw, content is rendered as-is. No
mode File permissions No
owner Owner of the file No
group Group of the file No
state Either present (create file) or absent (delete file), default is present No
content Content of the file (see type) No
post_command A dictionary for ansible.builtin.command No

post_command runs a command after the item status changes. It accepts the following keys:

Key Description Mandatory?
cmd Command to run Yes
args Args dictionary (supports chdir, creates, and removes) No
enabled Either yes or no; if yes, the command will run Yes

Primarily designed for securityadmin.sh. See Apply changes using securityadmin.sh for more details.

opensearch_http_auth

This variable is a dictionary used for user credentials when accessing API endpoints at opensearch_http_url.

Key Description Mandatory?
client_cert Path to client public key in PEM format No
client_key Path to client secret key in PEM format No
ca_path Path to CA's public key in PEM format No
url_username Username for basic authentication No
url_password Password for basic authentication No
validate_certs Verify remote certificate No

Known Issues with opensearch_http_auth and TLS

opensearch supports basic authentication and TLS client certificate authentication over TLS. However, some configurations may lead to failed API calls.

It's recommended to use basic authentication over TLS with ca_path. Avoid using TLS client authentication without username and password as it requires validate_certs to be set to no.

Platform-Specific Variable Defaults

Debian

Variable Default
__opensearch_user opensearch
__opensearch_group opensearch
__opensearch_log_dir /var/log/opensearch
__opensearch_db_dir /var/lib/opensearch
__opensearch_package opensearch
__opensearch_conf_dir /usr/local/opensearch/config
__opensearch_root_dir /usr/local/opensearch
__opensearch_plugins_dir /usr/local/opensearch/plugins
__opensearch_plugin_command /usr/local/opensearch/bin/opensearch-plugin
__opensearch_service opensearch
__opensearch_java_home /usr/local/opensearch/jdk

FreeBSD

Variable Default
__opensearch_user opensearch
__opensearch_group opensearch
__opensearch_log_dir /var/log/opensearch
__opensearch_db_dir /var/db/opensearch
__opensearch_package textproc/opensearch
__opensearch_conf_dir /usr/local/etc/opensearch
__opensearch_plugins_dir /usr/local/lib/opensearch/plugins
__opensearch_plugin_command /usr/local/lib/opensearch/bin/opensearch-plugin
__opensearch_service opensearch
__opensearch_java_home /usr/local

RedHat

Variable Default
__opensearch_user opensearch
__opensearch_group opensearch
__opensearch_log_dir /var/log/opensearch
__opensearch_db_dir /var/lib/opensearch
__opensearch_package opensearch
__opensearch_conf_dir /usr/local/opensearch/config
__opensearch_root_dir /usr/local/opensearch
__opensearch_plugins_dir /usr/local/opensearch/plugins
__opensearch_plugin_command /usr/local/opensearch/bin/opensearch-plugin
__opensearch_service opensearch
__opensearch_java_home /usr/local/opensearch/jdk

Dependencies

Example Playbook

This example shows how to install:

  • opensearch
  • opensearch-dashboards
  • haproxy
  • fluentd

haproxy acts as a reverse proxy for opensearch-dashboards. Logs from haproxy and syslog are sent to a local fluentd listener, which processes and forwards them to opensearch. The index pattern used is logstash-*.

Note that the fluentd elasticsearch output plugin does not support opensearch. This is worked around by:

  • Installing specific versions of fluentd-elasticsearch-plugin and related gems.
  • Setting verify_es_version_at_startup and default_elasticsearch_version in fluentd.conf.

Use the user admin with password admin to log in to the dashboards.

For a clustered example, see tests/serverspec/cluster.yml.

---
- hosts: localhost
  pre_tasks:
    - name: Allow HTTP port
      ansible.builtin.iptables:
        chain: INPUT
        destination_port: 80
        protocol: tcp
        jump: ACCEPT
      when: ansible_os_family == 'RedHat'

    - name: Enable syslog forwarding from rsyslog
      ansible.builtin.copy:
        dest: /etc/rsyslog.d/fluentd.conf
        content: |
          *.*;syslog;auth,authpriv.none action(
            Target="127.0.0.1"
            type="omfwd"
            Port="1514"
            Protocol="udp"
            template="RSYSLOG_SyslogProtocol23Format"
          )
        mode: "0644"
      when:
        - ansible_os_family == 'Debian' or ansible_os_family == 'RedHat'
      register: __register_project_rsyslog_config

    - name: Restart rsyslog
      ansible.builtin.service:
        name: rsyslog
        state: restarted
      when:
        - ansible_os_family == 'Debian' or ansible_os_family == 'RedHat'
        - __register_project_rsyslog_config['changed']

    - name: Enable syslog forwarding from syslogd
      ansible.builtin.copy:
        dest: /etc/syslog.d/fluentd.conf
        content: |
          *.*						@127.0.0.1:1514
        mode: "0644"
      when: ansible_os_family == 'FreeBSD'
      register: __register_project_syslog_config

    - name: Enable syslog rfc5424
      ansible.builtin.copy:
        dest: /etc/rc.conf.d/syslogd
        content: |
          syslogd_flags="-s -O rfc5424"
        mode: "0644"
      when: ansible_os_family == 'FreeBSD'
      register: __register_project_syslog_flags

    - name: Restart syslogd
      ansible.builtin.service:
        name: syslogd
        state: restarted
      when:
        - ansible_os_family == 'FreeBSD'
        - __register_project_syslog_config['changed'] or __register_project_syslog_flags['changed']
  roles:
    - role: trombik.freebsd_pkg_repo
      when: ansible_os_family == "FreeBSD"
    - name: trombik.apt_repo
      when: ansible_os_family == 'Debian'
    - name: trombik.redhat_repo
      when: ansible_os_family == 'RedHat'
    - role: trombik.java
      when: ansible_os_family == "FreeBSD"
    - role: trombik.sysctl
    - ansible-role-opensearch
    - role: trombik.opensearch_dashboards
    - role: trombik.fluentd
    - role: trombik.haproxy
  vars:
    freebsd_pkg_repo:
      local:
        enabled: "true"
        url: "http://pkg.i.trombik.org/{{ ansible_distribution_version | regex_replace('\\.') }}{{ ansible_architecture }}-default-default"
        mirror_type: none
        priority: 100
        state: present
    os_opensearch_extra_packages:
      FreeBSD: []
      Debian:
        - unzip
      RedHat: []
    opensearch_extra_packages: "{{ os_opensearch_extra_packages[ansible_os_family] }}"
    os_java_packages:
      FreeBSD:
        - openjdk11
        - jq
        - vim
        - tmux
        - p5-ack
      Debian:
        - openjdk-11-jdk
      RedHat:
        - java-11-openjdk-devel
    java_packages: "{{ os_java_packages[ansible_os_family] }}"
    os_sysctl:
      FreeBSD:
        kern.maxfilesperproc: 65536
        security.bsd.unprivileged_mlock: 1
      Debian:
        vm.max_map_count: 262144
      RedHat:
        vm.max_map_count: 262144
    sysctl: "{{ os_sysctl[ansible_os_family] }}"
    opensearch_wait_for_cluster_status: yellow
    os_opensearch_package:
      FreeBSD: "{{ __opensearch_package }}"
      Debian: "{{ __opensearch_package }}"
      RedHat: opensearch-1.13.2
    opensearch_package: "{{ os_opensearch_package[ansible_os_family] }}"
    os_opensearch_flags:
      FreeBSD: ""
      Debian: |
        ES_PATH_CONF={{ opensearch_conf_dir }}
        ES_STARTUP_SLEEP_TIME=5
      RedHat: |
        ES_PATH_CONF={{ opensearch_conf_dir }}
        ES_STARTUP_SLEEP_TIME=5
    opensearch_flags: "{{ os_opensearch_flags[ansible_os_family] }}"
    os_opensearch_jvm_options:
      FreeBSD: ""
      Debian: |
        -Dclk.tck=100
        -Djdk.attach.allowAttachSelf=true
        -Djava.security.policy={{ opensearch_root_dir }}/plugins/opensearch-performance-analyzer/pa_config/opensearch_security.policy
      RedHat: |
        -Dclk.tck=100
        -Djdk.attach.allowAttachSelf=true
        -Djava.security.policy={{ opensearch_root_dir }}/plugins/opensearch-performance-analyzer/pa_config/opensearch_security.policy

    os_opensearch_http_auth:
      FreeBSD:
        url_username: admin
        url_password: admin
        ca_path: "{{ role_path }}/files/test/certs/root-ca.pem"
        validate_certs: yes
      Debian:
        client_cert: "{{ role_path }}/files/test/certs/admin.pem"
        client_key: "{{ role_path }}/files/test/certs/admin-key.pem"
        validate_certs: no
      RedHat:
        client_cert: "{{ role_path }}/files/test/certs/admin.pem"
        client_key: "{{ role_path }}/files/test/certs/admin-key.pem"
        validate_certs: no
    opensearch_http_auth: "{{ os_opensearch_http_auth[ansible_os_family] }}"
    opensearch_jvm_options: "{{ lookup('file', 'test/jvm_options') + os_opensearch_jvm_options[ansible_os_family] }}"
    opensearch_config:
      discovery.type: single-node
      network.publish_host: ["10.0.2.15"]
      path.data: "{{ opensearch_db_dir }}"
      http.port: "{{ opensearch_http_port }}"
      path.logs: "{{ opensearch_log_dir }}"
      node.data: "true"
      http.compression: "true"
      network.host:
        - "{{ opensearch_http_host }}"
        - _site_
      cluster.name: testcluster
      node.name: testnode
      http.cors.enabled: "true"
      http.cors.allow-origin: "*"
      http.cors.max-age: 86400
      http.cors.allow-methods: "OPTIONS, HEAD, GET, POST, PUT, DELETE"
      http.cors.allow-headers: "X-Requested-With, Content-Type, Content-Length"
      http.cors.allow-credentials: "true"
      plugins.security.ssl.transport.pemcert_filepath: node.pem
      plugins.security.ssl.transport.pemkey_filepath: node-key.pem
      plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem
      plugins.security.ssl.transport.enforce_hostname_verification: false
      plugins.security.ssl.http.enabled: true
      plugins.security.ssl.http.pemcert_filepath: node.pem
      plugins.security.ssl.http.pemkey_filepath: node-key.pem
      plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem
      plugins.security.allow_unsafe_democertificates: true
      plugins.security.allow_default_init_securityindex: true
      plugins.security.authcz.admin_dn:
        - CN=Admin,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU
      plugins.security.nodes_dn:
        - CN=localhost,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU

      plugins.security.advanced_modules_enabled: false
      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: [".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*"]

      plugins.security.disabled: false
      cluster.routing.allocation.disk.threshold_enabled: false

    project_security_plugin_dir: "{{ opensearch_plugins_dir }}/opensearch-security"
    project_securityadmin_bin: "{{ project_security_plugin_dir }}/tools/securityadmin.sh"
    project_security_plugin_post_command:
      cmd: "{{ project_securityadmin_bin }} -icl -nhnv -cacert {{ opensearch_conf_dir }}/root-ca.pem -cert {{ opensearch_conf_dir }}/admin.pem -key {{ opensearch_conf_dir }}/admin-key.pem"
      args:
        chdir: "{{ project_security_plugin_dir }}/securityconfig"
      enabled: "{% if 1 == 1 %}yes{% else %}no{% endif %}"

    opensearch_plugins: []
    opensearch_extra_plugin_files:
      - path: opensearch-security/securityconfig/action_groups.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/action_groups.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/audit.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/audit.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/config.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/config.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/internal_users.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/internal_users.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/nodes_dn.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/nodes_dn.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/roles.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/roles.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/roles_mapping.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/roles_mapping.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/tenants.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/tenants.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"
      - path: opensearch-security/securityconfig/whitelist.yml
        type: yaml
        mode: "0640"
        group: "{{ opensearch_user }}"
        content: "{{ lookup('file', 'test/securityconfig/whitelist.yml') | from_yaml }}"
        post_command: "{{ project_security_plugin_post_command }}"

    opensearch_config_log4j2_properties: "{{ lookup('file', 'test/log4j2_properties') }}"

    x509_certificate_debug_log: yes
    x509_certificate:
      - name: node
        state: present
        public:
          path: "{{ opensearch_conf_dir }}/node.pem"
          mode: "0444"
          key: "{{ lookup('file', 'test/certs/node.pem') }}"
        secret:
          path: "{{ opensearch_conf_dir }}/node-key.pem"
          owner: "{{ opensearch_user }}"
          group: "{{ opensearch_group }}"
          mode: "0600"
          key: "{{ lookup('file', 'test/certs/node-key.pem') }}"
      - name: root-ca
        state: present
        public:
          path: "{{ opensearch_conf_dir }}/root-ca.pem"
          key: "{{ lookup('file', 'test/certs/root-ca.pem') }}"
        secret:
          path: "{{ opensearch_conf_dir }}/root-ca-key.pem"
          owner: "{{ opensearch_user }}"
          group: "{{ opensearch_group }}"
          key: "{{ lookup('file', 'test/certs/root-ca-key.pem') }}"
      - name: admin
        state: present
        public:
          path: "{{ opensearch_conf_dir }}/admin.pem"
          key: "{{ lookup('file', 'test/certs/admin.pem') }}"
        secret:
          path: "{{ opensearch_conf_dir }}/admin-key.pem"
          owner: "{{ opensearch_user }}"
          group: "{{ opensearch_group }}"
          key: "{{ lookup('file', 'test/certs/admin-key.pem') }}"

    opensearch_dashboards_config:
      server.host: "{{ opensearch_dashboards_bind_address }}"
      server.port: "{{ opensearch_dashboards_bind_port }}"
      server.name: "OpenSearch Dashboards"
      logging.dest: "{% if ansible_os_family == 'FreeBSD' %}/var/log/opensearch_dashboards.log{% else %}{{ opensearch_dashboards_log_file }}{% endif %}"
      logging.verbose: true
      opensearch.hosts: ["https://localhost:9200"]
      path.data: "{{ opensearch_dashboards_data_dir }}"
      opensearch.ssl.verificationMode: none
    project_backend_host: 127.0.0.1
    project_backend_port: 5601

    # Fluentd and HAProxy configuration would go here...

# License

Copyright (c) 2019 Tomoyuki Sakurai y@trombik.org

Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

```

Author Information

Tomoyuki Sakurai y@trombik.org

This README was created by qansible.

Informazioni sul progetto

Configures opensearch

Installa
ansible-galaxy install trombik.opensearch
Licenza
isc
Download
156
Proprietario
PGP finger print: 03EB 3D97 5E04 9B0C AB21 93A2 D693 42A9 EFBC 3577 Makerspace and Coliving in Siem Reap, Cambodia: http://info.mkrsgh.org/