Icinga / ansible-collection-icinga

Collection to setup and manage components of the Icinga software stack
Apache License 2.0
46 stars 35 forks source link

Setting up Icinga Agents without connection to Icinga Master #280

Open lucagubler opened 7 months ago

lucagubler commented 7 months ago

Hi all

I would like to use this Icinga collection to set up our monitoring. Currently I'm using this role to configure the Icinga Master and it's working great. Now I want to configure an Icinga Agent using the Icinga2 role with the API feature but I'm having some issues with this.

Our firewalls are configured to only allow the master to connect to the Icinga2 agents on port 5665, but not the other way round. When I manually configure the agents using the icinga2 node wizard, I can simply answer Do you want to establish a connection to the parent node from this node? [Y/n]: with no, which will configure the node accordingly. This will create a CSR on the Icinga2 master. I can review all CSRs using icinga2 ca list and icinga2 ca sign <fingerprint>.

I tried to replicate icinga2 node wizard part with this Ansible collection but was unsuccessful. Is this functionality implemented in the Ansible collection?

Thanks Luca

sol1-matt commented 7 months ago

The difference between a setup with a ticket and no ticket is the --ticket parameter when using icinga2 node setup which is the cli version of icinga2 node wizard.

It is possible to setup icinga2 manually without using the icinga2 node setup, this role appears to manually setup icinga2 without using icinga2 node setup. In the case of manual setup the absence of a ticket in the config will cause the endpoint to connect to the master at start and get put in the icinga2 ca list waiting for signing of removal.

For this ansible role I can't see how it would allow for a ticketless setup, it either degalates ticket generation from the headend or it tries to get it itself.

If your ansible server can see the headend you should be able to get this working using icinga2_ca_host. If your ansible server can't see the headend then the role would need to be modified.

    - name: delegate ticket request to master
      shell: icinga2 pki ticket --cn "{{ icinga2_cert_name }}" {% if icinga2_ticket_salt is defined %} --salt "{{ icinga2_ticket_salt }}"{% endif %}
      delegate_to: "{{ icinga2_delegate_host | default(icinga2_ca_host) }}"
      register: icinga2_ticket
      when: icinga2_ca_host != 'none'

    - name: get certificate
      shell: >-
        icinga2 pki {% if icinga2_ca_host != 'none' %} request
        --ticket "{{ icinga2_ticket.stdout }}"
        --host "{{ icinga2_ca_host }}"
        --port "{{ icinga2_ca_host_port | default('5665') }}"
        --ca "{{ icinga2_cert_path }}/ca.crt"
        --key "{{ icinga2_cert_path }}/{{ icinga2_cert_name }}.key"
        --trustedcert "{{ icinga2_cert_path }}/trusted-master.crt"
        {% else %} sign-csr --csr "{{ icinga2_cert_path }}/{{ icinga2_cert_name }}.csr" {%- endif %}
        --cert "{{ icinga2_cert_path }}/{{ icinga2_cert_name }}.crt"
      notify: reload icinga2 service

From: https://github.com/Icinga/ansible-collection-icinga/blob/a89669bd38250445e676bc0684bbc6e34cf09499/roles/icinga2/tasks/features/api.yml

widhalmt commented 6 months ago

If you have the ticket salt and the CN of the host, you can create the ticket on every Icinga node. There is no other secret information on the master besides the salt.

One of the tasks that fails is trying to fetch the trusted cert from the central node. It shouldn't be hard to change that but as of now the installation will break there.

mkayontour commented 6 months ago

Hey, I did solve this issue with manually creating certificates and deploy them via ansible on the agent. As the parent reconnects to the client (zones/endpoints configuration needs to be done first) the agent will send his CSR to the parent.

As the ansible.builtin.copy module has default to overwrite the files, consider using the module_defaults in your playbook.

---
- name: install icinga2
  hosts: ubuntu2204
  collections:
    - icinga.icinga
  module_defaults:
    ansible.builtin.copy:
      force: no
  vars:
    icinga2_constants:
      NodeName: "{{ ansible_fqdn }}"
    icinga2_features:
      - name: api
        ca_host: icinga-server
        ssl_cert: "/tmp/{{ ansible_fqdn }}.crt"
        ssl_key: "/tmp/{{ ansible_fqdn }}.key"
        ssl_cacert: "/tmp/ca.crt"
        endpoints:
          - name: NodeName
          - name: "icinga-server.localdomain"
        zones:
          - name: NodeName
            parent: main
            endpoints:
              - "{{ ansible_fqdn }}"
          - name: "main"
            endpoints: "icinga-server.localdomain"
      - name: checker
        state: present
      - name: mainlog
        severity: information

  pre_tasks:
    - name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
      community.crypto.openssl_privatekey:
        path: "/tmp/{{ ansible_fqdn }}.key"
      delegate_to: localhost

    - name: Generate an OpenSSL Certificate Signing Request
      community.crypto.openssl_csr:
        path: "/tmp/{{ ansible_fqdn }}.csr"
        privatekey_path: "/tmp/{{ ansible_fqdn }}.key"
        common_name: "{{ ansible_fqdn }}"
      delegate_to: localhost

    - name: Generate a Self Signed OpenSSL certificate
      community.crypto.x509_certificate:
        path: "/tmp/{{ ansible_fqdn }}.crt"
        privatekey_path: "/tmp/{{ ansible_fqdn }}.key"
        csr_path: "/tmp/{{ ansible_fqdn }}.csr"
        provider: selfsigned
      delegate_to: localhost

    - name: copy csr.
      ansible.builtin.copy:
        src: "/tmp/{{ ansible_fqdn }}.csr"
        dest: "/var/lib/icinga2/certs/{{ ansible_fqdn }}.csr"
  roles:
    - repos
    - icinga2