Le certificat SSL du Satellite et/ou Capsule est expiré, voici comment le regénérer avec IDM.
Dans mon cas l’IDM sert de PKI et de DNS.

Satellite

Générer le csr

$ ansible-playbook playbook/generate_csr.yaml -e "host=satellite.gnali.lab"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
---
# Generate certificate signin requests
- name: "Generate Satellite SSL certificates"
  hosts: "{{ host }}"

  tasks:

    - name: "Localhost: Create temporary directory"
      ansible.builtin.file:
        path: "{{ ssldir }}/{{ ansible_fqdn }}"
        state: "directory"
        recurse: yes
      delegate_to: localhost
      run_once: yes

    - name: "Localhost: Generate private key"
      community.crypto.openssl_privatekey:
        size: 4096
        type: "RSA"
        path: "{{ ssldir }}/{{ ansible_fqdn }}/{{ ansible_fqdn }}_key.pem"
      delegate_to: localhost
      run_once: yes

    - name: "Localhost: Generate Certificate Signin request"
      community.crypto.openssl_csr:
        path: "{{ ssldir }}/{{ ansible_fqdn }}/{{ ansible_fqdn }}_csr.pem"
        privatekey_path: "{{ ssldir }}/{{ ansible_fqdn }}/{{ ansible_fqdn }}_key.pem"
        country_name: "{{ main_dn_fields.C }}"
        state_or_province_name: "{{ main_dn_fields.ST }}"
        locality_name: "{{ main_dn_fields.L }}"
        organization_name: "{{ main_dn_fields.O }}"
        organizational_unit_name: "{{ main_dn_fields.OU }}"
        common_name: "{{ main_dn_fields.CN }}"
        key_usage:
          - digitalSignature
          - nonRepudiation
          - keyEncipherment
          - dataEncipherment
        extended_key_usage:
          - serverAuth
          - clientAuth
          - codeSigning
          - emailProtection
        subject_alt_name:
          - "DNS:{{ main_dn_fields.CN }}"
          - "DNS:{{ ansible_fqdn }}"
          - "IP:{{ ansible_all_ipv4_addresses[0] }}"
          - "IP:{{ ansible_all_ipv4_addresses[1] }}"
        basicConstraints:
          - CA:FALSE
      delegate_to: localhost
      run_once: yes

⚠️ S’assurer que les nom DNS et les ips utilisés dans le CSR sont bien connus du clusteur IDM.

Faire signer le CSR par l’IDM

$ ipa cert-request --principal=HTTP/satellite.gnali.lab --add files/satellite.gnali.lab/satellite.gnali.lab_csr.pem --certificate-out files/satellite.gnali.lab/satellite.gnali.lab.pem

Vérifier que le nouveau certificat a bien été généré avec les nouvelles dates

$ openssl x509 -noout -dates -in files/satellite.gnali.lab/satellite.gnali.lab.pem
notBefore=Mar  2 14:56:05 2026 GMT
notAfter=Mar  2 14:56:05 2028 GMT

Mettre à jour le certificat sur le Satellite

$ ansible-playbook playbook/update_satellite_ssl_certs.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
- name: Update Satellite with Corporate signed certificate
  hosts: satellite
  become: true

  tasks:
  - name: Create certificate directory
    ansible.builtin.file:
      path: "/root/satellite_cert/"
      state: directory

  - name: Copy Satellite Certificate
    ansible.builtin.copy:
     src: "{{ ssldir }}/{{ ansible_fqdn }}/{{ item }}"
     dest: "/root/satellite_cert/{{ item }}"
    with_items:
      - "{{ ansible_fqdn }}_key.pem"
      - "{{ main_dn_fields.CN }}.pem"

  - name: Create CA chain bundle
    ansible.builtin.assemble:
      remote_src: no
      src: "{{ ssldir }}/root_ca"
      dest: /root/satellite_cert/ca_cert_bundle.pem

  - name: "Update Certificates"
    include_role:
      name: redhat.satellite_operations.installer
    vars:
      satellite_installer_scenario: satellite
      satellite_installer_options:
        - '--certs-server-cert "/root/satellite_cert/{{ main_dn_fields.CN }}.pem"'
        - '--certs-server-key  "/root/satellite_cert/{{ ansible_fqdn }}_key.pem"'
        - '--certs-server-ca-cert  "/root/satellite_cert/ca_cert_bundle.pem"'
        - '--certs-update-server --certs-update-server-ca'

Renouveller le certificat des capsules.

Il est aussi fort probable qu’au même moment ou un peu plus tard nous ayons besoin de renouveller le certificat des capsules.

Générer le csr

$ ansible-playbook playbook/generate_csr.yaml -e "host=capsule.gnali.lab"

⚠️ S’assurer que les nom DNS et les ips utilisés dans le CSR sont bien connus du clusteur IDM.

Créer les services et hosts s’ils ne sont pas présent dans l’IDM

$ ipa service-add HTTP/capsule.gnali.lab
$ ipa host-add lb.gnali.lab --force
$ ipa service-add HTTP/lb.gnali.lab --force
$ ipa service-add-host HTTP/lb.gnali.lab --host capsule.gnali.lab #1

#1 Ajouter autant de --host que de capsule servit par le load-balancer

Faire signer le CSR par l’IDM

