Compare commits
2 commits
main
...
manage-use
Author | SHA1 | Date | |
---|---|---|---|
a812baa242 | |||
bebe621f3e |
22 changed files with 214 additions and 764 deletions
|
@ -1,18 +0,0 @@
|
|||
---
|
||||
on: [push]
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: code.waks.be/nishiki/molecule:docker
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: ansible-lint .
|
||||
- run: yamllint .
|
||||
molecule:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: code.waks.be/nishiki/molecule:docker
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: molecule test
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
image: nishiki/molecule:docker
|
||||
|
||||
before_script:
|
||||
- molecule --version
|
||||
|
||||
molecule:
|
||||
stage: test
|
||||
script:
|
||||
- molecule test
|
|
@ -4,9 +4,9 @@ extends: default
|
|||
ignore: |
|
||||
.kitchen/*
|
||||
vendor/
|
||||
.forgejo/
|
||||
|
||||
rules:
|
||||
line-length:
|
||||
max: 120
|
||||
level: warning
|
||||
truthy: false
|
||||
|
|
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -5,31 +5,9 @@ Which is based on [Keep A Changelog](http://keepachangelog.com/)
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- feat: add variable to set master
|
||||
- feat: manage user
|
||||
- feat: manage role
|
||||
- feat: add variable to set major version
|
||||
- feat: add ilm policy
|
||||
- test: add support debian 12
|
||||
|
||||
### Removed
|
||||
|
||||
- test: remove support debian 10
|
||||
- test: remove support debian 11
|
||||
|
||||
### Changed
|
||||
|
||||
- major default version is 8
|
||||
- replace kitchen to molecule
|
||||
- replace apt_key to get_url
|
||||
- test: use personal docker registry
|
||||
|
||||
### Fixed
|
||||
|
||||
- no_log only api_password for elasticsearch_template module
|
||||
- add full python3 support
|
||||
|
||||
## v1.1.0 - 2019-11-21
|
||||
|
||||
|
|
74
README.md
74
README.md
|
@ -1,63 +1,31 @@
|
|||
# Ansible role: Elasticsearch
|
||||
|
||||
[![Version](https://img.shields.io/badge/latest_version-1.1.0-green.svg)](https://code.waks.be/nishiki/ansible-role-elasticsearch/releases)
|
||||
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://code.waks.be/nishiki/ansible-role-elasticsearch/src/branch/main/LICENSE)
|
||||
[![Build](https://code.waks.be/nishiki/ansible-role-elasticsearch/actions/workflows/molecule.yml/badge.svg?branch=main)](https://code.waks.be/nishiki/ansible-role-elasticsearch/actions?workflow=molecule.yml)
|
||||
[![Version](https://img.shields.io/badge/latest_version-1.1.0-green.svg)](https://git.yaegashi.fr/nishiki/ansible-role-elasticsearch/releases)
|
||||
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://git.yaegashi.fr/nishiki/ansible-role-elasticsearch/src/branch/master/LICENSE)
|
||||
|
||||
Install and configure Elasticsearch
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ansible >= 2.9
|
||||
- Debian
|
||||
- Bookworm
|
||||
* Ansible >= 2.7
|
||||
* Debian Stretch and Buster
|
||||
|
||||
## Role variables
|
||||
|
||||
- `elasticsearch_major_version` - set the major version (default: `7`)
|
||||
- `elasticsearch_master` - set if the node is master (default: `true`)
|
||||
- `elasticsearch_heap_size` - set the heap size (default: `1g`)
|
||||
- `elasticsearch_api_user` - set the admin user (default: `elastic`)
|
||||
- `elasticsearch_api_password` - set the password for api
|
||||
- `elasticsearch_config` - hash with the configuration (see [elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html))
|
||||
* `elasticsearch_heap_size` - set the heap size (default: `1g`)
|
||||
* `elasticsearch_config` - hash with the configuration (see [elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html))
|
||||
|
||||
```yaml
|
||||
path.data: /var/lib/elasticsearch
|
||||
path.logs: /var/log/elasticsearch
|
||||
```
|
||||
path.data: /var/lib/elasticsearch
|
||||
path.logs: /var/log/elasticsearch
|
||||
```
|
||||
|
||||
- `elasticsearch_ssl_key`: - string contain ssl private key if `xpack.security.transport.ssl.key` is defined in elasticsearch_config
|
||||
- `elasticsearch_ssl_certificate`: - string contain ssl certificate if `xpack.security.transport.certificate.key` is defined in elasticsearch_config
|
||||
- `elasticsearch_roles` - hash with the roles to managed
|
||||
* `elasticsearch_index_templates` - hash with the index templates configuration
|
||||
|
||||
```yaml
|
||||
myrole:
|
||||
cluster:
|
||||
- all
|
||||
indices:
|
||||
- names: ["logstash*"]
|
||||
privileges:
|
||||
- create
|
||||
- write
|
||||
```
|
||||
|
||||
- `elasticsearch_users` - hash with the users to managed
|
||||
|
||||
```yaml
|
||||
toto:
|
||||
password: supers3cret
|
||||
roles:
|
||||
- viewer
|
||||
kibana_system:
|
||||
password: supertest2
|
||||
```
|
||||
|
||||
- `elasticsearch_index_templates` - hash with the index templates configuration
|
||||
|
||||
```yaml
|
||||
logstash:
|
||||
logstash:
|
||||
index_patterns:
|
||||
- "logstash-*"
|
||||
- 'logstash-*'
|
||||
settings:
|
||||
index:
|
||||
number_of_replicas: 3
|
||||
|
@ -69,15 +37,7 @@ logstash:
|
|||
format: YYYY-MM-dd
|
||||
```
|
||||
|
||||
- `elasticsearch_ilm_policies` - hash with the ilm policies configuration
|
||||
|
||||
```yaml
|
||||
autoclean:
|
||||
delete:
|
||||
min_age: 30d
|
||||
actions:
|
||||
delete: {}
|
||||
```
|
||||
* `elasticsearch_users` - hash to manage users
|
||||
|
||||
## How to use
|
||||
|
||||
|
@ -91,10 +51,10 @@ autoclean:
|
|||
|
||||
### Test with molecule and docker
|
||||
|
||||
- install [docker](https://docs.docker.com/engine/installation/)
|
||||
- install `python3` and `python3-pip`
|
||||
- install molecule and dependencies `pip3 install molecule 'molecule[docker]' ansible-lint testinfra yamllint`
|
||||
- run `molecule test`
|
||||
* install [docker](https://docs.docker.com/engine/installation/)
|
||||
* install `python3` and `python3-pip`
|
||||
* install molecule and dependencies `pip3 install molecule 'molecule[docker]' ansible-lint testinfra yamllint`
|
||||
* run `molecule test`
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
---
|
||||
elasticsearch_major_version: 8
|
||||
elasticsearch_master: true
|
||||
elasticsearch_api_user: elastic
|
||||
elasticsearch_heap_size: 1g
|
||||
elasticsearch_api_user: elastic
|
||||
elasticsearch_api_password: null
|
||||
elasticsearch_config: {}
|
||||
elasticsearch_default_config:
|
||||
path.data: /var/lib/elasticsearch
|
||||
path.logs: /var/log/elasticsearch
|
||||
xpack.security.transport.ssl.enabled: false
|
||||
xpack.security.http.ssl.enabled: false
|
||||
elasticsearch_full_config: "{{ elasticsearch_default_config | combine(elasticsearch_config) }}"
|
||||
elasticsearch_full_config: '{{ elasticsearch_default_config|combine(elasticsearch_config) }}'
|
||||
elasticsearch_index_templates: {}
|
||||
elasticsearch_ilm_policies: {}
|
||||
elasticsearch_roles: {}
|
||||
elasticsearch_users: {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
- name: Restart elasticsearch
|
||||
ansible.builtin.service:
|
||||
- name: restart elasticsearch
|
||||
systemd:
|
||||
name: elasticsearch
|
||||
state: restarted
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
from ansible.module_utils.elasticsearch_api import *
|
||||
|
||||
class ElasticsearchILMPolicy:
|
||||
def __init__(self, api, name):
|
||||
self.api = api
|
||||
self.name = name
|
||||
|
||||
def get_data(self):
|
||||
status_code, data = self.api.get('_ilm/policy/{}'.format(self.name))
|
||||
if status_code == 200:
|
||||
return data[self.name]
|
||||
else:
|
||||
return {}
|
||||
|
||||
def create(self, phases):
|
||||
self.api.put(
|
||||
'_ilm/policy/{}'.format(self.name),
|
||||
{ 'policy': { 'phases': phases } }
|
||||
)
|
||||
|
||||
def dict_has_changed(self, new_data, old_data):
|
||||
for option, value in new_data.items():
|
||||
if not option in old_data:
|
||||
if value:
|
||||
return True
|
||||
|
||||
elif type(value) is dict:
|
||||
if self.dict_has_changed(value, old_data[option]):
|
||||
return True
|
||||
|
||||
elif type(value) is list:
|
||||
if not type(data[option]) is list:
|
||||
return True
|
||||
if old_data[option].sort() != value.sort():
|
||||
return True
|
||||
|
||||
elif str(old_data[option]) != str(value):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def has_changed(self, phases):
|
||||
old_data = self.get_data()
|
||||
if not old_data or self.dict_has_changed(phases, old_data['policy']['phases']):
|
||||
self.create(phases)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
'name': { 'type': 'str', 'required': True },
|
||||
'phases': { 'type': 'dict', 'default': {} },
|
||||
'api_url': { 'type': 'str', 'default': 'http://127.0.0.1:9200' },
|
||||
'api_user': { 'type': 'str', 'default': None },
|
||||
'api_password': { 'type': 'str', 'default': None, 'no_log': True },
|
||||
}
|
||||
module = AnsibleModule(argument_spec=fields)
|
||||
|
||||
api = ElasticsearchApi(
|
||||
module.params['api_url'],
|
||||
module.params['api_user'],
|
||||
module.params['api_password']
|
||||
)
|
||||
|
||||
ilm = ElasticsearchILMPolicy(api, module.params['name'])
|
||||
changed = ilm.has_changed(module.params['phases'])
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
from ansible.module_utils.elasticsearch_api import *
|
||||
import subprocess
|
||||
|
||||
class ElasticsearchInitPassword:
|
||||
def __init__(self, api_url, api_user, api_password):
|
||||
self.api = ElasticsearchApi(
|
||||
api_url,
|
||||
api_user,
|
||||
api_password
|
||||
)
|
||||
self.user = api_user
|
||||
self.password = api_password
|
||||
|
||||
def is_set(self):
|
||||
status_code, _ = self.api.get('_cluster/health')
|
||||
if status_code == 401:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def change(self):
|
||||
subprocess.run(
|
||||
['/usr/share/elasticsearch/bin/elasticsearch-reset-password', '-u', self.user, '-b', '-i'],
|
||||
input='{}\n{}'.format(self.password, self.password).encode()
|
||||
)
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
'api_url': { 'type': 'str', 'default': 'http://127.0.0.1:9200' },
|
||||
'api_user': { 'type': 'str', 'default': None },
|
||||
'api_password': { 'type': 'str', 'default': None, 'no_log': True },
|
||||
}
|
||||
module = AnsibleModule(argument_spec=fields)
|
||||
changed = False
|
||||
|
||||
init = ElasticsearchInitPassword(
|
||||
module.params['api_url'],
|
||||
module.params['api_user'],
|
||||
module.params['api_password'],
|
||||
)
|
||||
|
||||
if not init.is_set():
|
||||
init.change()
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,126 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
from ansible.module_utils.elasticsearch_api import *
|
||||
|
||||
class ElasticsearchRole:
|
||||
def __init__(self, api_url, api_user, api_password, name, cluster, indices):
|
||||
self.api = ElasticsearchApi(
|
||||
api_url,
|
||||
api_user,
|
||||
api_password
|
||||
)
|
||||
self.api_url = api_url
|
||||
self.name = name
|
||||
self.cluster = cluster
|
||||
self.indices = indices
|
||||
self.exist = False
|
||||
self.data = {}
|
||||
|
||||
def get_data(self):
|
||||
status_code, data = self.api.get('_security/role/{}'.format(self.name))
|
||||
if status_code == 200:
|
||||
self.exist = True
|
||||
self.data = data[self.name]
|
||||
|
||||
def array_has_changed(self, list1, list2):
|
||||
for item in list1:
|
||||
if item not in list2:
|
||||
return True
|
||||
|
||||
for item in list2:
|
||||
if item not in list1:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def cluster_has_changed(self):
|
||||
return self.array_has_changed(self.cluster, self.data['cluster'])
|
||||
|
||||
def same_indice(self, indice1, indice2):
|
||||
if self.array_has_changed(indice1['names'], indice2['names']):
|
||||
return False
|
||||
|
||||
if self.array_has_changed(indice1['privileges'], indice2['privileges']):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def indices_have_changed(self):
|
||||
for indice1 in self.indices:
|
||||
exist = False
|
||||
for indice2 in self.data['indices']:
|
||||
if self.same_indice(indice1, indice2):
|
||||
exist = True
|
||||
break
|
||||
if not exist:
|
||||
return True
|
||||
|
||||
for indice1 in self.data['indices']:
|
||||
exist = False
|
||||
for indice2 in self.indices:
|
||||
if self.same_indice(indice1, indice2):
|
||||
exist = True
|
||||
break
|
||||
if not exist:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def has_changed(self):
|
||||
if self.cluster_has_changed():
|
||||
return True
|
||||
|
||||
if self.indices_have_changed():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def create(self):
|
||||
self.api.put(
|
||||
'_security/role/{}'.format(self.name),
|
||||
{
|
||||
'cluster': self.cluster,
|
||||
'indices': self.indices
|
||||
}
|
||||
)
|
||||
|
||||
def delete(self):
|
||||
self.api.delete('_security/role/{}'.format(self.name))
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
'name': { 'type': 'str', 'required': True },
|
||||
'indices': { 'type': 'list', 'default': [] },
|
||||
'cluster': { 'type': 'list', 'default': [] },
|
||||
'api_url': { 'type': 'str', 'default': 'http://127.0.0.1:9200' },
|
||||
'api_user': { 'type': 'str', 'default': None },
|
||||
'api_password': { 'type': 'str', 'default': None, 'no_log': True },
|
||||
'state': { 'type': 'str', 'default': 'present', 'choice': ['present', 'absent'] },
|
||||
}
|
||||
module = AnsibleModule(argument_spec=fields)
|
||||
changed = False
|
||||
|
||||
role = ElasticsearchRole(
|
||||
module.params['api_url'],
|
||||
module.params['api_user'],
|
||||
module.params['api_password'],
|
||||
module.params['name'],
|
||||
module.params['cluster'],
|
||||
module.params['indices'],
|
||||
)
|
||||
role.get_data()
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
if not role.exist or role.has_changed():
|
||||
role.create()
|
||||
changed = True
|
||||
elif user.exist:
|
||||
role.delete()
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -77,7 +77,7 @@ def main():
|
|||
'mappings': { 'type': 'dict', 'default': {} },
|
||||
'api_url': { 'type': 'str', 'default': 'http://127.0.0.1:9200' },
|
||||
'api_user': { 'type': 'str', 'default': None },
|
||||
'api_password': { 'type': 'str', 'default': None, 'no_log': True },
|
||||
'api_password': { 'type': 'str', 'default': None },
|
||||
}
|
||||
module = AnsibleModule(argument_spec=fields)
|
||||
changed = False
|
||||
|
|
|
@ -4,131 +4,90 @@ from ansible.module_utils.basic import *
|
|||
from ansible.module_utils.elasticsearch_api import *
|
||||
|
||||
class ElasticsearchUser:
|
||||
def __init__(self, api_url, api_user, api_password, name, password, roles):
|
||||
self.api = ElasticsearchApi(
|
||||
api_url,
|
||||
api_user,
|
||||
api_password
|
||||
)
|
||||
self.api_url = api_url
|
||||
def __init__(self, api, name):
|
||||
self.api = api
|
||||
self.name = name
|
||||
self.password = password
|
||||
self.roles = roles
|
||||
self.exist = False
|
||||
self.data = {}
|
||||
|
||||
def is_builtin(self):
|
||||
users = [
|
||||
'apm_system',
|
||||
'beats_system',
|
||||
'elastic',
|
||||
'kibana',
|
||||
'kibana_system',
|
||||
'logstash_system',
|
||||
'remote_monitoring_user'
|
||||
]
|
||||
if self.name in users:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_data(self):
|
||||
status_code, data = self.api.get('_security/user/{}'.format(self.name))
|
||||
if status_code == 200:
|
||||
self.exist = True
|
||||
self.data = data[self.name]
|
||||
|
||||
def roles_have_changed(self):
|
||||
for role in self.roles:
|
||||
if role not in self.data['roles']:
|
||||
return True
|
||||
|
||||
for role in self.data['roles']:
|
||||
if role not in self.roles:
|
||||
def has_changed(self, roles):
|
||||
if roles.sort() != self.data['roles'].sort():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def password_has_changed(self):
|
||||
api = ElasticsearchApi(
|
||||
self.api_url,
|
||||
self.name,
|
||||
self.password
|
||||
def password_has_changed(self, password):
|
||||
return not self.api.check_password(self.name, password)
|
||||
|
||||
def change_password(self, password):
|
||||
self.api.put(
|
||||
'_security/user/{}/_password'.format(self.name),
|
||||
{ 'password': password }
|
||||
)
|
||||
status_code, _ = api.get('_cluster/health')
|
||||
if status_code == 401:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def has_changed(self):
|
||||
if self.roles_have_changed():
|
||||
return True
|
||||
|
||||
if self.password_has_changed():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def create(self):
|
||||
def create(self, options):
|
||||
self.api.put(
|
||||
'_security/user/{}'.format(self.name),
|
||||
{
|
||||
'password': self.password,
|
||||
'roles': self.roles
|
||||
}
|
||||
options
|
||||
)
|
||||
|
||||
def change_password(self):
|
||||
self.api.post(
|
||||
'_security/user/{}/_password'.format(self.name),
|
||||
{
|
||||
'password': self.password
|
||||
}
|
||||
)
|
||||
|
||||
def delete(self):
|
||||
self.api.delete('_security/user/{}'.format(self.name))
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
'name': { 'type': 'str', 'required': True },
|
||||
'password': { 'type': 'str', 'required': True, 'no_log': True },
|
||||
'password': { 'type': 'str', 'required': True },
|
||||
'roles': { 'type': 'list', 'default': [] },
|
||||
'api_url': { 'type': 'str', 'default': 'http://127.0.0.1:9200' },
|
||||
'api_user': { 'type': 'str', 'default': None },
|
||||
'api_password': { 'type': 'str', 'default': None, 'no_log': True },
|
||||
'state': { 'type': 'str', 'default': 'present', 'choice': ['present', 'absent'] },
|
||||
'api_password': { 'type': 'str', 'default': None },
|
||||
'state': { 'type': 'str', 'default': 'present', 'required': True, 'choice': ['absent', 'present'] },
|
||||
}
|
||||
module = AnsibleModule(argument_spec=fields)
|
||||
changed = False
|
||||
special_users = [
|
||||
'elastic', 'kibana', 'logstash_system',
|
||||
'beats_system', 'apm_system', 'remote_monitoring_user'
|
||||
]
|
||||
|
||||
user = ElasticsearchUser(
|
||||
options = {
|
||||
'roles': module.params['roles'],
|
||||
'password': module.params['password'],
|
||||
}
|
||||
|
||||
api = ElasticsearchApi(
|
||||
module.params['api_url'],
|
||||
module.params['api_user'],
|
||||
module.params['api_password'],
|
||||
module.params['api_password']
|
||||
)
|
||||
|
||||
user = ElasticsearchUser(
|
||||
api,
|
||||
module.params['name'],
|
||||
module.params['password'],
|
||||
module.params['roles'],
|
||||
)
|
||||
user.get_data()
|
||||
|
||||
if user.is_builtin():
|
||||
if user.password_has_changed():
|
||||
user.change_password()
|
||||
changed = True
|
||||
else:
|
||||
if module.params['state'] == 'present':
|
||||
if not user.exist or user.has_changed():
|
||||
user.create()
|
||||
changed = True
|
||||
else:
|
||||
if not module.params['name'] in special_users:
|
||||
if module.params['state'] == 'absent':
|
||||
if user.exist:
|
||||
user.delete()
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
if not user.exist or user.has_changed(module.params['roles']):
|
||||
user.create(options)
|
||||
changed = True
|
||||
|
||||
if user.password_has_changed(module.params['password']):
|
||||
user.change_password(module.params['password'])
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
galaxy_info:
|
||||
role_name: elasticsearch
|
||||
namespace: nishiki
|
||||
author: Adrien Waksberg
|
||||
company: Adrien Waksberg
|
||||
description: Install and configure elasticsearch
|
||||
license: Apache2
|
||||
min_ansible_version: "2.9"
|
||||
min_ansible_version: 2.7
|
||||
|
||||
platforms:
|
||||
- name: Debian
|
||||
versions:
|
||||
- bookworm
|
||||
- stretch
|
||||
- buster
|
||||
|
||||
galaxy_tags:
|
||||
- database
|
||||
|
|
|
@ -5,39 +5,38 @@ import base64
|
|||
class ElasticsearchApi:
|
||||
def __init__(self, url, user, password):
|
||||
self.url = url
|
||||
self.basic = None
|
||||
self.headers = {}
|
||||
if user and password:
|
||||
self.basic = requests.auth.HTTPBasicAuth(user, password)
|
||||
token = base64.b64encode('{}:{}'.format(user, password))
|
||||
self.headers = { 'Authorization': 'Basic {}'.format(token) }
|
||||
|
||||
def check_password(self, user, password):
|
||||
token = base64.b64encode('{}:{}'.format(user, password))
|
||||
headers = { 'Authorization': 'Basic {}'.format(token) }
|
||||
|
||||
r = requests.get(self.url, headers=headers)
|
||||
if r.status_code != 401:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get(self, path):
|
||||
r = requests.get(
|
||||
'{}/{}'.format(self.url, path),
|
||||
auth=self.basic
|
||||
)
|
||||
|
||||
if r.status_code == 500:
|
||||
raise Exception('Server return 500 error: {}'.format(r.text))
|
||||
|
||||
return r.status_code, r.json()
|
||||
|
||||
def post(self, path, data):
|
||||
r = requests.post(
|
||||
'{}/{}'.format(self.url, path),
|
||||
auth=self.basic,
|
||||
json=data
|
||||
headers=self.headers
|
||||
)
|
||||
|
||||
if r.status_code == 500:
|
||||
raise Exception('Server return 500 error: {}'.format(r.text))
|
||||
elif r.status_code == 401:
|
||||
raise Exception('Authentification has failed')
|
||||
elif r.status_code != 200:
|
||||
raise Exception('Server return an unknown error: {}'.format(r.text))
|
||||
|
||||
return r.status_code, r.json()
|
||||
|
||||
def put(self, path, data):
|
||||
r = requests.put(
|
||||
'{}/{}'.format(self.url, path),
|
||||
auth=self.basic,
|
||||
headers=self.headers,
|
||||
json=data
|
||||
)
|
||||
|
||||
|
|
|
@ -4,78 +4,8 @@
|
|||
roles:
|
||||
- ansible-role-elasticsearch
|
||||
vars:
|
||||
elasticsearch_password: mysecret
|
||||
elasticsearch_api_password: secret
|
||||
elasticsearch_heap_size: 512m
|
||||
elasticsearch_config:
|
||||
xpack.security.transport.ssl.enabled: true
|
||||
xpack.security.transport.ssl.certificate: /etc/elasticsearch/certificate.pem
|
||||
xpack.security.transport.ssl.key: /etc/elasticsearch/key.pem
|
||||
elasticsearch_ssl_certificate: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDOzCCAiMCFF0yQzyw+sBIqfYykFNGS9xImVk2MA0GCSqGSIb3DQEBCwUAMFkx
|
||||
CzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAMBgNVBAcMBVBhcmlzMRMw
|
||||
EQYDVQQKDApFbnRyZXByaXNlMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAgFw0yMzEx
|
||||
MTMxNTAwMzJaGA8yMTIzMTAyMDE1MDAzMlowWTELMAkGA1UEBhMCRlIxDzANBgNV
|
||||
BAgMBkZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxEzARBgNVBAoMCkVudHJlcHJpc2Ux
|
||||
FDASBgNVBAMMC2V4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAoM8v9Gp+nLULI6XjFiXgQzz1wjsCSAyBgPOApaA5QcMTeTVrCphGQX0A
|
||||
3wfT4rs1bBrVphbM9FpV85QzL6fmw3SOSPh6SdSJE+pd7V0mFX1/foeJJcIJnQfU
|
||||
3k5eUfDBwgsU4ad/oxyP/GLs4ZPyjeh7L8oOcejeY37T7IX2y3af7TyfIS7hDof8
|
||||
DOFjhv0/FB9nexpdh7toGlbjjHljg0BNupWog2Nr1W55/4UCMOnX+iUrgUpU3a7j
|
||||
e6TgFgBYMel4KCH9MNdJ5+pPs4Nt8cVkX4FfZSJnfnLlVYHw8mTpTtw1gSsjuDxS
|
||||
bKrDd5i3+2xLr7GCyd9SnEBwiDZ13QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA2
|
||||
rKOA7EAgJrGPkZMT1s9k0ABMX7FU5QHwHPNA3pxjpFSHGRnX9nV+/qSgQugo3Qs8
|
||||
s+eEa7i37G8fgCN6XrSd+jhcWjKbMQOa1FwxBEQg+giUeWXZBei71hx0naBIJ8On
|
||||
Mm6mctHQDlEymRvCxzyo/280tCE+gI6pF4JCf5D8pcJVcavkubp/saMhhiK6E3pH
|
||||
KM/lbUoO6Ly4dRhIf5SFAHOxth6lsAGMIFwZr0+tYBNln2vvHuexbIrj7I9GFcme
|
||||
PGIV+cLQEoYhuz+2C9V/FRQwm5p3bNbd9hSYJ93Vi6n9/25OzsCmM4YGbrPnixWe
|
||||
EOT8/oluROEiuHHikq5/
|
||||
-----END CERTIFICATE-----
|
||||
elasticsearch_ssl_key: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCgzy/0an6ctQsj
|
||||
peMWJeBDPPXCOwJIDIGA84CloDlBwxN5NWsKmEZBfQDfB9PiuzVsGtWmFsz0WlXz
|
||||
lDMvp+bDdI5I+HpJ1IkT6l3tXSYVfX9+h4klwgmdB9TeTl5R8MHCCxThp3+jHI/8
|
||||
Yuzhk/KN6Hsvyg5x6N5jftPshfbLdp/tPJ8hLuEOh/wM4WOG/T8UH2d7Gl2Hu2ga
|
||||
VuOMeWODQE26laiDY2vVbnn/hQIw6df6JSuBSlTdruN7pOAWAFgx6XgoIf0w10nn
|
||||
6k+zg23xxWRfgV9lImd+cuVVgfDyZOlO3DWBKyO4PFJsqsN3mLf7bEuvsYLJ31Kc
|
||||
QHCINnXdAgMBAAECggEABG86OBAAvlMKw9ik/r0cJlaFw22rpi98GcF9RHP66DqY
|
||||
LKFBuqjQ1Sj8j2nwmKHHexvxVNNvovRjxuQJFlEXvr+V1eLOQn9zKUKvBObq8DBG
|
||||
Bgf4SvuDFtq6rsez96f/O9ng4UkkbqvQt6nFtQHGsE2fKgX1KIR+r3k1oGHgWKN5
|
||||
Sd71E6yr0/4q3m8TleV9PrC4kghQ5j8sntXurdfhlRM9w4wNMb5M9F8ebgxErd7i
|
||||
6ncVoKdpe18cubU+9wUxW5MxrasheHmfwdgjIQyU69srsERhxRZ4mhBl7n7UCCDK
|
||||
1MZ5tKph+fV4t3P/xHXW1HGhMj4UgRTLjnr6e5yOGQKBgQDjQonV85cga1SeLh4Y
|
||||
8NXLKHZHL56VmS7jOQ4V6GEEWqz/2IGi1GZjKv1KOY14M+GnRPD+0LTWex8ubELL
|
||||
r/0tvlx3kiuPyEMsSnIrVlaiVr1yWPLdrVaerfO8hD3WykpwH5enHOdhaoezN314
|
||||
4X3Xj0+V8zZ7I1mzA0T1bPmCBQKBgQC1JVV67qoPg6X7g54j9HK4fWzRAT0cGXV7
|
||||
60x78JQdcDSP4yqwDHqvryRDMP38xwSbvyegERQcbZjLbl1YY5T6ZL2ovu1OemC7
|
||||
6lSOSwOCD89QVsrYV52mY1qmOsuNgLIwJ1PJVY5IeFmfCpR9IFeIhdPhj2VtsAqC
|
||||
M4T1hCAz+QKBgQCSIIq4g7S9J8Z1H3pC1zjhNNc41qnFz4WSnXEtLQqU3ik3KWPR
|
||||
63kact4DCBarH9EM2QuNDW36K5jVJM+eYT8OVsTmLZrNDRwEMqpOq2lxYQzXpdIk
|
||||
L/zuczOyF+YbYl+S0P2WesNcpD81QYzwWS2tmXy3EngJnaVjscp5dOTKcQKBgFAJ
|
||||
r+xCWdfDBmrMK+qdDrdfi94JWxP4V8WqIMA+e2NKeZ7985WX3fmUPESH+CFhWjLq
|
||||
0jpScX1iG3n/SLVOQrwkGPzfZ4EeZ3GAR14b3O/xxlssDjJq/BhRm/MI1XmvXIwU
|
||||
RFwYNmbk7kxsY1GqIaML5qOqNVmyx+Hhm6TTfVsZAoGBALubBpgAoT+lKHw6fC6D
|
||||
7TSCcxFd5tYHHw4RUmK85RcTrbjC7LksAd01T54tdM7nZRlijgJUNsYzDfv/SuSp
|
||||
F3OGK/Tmx3MW5O+lq5O+2oRmUSfcIUgnrjgUeevj6Rgt1qx33WEoKBM2rVBIBqOn
|
||||
ZKrzDBkVG/H+H0hwiV219PLE
|
||||
-----END PRIVATE KEY-----
|
||||
elasticsearch_roles:
|
||||
myrole:
|
||||
cluster:
|
||||
- all
|
||||
indices:
|
||||
- names: ["logstash*"]
|
||||
privileges:
|
||||
- create
|
||||
- write
|
||||
elasticsearch_users:
|
||||
toto:
|
||||
password: supers3cret
|
||||
roles:
|
||||
- viewer
|
||||
kibana_system:
|
||||
password: supertest2
|
||||
elasticsearch_index_templates:
|
||||
test:
|
||||
index_patterns:
|
||||
|
@ -86,8 +16,3 @@
|
|||
mappings:
|
||||
metrics:
|
||||
type: short
|
||||
|
||||
pre_tasks:
|
||||
- name: update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
|
|
|
@ -2,18 +2,17 @@
|
|||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: debian12
|
||||
image: code.waks.be/nishiki/molecule:debian12
|
||||
- name: debian10
|
||||
image: nishiki/debian10:molecule
|
||||
privileged: true
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:ro
|
||||
command: /bin/systemd
|
||||
capabilities:
|
||||
- SYS_ADMIN
|
||||
lint: |
|
||||
set -e
|
||||
yamllint .
|
||||
ansible-lint .
|
||||
ansible-lint
|
||||
verifier:
|
||||
name: testinfra
|
||||
|
|
|
@ -12,20 +12,6 @@ def test_config_file(host):
|
|||
assert config.mode == 0o640
|
||||
assert config.contains('path.data: /var/lib/elasticsearch')
|
||||
|
||||
def test_ssl_key_file(host):
|
||||
config = host.file('/etc/elasticsearch/key.pem')
|
||||
assert config.user == 'root'
|
||||
assert config.group == 'elasticsearch'
|
||||
assert config.mode == 0o640
|
||||
assert config.contains('-----BEGIN PRIVATE KEY-----')
|
||||
|
||||
def test_ssl_certificate_file(host):
|
||||
config = host.file('/etc/elasticsearch/certificate.pem')
|
||||
assert config.user == 'root'
|
||||
assert config.group == 'elasticsearch'
|
||||
assert config.mode == 0o640
|
||||
assert config.contains('-----BEGIN CERTIFICATE-----')
|
||||
|
||||
def test_service(host):
|
||||
service = host.service('elasticsearch')
|
||||
assert service.is_running
|
||||
|
@ -37,20 +23,10 @@ def test_socket(host):
|
|||
assert socket.is_listening
|
||||
|
||||
def test_java_memory(host):
|
||||
process = host.process.filter(user='elasticsearch', comm='java')
|
||||
assert '-Xms512m' in process[1].args
|
||||
assert '-Xmx512m' in process[1].args
|
||||
process = host.process.get(user='elasticsearch', comm='java')
|
||||
assert '-Xms512m' in process.args
|
||||
assert '-Xmx512m' in process.args
|
||||
|
||||
def test_elasticsearch_template(host):
|
||||
result = host.check_output('curl -v -u elastic:mysecret http://127.0.0.1:9200/_template/test')
|
||||
result = host.check_output('curl -v http://127.0.0.1:9200/_template/test')
|
||||
assert '"number_of_replicas":"1"' in result
|
||||
|
||||
def test_elasticsearch_role(host):
|
||||
result = host.check_output('curl -v -u elastic:mysecret http://127.0.0.1:9200/_security/role/myrole')
|
||||
assert '"names":["logstash*"]' in result
|
||||
assert '"privileges":["create","write"]' in result
|
||||
|
||||
def test_elasticsearch_user(host):
|
||||
result = host.check_output('curl -v -u elastic:mysecret http://127.0.0.1:9200/_security/user/toto')
|
||||
assert '"username":"toto"' in result
|
||||
assert '"roles":["viewer"]' in result
|
||||
|
|
|
@ -1,43 +1,21 @@
|
|||
---
|
||||
- name: Set heap size
|
||||
ansible.builtin.lineinfile:
|
||||
- name: set heap size
|
||||
lineinfile:
|
||||
path: /etc/elasticsearch/jvm.options
|
||||
regexp: "^-{{ item }}"
|
||||
line: "-{{ item }}{{ elasticsearch_heap_size }}"
|
||||
regexp: '^-{{ item }}'
|
||||
line: '-{{ item }}{{ elasticsearch_heap_size }}'
|
||||
loop:
|
||||
- Xms
|
||||
- Xmx
|
||||
notify: Restart elasticsearch
|
||||
notify: restart elasticsearch
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Copy SSL certificate
|
||||
ansible.builtin.copy:
|
||||
content: "{{ elasticsearch_ssl_certificate }}"
|
||||
dest: "{{ elasticsearch_full_config['xpack.security.transport.ssl.certificate'] }}"
|
||||
owner: root
|
||||
group: elasticsearch
|
||||
mode: "0640"
|
||||
when: "'xpack.security.transport.ssl.certificate' in elasticsearch_full_config"
|
||||
notify: Restart elasticsearch
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Copy SSL key
|
||||
ansible.builtin.copy:
|
||||
content: "{{ elasticsearch_ssl_key }}"
|
||||
dest: "{{ elasticsearch_full_config['xpack.security.transport.ssl.key'] }}"
|
||||
owner: root
|
||||
group: elasticsearch
|
||||
mode: "0640"
|
||||
when: "'xpack.security.transport.ssl.key' in elasticsearch_full_config"
|
||||
notify: Restart elasticsearch
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Copy config file
|
||||
ansible.builtin.copy:
|
||||
content: "{{ elasticsearch_full_config | to_yaml }}"
|
||||
- name: copy config file
|
||||
copy:
|
||||
content: '{{ elasticsearch_full_config|to_nice_yaml }}'
|
||||
dest: /etc/elasticsearch/elasticsearch.yml
|
||||
owner: root
|
||||
group: elasticsearch
|
||||
mode: "0640"
|
||||
notify: Restart elasticsearch
|
||||
mode: 0640
|
||||
notify: restart elasticsearch
|
||||
tags: elasticsearch
|
||||
|
|
|
@ -1,61 +1,26 @@
|
|||
---
|
||||
- name: Init elastic password
|
||||
elasticsearch_init_password:
|
||||
api_user: "{{ elasticsearch_api_user }}"
|
||||
api_password: "{{ elasticsearch_password }}"
|
||||
run_once: true
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Manage roles
|
||||
elasticsearch_role:
|
||||
name: "{{ item.key }}"
|
||||
cluster: "{{ item.value.cluster | default(omit) }}"
|
||||
indices: "{{ item.value.indices | default(omit) }}"
|
||||
api_user: "{{ elasticsearch_api_user }}"
|
||||
api_password: "{{ elasticsearch_password }}"
|
||||
state: "{{ item.value.state | default('present') }}"
|
||||
loop: "{{ elasticsearch_roles | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
run_once: true
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Manage users
|
||||
- name: manage users
|
||||
elasticsearch_user:
|
||||
name: "{{ item.key }}"
|
||||
password: "{{ item.value.password }}"
|
||||
roles: "{{ item.value.roles | default(omit) }}"
|
||||
api_user: "{{ elasticsearch_api_user }}"
|
||||
api_password: "{{ elasticsearch_password }}"
|
||||
state: "{{ item.value.state | default('present') }}"
|
||||
loop: "{{ elasticsearch_users | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
name: '{{ item.key }}'
|
||||
password: '{{ item.value.password }}'
|
||||
api_user: '{{ elasticsearch_api_user }}'
|
||||
api_password: '{{ elasticsearch_api_password }}'
|
||||
loop: '{{ elasticsearch_users|dict2items }}'
|
||||
when: |
|
||||
'xpack.security.enabled' in elasticsearch_full_config and
|
||||
elasticsearch_full_config['xpack.security.enabled'] == True
|
||||
run_once: true
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Copy ilm policies
|
||||
elasticsearch_ilm_policy:
|
||||
name: "{{ item.key }}"
|
||||
phases: "{{ item.value | default({}) }}"
|
||||
api_user: "{{ elasticsearch_api_user }}"
|
||||
api_password: "{{ elasticsearch_password }}"
|
||||
loop: "{{ elasticsearch_ilm_policies | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
run_once: true
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Copy index templates
|
||||
- name: copy index templates
|
||||
elasticsearch_template:
|
||||
name: "{{ item.key }}"
|
||||
index_patterns: "{{ item.value.index_patterns }}"
|
||||
settings: "{{ item.value.settings | default({}) }}"
|
||||
mappings: "{{ item.value.mappings | default({}) }}"
|
||||
api_user: "{{ elasticsearch_api_user }}"
|
||||
api_password: "{{ elasticsearch_password }}"
|
||||
loop: "{{ elasticsearch_index_templates | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
name: '{{ item.key }}'
|
||||
index_patterns: '{{ item.value.index_patterns }}'
|
||||
settings: '{{ item.value.settings|default({}) }}'
|
||||
mappings: '{{ item.value.mappings|default({}) }}'
|
||||
api_user: '{{ elasticsearch_api_user }}'
|
||||
api_password: '{{ elasticsearch_api_password }}'
|
||||
no_log: true
|
||||
loop: '{{ elasticsearch_index_templates|dict2items }}'
|
||||
run_once: true
|
||||
tags: elasticsearch
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
---
|
||||
- name: Import pacakge tasks
|
||||
ansible.builtin.import_tasks: packages.yml
|
||||
- name: Import config tasks
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
- name: Import service tasks
|
||||
ansible.builtin.import_tasks: service.yml
|
||||
- name: Import data tasks
|
||||
ansible.builtin.import_tasks: data.yml
|
||||
when: elasticsearch_master
|
||||
- import_tasks: packages.yml
|
||||
- import_tasks: config.yml
|
||||
- import_tasks: service.yml
|
||||
- import_tasks: data.yml
|
||||
|
|
|
@ -1,31 +1,33 @@
|
|||
---
|
||||
- name: Install dependencies packages
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- name: install dependencies packages
|
||||
apt:
|
||||
name: '{{ packages }}'
|
||||
vars:
|
||||
packages:
|
||||
- apt-transport-https
|
||||
- python3-requests
|
||||
- python-requests
|
||||
retries: 2
|
||||
register: result
|
||||
until: result is succeeded
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Add repository key
|
||||
ansible.builtin.get_url:
|
||||
- name: add repository key
|
||||
apt_key:
|
||||
url: https://artifacts.elastic.co/GPG-KEY-elasticsearch
|
||||
dest: /etc/apt/keyrings/elastic.asc
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
checksum: sha256:db52809c5f6b27f9c2bed45cb43e398c659275f3d35305653c6750a0db90f5eb
|
||||
retries: 2
|
||||
register: result
|
||||
until: result is succeeded
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Add repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >
|
||||
deb [signed-by=/etc/apt/keyrings/elastic.asc]
|
||||
https://artifacts.elastic.co/packages/{{ elasticsearch_major_version }}.x/apt stable main
|
||||
filename: elastic
|
||||
- name: add repository
|
||||
apt_repository:
|
||||
repo: deb https://artifacts.elastic.co/packages/7.x/apt stable main
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Install package
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- elasticsearch
|
||||
- name: install package
|
||||
apt:
|
||||
name: elasticsearch
|
||||
retries: 2
|
||||
register: result
|
||||
until: result is succeeded
|
||||
tags: elasticsearch
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
- name: Enable and start service
|
||||
ansible.builtin.service:
|
||||
- name: enable and start service
|
||||
systemd:
|
||||
name: elasticsearch
|
||||
state: started
|
||||
enabled: true
|
||||
tags: elasticsearch
|
||||
|
||||
- name: Wait for api is available
|
||||
ansible.builtin.wait_for:
|
||||
- name: wait for api is available
|
||||
wait_for:
|
||||
port: 9200
|
||||
timeout: 10
|
||||
tags: elasticsearch
|
||||
|
|
Loading…
Reference in a new issue