From abb71c587bdaea6016cf7b0198645a5a950bb694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=A4b?= <alexander.kaeb@h-da.de> Date: Fri, 10 Mar 2023 14:15:38 +0100 Subject: [PATCH] feat(*): Update tasks to allow for a single host as CA cert source Modify the role tasks to allow for a single host to be used for CA cert download instead of separate hosts for the sidecar and graylog CA certs. Furthermore, use ansible tempfile module instead of predictable tempdir for cert creation. Implements #2 --- README.md | 26 +++++++++++++--- defaults/main.yml | 1 - tasks/filebeat.yml | 66 +++++++++++++++++++--------------------- tasks/main.yml | 63 ++++++++++++++++++++++++++++++++++---- tasks/node-certs.yml | 26 ++++++++-------- templates/sidecar.yml.j2 | 2 +- 6 files changed, 126 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index a6be0f6..a09500c 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,22 @@ graylog_sidecar_server_api_token: ## Node Certificates For node certificates to be generated you will need to create an additional host group -named `sidecar-ca` with a single host, that stores the CA certificate that should be -used for client certificate generation. +named `sidecar-ca` with a single host (or multiple but only the first will be used), +that stores the CA certificate that should be used for client certificate generation. -The CA file must be available at: `/etc/graylog/sidecar/sidecar-ca.pem` -The CA file's key must be available at: `/etc/graylog/sidecar/sidecar-ca.key` +In addition, the CA certificate that was used to create the certificates for the Graylog +nodes themselves must also be available to be distributed, as it is required for TLS +communication of `filebeat` for example. Therefore, make the graylog nodes available +via a host group called `graylog-nodes`. + +You may also use a completely separate host to store the CA files for Graylog and the +Sidecar service. If this is the case, you need to set the `use_central_ca_host` variable +to `true` and provide a host group called `ca-store`. The other groups mentioned earlier +may be omitted. + +The log node CA file must be available at: `/etc/graylog/graylog-ca.pem` +The sidecar CA file must be available at: `/etc/graylog/sidecar/sidecar-ca.pem` +The sidecar CA file's key must be available at: `/etc/graylog/sidecar/sidecar-ca.key` The location of the files can be configured via variable. The name of the files however must be as specified. The following variables are available in regard to the node @@ -49,9 +60,16 @@ certificates. # Whether to generate node certificates (default: true) generate_node_certs: true +# Whether to use a central host to obtain the required certificates from (default: false) +use_central_ca_host: false + # The local directory where certs are stored before being uploaded tmp_cert_dir: "/tmp/graylog-sidecar-certs" +# The path where the CA certificate of the graylog nodes should be +# fetched from the remote machine specified in the 'graylog-nodes' host group +gl_node_ca_path: "/etc/graylog/" + # The path where the CA certificate and key should be fetched from # the remote machine specified in the 'sidecar-ca' host group gl_sidecar_ca_path: "/etc/graylog/sidecar" diff --git a/defaults/main.yml b/defaults/main.yml index bc9969e..74e7a33 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -12,7 +12,6 @@ filebeat_repo_urls: # --- OTHER --- generate_node_certs: true -tmp_cert_dir: "/tmp/graylog-sidecar-certs" # local directory gl_sidecar_ca_path: "/etc/graylog/sidecar" sidecar_cert_dir: "/etc/graylog/sidecar" cert_valid_days: 1095 diff --git a/tasks/filebeat.yml b/tasks/filebeat.yml index 174651e..e94f359 100644 --- a/tasks/filebeat.yml +++ b/tasks/filebeat.yml @@ -1,39 +1,37 @@ -- name: Run filebeat tasks - when: (groups['sidecar-ca'] is defined | ternary(inventory_hostname not in groups['sidecar-ca'], true)) +--- +- name: Add filebeat repository (Debian | Ubuntu) + become: true + when: ansible_os_family == 'Debian' block: - - name: Add filebeat repository (Debian | Ubuntu) - become: true - when: ansible_os_family == 'Debian' - block: - - name: Ensure Apt Can Use Https - ansible.builtin.apt: - name: apt-transport-https - state: present - - - name: Ensure ES Signing Key Is Present - ansible.builtin.apt_key: - url: 'https://artifacts.elastic.co/GPG-KEY-elasticsearch' - id: '46095ACC8548582C1A2699A9D27D666CD88E42B4' - state: present^ + - name: Ensure Apt Can Use Https + ansible.builtin.apt: + name: apt-transport-https + state: present - - name: Ensure ES Repo Is Enabled - ansible.builtin.apt_repository: - repo: "deb {{ filebeat_repo_urls['Debian'] }} stable main" - state: present + - name: Ensure ES Signing Key Is Present + ansible.builtin.apt_key: + url: 'https://artifacts.elastic.co/GPG-KEY-elasticsearch' + id: '46095ACC8548582C1A2699A9D27D666CD88E42B4' + state: present^ - - name: Add filebeat repository (RedHat) - ansible.builtin.yum_repository: - name: elastic-8.x - description: Elastic Yum Repo 8.x - baseurl: "{{ filebeat_repo_urls['RedHat'] }}" - gpgcheck: true - gpgkey: 'https://artifacts.elastic.co/GPG-KEY-elasticsearch' + - name: Ensure ES Repo Is Enabled + ansible.builtin.apt_repository: + repo: "deb {{ filebeat_repo_urls['Debian'] }} stable main" state: present - when: ansible_os_family == 'RedHat' - become: true - - name: Install filebeat package - ansible.builtin.package: - name: filebeat - state: present - become: true +- name: Add filebeat repository (RedHat) + ansible.builtin.yum_repository: + name: elastic-8.x + description: Elastic Yum Repo 8.x + baseurl: "{{ filebeat_repo_urls['RedHat'] }}" + gpgcheck: true + gpgkey: 'https://artifacts.elastic.co/GPG-KEY-elasticsearch' + state: present + when: ansible_os_family == 'RedHat' + become: true + +- name: Install filebeat package + ansible.builtin.package: + name: filebeat + state: present + become: true diff --git a/tasks/main.yml b/tasks/main.yml index 25aa826..a372e10 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -5,13 +5,64 @@ changed_when: false become: true -- name: Include sidecar tasks - ansible.builtin.include_tasks: sidecar.yml - when: (groups['sidecar-ca'] is defined | ternary(inventory_hostname not in groups['sidecar-ca'], true)) +- name: Verify that host groups are available if not using a single host + when: not use_central_ca_host + block: + - name: Fail if 'sidecar-ca' host group is missing # noqa: run_once[task] + ansible.builtin.fail: + msg: "Please add a host group 'sidecar-ca' with the host(s) storing the CA file first" + run_once: true + when: "not (groups['sidecar-ca'] is defined)" -- name: Include filebeat tasks - ansible.builtin.import_tasks: filebeat.yml - when: install_filebeat and (groups['sidecar-ca'] is defined | ternary(inventory_hostname not in groups['sidecar-ca'], true)) + - name: Fail if 'graylog-nodes' host group is missing # noqa: run_once[task] + ansible.builtin.fail: + msg: "Please add a host group 'graylog-nodes' with the host(s) storing the log node CA file first" + run_once: true + when: "not (groups['graylog-nodes'] is defined)" + +- name: Fail if 'ca-store' host group is missing while using opetion 'use_central_ca_host' # noqa: run_once[task] + ansible.builtin.fail: + msg: "Please add a host group 'sidecar-ca' with the host(s) storing the CA file first" + run_once: true + when: "(not (groups['ca-store'] is defined)) and use_central_ca_host" + +- name: Include tasks when not using single ca-host + when: not use_central_ca_host + block: + - name: Include sidecar tasks (when not using a single ca store) + ansible.builtin.include_tasks: sidecar.yml + when: > + (inventory_hostname not in groups['sidecar-ca']) and + (inventory_hostname not in groups['graylog-nodes']) + + - name: Include filebeat tasks + ansible.builtin.include_tasks: filebeat.yml + when: > + install_filebeat and + (inventory_hostname not in groups['sidecar-ca']) and + (inventory_hostname not in groups['graylog-nodes']) + +- name: Include tasks when using single ca-host + when: use_central_ca_host + block: + - name: Include sidecar tasks (when using a single ca store) + ansible.builtin.include_tasks: sidecar.yml + when: > + ((groups['sidecar-ca'] is defined) and (groups['graylog-nodes'] is defined) | ternary( + (inventory_hostname not in groups['sidecar-ca']) and + (inventory_hostname not in groups['graylog-nodes']) + , true)) and + (inventory_hostname not in groups['ca-store']) + + - name: Include filebeat tasks + ansible.builtin.include_tasks: filebeat.yml + when: > + install_filebeat and + ((groups['sidecar-ca'] is defined) and (groups['graylog-nodes'] is defined) | ternary( + (inventory_hostname not in groups['sidecar-ca']) and + (inventory_hostname not in groups['graylog-nodes']) + , true)) and + (inventory_hostname not in groups['ca-store']) - name: Switch back to default policy ansible.builtin.command: diff --git a/tasks/node-certs.yml b/tasks/node-certs.yml index 2f19039..21840ad 100644 --- a/tasks/node-certs.yml +++ b/tasks/node-certs.yml @@ -1,17 +1,11 @@ --- -- name: Fail if 'sidecar-ca' host group is missing # noqa: run_once[task] - ansible.builtin.fail: - msg: "Please add a host group 'sidecar-ca' with the host(s) storing the CA file first" - run_once: true - when: "not (groups['sidecar-ca'] is defined)" - - name: Node Certificates | Create temporary directopry for certificates # noqa: run_once[task] - ansible.builtin.file: - path: "{{ tmp_cert_dir }}" + ansible.builtin.tempfile: state: directory - mode: 0755 + prefix: "graylog." run_once: true delegate_to: localhost + register: tmp_cert_dir - name: Node Certificates | Fetch Sidecar CA Cert ansible.builtin.fetch: @@ -21,13 +15,21 @@ with_items: - "{{ gl_sidecar_ca_path }}/sidecar-ca.pem" - "{{ gl_sidecar_ca_path }}/sidecar-ca.key" - delegate_to: "{{ groups['sidecar-ca'] | first }}" + delegate_to: "{{ groups[use_central_ca_host | bool | ternary('ca-store', 'sidecar-ca')] | first }}" + become: true + run_once: true + +- name: Node Certificates | Fetch Graylog Node CA Cert + ansible.builtin.fetch: + src: "{{ gl_node_ca_path }}/graylog-ca.pem" + dest: "{{ tmp_cert_dir }}/" + flat: true + delegate_to: "{{ groups[use_central_ca_host | bool | ternary('ca-store', 'graylog-nodes')] | first }}" become: true run_once: true - name: Node Certificates delegate_to: localhost - when: (groups['sidecar-ca'] is defined | ternary(inventory_hostname not in groups['sidecar-ca'], true)) block: - name: Node Certificates | Generate private keys community.crypto.openssl_privatekey: @@ -55,7 +57,6 @@ - name: Node Certificates | Copy Certificates become: true - when: (groups['sidecar-ca'] is defined | ternary(inventory_hostname not in groups['sidecar-ca'], true)) block: - name: Node Certificates | Copy Node certificates ansible.builtin.copy: @@ -66,3 +67,4 @@ - { file: "sidecar-{{ inventory_hostname }}.key", mode: "0600" } - { file: "sidecar-{{ inventory_hostname }}.pem", mode: "0644" } - { file: "sidecar-ca.pem", mode: "0644" } + - { file: "graylog-ca.pem", mode: "0644" } diff --git a/templates/sidecar.yml.j2 b/templates/sidecar.yml.j2 index 82b2c31..f55db49 100644 --- a/templates/sidecar.yml.j2 +++ b/templates/sidecar.yml.j2 @@ -2,4 +2,4 @@ server_url: {{ graylog_sidecar_server_url }} server_api_token: {{ graylog_sidecar_server_api_token }} -node_id: {{ graylog_sidecar_node_id }} \ No newline at end of file +node_id: {{ graylog_sidecar_node_id }} -- GitLab