From 5972e878ead7619d5f26229b2ca912752075b31e Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Wed, 17 Jan 2024 19:12:18 +0100 Subject: [PATCH 1/8] Add elasticsearch_role module --- .../elasticsearch_test_modules/converge.yml | 50 ++++++++++++ .../elasticsearch_test_modules/molecule.yml | 34 ++++++++ .../elasticsearch_test_modules/prepare.yml | 23 ++++++ .../requirements.yml | 3 + plugins/module_utils/api.py | 74 +++++++++++++++++ plugins/modules/elasticsearch_role.py | 80 +++++++++++++++++++ plugins/modules/elasticsearch_user.py | 80 +++++++++++++++++++ 7 files changed, 344 insertions(+) create mode 100644 molecule/elasticsearch_test_modules/converge.yml create mode 100644 molecule/elasticsearch_test_modules/molecule.yml create mode 100644 molecule/elasticsearch_test_modules/prepare.yml create mode 100644 molecule/elasticsearch_test_modules/requirements.yml create mode 100644 plugins/module_utils/api.py create mode 100644 plugins/modules/elasticsearch_role.py create mode 100644 plugins/modules/elasticsearch_user.py diff --git a/molecule/elasticsearch_test_modules/converge.yml b/molecule/elasticsearch_test_modules/converge.yml new file mode 100644 index 00000000..672e7b2a --- /dev/null +++ b/molecule/elasticsearch_test_modules/converge.yml @@ -0,0 +1,50 @@ +--- +# The workaround for arbitrarily named role directory is important because the git repo has one name and the role within it another +# Found at: https://github.com/ansible-community/molecule/issues/1567#issuecomment-436876722 +- name: Converge + collections: + - netways.elasticstack + hosts: all + vars: + #elasticsearch_security: true # needed for tests of > 7 releases + elasticstack_full_stack: false + elasticsearch_jna_workaround: true + elasticsearch_disable_systemcallfilterchecks: true + elasticstack_release: 8 + elasticsearch_heap: "1" + elasticstack_no_log: false + tasks: + - name: Include Elastics repos role + ansible.builtin.include_role: + name: repos + - name: Include Elasticsearch + ansible.builtin.include_role: + name: elasticsearch + + - name: Fetch Elastic password # noqa: risky-shell-pipe + ansible.builtin.shell: > + if test -n "$(ps -p $$ | grep bash)"; then set -o pipefail; fi; + grep "PASSWORD elastic" /usr/share/elasticsearch/initial_passwords | + awk {' print $4 '} + register: elasticstack_password + changed_when: false + + - name: Create role + netways.elasticstack.elasticsearch_role: + name: new-role3 + cluster: + - manage_own_api_key + - delegate_pki + indicies: + - names: + - foobar321 + - barfoo123 + privileges: + - read + - write + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: "{{ elasticstack_password.stdout }}" + verify_certs: false + ca_certs: /etc/elasticsearch/certs/http_ca.crt diff --git a/molecule/elasticsearch_test_modules/molecule.yml b/molecule/elasticsearch_test_modules/molecule.yml new file mode 100644 index 00000000..1cfcb2eb --- /dev/null +++ b/molecule/elasticsearch_test_modules/molecule.yml @@ -0,0 +1,34 @@ +--- +dependency: + name: galaxy + options: + requirements-file: requirements.yml +driver: + name: docker +platforms: + - name: elasticsearch_default1 + groups: + - elasticsearch + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + #- name: elasticsearch_default2 + # groups: + # - elasticsearch + # image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + # command: ${MOLECULE_DOCKER_COMMAND:-""} + # volumes: + # - /sys/fs/cgroup:/sys/fs/cgroup:rw + # cgroupns_mode: host + # privileged: true + # pre_build_image: true +provisioner: + name: ansible + env: + ANSIBLE_VERBOSITY: 3 +verifier: + name: ansible diff --git a/molecule/elasticsearch_test_modules/prepare.yml b/molecule/elasticsearch_test_modules/prepare.yml new file mode 100644 index 00000000..f6ca1291 --- /dev/null +++ b/molecule/elasticsearch_test_modules/prepare.yml @@ -0,0 +1,23 @@ +--- +- name: Prepare + hosts: all + tasks: + - name: Install packages for Debian + ansible.builtin.apt: + name: + - gpg + - gpg-agent + - procps + - curl + - iproute2 + - git + - openssl + - python3 + update_cache: yes + + - name: Install python module dependencies + ansible.builtin.pip: + name: "{{ item }}" + loop: + - elasticsearch + - certifi diff --git a/molecule/elasticsearch_test_modules/requirements.yml b/molecule/elasticsearch_test_modules/requirements.yml new file mode 100644 index 00000000..8dd51618 --- /dev/null +++ b/molecule/elasticsearch_test_modules/requirements.yml @@ -0,0 +1,3 @@ +--- +collections: + - community.general diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py new file mode 100644 index 00000000..e80ca7e7 --- /dev/null +++ b/plugins/module_utils/api.py @@ -0,0 +1,74 @@ +# !/usr/bin/python3 + +# Copyright (c) 2024, Tobias Bauriedel +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or +# https://www.gnu.org/licenses/gpl-3.0.txt) + +from asyncio.constants import SENDFILE_FALLBACK_READBUFFER_SIZE +from elasticsearch import Elasticsearch +import ssl + +def new_client_basic_auth(host, auth_user, auth_pass, ca_certs, verify_certs) -> Elasticsearch: + ctx = ssl.create_default_context(cafile=ca_certs) + ctx.check_hostname = False + ctx.verify_mode = False + return Elasticsearch(hosts=[host], basic_auth=(auth_user, auth_pass), ssl_context=ctx, verify_certs=verify_certs) + + +class Role(): + def __init__(self, result, role_name, cluster, indicies, state, host, auth_user, auth_pass, verify_certs, ca_certs): + self.role_name = role_name + self.cluster = cluster + self.indicies = indicies + self.state = state + self.result = result + + if auth_user == "" or auth_pass == "": + result['stderr'] = "'basic_auth' for authentication defined but 'auth_user' or auth_pass' is empty" + return + self.client = new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, verify_certs=verify_certs, ca_certs=ca_certs) + + self.handle() + + + def return_result(self) -> dict: + return self.result + + + def handle(self): + if self.state == 'absent': + res = self.delete() + if res['found'] == True: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been deleted." + return + + elif self.state == 'present': + pre_role = self.get() + self.result['foo1'] = pre_role.raw + res = self.put() + + if res.raw['role']['created'] == True: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been created." + return + + self.result['foo2'] = self.get().raw + if pre_role.raw != self.get().raw: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been updated" + return + + return + + + def get(self): + return self.client.security.get_role(name=self.role_name) + + + def put(self): + return self.client.security.put_role(name=self.role_name, cluster=self.cluster, indices=self.indicies) + + + def delete(self): + return self.client.security.delete_role(name=self.role_name) \ No newline at end of file diff --git a/plugins/modules/elasticsearch_role.py b/plugins/modules/elasticsearch_role.py new file mode 100644 index 00000000..31a7aef3 --- /dev/null +++ b/plugins/modules/elasticsearch_role.py @@ -0,0 +1,80 @@ +#!/usr/bin/python + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.netways.elasticstack.plugins.module_utils.api import ( + Role +) + +def run_module(): + ''' + Elasticsearch user management. + + ``` + netways.elasticstack.elasticsearch_role: + name: new-role + cluster: + - manage_own_api_key + - delegate_pki + indicies: + - names: + - foobar + privileges: + - read + - write + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: changeMe123! + verify_certs: false + ca_certs: /etc/elasticsearch/certs/http_ca.crt + ``` + ''' + + # get role + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-role.html + + # create or update role + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-role.html + + module = AnsibleModule( + argument_spec=dict( + name=dict(type=str, required=True), + cluster=dict(type=list, required=False), + indicies=dict(type=list, required=False), # indicies.{n}.name, indicies.{n}.privileges + state=dict(type=str, required=False, default='present'), + host=dict(type=str, required=True), + auth_user=dict(type=str, required=True), + auth_pass=dict(type=str, required=True), + ca_certs=dict(type=str, required=False), + verify_certs=dict(type=bool, required=False, default=True) + ) + ) + + result = dict( + failed=False, + changed=False + ) + + role = Role( + result=result, + role_name=module.params['name'], + cluster=module.params['cluster'], + indicies=module.params['indicies'], + state=module.params['state'], + host=module.params['host'], + auth_user=module.params['auth_user'], + auth_pass=module.params['auth_pass'], + ca_certs=module.params['ca_certs'], + verify_certs=module.params['verify_certs'], + ) + + result = role.return_result() + + module.exit_json(**result) + + +if __name__ == "__main__": + run_module() \ No newline at end of file diff --git a/plugins/modules/elasticsearch_user.py b/plugins/modules/elasticsearch_user.py new file mode 100644 index 00000000..7d27e2a0 --- /dev/null +++ b/plugins/modules/elasticsearch_user.py @@ -0,0 +1,80 @@ +#!/usr/bin/python + +# Copyright (c) 2024, Tobias Bauriedel +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or +# https://www.gnu.org/licenses/gpl-3.0.txt) + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.netways.elasticstack.plugins.module_utils.elasticsearch_api import ( + UserObject, +) +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +def run_module(): + ''' + Elasticsearch user management. + ''' + + # https://github.com/NETWAYS/ansible-collection-elasticstack/blob/main/roles/logstash/tasks/logstash-security.yml#L405-L472 + + # get user + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-user.html + + # create or update user + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html + + # delete user + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-user.html + + # enable user + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html + + # disable user + # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-disable-user.html + + module = AnsibleModule( + argument_spec=dict( + name=dict(type=str, required=True), + fullname=dict(type=str, required=False), + password=dict(type=str, required=True), + email=dict(type=str, required=False), + roles=dict(type=list, required=True), + metadata=dict(type=dict, required=False), + state=dict(type=str, required=False, default="present"), # 'present' or 'absent' + enabled=dict(type=bool, required=False, default=True), # True=enabled & False=disabled + endpoint=dict(type=str, required=False, default="https://localhost:9200"), + ca=dict(type=str, required=True), # Path to ca to authenticate API requests + es_version=dict(type=int, required=False, default=8), # Elasticsearch version + ) + ) + + # Check if provided state is valid + valid_states = list("present", "absent") + if module.params['state'] not in valid_states: + module.exit_json( + failed=True, + changed=False, + stderr="Invalid state provided. Use 'present' or 'absent." + ) + + user = UserObject(module) + + module.exit_json( + debug=user + ) + + # Block 1 + # if (current state == configured state) && (current properties == configured properties) -> exit + + # if (current enabled != configured enable) -> change + + # if current state != configured state -> create or delete (based on configured state) + + # if (current state == configured state) && (current properties != configured properties) -> update user properties + + # Block 2 + +if __name__ == "__main__": + run_module() \ No newline at end of file From 765c12f70bad70724b5664cd2e1100c51e63f4e4 Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Thu, 1 Feb 2024 14:46:22 +0100 Subject: [PATCH 2/8] Add elasticsearch_user module --- .gitignore | 3 +- README.md | 7 +- docs/module-elasticsearch_role.md | 49 ++++++++ docs/module-elasticsearch_user.md | 48 +++++++ .../elasticsearch_test_modules/converge.yml | 24 +++- plugins/module_utils/api.py | 118 +++++++++++++++--- plugins/modules/elasticsearch_role.py | 9 +- plugins/modules/elasticsearch_user.py | 99 ++++++++------- requirements-test.txt | 1 + 9 files changed, 284 insertions(+), 74 deletions(-) create mode 100644 docs/module-elasticsearch_role.md create mode 100644 docs/module-elasticsearch_user.md diff --git a/.gitignore b/.gitignore index 18c9f355..6faba4d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .cache *.swp -__pycache__* \ No newline at end of file +__pycache__* +.vscode \ No newline at end of file diff --git a/README.md b/README.md index b401cb14..14a36df5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Every role is documented with all variables, please refer to the documentation f **Please note**: If you are already using this collection before version `1.0.0`, please note that we had to rename a significant amount of variables due to naming schema changes made by Ansible. Please review the variables you have set in your playbooks and variable files. -## Roles Documentation +## Roles documentation * [Beats](docs/role-beats.md) * [Elasticsearch](docs/role-elasticsearch.md) @@ -16,6 +16,11 @@ Every role is documented with all variables, please refer to the documentation f * [Logstash](docs/role-logstash.md) * [Repos](docs/role-repos.md) +## Modules documentation + +* [elasticsearch_role](docs/module-elasticsearch_role.md) +* [elasticsearch_user](docs/module-elasticsearch_user.md) + ## Installation You can easily install the collection with the `ansible-galaxy` command. diff --git a/docs/module-elasticsearch_role.md b/docs/module-elasticsearch_role.md new file mode 100644 index 00000000..105c8f96 --- /dev/null +++ b/docs/module-elasticsearch_role.md @@ -0,0 +1,49 @@ +Ansible module: elasticsearch_role +=== + +This module creates, updates and deletes roles from your Elasticsearch. + +Requirements +--- + +As this module uses the Elasticsearch API you will need to install the `elasticsearch` Python3 library. +``` +pip3 install elasticsearch +``` + +Module arguments +--- + +* *name*: Name of your role (**Required**) +* *cluster*: List of clusters +* *indicies*: List of indicies + * *names*: List of names (**Required**) + * *privileges*: List of privileges (**Required**) +* *state*: State of the role (Default: `present`) +* *host*: API endpoint (**Required**) +* *auth_user*: User to authenticate on the Elasticsearch API (**Required**) +* *auth_pass*: Password for the given user (**Required**) +* *verify_certs*: Verify certificates (Default: True) +* *ca_certs*: Verify HTTPS connection by using ca certificate. Path to ca needs to be given + +Example usage +--- +``` + - name: Create elasticsearch role 'new-role' + netways.elasticstack.elasticsearch_role: + name: new-role + cluster: + - manage_own_api_key + - delegate_pki + indicies: + - names: + - default01 + privileges: + - read + - write + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: changeMe123! + verify_certs: false +``` \ No newline at end of file diff --git a/docs/module-elasticsearch_user.md b/docs/module-elasticsearch_user.md new file mode 100644 index 00000000..3513d6ee --- /dev/null +++ b/docs/module-elasticsearch_user.md @@ -0,0 +1,48 @@ +Ansible module: elasticsearch_user +=== + +This module creates, updates and deletes users from your Elasticsearch. + +Requirements +--- + +As this module uses the Elasticsearch API you will need to install the `elasticsearch` Python3 library. +``` +pip3 install elasticsearch +``` + +Module arguments +--- + +* *name*: Name of your user (**Required**) +* *fullname*: Fullname of your user +* *password*: Password for your user (**Required**) +* *email*: Email for your user +* *roles*: List of roles (**Required**) +* *enabled*: Define wheter this user should be enabled (Default: `true`) +* *state*: State of the role. `absent` to delete the user (Default: `present`) +* *host*: API endpoint (**Required**) +* *auth_user*: User to authenticate on the Elasticsearch API (**Required**) +* *auth_pass*: Password for the given user (**Required**) +* *verify_certs*: Verify certificates (Default: True) +* *ca_certs*: Verify HTTPS connection by using ca certificate. Path to ca needs to be given + +Example usage +--- +``` + - name: Create elasticsearch user 'new-user' + netways.elasticstack.elasticsearch_user: + name: new-user + fullname: New User + password: changeMe321! + email: new@user.de + roles: + - new-role + - logstash-writer + enabled: true + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: changeMe123! + verify_certs: false +``` \ No newline at end of file diff --git a/molecule/elasticsearch_test_modules/converge.yml b/molecule/elasticsearch_test_modules/converge.yml index 672e7b2a..7e7252fb 100644 --- a/molecule/elasticsearch_test_modules/converge.yml +++ b/molecule/elasticsearch_test_modules/converge.yml @@ -29,16 +29,15 @@ register: elasticstack_password changed_when: false - - name: Create role + - name: Create elasticsearch role 'new-role' netways.elasticstack.elasticsearch_role: - name: new-role3 + name: new-role1 cluster: - manage_own_api_key - delegate_pki indicies: - names: - foobar321 - - barfoo123 privileges: - read - write @@ -47,4 +46,21 @@ auth_user: elastic auth_pass: "{{ elasticstack_password.stdout }}" verify_certs: false - ca_certs: /etc/elasticsearch/certs/http_ca.crt + #ca_certs: /etc/elasticsearch/certs/http_ca.crt + + - name: Create elasticsearch user 'new-user' + netways.elasticstack.elasticsearch_user: + name: new-user1 + fullname: New User + password: changeMe123! + email: new@user.de + roles: + - new-role1 + - logstash-writer + enabled: true + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: "{{ elasticstack_password.stdout }}" + verify_certs: false + #ca_certs: /etc/elasticsearch/certs/http_ca.crt \ No newline at end of file diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index e80ca7e7..213c2148 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -4,7 +4,9 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or # https://www.gnu.org/licenses/gpl-3.0.txt) -from asyncio.constants import SENDFILE_FALLBACK_READBUFFER_SIZE +from difflib import restore +from pickle import NONE +from xml.sax.saxutils import prepare_input_source from elasticsearch import Elasticsearch import ssl @@ -16,16 +18,13 @@ def new_client_basic_auth(host, auth_user, auth_pass, ca_certs, verify_certs) -> class Role(): - def __init__(self, result, role_name, cluster, indicies, state, host, auth_user, auth_pass, verify_certs, ca_certs): + def __init__(self, result, role_name, cluster, indicies, state, host, auth_user, auth_pass, verify_certs, ca_certs): self.role_name = role_name self.cluster = cluster self.indicies = indicies self.state = state self.result = result - if auth_user == "" or auth_pass == "": - result['stderr'] = "'basic_auth' for authentication defined but 'auth_user' or auth_pass' is empty" - return self.client = new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, verify_certs=verify_certs, ca_certs=ca_certs) self.handle() @@ -36,39 +35,118 @@ def return_result(self) -> dict: def handle(self): + all_roles = self.get_all() + if self.state == 'absent': - res = self.delete() - if res['found'] == True: - self.result['changed'] = True - self.result['msg'] = self.role_name + " has been deleted." - return + if self.role_name in all_roles: + res = self.delete() + if res['found'] == True: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been deleted" + return elif self.state == 'present': - pre_role = self.get() - self.result['foo1'] = pre_role.raw + if self.role_name in all_roles.raw: + pre_role = self.get() + else: + pre_role = None + res = self.put() if res.raw['role']['created'] == True: self.result['changed'] = True - self.result['msg'] = self.role_name + " has been created." + self.result['msg'] = self.role_name + " has been created" return - self.result['foo2'] = self.get().raw - if pre_role.raw != self.get().raw: - self.result['changed'] = True - self.result['msg'] = self.role_name + " has been updated" - return + if pre_role != None: + if pre_role.raw != self.get().raw: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been updated" + return return + def get_all(self): + return self.client.security.get_role() + + def get(self): return self.client.security.get_role(name=self.role_name) - def put(self): + def put(self): return self.client.security.put_role(name=self.role_name, cluster=self.cluster, indices=self.indicies) def delete(self): - return self.client.security.delete_role(name=self.role_name) \ No newline at end of file + return self.client.security.delete_role(name=self.role_name) + + +class User(): + def __init__(self, result, user_name, full_name, password, email, roles, enabled, state, host, auth_user, auth_pass, verify_certs, ca_certs): + self.user_name = user_name + self.full_name = full_name + self.password = password + self.email = email + self.roles = roles + self.enabled = enabled + self.state = state + self.result = result + + self.client = new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, ca_certs=ca_certs, verify_certs=verify_certs) + + self.handle() + + + def return_result(self) -> dict: + return self.result + + + def handle(self): + all_users = self.get_all() + + if self.state == 'absent': + if self.user_name in all_users: + res = self.delete() + if res['found'] == True: + self.result['changed'] = True + self.result['msg'] = self.user_name + " has been deleted" + return + + elif self.state == 'present': + if self.user_name in all_users.raw: + pre_user = self.get() + else: + pre_user = None + + res = self.put() + + if res.raw['created'] == True: + self.result['changed'] = True + self.result['msg'] = self.user_name + " has been created" + return + + if pre_user != None: + if pre_user.raw != self.get().raw: + self.result['changed'] = True + self.result['msg'] = self.user_name + " has beed updated" + return + + return + + + def get_all(self): + return self.client.security.get_user() + + + def get(self): + return self.client.security.get_user(username=self.user_name) + + + def put(self): + return self.client.security.put_user(username=self.user_name, password=self.password, email=self.email, full_name=self.full_name, enabled=self.enabled, roles=self.roles) + + + def delete(self): + return self.client.security.delete_user(username=self.user_name) \ No newline at end of file diff --git a/plugins/modules/elasticsearch_role.py b/plugins/modules/elasticsearch_role.py index 31a7aef3..e42c1662 100644 --- a/plugins/modules/elasticsearch_role.py +++ b/plugins/modules/elasticsearch_role.py @@ -1,5 +1,9 @@ #!/usr/bin/python +# Copyright (c) 2024, Tobias Bauriedel +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or +# https://www.gnu.org/licenses/gpl-3.0.txt) + from __future__ import (absolute_import, division, print_function) __metaclass__ = type @@ -41,10 +45,13 @@ def run_module(): module = AnsibleModule( argument_spec=dict( + # User args name=dict(type=str, required=True), cluster=dict(type=list, required=False), - indicies=dict(type=list, required=False), # indicies.{n}.name, indicies.{n}.privileges + indicies=dict(type=list, required=False), state=dict(type=str, required=False, default='present'), + + # Auth args host=dict(type=str, required=True), auth_user=dict(type=str, required=True), auth_pass=dict(type=str, required=True), diff --git a/plugins/modules/elasticsearch_user.py b/plugins/modules/elasticsearch_user.py index 7d27e2a0..44d0d24a 100644 --- a/plugins/modules/elasticsearch_user.py +++ b/plugins/modules/elasticsearch_user.py @@ -4,77 +4,82 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or # https://www.gnu.org/licenses/gpl-3.0.txt) -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.netways.elasticstack.plugins.module_utils.elasticsearch_api import ( - UserObject, -) from __future__ import (absolute_import, division, print_function) __metaclass__ = type +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.netways.elasticstack.plugins.module_utils.api import ( + User +) + def run_module(): ''' Elasticsearch user management. - ''' - - # https://github.com/NETWAYS/ansible-collection-elasticstack/blob/main/roles/logstash/tasks/logstash-security.yml#L405-L472 - - # get user - # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-user.html - - # create or update user - # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-user.html - # delete user - # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-user.html - - # enable user - # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html - - # disable user - # https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-disable-user.html + ``` + netways.elasticstack.elasticsearch_user: + name: new-user1 + fullname: New User + password: changeMe123! + email: "new@user.de" + roles: + - new-role1 + enabled: true + state: absent + host: https://localhost:9200 + auth_user: elastic + auth_pass: "{{ elasticstack_password.stdout }}" + verify_certs: false + ca_certs: /etc/elasticsearch/certs/http_ca.crt + ``` + ''' module = AnsibleModule( argument_spec=dict( + # User args name=dict(type=str, required=True), fullname=dict(type=str, required=False), password=dict(type=str, required=True), email=dict(type=str, required=False), roles=dict(type=list, required=True), - metadata=dict(type=dict, required=False), - state=dict(type=str, required=False, default="present"), # 'present' or 'absent' - enabled=dict(type=bool, required=False, default=True), # True=enabled & False=disabled - endpoint=dict(type=str, required=False, default="https://localhost:9200"), - ca=dict(type=str, required=True), # Path to ca to authenticate API requests - es_version=dict(type=int, required=False, default=8), # Elasticsearch version + enabled=dict(type=bool, required=False, default=True), + state=dict(type=str, required=False, default="present"), + + # Auth args + host=dict(type=str, required=True), + auth_user=dict(type=str, required=True), + auth_pass=dict(type=str, required=True), + ca_certs=dict(type=str, required=False), + verify_certs=dict(type=bool, required=False, default=True) ) ) - # Check if provided state is valid - valid_states = list("present", "absent") - if module.params['state'] not in valid_states: - module.exit_json( - failed=True, - changed=False, - stderr="Invalid state provided. Use 'present' or 'absent." - ) - - user = UserObject(module) - - module.exit_json( - debug=user + result = dict( + failed=False, + changed=False ) - # Block 1 - # if (current state == configured state) && (current properties == configured properties) -> exit - - # if (current enabled != configured enable) -> change + user = User( + result=result, + user_name=module.params['name'], + full_name=module.params['fullname'], + password=module.params['password'], + email=module.params['email'], + roles=module.params['roles'], + enabled=module.params['enabled'], + state=module.params['state'], + host=module.params['host'], + auth_user=module.params['auth_user'], + auth_pass=module.params['auth_pass'], + ca_certs=module.params['ca_certs'], + verify_certs=module.params['verify_certs'], + ) - # if current state != configured state -> create or delete (based on configured state) + result = user.return_result() - # if (current state == configured state) && (current properties != configured properties) -> update user properties + module.exit_json(**result) - # Block 2 if __name__ == "__main__": run_module() \ No newline at end of file diff --git a/requirements-test.txt b/requirements-test.txt index ac24d2cf..c508b1c5 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -4,3 +4,4 @@ molecule molecule-plugins[docker] pytest passlib +elasticsearch \ No newline at end of file From a96c5e9967c01b2365e25f99a0d449174fd16903 Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Thu, 1 Feb 2024 14:49:00 +0100 Subject: [PATCH 3/8] fix lint --- molecule/elasticsearch_test_modules/converge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molecule/elasticsearch_test_modules/converge.yml b/molecule/elasticsearch_test_modules/converge.yml index 7e7252fb..f2bfdcb5 100644 --- a/molecule/elasticsearch_test_modules/converge.yml +++ b/molecule/elasticsearch_test_modules/converge.yml @@ -63,4 +63,4 @@ auth_user: elastic auth_pass: "{{ elasticstack_password.stdout }}" verify_certs: false - #ca_certs: /etc/elasticsearch/certs/http_ca.crt \ No newline at end of file + #ca_certs: /etc/elasticsearch/certs/http_ca.crt From b1fd58cc5e0d3c820c263b4d3ea32460bc39687a Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Thu, 1 Feb 2024 16:15:55 +0100 Subject: [PATCH 4/8] remove unused imports --- plugins/module_utils/api.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 213c2148..36e15c2d 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -4,9 +4,6 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or # https://www.gnu.org/licenses/gpl-3.0.txt) -from difflib import restore -from pickle import NONE -from xml.sax.saxutils import prepare_input_source from elasticsearch import Elasticsearch import ssl From d0f2c2ba54060a9806b0d747d047497ed75067f6 Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Mon, 5 Feb 2024 16:40:51 +0100 Subject: [PATCH 5/8] outsource classes --- .../workflows/test_elasticsearch_modules.yml | 63 ++++++++ docs/module-elasticsearch_role.md | 23 ++- docs/module-elasticsearch_user.md | 25 ++- .../elasticsearch_test_modules/converge.yml | 5 +- .../elasticsearch_test_modules/molecule.yml | 12 +- plugins/module_utils/api.py | 146 +----------------- plugins/module_utils/elasticsearch_role.py | 84 ++++++++++ plugins/module_utils/elasticsearch_user.py | 85 ++++++++++ plugins/modules/elasticsearch_role.py | 9 +- plugins/modules/elasticsearch_user.py | 10 +- 10 files changed, 299 insertions(+), 163 deletions(-) create mode 100644 .github/workflows/test_elasticsearch_modules.yml create mode 100644 plugins/module_utils/elasticsearch_role.py create mode 100644 plugins/module_utils/elasticsearch_user.py diff --git a/.github/workflows/test_elasticsearch_modules.yml b/.github/workflows/test_elasticsearch_modules.yml new file mode 100644 index 00000000..2fd273ee --- /dev/null +++ b/.github/workflows/test_elasticsearch_modules.yml @@ -0,0 +1,63 @@ +--- +name: Test Elasticsearch modules +on: + workflow_dispatch: + inputs: + logLevel: + description: 'Log level' + required: true + default: 'warning' + type: choice + options: + - info + - warning + - debug + pull_request: + paths: + - '.github/workflows/test_elasticsearch_modules.yml' + - 'molecule/elasticsearch_test_modules/*' + +jobs: + molecule_elasticsearch_modules: + runs-on: ubuntu-latest + + env: + COLLECTION_NAMESPACE: netways + COLLECTION_NAME: elasticstack + + strategy: + fail-fast: false + matrix: + distro: [ubuntu2204] + scenario: + - elasticsearch_test_modules + release: + - 8 + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Python 3.8 + uses: actions/setup-python@v5 + with: + python-version: 3.8 + + - name: Install dependencies + run: | + python3 -m pip install --upgrade pip + python3 -m pip install -r requirements-test.txt + + - name: Install collection + run: | + mkdir -p ~/.ansible/collections/ansible_collections/$COLLECTION_NAMESPACE + cp -a ../ansible-collection-$COLLECTION_NAME ~/.ansible/collections/ansible_collections/$COLLECTION_NAMESPACE/$COLLECTION_NAME + + - name: Test with molecule + run: | + molecule test -s ${{ matrix.scenario }} + env: + MOLECULE_DISTRO: ${{ matrix.distro }} + PY_COLORS: '1' + ANSIBLE_FORCE_COLOR: '1' + ELASTIC_RELEASE: ${{ matrix.release }} diff --git a/docs/module-elasticsearch_role.md b/docs/module-elasticsearch_role.md index 105c8f96..ae33c5a9 100644 --- a/docs/module-elasticsearch_role.md +++ b/docs/module-elasticsearch_role.md @@ -29,9 +29,28 @@ Module arguments Example usage --- ``` - - name: Create elasticsearch role 'new-role' + - name: Create elasticsearch role 'new-role1' netways.elasticstack.elasticsearch_role: - name: new-role + name: new-role1 + cluster: + - manage_own_api_key + - delegate_pki + indicies: + - names: + - default01 + privileges: + - read + - write + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: changeMe123! + verify_certs: true + ca_certs: /etc/elasticsearch/certs/http_ca.crt + + - name: Create elasticsearch role 'new-role2' + netways.elasticstack.elasticsearch_role: + name: new-role2 cluster: - manage_own_api_key - delegate_pki diff --git a/docs/module-elasticsearch_user.md b/docs/module-elasticsearch_user.md index 3513d6ee..74d6cc64 100644 --- a/docs/module-elasticsearch_user.md +++ b/docs/module-elasticsearch_user.md @@ -30,12 +30,29 @@ Module arguments Example usage --- ``` - - name: Create elasticsearch user 'new-user' + - name: Create elasticsearch user 'new-user1' netways.elasticstack.elasticsearch_user: - name: new-user - fullname: New User + name: new-user1 + fullname: New User 1 password: changeMe321! - email: new@user.de + email: new1@user.de + roles: + - new-role + - logstash-writer + enabled: true + state: present + host: https://localhost:9200 + auth_user: elastic + auth_pass: changeMe123! + verify_certs: true + ca_certs: /etc/elasticsearch/certs/http_ca.crt + + - name: Create elasticsearch user 'new-user2' + netways.elasticstack.elasticsearch_user: + name: new-user2 + fullname: New User 2 + password: changeMe321! + email: new2@user.de roles: - new-role - logstash-writer diff --git a/molecule/elasticsearch_test_modules/converge.yml b/molecule/elasticsearch_test_modules/converge.yml index f2bfdcb5..7f3e3ad0 100644 --- a/molecule/elasticsearch_test_modules/converge.yml +++ b/molecule/elasticsearch_test_modules/converge.yml @@ -10,7 +10,7 @@ elasticstack_full_stack: false elasticsearch_jna_workaround: true elasticsearch_disable_systemcallfilterchecks: true - elasticstack_release: 8 + elasticstack_release: "{{ lookup('env', 'ELASTIC_RELEASE') | int}}" elasticsearch_heap: "1" elasticstack_no_log: false tasks: @@ -46,7 +46,6 @@ auth_user: elastic auth_pass: "{{ elasticstack_password.stdout }}" verify_certs: false - #ca_certs: /etc/elasticsearch/certs/http_ca.crt - name: Create elasticsearch user 'new-user' netways.elasticstack.elasticsearch_user: @@ -63,4 +62,4 @@ auth_user: elastic auth_pass: "{{ elasticstack_password.stdout }}" verify_certs: false - #ca_certs: /etc/elasticsearch/certs/http_ca.crt + ca_certs: /etc/elasticsearch/certs/http_ca.crt diff --git a/molecule/elasticsearch_test_modules/molecule.yml b/molecule/elasticsearch_test_modules/molecule.yml index 1cfcb2eb..ee0c0a47 100644 --- a/molecule/elasticsearch_test_modules/molecule.yml +++ b/molecule/elasticsearch_test_modules/molecule.yml @@ -6,7 +6,7 @@ dependency: driver: name: docker platforms: - - name: elasticsearch_default1 + - name: elasticsearch_default groups: - elasticsearch image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" @@ -16,16 +16,6 @@ platforms: cgroupns_mode: host privileged: true pre_build_image: true - #- name: elasticsearch_default2 - # groups: - # - elasticsearch - # image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" - # command: ${MOLECULE_DOCKER_COMMAND:-""} - # volumes: - # - /sys/fs/cgroup:/sys/fs/cgroup:rw - # cgroupns_mode: host - # privileged: true - # pre_build_image: true provisioner: name: ansible env: diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 36e15c2d..9eca6a85 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -7,143 +7,9 @@ from elasticsearch import Elasticsearch import ssl -def new_client_basic_auth(host, auth_user, auth_pass, ca_certs, verify_certs) -> Elasticsearch: - ctx = ssl.create_default_context(cafile=ca_certs) - ctx.check_hostname = False - ctx.verify_mode = False - return Elasticsearch(hosts=[host], basic_auth=(auth_user, auth_pass), ssl_context=ctx, verify_certs=verify_certs) - - -class Role(): - def __init__(self, result, role_name, cluster, indicies, state, host, auth_user, auth_pass, verify_certs, ca_certs): - self.role_name = role_name - self.cluster = cluster - self.indicies = indicies - self.state = state - self.result = result - - self.client = new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, verify_certs=verify_certs, ca_certs=ca_certs) - - self.handle() - - - def return_result(self) -> dict: - return self.result - - - def handle(self): - all_roles = self.get_all() - - if self.state == 'absent': - if self.role_name in all_roles: - res = self.delete() - if res['found'] == True: - self.result['changed'] = True - self.result['msg'] = self.role_name + " has been deleted" - return - - elif self.state == 'present': - if self.role_name in all_roles.raw: - pre_role = self.get() - else: - pre_role = None - - res = self.put() - - if res.raw['role']['created'] == True: - self.result['changed'] = True - self.result['msg'] = self.role_name + " has been created" - return - - if pre_role != None: - if pre_role.raw != self.get().raw: - self.result['changed'] = True - self.result['msg'] = self.role_name + " has been updated" - return - - return - - - def get_all(self): - return self.client.security.get_role() - - - def get(self): - return self.client.security.get_role(name=self.role_name) - - - def put(self): - return self.client.security.put_role(name=self.role_name, cluster=self.cluster, indices=self.indicies) - - - def delete(self): - return self.client.security.delete_role(name=self.role_name) - - -class User(): - def __init__(self, result, user_name, full_name, password, email, roles, enabled, state, host, auth_user, auth_pass, verify_certs, ca_certs): - self.user_name = user_name - self.full_name = full_name - self.password = password - self.email = email - self.roles = roles - self.enabled = enabled - self.state = state - self.result = result - - self.client = new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, ca_certs=ca_certs, verify_certs=verify_certs) - - self.handle() - - - def return_result(self) -> dict: - return self.result - - - def handle(self): - all_users = self.get_all() - - if self.state == 'absent': - if self.user_name in all_users: - res = self.delete() - if res['found'] == True: - self.result['changed'] = True - self.result['msg'] = self.user_name + " has been deleted" - return - - elif self.state == 'present': - if self.user_name in all_users.raw: - pre_user = self.get() - else: - pre_user = None - - res = self.put() - - if res.raw['created'] == True: - self.result['changed'] = True - self.result['msg'] = self.user_name + " has been created" - return - - if pre_user != None: - if pre_user.raw != self.get().raw: - self.result['changed'] = True - self.result['msg'] = self.user_name + " has beed updated" - return - - return - - - def get_all(self): - return self.client.security.get_user() - - - def get(self): - return self.client.security.get_user(username=self.user_name) - - - def put(self): - return self.client.security.put_user(username=self.user_name, password=self.password, email=self.email, full_name=self.full_name, enabled=self.enabled, roles=self.roles) - - - def delete(self): - return self.client.security.delete_user(username=self.user_name) \ No newline at end of file +class Api(): + def new_client_basic_auth(host, auth_user, auth_pass, ca_certs, verify_certs) -> Elasticsearch: + ctx = ssl.create_default_context(cafile=ca_certs) + ctx.check_hostname = False + ctx.verify_mode = False + return Elasticsearch(hosts=[host], basic_auth=(auth_user, auth_pass), ssl_context=ctx, verify_certs=verify_certs) \ No newline at end of file diff --git a/plugins/module_utils/elasticsearch_role.py b/plugins/module_utils/elasticsearch_role.py new file mode 100644 index 00000000..d98d58ab --- /dev/null +++ b/plugins/module_utils/elasticsearch_role.py @@ -0,0 +1,84 @@ +#!/usr/bin/python + +# Copyright (c) 2024, Tobias Bauriedel +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or +# https://www.gnu.org/licenses/gpl-3.0.txt) + +from ansible_collections.netways.elasticstack.plugins.module_utils.api import ( + Api +) + +class Role(): + def __init__(self, result, role_name, cluster, indicies, state, host, auth_user, auth_pass, verify_certs, ca_certs): + self.role_name = role_name + self.cluster = cluster + self.indicies = indicies + self.state = state + self.result = result + + self.client = Api.new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, verify_certs=verify_certs, ca_certs=ca_certs) + + self.handle() + + + def return_result(self) -> dict: + return self.result + + + def handle(self): + + if self.state == 'absent': + self.handle_absent() + elif self.state == 'present': + self.handle_present() + + return + + + def handle_absent(self): + if self.role_name not in self.get_all().raw: + return + + res = self.delete() + if res['found'] == True: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been deleted" + + return + + + def handle_present(self): + if self.role_name in self.get_all().raw: + pre_role = self.get() + else: + pre_role = None + + res = self.put() + + if res.raw['role']['created'] == True: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been created" + return + + if pre_role != None: + if pre_role.raw != self.get().raw: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been updated" + + return + + + def get_all(self): + return self.client.security.get_role() + + + def get(self): + return self.client.security.get_role(name=self.role_name) + + + def put(self): + return self.client.security.put_role(name=self.role_name, cluster=self.cluster, indices=self.indicies) + + + def delete(self): + return self.client.security.delete_role(name=self.role_name) diff --git a/plugins/module_utils/elasticsearch_user.py b/plugins/module_utils/elasticsearch_user.py new file mode 100644 index 00000000..50df2712 --- /dev/null +++ b/plugins/module_utils/elasticsearch_user.py @@ -0,0 +1,85 @@ +#!/usr/bin/python + +# Copyright (c) 2024, Tobias Bauriedel +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or +# https://www.gnu.org/licenses/gpl-3.0.txt) + +from ansible_collections.netways.elasticstack.plugins.module_utils.api import ( + Api +) + +class User(): + def __init__(self, result, user_name, full_name, password, email, roles, enabled, state, host, auth_user, auth_pass, verify_certs, ca_certs): + self.user_name = user_name + self.full_name = full_name + self.password = password + self.email = email + self.roles = roles + self.enabled = enabled + self.state = state + self.result = result + + self.client = Api.new_client_basic_auth(host=host, auth_user=auth_user, auth_pass=auth_pass, ca_certs=ca_certs, verify_certs=verify_certs) + + self.handle() + + + def return_result(self) -> dict: + return self.result + + + def handle(self): + if self.state == 'absent': + self.handle_absent() + elif self.state == 'present': + self.handle_present() + + return + + + def handle_absent(self): + if self.user_name not in self.get_all().raw: + return + + res = self.delete() + if res['found'] == True: + self.result['changed'] = True + self.result['msg'] = self.user_name + " has been deleted" + + return + + + def handle_present(self): + if self.user_name in self.get_all().raw: + pre_user = self.get() + else: + pre_user = None + + res = self.put() + + if res.raw['created'] == True: + self.result['changed'] = True + self.result['msg'] = self.user_name + " has been created" + return + + if pre_user != None and pre_user.raw != self.get().raw: + self.result['changed'] = True + self.result['msg'] = self.user_name + " has beed updated" + + return + + + def get_all(self): + return self.client.security.get_user() + + + def get(self): + return self.client.security.get_user(username=self.user_name) + + + def put(self): + return self.client.security.put_user(username=self.user_name, password=self.password, email=self.email, full_name=self.full_name, enabled=self.enabled, roles=self.roles) + + + def delete(self): + return self.client.security.delete_user(username=self.user_name) \ No newline at end of file diff --git a/plugins/modules/elasticsearch_role.py b/plugins/modules/elasticsearch_role.py index e42c1662..6318428f 100644 --- a/plugins/modules/elasticsearch_role.py +++ b/plugins/modules/elasticsearch_role.py @@ -8,7 +8,7 @@ __metaclass__ = type from ansible.module_utils.basic import AnsibleModule -from ansible_collections.netways.elasticstack.plugins.module_utils.api import ( +from ansible_collections.netways.elasticstack.plugins.module_utils.elasticsearch_role import ( Role ) @@ -65,6 +65,13 @@ def run_module(): changed=False ) + if module.params['state'] != 'absent' and module.params['state'] != 'present': + result['stderr'] = "Invalid state given. Please use 'absent' or 'present'" + result['failed'] = True + + module.exit_json(**result) + + role = Role( result=result, role_name=module.params['name'], diff --git a/plugins/modules/elasticsearch_user.py b/plugins/modules/elasticsearch_user.py index 44d0d24a..8a854e1b 100644 --- a/plugins/modules/elasticsearch_user.py +++ b/plugins/modules/elasticsearch_user.py @@ -8,7 +8,7 @@ __metaclass__ = type from ansible.module_utils.basic import AnsibleModule -from ansible_collections.netways.elasticstack.plugins.module_utils.api import ( +from ansible_collections.netways.elasticstack.plugins.module_utils.elasticsearch_user import ( User ) @@ -60,6 +60,13 @@ def run_module(): changed=False ) + if module.params['state'] != 'absent' and module.params['state'] != 'present': + result['stderr'] = "Invalid state given. Please use 'absent' or 'present'" + result['failed'] = True + + module.exit_json(**result) + + user = User( result=result, user_name=module.params['name'], @@ -80,6 +87,5 @@ def run_module(): module.exit_json(**result) - if __name__ == "__main__": run_module() \ No newline at end of file From 1b20d0f27762dea4b8a963e94caf147a21a9ee4c Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Tue, 6 Feb 2024 10:02:27 +0100 Subject: [PATCH 6/8] change ansible verbository --- molecule/elasticsearch_test_modules/molecule.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/molecule/elasticsearch_test_modules/molecule.yml b/molecule/elasticsearch_test_modules/molecule.yml index ee0c0a47..3a08fd46 100644 --- a/molecule/elasticsearch_test_modules/molecule.yml +++ b/molecule/elasticsearch_test_modules/molecule.yml @@ -18,7 +18,5 @@ platforms: pre_build_image: true provisioner: name: ansible - env: - ANSIBLE_VERBOSITY: 3 verifier: name: ansible From 8ac075e8af19b4d63c9edcbfa9f17c84ac1f0229 Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Wed, 7 Feb 2024 12:51:13 +0100 Subject: [PATCH 7/8] un-nest conditions --- plugins/module_utils/elasticsearch_role.py | 10 ++++++---- plugins/module_utils/elasticsearch_user.py | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/module_utils/elasticsearch_role.py b/plugins/module_utils/elasticsearch_role.py index d98d58ab..77504af1 100644 --- a/plugins/module_utils/elasticsearch_role.py +++ b/plugins/module_utils/elasticsearch_role.py @@ -60,10 +60,12 @@ def handle_present(self): self.result['msg'] = self.role_name + " has been created" return - if pre_role != None: - if pre_role.raw != self.get().raw: - self.result['changed'] = True - self.result['msg'] = self.role_name + " has been updated" + if pre_role == None: + return + + if pre_role.raw != self.get().raw: + self.result['changed'] = True + self.result['msg'] = self.role_name + " has been updated" return diff --git a/plugins/module_utils/elasticsearch_user.py b/plugins/module_utils/elasticsearch_user.py index 50df2712..c84da609 100644 --- a/plugins/module_utils/elasticsearch_user.py +++ b/plugins/module_utils/elasticsearch_user.py @@ -62,7 +62,10 @@ def handle_present(self): self.result['msg'] = self.user_name + " has been created" return - if pre_user != None and pre_user.raw != self.get().raw: + if pre_user == None: + return + + if pre_user.raw != self.get().raw: self.result['changed'] = True self.result['msg'] = self.user_name + " has beed updated" From aaa8fb4c91de91694f2ffb93d6d4ce85f21ee113 Mon Sep 17 00:00:00 2001 From: Tobias Bauriedel Date: Mon, 12 Feb 2024 15:09:13 +0100 Subject: [PATCH 8/8] changes by review --- .gitignore | 2 +- docs/module-elasticsearch_role.md | 2 +- docs/module-elasticsearch_user.md | 2 +- molecule/elasticsearch_test_modules/converge.yml | 4 ++-- molecule/elasticsearch_test_modules/molecule.yml | 2 ++ molecule/elasticsearch_test_modules/prepare.yml | 1 - plugins/module_utils/api.py | 2 +- plugins/modules/elasticsearch_role.py | 2 +- plugins/modules/elasticsearch_user.py | 4 ++-- 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 6faba4d3..5fa051f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .cache *.swp __pycache__* -.vscode \ No newline at end of file +.vscode diff --git a/docs/module-elasticsearch_role.md b/docs/module-elasticsearch_role.md index ae33c5a9..1127a344 100644 --- a/docs/module-elasticsearch_role.md +++ b/docs/module-elasticsearch_role.md @@ -23,7 +23,7 @@ Module arguments * *host*: API endpoint (**Required**) * *auth_user*: User to authenticate on the Elasticsearch API (**Required**) * *auth_pass*: Password for the given user (**Required**) -* *verify_certs*: Verify certificates (Default: True) +* *verify_certs*: Verify certificates (Default: `true`) * *ca_certs*: Verify HTTPS connection by using ca certificate. Path to ca needs to be given Example usage diff --git a/docs/module-elasticsearch_user.md b/docs/module-elasticsearch_user.md index 74d6cc64..9ab1ea07 100644 --- a/docs/module-elasticsearch_user.md +++ b/docs/module-elasticsearch_user.md @@ -24,7 +24,7 @@ Module arguments * *host*: API endpoint (**Required**) * *auth_user*: User to authenticate on the Elasticsearch API (**Required**) * *auth_pass*: Password for the given user (**Required**) -* *verify_certs*: Verify certificates (Default: True) +* *verify_certs*: Verify certificates (Default: `true`) * *ca_certs*: Verify HTTPS connection by using ca certificate. Path to ca needs to be given Example usage diff --git a/molecule/elasticsearch_test_modules/converge.yml b/molecule/elasticsearch_test_modules/converge.yml index 7f3e3ad0..aeef2985 100644 --- a/molecule/elasticsearch_test_modules/converge.yml +++ b/molecule/elasticsearch_test_modules/converge.yml @@ -6,11 +6,11 @@ - netways.elasticstack hosts: all vars: - #elasticsearch_security: true # needed for tests of > 7 releases elasticstack_full_stack: false elasticsearch_jna_workaround: true elasticsearch_disable_systemcallfilterchecks: true - elasticstack_release: "{{ lookup('env', 'ELASTIC_RELEASE') | int}}" + #elasticstack_release: "{{ lookup('env', 'ELASTIC_RELEASE') | int}}" + elasticstack_release: 8 elasticsearch_heap: "1" elasticstack_no_log: false tasks: diff --git a/molecule/elasticsearch_test_modules/molecule.yml b/molecule/elasticsearch_test_modules/molecule.yml index 3a08fd46..ee0c0a47 100644 --- a/molecule/elasticsearch_test_modules/molecule.yml +++ b/molecule/elasticsearch_test_modules/molecule.yml @@ -18,5 +18,7 @@ platforms: pre_build_image: true provisioner: name: ansible + env: + ANSIBLE_VERBOSITY: 3 verifier: name: ansible diff --git a/molecule/elasticsearch_test_modules/prepare.yml b/molecule/elasticsearch_test_modules/prepare.yml index f6ca1291..e55e3df0 100644 --- a/molecule/elasticsearch_test_modules/prepare.yml +++ b/molecule/elasticsearch_test_modules/prepare.yml @@ -20,4 +20,3 @@ name: "{{ item }}" loop: - elasticsearch - - certifi diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 9eca6a85..6dada178 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -12,4 +12,4 @@ def new_client_basic_auth(host, auth_user, auth_pass, ca_certs, verify_certs) -> ctx = ssl.create_default_context(cafile=ca_certs) ctx.check_hostname = False ctx.verify_mode = False - return Elasticsearch(hosts=[host], basic_auth=(auth_user, auth_pass), ssl_context=ctx, verify_certs=verify_certs) \ No newline at end of file + return Elasticsearch(hosts=[host], basic_auth=(auth_user, auth_pass), ssl_context=ctx, verify_certs=verify_certs) diff --git a/plugins/modules/elasticsearch_role.py b/plugins/modules/elasticsearch_role.py index 6318428f..050a907a 100644 --- a/plugins/modules/elasticsearch_role.py +++ b/plugins/modules/elasticsearch_role.py @@ -54,7 +54,7 @@ def run_module(): # Auth args host=dict(type=str, required=True), auth_user=dict(type=str, required=True), - auth_pass=dict(type=str, required=True), + auth_pass=dict(type=str, required=True, no_log=True), ca_certs=dict(type=str, required=False), verify_certs=dict(type=bool, required=False, default=True) ) diff --git a/plugins/modules/elasticsearch_user.py b/plugins/modules/elasticsearch_user.py index 8a854e1b..3e05e91b 100644 --- a/plugins/modules/elasticsearch_user.py +++ b/plugins/modules/elasticsearch_user.py @@ -40,7 +40,7 @@ def run_module(): # User args name=dict(type=str, required=True), fullname=dict(type=str, required=False), - password=dict(type=str, required=True), + password=dict(type=str, required=True, no_log=True), email=dict(type=str, required=False), roles=dict(type=list, required=True), enabled=dict(type=bool, required=False, default=True), @@ -49,7 +49,7 @@ def run_module(): # Auth args host=dict(type=str, required=True), auth_user=dict(type=str, required=True), - auth_pass=dict(type=str, required=True), + auth_pass=dict(type=str, required=True, no_log=True), ca_certs=dict(type=str, required=False), verify_certs=dict(type=bool, required=False, default=True) )