Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Elasticstack Ansible Collection

## Fix Workflow

When fixing a bug:

1. Before implementing, identify which molecule scenario covers this code path.
2. If no existing scenario catches the bug, add a verify assertion to the closest
existing scenario — or extend its converge — rather than creating a new scenario.
A new scenario is a last resort (each one adds ~10 min to CI).
3. Prefer the lightest test that proves the fix: a config assertion in verify.yml
beats a full multi-node deployment. Only add nodes/complexity when the bug
genuinely requires it (e.g. inter-node communication).
4. The test should fail without the fix and pass with it. Confirm this mentally
or by describing the failure mode before implementing.
55 changes: 46 additions & 9 deletions molecule/elasticsearch_custom_certs/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,53 @@
- ca_cert_stat.stat.exists
fail_msg: "CA certificate file not found"

- name: Check elasticsearch.yml has PEM config
ansible.builtin.command:
cmd: grep 'xpack.security.transport.ssl.certificate' /etc/elasticsearch/elasticsearch.yml
register: es_yml_check
changed_when: false
- name: Read elasticsearch.yml
ansible.builtin.slurp:
src: /etc/elasticsearch/elasticsearch.yml
register: es_yml_raw

- name: Parse elasticsearch.yml content
ansible.builtin.set_fact:
_es_config: "{{ es_yml_raw.content | b64decode }}"

- name: Verify PEM-style config (not keystore)
- name: Verify PEM-style transport config
ansible.builtin.assert:
that:
- "'transport.crt' in es_yml_check.stdout"
- "'xpack.security.transport.ssl.certificate' in _es_config"
- "'xpack.security.transport.ssl.key' in _es_config"
fail_msg: "Expected PEM-style transport SSL config in elasticsearch.yml"

- name: Verify CA referenced in both transport and HTTP sections
ansible.builtin.assert:
that:
- "'transport.ssl.certificate_authorities' in _es_config"
- "'http.ssl.certificate_authorities' in _es_config"
fail_msg: >-
Expected PEM-style transport config in elasticsearch.yml.
Got: {{ es_yml_check.stdout }}
certificate_authorities missing from elasticsearch.yml — CA was
configured but the template omitted it (first-install rendering bug).

- name: Verify verification_mode is not 'none'
ansible.builtin.assert:
that:
- "'verification_mode: none' not in _es_config"
fail_msg: "SSL verification_mode is 'none' — certs provide no security"

- name: Verify cert paths in config match files on disk
ansible.builtin.stat:
path: "/etc/elasticsearch/{{ item }}"
register: _cert_path_check
loop:
- "certs/{{ inventory_hostname }}-transport.crt"
- "certs/{{ inventory_hostname }}-transport.key"
- "certs/{{ inventory_hostname }}-http.crt"
- "certs/{{ inventory_hostname }}-http.key"
- certs/ca.crt

- name: Assert all referenced cert files exist
ansible.builtin.assert:
that:
- item.stat.exists
fail_msg: "{{ item.item }} referenced in config but not on disk"
loop: "{{ _cert_path_check.results }}"
loop_control:
label: "{{ item.item }}"
13 changes: 0 additions & 13 deletions roles/elasticsearch/tasks/elasticsearch-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@
group: elasticsearch
mode: "0640"
when: _elasticsearch_transport_content_mode | bool
notify: Restart Elasticsearch

- name: Copy transport certificate (from file)
ansible.builtin.copy:
Expand All @@ -161,7 +160,6 @@
mode: "0640"
remote_src: "{{ elasticsearch_tls_remote_src }}"
when: not (_elasticsearch_transport_content_mode | bool)
notify: Restart Elasticsearch

- name: Write transport key (from content)
ansible.builtin.copy:
Expand All @@ -171,7 +169,6 @@
group: elasticsearch
mode: "0640"
when: _elasticsearch_transport_content_mode | bool
notify: Restart Elasticsearch

- name: Copy transport key (from file, PEM only)
ansible.builtin.copy:
Expand All @@ -184,7 +181,6 @@
when:
- not (_elasticsearch_transport_content_mode | bool)
- _elasticsearch_transport_cert_format == 'pem'
notify: Restart Elasticsearch

# -- HTTP cert/key (falls back to transport if not set separately) --

Expand All @@ -198,7 +194,6 @@
when:
- _elasticsearch_http_content_mode | bool
- elasticsearch_http_security | bool
notify: Restart Elasticsearch

- name: Copy HTTP certificate (from file)
ansible.builtin.copy:
Expand All @@ -211,7 +206,6 @@
when:
- not (_elasticsearch_http_content_mode | bool)
- elasticsearch_http_security | bool
notify: Restart Elasticsearch

- name: Write HTTP key (from content)
ansible.builtin.copy:
Expand All @@ -223,7 +217,6 @@
when:
- _elasticsearch_http_content_mode | bool
- elasticsearch_http_security | bool
notify: Restart Elasticsearch

- name: Copy HTTP key (from file, PEM only)
ansible.builtin.copy:
Expand All @@ -237,7 +230,6 @@
- not (_elasticsearch_http_content_mode | bool)
- elasticsearch_http_security | bool
- _elasticsearch_http_cert_format == 'pem'
notify: Restart Elasticsearch

# -- CA certificate --

Expand All @@ -249,7 +241,6 @@
group: elasticsearch
mode: "0640"
when: elasticsearch_tls_ca_certificate_content | default('', true) | length > 0
notify: Restart Elasticsearch

- name: Copy CA certificate (from file)
ansible.builtin.copy:
Expand All @@ -262,11 +253,10 @@
when:
- elasticsearch_tls_ca_certificate_content | default('', true) | length == 0
- elasticsearch_tls_ca_certificate | length > 0
notify: Restart Elasticsearch

