diff --git a/molecule/kibana_custom/converge.yml b/molecule/kibana_custom/converge.yml index 1f8e1152..76badd9a 100644 --- a/molecule/kibana_custom/converge.yml +++ b/molecule/kibana_custom/converge.yml @@ -12,6 +12,8 @@ # Kibana custom settings kibana_config_backup: true kibana_sniff_on_start: true + kibana_security_encryptionkey: "moleculeProvidedSecurityKey0123456789abcd" + kibana_encryptedsavedobjects_encryptionkey: "moleculeProvidedSavedObjectsKey0123456789" kibana_extra_config: |- ops.interval: 10000 logging.root.level: warn diff --git a/molecule/kibana_custom/verify.yml b/molecule/kibana_custom/verify.yml index de04ef16..cd5893d2 100644 --- a/molecule/kibana_custom/verify.yml +++ b/molecule/kibana_custom/verify.yml @@ -72,6 +72,24 @@ - "'logging.root.level: warn' in (kibana_yml.content | b64decode)" fail_msg: "Extra config not found in kibana.yml" + - name: Read provided encryption keys from the keystore + ansible.builtin.command: > + /usr/share/kibana/bin/kibana-keystore show {{ item }} + environment: + KBN_PATH_CONF: /etc/kibana + loop: + - xpack.security.encryptionKey + - xpack.encryptedSavedObjects.encryptionKey + register: provided_keys + changed_when: false + + - name: Verify provided encryption keys are honoured in the keystore + ansible.builtin.assert: + that: + - "provided_keys.results[0].stdout_lines[-1] == 'moleculeProvidedSecurityKey0123456789abcd'" + - "provided_keys.results[1].stdout_lines[-1] == 'moleculeProvidedSavedObjectsKey0123456789'" + fail_msg: "Provided encryption keys not stored in the Kibana keystore" + - name: Verify sniff on start is enabled (pre-9.x only) ansible.builtin.assert: that: diff --git a/roles/kibana/defaults/main.yml b/roles/kibana/defaults/main.yml index 12ad5d86..f8d6478d 100644 --- a/roles/kibana/defaults/main.yml +++ b/roles/kibana/defaults/main.yml @@ -37,6 +37,22 @@ kibana_tls: false kibana_tls_key_passphrase: PleaseChangeMe # @var kibana_keystore_password:description: Password to encrypt the Kibana keystore file. Empty means no encryption (same as ES default) kibana_keystore_password: "" + +# @var kibana_security_encryptionkey:description: > +# Value for xpack.security.encryptionKey (stored in the Kibana keystore). +# Set this to reuse an existing key when migrating Kibana to a new host or +# running multiple instances, so encrypted session state stays valid. Empty +# generates a random key on first run. +# @end +kibana_security_encryptionkey: "" + +# @var kibana_encryptedsavedobjects_encryptionkey:description: > +# Value for xpack.encryptedSavedObjects.encryptionKey (stored in the keystore). +# Set this to reuse an existing key when migrating or scaling out, otherwise +# encrypted saved objects (alerting rules, connectors, Fleet tokens) cannot be +# decrypted by the new instance. Empty generates a random key on first run. +# @end +kibana_encryptedsavedobjects_encryptionkey: "" # @var kibana_cert_expiration_buffer:description: Days before certificate expiry to trigger renewal kibana_cert_expiration_buffer: 30 # @var kibana_cert_validity_period:description: Validity period in days for generated TLS certificates diff --git a/roles/kibana/tasks/kibana-security.yml b/roles/kibana/tasks/kibana-security.yml index 1cb18f31..f2a327ee 100644 --- a/roles/kibana/tasks/kibana-security.yml +++ b/roles/kibana/tasks/kibana-security.yml @@ -292,6 +292,16 @@ loop_control: label: "{{ item.item }}" + - name: kibana-security | Use provided encryption key + ansible.builtin.copy: + dest: "{{ elasticstack_ca_dir }}/encryption_key" + content: "{{ kibana_security_encryptionkey }}" + owner: root + group: elasticsearch + mode: "0600" + when: kibana_security_encryptionkey | default('') | length > 0 + no_log: true + - name: kibana-security | Generate encryption key ansible.builtin.shell: > set -o pipefail; @@ -309,6 +319,16 @@ register: kibana_encryption_key check_mode: false + - name: kibana-security | Use provided saved objects encryption key + ansible.builtin.copy: + dest: "{{ elasticstack_ca_dir }}/savedobjects_encryption_key" + content: "{{ kibana_encryptedsavedobjects_encryptionkey }}" + owner: root + group: elasticsearch + mode: "0600" + when: kibana_encryptedsavedobjects_encryptionkey | default('') | length > 0 + no_log: true + - name: kibana-security | Generate saved objects encryption key ansible.builtin.shell: > set -o pipefail;