Add ansible provisioning (#122)
* first ansible skeleton * first commit of ansible installation of vulnwhisperer outside docker * first ansible skeleton * first commit of ansible installation of vulnwhisperer outside docker * refactor the ansible role a bit * update readme, add fail validation step to provision.yml and fix typo when calling a logging funciton
This commit is contained in:

committed by
Quim Montal

parent
a8671a7303
commit
3a09f60543
@ -0,0 +1,89 @@
|
||||
---
|
||||
- name: set fact manage_file_users
|
||||
set_fact: manage_file_users=es_users is defined and es_users.file is defined and es_users.file.keys() | length > 0
|
||||
|
||||
- name: Create the users file if it doesn't exist
|
||||
copy:
|
||||
content: ""
|
||||
dest: "{{ conf_dir }}{{ es_xpack_conf_subdir }}/users"
|
||||
force: no # this ensures it only creates it if it does not exist
|
||||
group: "{{ es_group }}"
|
||||
owner: "{{ es_user }}"
|
||||
mode: 0555
|
||||
|
||||
#List current users
|
||||
- name: List Users
|
||||
become: yes
|
||||
shell: cat {{conf_dir}}{{es_xpack_conf_subdir}}/users | awk -F':' '{print $1}'
|
||||
register: current_file_users
|
||||
when: manage_file_users
|
||||
changed_when: False
|
||||
|
||||
- name: set fact users_to_remove
|
||||
set_fact: users_to_remove={{ current_file_users.stdout_lines | difference (es_users.file.keys()) }}
|
||||
when: manage_file_users
|
||||
|
||||
#Remove users
|
||||
- name: Remove Users
|
||||
become: yes
|
||||
command: >
|
||||
{{es_home}}/bin/{{es_xpack_users_command}} userdel {{item}}
|
||||
with_items: "{{users_to_remove | default([])}}"
|
||||
when: manage_file_users
|
||||
environment:
|
||||
CONF_DIR: "{{ conf_dir }}"
|
||||
ES_PATH_CONF: "{{ conf_dir }}"
|
||||
ES_HOME: "{{es_home}}"
|
||||
|
||||
- name: set fact users_to_add
|
||||
set_fact: users_to_add={{ es_users.file.keys() | difference (current_file_users.stdout_lines) }}
|
||||
when: manage_file_users
|
||||
|
||||
#Add users
|
||||
- name: Add Users
|
||||
become: yes
|
||||
command: >
|
||||
{{es_home}}/bin/{{es_xpack_users_command}} useradd {{item}} -p {{es_users.file[item].password}}
|
||||
with_items: "{{ users_to_add | default([]) }}"
|
||||
when: manage_file_users
|
||||
no_log: True
|
||||
environment:
|
||||
CONF_DIR: "{{ conf_dir }}"
|
||||
ES_PATH_CONF: "{{ conf_dir }}"
|
||||
ES_HOME: "{{es_home}}"
|
||||
|
||||
#Set passwords for all users declared - Required as the useradd will not change existing user passwords
|
||||
- name: Set User Passwords
|
||||
become: yes
|
||||
command: >
|
||||
{{es_home}}/bin/{{es_xpack_users_command}} passwd {{ item }} -p {{es_users.file[item].password}}
|
||||
with_items: "{{ es_users.file.keys() | default([]) }}"
|
||||
when: manage_file_users
|
||||
#Currently no easy way to figure out if the password has changed or to know what it currently is so we can skip.
|
||||
changed_when: False
|
||||
no_log: True
|
||||
environment:
|
||||
CONF_DIR: "{{ conf_dir }}"
|
||||
ES_PATH_CONF: "{{ conf_dir }}"
|
||||
ES_HOME: "{{es_home}}"
|
||||
|
||||
- name: set fact users_roles
|
||||
set_fact: users_roles={{es_users.file | extract_role_users () }}
|
||||
when: manage_file_users
|
||||
|
||||
#Copy Roles files
|
||||
- name: Copy roles.yml File for Instance
|
||||
become: yes
|
||||
template: src=security/roles.yml.j2 dest={{conf_dir}}{{es_xpack_conf_subdir}}/roles.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes
|
||||
when: es_roles is defined and es_roles.file is defined
|
||||
|
||||
#Overwrite users_roles file
|
||||
- name: Copy User Roles
|
||||
become: yes
|
||||
template: src=security/users_roles.j2 dest={{conf_dir}}{{es_xpack_conf_subdir}}/users_roles mode=0644 force=yes
|
||||
when: manage_file_users and users_roles | length > 0
|
||||
|
||||
#Set permission on security directory. E.g. if 2 nodes are installed on the same machine, the second node will not get the users file created at install, causing the files being created at es_users call and then having the wrong Permissions.
|
||||
- name: Set Security Directory Permissions Recursive
|
||||
become: yes
|
||||
file: state=directory path={{conf_dir}}{{es_xpack_conf_subdir}}/ owner={{ es_user }} group={{ es_group }} recurse=yes
|
@ -0,0 +1,191 @@
|
||||
---
|
||||
- name: set fact change_api_password to false
|
||||
set_fact: change_api_password=false
|
||||
|
||||
- name: set fact manage_native_users to false
|
||||
set_fact: manage_native_users=false
|
||||
|
||||
- name: set fact manage_native_users to true
|
||||
set_fact: manage_native_users=true
|
||||
when: es_users is defined and es_users.native is defined and es_users.native.keys() | length > 0
|
||||
|
||||
- name: set fact manage_native_role to false
|
||||
set_fact: manage_native_roles=false
|
||||
|
||||
- name: set fact manange_native_roles to true
|
||||
set_fact: manage_native_roles=true
|
||||
when: es_roles is defined and es_roles.native is defined and es_roles.native.keys() | length > 0
|
||||
|
||||
#If the node has just has security installed it maybe either stopped or started 1. if stopped, we need to start to load native realms 2. if started, we need to restart to load
|
||||
|
||||
#List current users
|
||||
- name: List Native Users
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/user
|
||||
method: GET
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
status_code: 200
|
||||
register: user_list_response
|
||||
when: manage_native_users
|
||||
|
||||
- name: set fact reserved_users equals user_list_response.json
|
||||
set_fact: reserved_users={{ user_list_response.json | filter_reserved }}
|
||||
when: manage_native_users
|
||||
|
||||
#Current users not inc. those reserved
|
||||
- name: set fact current_users equals user_list_response.json.keys not including reserved
|
||||
set_fact: current_users={{ user_list_response.json.keys() | difference (reserved_users) }}
|
||||
when: manage_native_users
|
||||
|
||||
#We are changing the es_api_basic_auth_username password, so we need to do it first and update the param
|
||||
- name: set fact native_users
|
||||
set_fact: native_users={{ es_users.native }}
|
||||
when: manage_native_users
|
||||
|
||||
- name: set fact change_api_password to true
|
||||
set_fact: change_api_password=true
|
||||
when: manage_native_users and es_api_basic_auth_username in native_users and native_users[es_api_basic_auth_username].password is defined
|
||||
|
||||
- name: Update API User Password
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/user/{{es_api_basic_auth_username}}/_password
|
||||
method: POST
|
||||
body_format: json
|
||||
body: "{ \"password\":\"{{native_users[es_api_basic_auth_username].password}}\" }"
|
||||
status_code: 200
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
when: change_api_password
|
||||
|
||||
- name: set fact es_api_basic_auth_password
|
||||
set_fact: es_api_basic_auth_password={{native_users[es_api_basic_auth_username].password}}
|
||||
when: change_api_password
|
||||
|
||||
#Identify users that are present in ES but not declared and thus should be removed
|
||||
- name: set fact users_to_remove
|
||||
set_fact: users_to_remove={{ current_users | difference ( native_users.keys() ) }}
|
||||
when: manage_native_users
|
||||
|
||||
#Delete all non required users NOT inc. reserved
|
||||
- name: Delete Native Users
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/user/{{item}}
|
||||
method: DELETE
|
||||
status_code: 200
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
when: manage_native_users
|
||||
with_items: "{{ users_to_remove | default([]) }}"
|
||||
|
||||
- name: set fact users_to_ignore
|
||||
set_fact: users_to_ignore={{ native_users.keys() | intersect (reserved_users) }}
|
||||
when: manage_native_users
|
||||
|
||||
- name: debug message
|
||||
debug:
|
||||
msg: "WARNING: YOU CAN ONLY CHANGE THE PASSWORD FOR RESERVED USERS IN THE NATIVE REALM. ANY ROLE CHANGES WILL BE IGNORED: {{users_to_ignore}}"
|
||||
when: manage_native_users and users_to_ignore | length > 0
|
||||
|
||||
#Update password on all reserved users
|
||||
- name: Update Reserved User Passwords
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/user/{{item}}/_password
|
||||
method: POST
|
||||
body_format: json
|
||||
body: "{ \"password\":\"{{native_users[item].password}}\" }"
|
||||
status_code: 200
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
when: native_users[item].password is defined
|
||||
no_log: True
|
||||
with_items: "{{ users_to_ignore | default([]) }}"
|
||||
|
||||
- name: set fact users_to_modify
|
||||
set_fact: users_to_modify={{ native_users.keys() | difference (reserved_users) }}
|
||||
when: manage_native_users
|
||||
|
||||
#Overwrite all other users NOT inc. those reserved
|
||||
- name: Update Non-Reserved Native User Details
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/user/{{item}}
|
||||
method: POST
|
||||
body_format: json
|
||||
body: "{{ native_users[item] | to_json }}"
|
||||
status_code: 200
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
when: manage_native_users
|
||||
no_log: True
|
||||
with_items: "{{ users_to_modify | default([]) }}"
|
||||
|
||||
## ROLE CHANGES
|
||||
|
||||
#List current roles not. inc those reserved
|
||||
- name: List Native Roles
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/role
|
||||
method: GET
|
||||
body_format: json
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
status_code: 200
|
||||
register: role_list_response
|
||||
when: manage_native_roles
|
||||
|
||||
- name: set fact reserved roles
|
||||
set_fact: reserved_roles={{ role_list_response.json | filter_reserved }}
|
||||
when: manage_native_roles
|
||||
|
||||
- name: set fact current roles
|
||||
set_fact: current_roles={{ role_list_response.json.keys() | difference (reserved_roles) }}
|
||||
when: manage_native_roles
|
||||
|
||||
- name: set fact roles to ignore
|
||||
set_fact: roles_to_ignore={{ es_roles.native.keys() | intersect (reserved_roles) | default([]) }}
|
||||
when: manage_native_roles
|
||||
|
||||
- name: debug message
|
||||
debug:
|
||||
msg: "WARNING: YOU CANNOT CHANGE RESERVED ROLES. THE FOLLOWING WILL BE IGNORED: {{roles_to_ignore}}"
|
||||
when: manage_native_roles and roles_to_ignore | length > 0
|
||||
|
||||
- name: set fact roles_to_remove
|
||||
set_fact: roles_to_remove={{ current_roles | difference ( es_roles.native.keys() ) }}
|
||||
when: manage_native_roles
|
||||
|
||||
#Delete all non required roles NOT inc. reserved
|
||||
- name: Delete Native Roles
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/role/{{item}}
|
||||
method: DELETE
|
||||
status_code: 200
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
when: manage_native_roles
|
||||
with_items: "{{roles_to_remove | default([]) }}"
|
||||
|
||||
- name: set fact roles_to_modify
|
||||
set_fact: roles_to_modify={{ es_roles.native.keys() | difference (reserved_roles) }}
|
||||
when: manage_native_roles
|
||||
|
||||
#Update other roles - NOT inc. reserved roles
|
||||
- name: Update Native Roles
|
||||
uri:
|
||||
url: http://{{es_api_host}}:{{es_api_port}}/_xpack/security/role/{{item}}
|
||||
method: POST
|
||||
body_format: json
|
||||
body: "{{ es_roles.native[item] | to_json}}"
|
||||
status_code: 200
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
force_basic_auth: yes
|
||||
when: manage_native_roles
|
||||
with_items: "{{ roles_to_modify | default([]) }}"
|
@ -0,0 +1,74 @@
|
||||
---
|
||||
#Security specific configuration done here
|
||||
|
||||
#TODO: 1. Skip users with no password defined or error 2. Passwords | length > 6
|
||||
|
||||
#Ensure x-pack conf directory is created if necessary
|
||||
- name: Ensure x-pack conf directory exists (file)
|
||||
file: path={{ conf_dir }}{{ es_xpack_conf_subdir }} state=directory owner={{ es_user }} group={{ es_group }}
|
||||
changed_when: False
|
||||
when:
|
||||
- es_enable_xpack and "security" in es_xpack_features
|
||||
- (es_users is defined and es_users.file is defined) or (es_roles is defined and es_roles.file is defined) or (es_role_mapping is defined)
|
||||
|
||||
#-----------------------------Create Bootstrap User-----------------------------------
|
||||
### START BLOCK elasticsearch keystore ###
|
||||
- name: create the elasticsearch keystore
|
||||
when: (es_enable_xpack and "security" in es_xpack_features) and (es_version | version_compare('6.0.0', '>'))
|
||||
block:
|
||||
- name: create the keystore if it doesn't exist yet
|
||||
become: yes
|
||||
command: >
|
||||
{{es_home}}/bin/elasticsearch-keystore create
|
||||
args:
|
||||
creates: "{{ conf_dir }}/elasticsearch.keystore"
|
||||
environment:
|
||||
ES_PATH_CONF: "{{ conf_dir }}"
|
||||
|
||||
- name: Check if bootstrap password is set
|
||||
become: yes
|
||||
command: >
|
||||
{{es_home}}/bin/elasticsearch-keystore list
|
||||
register: list_keystore
|
||||
changed_when: False
|
||||
environment:
|
||||
ES_PATH_CONF: "{{ conf_dir }}"
|
||||
|
||||
- name: Create Bootstrap password for elastic user
|
||||
become: yes
|
||||
shell: echo "{{es_api_basic_auth_password}}" | {{es_home}}/bin/elasticsearch-keystore add -x 'bootstrap.password'
|
||||
when:
|
||||
- es_api_basic_auth_username is defined and list_keystore is defined and es_api_basic_auth_username == 'elastic' and 'bootstrap.password' not in list_keystore.stdout_lines
|
||||
environment:
|
||||
ES_PATH_CONF: "{{ conf_dir }}"
|
||||
no_log: true
|
||||
### END BLOCK elasticsearch keystore ###
|
||||
|
||||
#-----------------------------FILE BASED REALM----------------------------------------
|
||||
|
||||
- include: elasticsearch-security-file.yml
|
||||
when: (es_enable_xpack and "security" in es_xpack_features) and ((es_users is defined and es_users.file is defined) or (es_roles is defined and es_roles.file is defined))
|
||||
|
||||
#-----------------------------ROLE MAPPING ----------------------------------------
|
||||
|
||||
#Copy Roles files
|
||||
- name: Copy role_mapping.yml File for Instance
|
||||
become: yes
|
||||
template: src=security/role_mapping.yml.j2 dest={{conf_dir}}{{es_xpack_conf_subdir}}/role_mapping.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes
|
||||
when: es_role_mapping is defined
|
||||
|
||||
#-----------------------------AUTH FILE----------------------------------------
|
||||
|
||||
- name: Copy message auth key to elasticsearch
|
||||
become: yes
|
||||
copy: src={{ es_message_auth_file }} dest={{conf_dir}}{{es_xpack_conf_subdir}}/system_key owner={{ es_user }} group={{ es_group }} mode=0600 force=yes
|
||||
when: es_message_auth_file is defined
|
||||
|
||||
#------------------------------------------------------------------------------------
|
||||
|
||||
#Ensure security conf directory is created
|
||||
- name: Ensure security conf directory exists
|
||||
become: yes
|
||||
file: path={{ conf_dir }}/security state=directory owner={{ es_user }} group={{ es_group }}
|
||||
changed_when: False
|
||||
when: es_enable_xpack and "security" in es_xpack_features
|
@ -0,0 +1,37 @@
|
||||
---
|
||||
|
||||
- name: Activate ES license (without security authentication)
|
||||
uri:
|
||||
method: PUT
|
||||
url: "http://{{es_api_host}}:{{es_api_port}}/_xpack/license?acknowledge=true"
|
||||
body_format: json
|
||||
body: "{{ es_xpack_license }}"
|
||||
return_content: yes
|
||||
register: license_activated
|
||||
no_log: True
|
||||
when: not "security" in es_xpack_features
|
||||
failed_when: >
|
||||
license_activated.status != 200 or
|
||||
license_activated.json.license_status is not defined or
|
||||
license_activated.json.license_status != 'valid'
|
||||
|
||||
- name: Activate ES license (with security authentication)
|
||||
uri:
|
||||
method: PUT
|
||||
url: "http://{{es_api_host}}:{{es_api_port}}/_xpack/license?acknowledge=true"
|
||||
user: "{{es_api_basic_auth_username}}"
|
||||
password: "{{es_api_basic_auth_password}}"
|
||||
body_format: json
|
||||
force_basic_auth: yes
|
||||
body: "{{ es_xpack_license }}"
|
||||
return_content: yes
|
||||
register: license_activated
|
||||
no_log: True
|
||||
when: "'security' in es_xpack_features"
|
||||
failed_when: >
|
||||
license_activated.status != 200 or
|
||||
license_activated.json.license_status is not defined or
|
||||
license_activated.json.license_status != 'valid'
|
||||
|
||||
- debug:
|
||||
msg: "License: {{ license_activated }}"
|
Reference in New Issue
Block a user