$ ipa cert-request --principal=HTTP/lb.gnali.lab --add files/capsule.gnali.lab/capsule.gnali.lab_csr.pem --certificate-out files/capsule.gnali.lab/capsule.gnali.lab.pem

Vérifier que le nouveau certificat a bien été généré avec les nouvelles dates

$ openssl x509 -noout -dates -in files/capsule.gnali.lab/capsule.gnali.lab.pem
notBefore=Mar  3 08:15:37 2026 GMT
notAfter=Mar  3 08:15:37 2028 GMT

Mettre à jour le certificat sur la capsule

$ ansible-playbook playbook/update_capsule_ssl_certs.yaml -e "host=capsule.gnali.lab"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
---
- name: Update Capsule with Corporate signed certificate
  hosts: "{{ host }}"
  become: true

  pre_tasks:
  - name: Create certificate directory
    ansible.builtin.file:
      path: "/root/{{ host }}_cert/"
      state: directory
    delegate_to: satellite

  - name: Copy Capsule Certificate
    ansible.builtin.copy:
     src: "{{ ssldir }}/{{ ansible_fqdn }}/{{ item }}"
     dest: "/root/{{ host }}_cert/{{ item }}"
    with_items:
      - "{{ ansible_fqdn }}_key.pem"
      - "{{ ansible_fqdn }}.pem"
    delegate_to: satellite

  - name: Create CA chain bundle
    ansible.builtin.assemble:
      remote_src: no
      src: "{{ ssldir }}/root_ca"
      dest: /root/{{ host }}_cert/ca_cert_bundle.pem
    delegate_to: satellite

  roles:
    - role: redhat.satellite_operations.capsule_certs_generate
      vars:
      satellite_capsule_certs_generate_fqdn: "{{ host }}"
      satellite_capsule_certs_generate_options:
        - '--foreman-proxy-cname {{ main_dn_fields.CN }}'
        - '--server-ca-cert /root/{{ host }}_cert/ca_cert_bundle.pem'
        - '--server-cert /root/{{ host }}_cert/{{ ansible_fqdn }}.pem'
        - '--server-key /root/{{ host }}_cert/{{ ansible_fqdn }}_key.pem'
      delegate_to: satellite

  post_tasks:
  - name: Get Satellite answers file
    ansible.builtin.slurp:
      src: /etc/foreman-installer/scenarios.d/satellite-answers.yaml
    register: answers_output
    delegate_to: satellite

  - name: Parse Satellite answers file
    ansible.builtin.set_fact:
      satellite_answers: "{{ answers_output['content'] | b64decode | from_yaml }}"

  - name: Fetch Capsule Certs tarball from Satellite
    ansible.builtin.fetch:
      src: "/root/{{ host }}.tar.gz"
      dest: "{{ ssldir }}/{{ ansible_fqdn }}/{{ host }}.tar.gz"
      flat: yes
    run_once: yes
    delegate_to: satellite

  - name: Copy Capsule Certs tarball to Capsule
    ansible.builtin.copy:
      src: "{{ ssldir }}/{{ ansible_fqdn }}/{{ host }}.tar.gz"
      dest: "/root/{{ host }}.tar.gz"

  - name: "Update Certificates"
    include_role:
      name: redhat.satellite_operations.installer
    vars:
      satellite_installer_scenario: capsule
      satellite_installer_options:
        -  '--certs-cname {{ main_dn_fields.CN }}'
        -  '--certs-tar-file /root/{{ host }}.tar.gz'
        -  '--enable-foreman-proxy-plugin-remote-execution-script'
        -  '--foreman-proxy-foreman-base-url https://{{ hostvars[groups["satellite"][0]].main_dn_fields.CN }}'
        -  '--foreman-proxy-oauth-consumer-key {{ satellite_answers.foreman.oauth_consumer_key }}'
        -  '--foreman-proxy-oauth-consumer-secret {{ satellite_answers.foreman.oauth_consumer_secret }}'
        -  '--foreman-proxy-trusted-hosts {{ hostvars[groups["satellite"][0]].main_dn_fields.CN }}'
        -  '--foreman-proxy-trusted-hosts {{ host }}'

Inventory

A toute fin utile l’inventory ansible ressemble à ca:

inventory/host_vars/satellite.gnali.lab.yaml
inventory/host_vars/capsule.gnali.lab.yaml
inventory/hosts.yaml

inventory/hosts.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---
all:
  children:
    satellite:
      hosts:
        satellite.gnali.lab:
          ansible_host: xxx.xxx.xxx.xxx
    capsule:
      hosts:
        capsule.gnali.lab:
          ansible_host: xxx.xxx.xxx.xxx

inventory/host_vars/satellite.gnali.lab.yaml

1
2
3
4
5
6
7
8
9
main_dn_fields:
  CN: "satellite.gnali.lab"
  OU: "Customer Success"
  O:  "Red Hat"
  ST: "IDF"
  L:  "Puteaux"
  C:  "FR"

ssldir: "{{ playbook_dir }}/../files"

inventory/host_vars/capsule.gnali.lab.yaml

1
2
3
4
5
6
7
8
9
main_dn_fields:
  CN: "lb.gnali.lab"
  OU: "Customer Success"
  O:  "Red Hat"
  ST: "IDF"
  L:  "Cloud"
  C:  "FR"

ssldir: "{{ playbook_dir }}/../files"