diff --git a/README.md b/README.md
index 92a55e0..6fc904e 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,8 @@ Install and configure Elasticsearch
         format: YYYY-MM-dd
 ```
 
+* `elasticsearch_users` - hash to manage users
+
 ## How to use
 
 ```
diff --git a/defaults/main.yml b/defaults/main.yml
index ea82f64..12afd16 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -1,8 +1,11 @@
 ---
 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
 elasticsearch_full_config: '{{ elasticsearch_default_config|combine(elasticsearch_config) }}'
 elasticsearch_index_templates: {}
+elasticsearch_users: {}
diff --git a/library/elasticsearch_user.py b/library/elasticsearch_user.py
new file mode 100644
index 0000000..b73a897
--- /dev/null
+++ b/library/elasticsearch_user.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+
+from ansible.module_utils.basic import *
+from ansible.module_utils.elasticsearch_api import *
+
+class ElasticsearchUser:
+  def __init__(self, api, name):
+    self.api   = api
+    self.name  = name
+    self.exist = False
+    self.data  = {}
+
+  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 has_changed(self, roles):
+    if roles.sort() != self.data['roles'].sort():
+      return True
+
+    return False
+
+  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 }
+    )
+    
+  def create(self, options):
+    self.api.put(
+      '_security/user/{}'.format(self.name),
+      options
+    )
+    
+def main():
+  fields = {
+    'name':         { 'type': 'str',  'required': 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 },
+    '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'
+  ]
+
+  options = {
+    'roles':    module.params['roles'],
+    'password': module.params['password'],
+  }
+
+  api = ElasticsearchApi(
+    module.params['api_url'],
+    module.params['api_user'],
+    module.params['api_password']
+  )
+
+  user = ElasticsearchUser(
+    api,
+    module.params['name'],
+  )
+  user.get_data()
+
+  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()
diff --git a/module_utils/elasticsearch_api.py b/module_utils/elasticsearch_api.py
index e8d858c..bf7f7f5 100644
--- a/module_utils/elasticsearch_api.py
+++ b/module_utils/elasticsearch_api.py
@@ -7,8 +7,18 @@ class ElasticsearchApi:
     self.url     = url
     self.headers = {}
     if user and password:
-      token = base64.b64encode('{}:{}',)
-      self.headers = { 'Authorization': 'Basic ' + base64.b64encode({},) }
+      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(
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
index a098a8b..0b33cdc 100644
--- a/molecule/default/converge.yml
+++ b/molecule/default/converge.yml
@@ -1,7 +1,10 @@
 ---
 - name: Converge
   hosts: all
+  roles:
+    - ansible-role-elasticsearch
   vars:
+    elasticsearch_api_password: secret
     elasticsearch_heap_size: 512m
     elasticsearch_index_templates:
       test:
@@ -13,10 +16,3 @@
         mappings:
           metrics:
             type: short
-  roles:
-    - ansible-role-elasticsearch
-#
-#  tasks:
-#    - name: "Include ansible-role-elasticsearch"
-#      include_role:
-#        name: "ansible-role-elasticsearch"
diff --git a/tasks/config.yml b/tasks/config.yml
index 08db1da..d7ed8a6 100644
--- a/tasks/config.yml
+++ b/tasks/config.yml
@@ -12,7 +12,7 @@
 
 - name: copy config file
   copy:
-    content: '{{ elasticsearch_full_config|to_yaml }}'
+    content: '{{ elasticsearch_full_config|to_nice_yaml }}'
     dest: /etc/elasticsearch/elasticsearch.yml
     owner: root
     group: elasticsearch
diff --git a/tasks/data.yml b/tasks/data.yml
index 6ee4fdc..b6ca4d2 100644
--- a/tasks/data.yml
+++ b/tasks/data.yml
@@ -1,10 +1,25 @@
 ---
+- name: manage users
+  elasticsearch_user:
+    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 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_api_password }}'
   no_log: true
   loop: '{{ elasticsearch_index_templates|dict2items }}'
   run_once: true