From 8b734f3a36dde9f0ab68da02c70eb87ce01ff976 Mon Sep 17 00:00:00 2001 From: Maciej Delmanowski Date: Fri, 12 Jan 2024 00:59:49 +0100 Subject: [PATCH 1/2] [elasticsearch] Separate passwords in clusters --- CHANGELOG.rst | 9 +++++++++ ansible/roles/elasticsearch/defaults/main.yml | 13 +++++++++++-- .../roles/elasticsearch/tasks/authentication.yml | 4 ++-- .../roles/elasticsearch/tasks/reset_password.yml | 4 ++-- .../ansible/roles/elasticsearch/getting-started.rst | 6 +++--- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 274f140e4b..3dee4c9a4e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -41,6 +41,15 @@ Changed - The role now supports new Elasticsearch v8.x password management mechanism. +- The role can now manage passwords in separate Elasticsearch clusters defined + in one Ansible inventory. + + .. warning:: Due to this change, Elasticsearch passwords stored in the + :file:`ansible/secret/` subdirectory will be read from a different + location. If passwords are not moved to the new location, role + will reset the Elasticsearch built-in users passwords + automatically. This might result in data loss. + `debops v3.1.0`_ - 2023-11-29 ----------------------------- diff --git a/ansible/roles/elasticsearch/defaults/main.yml b/ansible/roles/elasticsearch/defaults/main.yml index 5fe196617f..07b49a1c78 100644 --- a/ansible/roles/elasticsearch/defaults/main.yml +++ b/ansible/roles/elasticsearch/defaults/main.yml @@ -251,13 +251,22 @@ elasticsearch__api_base_url: '{{ "https://" + ansible_fqdn + ":9200" }}' # ``elastic`` user account has superuser privileges. elasticsearch__api_username: 'elastic' + # ]]] +# .. envvar:: elasticsearch__secret_path [[[ +# +# Path to the directory in the :ref:`debops.secret` storage where passwords of +# Elastcisearch built-in users will be stored. +elasticsearch__secret_path: '{{ "elasticsearch/credentials/" + + elasticsearch__cluster_name + "/built-in" }}' + # ]]] # .. envvar:: elasticsearch__api_password [[[ # # The password used to access the Elasticsearch API, stored in the # :file:`secret/` directory, managed by the :ref:`debops.secret` Ansible role. -elasticsearch__api_password: '{{ lookup("password", secret + "/elasticsearch/credentials/" - + "built-in/" + elasticsearch__api_username + "/password") }}' +elasticsearch__api_password: '{{ lookup("password", secret + "/" + + elasticsearch__secret_path + "/" + + elasticsearch__api_username + "/password") }}' # ]]] # .. envvar:: elasticsearch__native_roles [[[ diff --git a/ansible/roles/elasticsearch/tasks/authentication.yml b/ansible/roles/elasticsearch/tasks/authentication.yml index b849cd96f5..1e1926933b 100644 --- a/ansible/roles/elasticsearch/tasks/authentication.yml +++ b/ansible/roles/elasticsearch/tasks/authentication.yml @@ -31,7 +31,7 @@ - name: Create required directories on Ansible Controller ansible.builtin.file: - path: '{{ secret + "/elasticsearch/credentials/built-in/" + item.split()[0] }}' + path: '{{ secret + "/" + elasticsearch__secret_path + "/" + item.split()[0] }}' state: 'directory' mode: '0755' loop: '{{ elasticsearch__register_builtin_users.stdout_lines }}' @@ -43,7 +43,7 @@ - name: Save generated user passwords on Ansible Controller ansible.builtin.copy: content: '{{ item.split()[1] }}' - dest: '{{ secret + "/elasticsearch/credentials/built-in/" + item.split()[0] + "/password" }}' + dest: '{{ secret + "/" + elasticsearch__secret_path + "/" + item.split()[0] + "/password" }}' mode: '0644' loop: '{{ elasticsearch__register_builtin_users.stdout_lines }}' become: False diff --git a/ansible/roles/elasticsearch/tasks/reset_password.yml b/ansible/roles/elasticsearch/tasks/reset_password.yml index f273f8ba55..9f43897c2a 100644 --- a/ansible/roles/elasticsearch/tasks/reset_password.yml +++ b/ansible/roles/elasticsearch/tasks/reset_password.yml @@ -16,7 +16,7 @@ - name: Create required directories on Ansible Controller ansible.builtin.file: - path: '{{ secret + "/elasticsearch/credentials/built-in/" + item }}' + path: '{{ secret + "/" + elasticsearch__secret_path + "/" + item }}' state: 'directory' mode: '0755' become: False @@ -27,7 +27,7 @@ - name: Save generated password of account '{{ item }}' ansible.builtin.copy: content: '{{ elasticsearch__register_builtin_password.stdout }}' - dest: '{{ secret + "/elasticsearch/credentials/built-in/" + item + "/password" }}' + dest: '{{ secret + "/" + elasticsearch__secret_path + "/" + item + "/password" }}' mode: '0644' become: False delegate_to: 'localhost' diff --git a/docs/ansible/roles/elasticsearch/getting-started.rst b/docs/ansible/roles/elasticsearch/getting-started.rst index 72ad42c984..4d08ed1a68 100644 --- a/docs/ansible/roles/elasticsearch/getting-started.rst +++ b/docs/ansible/roles/elasticsearch/getting-started.rst @@ -49,9 +49,9 @@ With secure cluster communication over TLS, the :ref:`debops.elasticsearch` role can use the Elasticsearch API to manage user accounts and role definitions in the cluster. A default set of `built-in users`__ will be created automatically; passwords of these users will be stored in the -:file:`secret/elasticsearch/credentials/built-in/` directory on the Ansible -Controller (managed by the :ref:`debops.secret` role). After that, with the -base URL of the Elasticsearch API set in the +:file:`secret/elasticsearch/credentials//built-in/` directory on +the Ansible Controller (managed by the :ref:`debops.secret` role). After that, +with the base URL of the Elasticsearch API set in the :envvar:`elasticsearch__api_base_url` variable, the role can manage Elasticsearch roles and user accounts using the ``elastic`` superuser account. From 4e4a48b83274ba3b7f2da8751883a1697cd33f2c Mon Sep 17 00:00:00 2001 From: Maciej Delmanowski Date: Fri, 12 Jan 2024 01:33:16 +0100 Subject: [PATCH 2/2] [kibana] Use new Elasticsearch password scheme --- CHANGELOG.rst | 11 +++++++++ ansible/roles/kibana/defaults/main.yml | 23 +++++++++++++++++-- docs/ansible/roles/kibana/getting-started.rst | 20 ++++++++++++---- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3dee4c9a4e..dbfede8502 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -50,6 +50,17 @@ Changed will reset the Elasticsearch built-in users passwords automatically. This might result in data loss. +:ref:`debops.kibana` role +''''''''''''''''''''''''' + +- The path to the password file stored in :file:`ansible/secret/` subdirectory + is now configurable using a variable. + +- The role uses new per-cluster Elasticsearch passwords by default. This is + done using a separate :envvar:`kibana__elasticsearch_cluster_name` variable, + which needs to be synchronized with the Elasticsearch configuration via + Ansible inventory (Kibana can be installed separately from Elasticsearch). + `debops v3.1.0`_ - 2023-11-29 ----------------------------- diff --git a/ansible/roles/kibana/defaults/main.yml b/ansible/roles/kibana/defaults/main.yml index e3f56392cf..db36a5c73f 100644 --- a/ansible/roles/kibana/defaults/main.yml +++ b/ansible/roles/kibana/defaults/main.yml @@ -156,6 +156,14 @@ kibana__elasticsearch_url: 'http://localhost:9200' # This variable is used on Kibana >= 7.0.0. kibana__elasticsearch_hosts: [ 'http://localhost:9200' ] + # ]]] +# .. envvar:: kibana__elasticsearch_cluster_name [[[ +# +# Name of the Elasticsearch cluster, used to lookup passwords in the +# :ref:`debops.secret` subdirectory. This variable should be synchronized with +# the :envvar:`elasticsearch__cluster_name` variable using Ansible inventory. +kibana__elasticsearch_cluster_name: '{{ kibana__domain | replace(".", "-") }}' + # ]]] # .. envvar:: kibana__elasticsearch_username [[[ # @@ -167,6 +175,16 @@ kibana__elasticsearch_username: '{{ "" if (kibana__version is version("7.0.0", "<")) else "kibana_system") }}' + # ]]] +# .. envvar:: kibana__elasticsearch_secret_path [[[ +# +# Path to the Elasticsearch passwords stored in the :ref:`debops.secret` +# directory. It should be synchronized with :envvar:`elasticsearch__secret_path` +# variable for best results. +kibana__elasticsearch_secret_path: '{{ "elasticsearch/credentials/" + + kibana__elasticsearch_cluster_name + + "/built-in" }}' + # ]]] # .. envvar:: kibana__elasticsearch_password [[[ # @@ -174,8 +192,9 @@ kibana__elasticsearch_username: '{{ "" # Elasticsearch clusters. kibana__elasticsearch_password: '{{ "" if (kibana__elasticsearch_hosts[0].startswith("http://")) - else (lookup("password", secret + "/elasticsearch/credentials/" - + "built-in/" + kibana__elasticsearch_username + else (lookup("password", secret + "/" + + kibana__elasticsearch_secret_path + "/" + + kibana__elasticsearch_username + "/password")) }}' # ]]] diff --git a/docs/ansible/roles/kibana/getting-started.rst b/docs/ansible/roles/kibana/getting-started.rst index 2b3e2746a5..2b63970833 100644 --- a/docs/ansible/roles/kibana/getting-started.rst +++ b/docs/ansible/roles/kibana/getting-started.rst @@ -44,10 +44,22 @@ the Elasticsearch cluster. If the first host used for connections to the Elasticsearch cluster uses a ``https://`` connection, Kibana will try to use the ``kibana_system`` Elasticsearch user account and password stored in the -:file:`secret/elasticsearch/credentials/` directory (managed by the -:ref:`debops.secret` role) to authorize itself with the cluster and set up its -own configuration. After that, you can use other users (notably ``elastic`` -superuser account) to access the web interface. +:file:`secret/elasticsearch/credentials//built-in/kibana_system/password` +file (managed by the :ref:`debops.secret` role) to authorize itself with the +cluster and set up its own configuration. After that, you can use other users +(notably ``elastic`` superuser account) to access the web interface. + +.. note:: Make sure that the Elasticsearch cluster name specified via the + :envvar:`elasticsearch__cluster_name` variable is synchronized with + the :envvar:`kibana__elasticsearch_cluster_name` variable in the + inventory. Otherwise, the :ref:`debops.kibana` role might not find + the correct password file and will not connect with the Elasticsearch + cluster. + + The reason for doing it this way is that Kibana can be installed + separately from Elasticsearch (on separate hosts), and there's no way + for the :ref:`debops.kibana` role to find out the correct cluster + name on its own, if it's not the default. You can install additional plugins that provide encrypted connections, authentication, authorization and access control: