telekom-mms/ansible-collection-icinga

Icinga master does not recognize ticket created on agent

Closed this issue · 3 comments

In the icinga_agent role during agent registration, there are a critical series of steps that create the agent certificate and send a pki request to the master:

    - name: generate ticket and save it as a variable
      ansible.builtin.shell: /usr/sbin/icinga2 pki ticket --cn {{ ansible_hostname }} --salt {{ icinga_agent_salt }}
      environment:
        LD_LIBRARY_PATH: "/usr/lib64"
      register: ticket

    - name: create certificate
      ansible.builtin.command: "/usr/sbin/icinga2 pki new-cert --cn {{ ansible_hostname }} --key /var/lib/icinga2/certs/{{ ansible_hostname }}.key --cert /var/lib/icinga2/certs/{{ ansible_hostname }}.crt"
      args:
        creates: "/var/lib/icinga2/certs/{{ ansible_hostname }}.crt"

    - name: save the icinga master's certificate to the host
      ansible.builtin.command: "/usr/sbin/icinga2 pki save-cert --key /var/lib/icinga2/certs/{{ ansible_hostname }}.key --cert /var/lib/icinga2/certs/{{ ansible_hostname }}.crt --trustedcert /var/lib/icinga2/certs/trusted-master.crt --host {{ icinga_agent_ca_host }}"
      args:
        creates: "/var/lib/icinga2/certs/trusted-master.crt"

    - name: generate ticket and save it as a variable
      ansible.builtin.command: "/usr/sbin/icinga2 pki ticket --cn {{ ansible_hostname }} --salt {{ icinga_agent_salt }}"
      register: ticket
      args:
        creates: "/var/lib/icinga2/certs/ca.crt"

    - name: send a pki request to the icinga master
      ansible.builtin.command: "/usr/sbin/icinga2 pki request --host {{ icinga_agent_ca_host }} --port {{ icinga_agent_ca_host_icinga_port }} --ticket {{ ticket.stdout }} --key /var/lib/icinga2/certs/{{ ansible_hostname }}.key --cert /var/lib/icinga2/certs/{{ ansible_hostname }}.crt --trustedcert /var/lib/icinga2/certs/trusted-master.crt --ca /var/lib/icinga2/certs/ca.crt"
      args:
        creates: "/var/lib/icinga2/certs/ca.crt"
      notify:
        - restart icinga2-agent

In my testing, it appears that the "generate ticket and save it as a variable" step (which is repeated twice for unknown reasons) generates a ticket that only the agent knows about. Thus, in the final step, when the agent sends a pki request to the icinga master, the request is rejected due to an unknown ticket:

critical/cli: !!! Invalid ticket for CN 'icinga-agent'.

When I removed the ticket generation from the above steps, the pki request registered properly with the Icinga master and I was able to subsequently approve it.

My question is, what is the intended purpose of the ticket generation? Are these tasks assumed to be ran on the master instead of the agent?

Thanks for maintaining such a useful library! Cheers!

Hi,

on the master, you can configure a constant named TicketSalt, which is a secret shared between master and agents.

When you generate an agent certificate, the agent can also generate the so called ticket, which is an hash of the hostname of the agent and the TicketSalt.
The agent then sends the certificate and the ticket to the master. The master also generates the ticket with the hostname from the agent certificate and the TicketSalt. When the ticket send from the agent matches with the ticket generated on the master, the master automatically signs the certificate and sends it back to the agent.

Using this way, you dont have to approve the pki request manually on the master.

Thank you for the explanation! I understand how this works now. I would like to point out, however, that if this playbook was run locally on each agent, there would be some security concerns with this approach as the TicketSalt would need to be distributed, which is essentially a global password to the Icinga Master.

The Icinga documentation mentions the following regarding handling of TicketSalt:

Never expose the ticket salt and/or ApiUser credentials to your client nodes. Example: Retrieve the ticket on the Puppet master node and send the compiled catalog to the authorized Puppet agent node which will invoke the automated setup steps.

Unfortunately, my use-case prohibits running this playbook remotely, so I will have to follow the standard ticket-based approach to avoid distribution of my global TicketSalt. It may be helpful to add a clarification in the docs that the TicketSalt must be the same global password set on the Icinga Master.

tl;dr for future readers: The above error is caused by the TicketSalt being different on the agent and master. The practice of pre-sharing the secret TicketSalt on the Icinga Master raises some security concerns, but in the case of this library, it is intended behavior.