# Extract CA chain from the already-deployed transport cert on the node.
# Uses copy+content for idempotency (only writes when content changes).
- name: Read CA chain from PEM bundle (transport cert)

Check warning on line 259 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _extracted_ca_chain)

Check warning on line 259 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _extracted_ca_chain)

Check warning on line 259 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _extracted_ca_chain)

Check warning on line 259 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _extracted_ca_chain)
ansible.builtin.shell:
cmd: >-
awk '/-----BEGIN CERTIFICATE-----/{n++} n>1'
Expand All @@ -289,7 +279,6 @@
- elasticsearch_tls_ca_certificate | length == 0
- elasticsearch_tls_ca_certificate_content | default('', true) | length == 0
- _elasticsearch_transport_ca_extracted | bool
notify: Restart Elasticsearch

- name: Set effective CA availability fact
ansible.builtin.set_fact:
Expand All @@ -300,7 +289,7 @@

# -- Remove stale auto-generated P12 files from a previous elasticsearch_ca deployment --

- name: Find stale auto-generated P12 certificate files

Check warning on line 292 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _stale_p12_files)

Check warning on line 292 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _stale_p12_files)

Check warning on line 292 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _stale_p12_files)

Check warning on line 292 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _stale_p12_files)
ansible.builtin.find:
paths: /etc/elasticsearch/certs
patterns: "*.p12"
Expand Down Expand Up @@ -366,7 +355,7 @@
# The CA backup removes the entire elasticstack_ca_dir, which also
# contains Kibana encryption key files. If those are regenerated,
# Kibana can't decrypt its existing saved objects and enters 503.
- name: Check for Kibana encryption keys before CA backup

Check warning on line 358 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _kibana_enckeys_before_backup)

Check warning on line 358 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _kibana_enckeys_before_backup)

Check warning on line 358 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _kibana_enckeys_before_backup)

Check warning on line 358 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _kibana_enckeys_before_backup)
ansible.builtin.stat:
path: "{{ elasticstack_ca_dir }}/{{ item }}"
loop:
Expand Down Expand Up @@ -583,7 +572,6 @@
_cert_group: elasticsearch
_cert_mode: "0640"
_cert_notify:
- Restart Elasticsearch
- Restart kibana if available for elasticsearch certificates
tags:
- certificates
Expand All @@ -606,7 +594,6 @@
_cert_group: elasticsearch
_cert_mode: "0640"
_cert_notify:
- Restart Elasticsearch
- Restart kibana if available for elasticsearch certificates
tags:
- certificates
Expand Down Expand Up @@ -689,7 +676,7 @@
- elasticsearch_api_status_bootstrap is failed
- inventory_hostname == elasticstack_ca_host
block:
- name: Reset elastic user password via elasticsearch-reset-password

Check warning on line 679 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _elastic_reset_pw)

Check warning on line 679 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _elastic_reset_pw)

Check warning on line 679 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _elastic_reset_pw)
ansible.builtin.command: >
/usr/share/elasticsearch/bin/elasticsearch-reset-password
-u elastic -b -s
Expand All @@ -697,7 +684,7 @@
changed_when: true
no_log: "{{ elasticstack_no_log }}"

- name: Verify API access with recovered password

Check warning on line 687 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _elastic_recovery_check)

Check warning on line 687 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _elastic_recovery_check)

Check warning on line 687 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _elastic_recovery_check)
ansible.builtin.uri:
url: "{{ elasticsearch_http_protocol }}://{{ elasticsearch_api_host }}:{{ elasticstack_elasticsearch_http_port }}"
user: elastic
Expand Down Expand Up @@ -848,7 +835,7 @@

# ES 8.x: elasticsearch-setup-passwords creates all built-in user passwords
# ES 9.x: setup-passwords is removed; use elasticsearch-reset-password per user
- name: Create initial passwords (ES 8.x)

Check warning on line 838 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _setup_passwords_result)

Check warning on line 838 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _setup_passwords_result)

Check warning on line 838 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _setup_passwords_result)
ansible.builtin.shell: >
set -o pipefail;
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto -b >
Expand All @@ -871,12 +858,12 @@
- inventory_hostname == elasticstack_ca_host
- elasticstack_release | int >= 9
block:
- name: Check if passwords file already exists

Check warning on line 861 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _pw_file_check)

Check warning on line 861 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _pw_file_check)

Check warning on line 861 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _pw_file_check)
ansible.builtin.stat:
path: "{{ elasticstack_initial_passwords }}"
register: _pw_file_check

- name: Reset built-in user passwords

Check warning on line 866 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _reset_password_results)

Check warning on line 866 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _reset_password_results)

Check warning on line 866 in roles/elasticsearch/tasks/elasticsearch-security.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

var-naming[no-role-prefix]

Variables names from within roles should use elasticsearch_ as a prefix. (register: _reset_password_results)
ansible.builtin.command: >
/usr/share/elasticsearch/bin/elasticsearch-reset-password
-u {{ item }} -b -s
Expand Down
4 changes: 3 additions & 1 deletion roles/elasticsearch/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@
_elasticsearch_external_has_ca: true
when:
- elasticsearch_cert_source == 'external'
- _existing_ca_cert.stat.exists | default(false)
- (_existing_ca_cert.stat.exists | default(false)) or
(elasticsearch_tls_ca_certificate | default('') | length > 0) or
(elasticsearch_tls_ca_certificate_content | default('') | length > 0)

- name: Warn about conflicting keys in elasticsearch_extra_config
ansible.builtin.debug:
Expand Down
Loading