From 7b60c0e150992735c4d6ceed7aaadfa61e06eb66 Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Wed, 19 Mar 2025 10:49:32 +0200 Subject: [PATCH] add gpg_key_rotation ansible playbook ensures reprepro files are signed with the current GPG key, without having to build new packages. --- .../gpg_key_rotation/distributions.conf.j2 | 55 +++++++++++++++++++ data/ansible/gpg_key_rotation/gen-key-script | 13 +++++ .../ansible/gpg_key_rotation/gpg-gen-key.yaml | 51 +++++++++++++++++ data/ansible/gpg_key_rotation/gpg.conf.j2 | 5 ++ data/ansible/gpg_key_rotation/gpg.yaml | 47 ++++++++++++++++ data/ansible/gpg_key_rotation/hosts | 2 + data/ansible/gpg_key_rotation/main.yaml | 42 ++++++++++++++ data/ansible/gpg_key_rotation/options.conf.j2 | 3 + data/ansible/gpg_key_rotation/reprepro.yaml | 43 +++++++++++++++ 9 files changed, 261 insertions(+) create mode 100644 data/ansible/gpg_key_rotation/distributions.conf.j2 create mode 100644 data/ansible/gpg_key_rotation/gen-key-script create mode 100644 data/ansible/gpg_key_rotation/gpg-gen-key.yaml create mode 100644 data/ansible/gpg_key_rotation/gpg.conf.j2 create mode 100644 data/ansible/gpg_key_rotation/gpg.yaml create mode 100644 data/ansible/gpg_key_rotation/hosts create mode 100644 data/ansible/gpg_key_rotation/main.yaml create mode 100644 data/ansible/gpg_key_rotation/options.conf.j2 create mode 100644 data/ansible/gpg_key_rotation/reprepro.yaml diff --git a/data/ansible/gpg_key_rotation/distributions.conf.j2 b/data/ansible/gpg_key_rotation/distributions.conf.j2 new file mode 100644 index 000000000..adf149cc3 --- /dev/null +++ b/data/ansible/gpg_key_rotation/distributions.conf.j2 @@ -0,0 +1,55 @@ +{{ ansible_managed | comment }} +Origin: apt.cgrates.org +Label: apt.cgrates.org +Suite: stable +Codename: v0.10 +Architectures: amd64 +Components: main +Description: CGRateS v0.10 APT repository +SignWith: yes +DebOverride: override.testing +DscOverride: override.testing + +Origin: apt.cgrates.org +Label: apt.cgrates.org +Suite: master +Codename: master +Architectures: amd64 +Components: main +Description: CGRateS master APT repository +SignWith: yes +DebOverride: override.testing +DscOverride: override.testing + +{% for distribution in distributions %} +Origin: apt.cgrates.org +Label: apt.cgrates.org +Suite: stable-{{ distribution['codename'] }} +Codename: v0.10-{{ distribution['codename'] }} +Architectures: amd64 source +Components: main +Description: CGRateS v0.10 APT repository for {{ distribution['codename'] }} +DebIndices: Packages Release . .gz +Contents: . .gz +ContentsArchitectures: amd64 source +ContentsComponents: main +SignWith: yes +DebOverride: override.testing +DscOverride: override.testing + +Origin: apt.cgrates.org +Label: apt.cgrates.org +Suite: master-{{ distribution['codename'] }} +Codename: master-{{ distribution['codename'] }} +Architectures: amd64 source +Components: main +Description: CGRateS master APT repository for {{ distribution['codename'] }} +DebIndices: Packages Release . .gz +Contents: . .gz +ContentsArchitectures: amd64 source +ContentsComponents: main +SignWith: yes +DebOverride: override.testing +DscOverride: override.testing + +{% endfor %} diff --git a/data/ansible/gpg_key_rotation/gen-key-script b/data/ansible/gpg_key_rotation/gen-key-script new file mode 100644 index 000000000..e1ad3c585 --- /dev/null +++ b/data/ansible/gpg_key_rotation/gen-key-script @@ -0,0 +1,13 @@ +{{ ansible_managed | comment }} +%echo Generating a basic OpenPGP key +%no-protection +Key-Type: RSA +Key-Length: {{ gpg_keylength }} +Subkey-Type: RSA +Subkey-Length: {{ 2048 }} +Name-Real: {{ gpg_realname }} +Name-Email: {{ gpg_useremail }} +Expire-Date: {{ gpg_expire }} +%no-ask-passphrase +%commit +%echo done \ No newline at end of file diff --git a/data/ansible/gpg_key_rotation/gpg-gen-key.yaml b/data/ansible/gpg_key_rotation/gpg-gen-key.yaml new file mode 100644 index 000000000..c1ae65488 --- /dev/null +++ b/data/ansible/gpg_key_rotation/gpg-gen-key.yaml @@ -0,0 +1,51 @@ +--- +- name: Set defaut gpg options + become: true + ansible.builtin.template: + src: gpg.conf.j2 + dest: "{{ gpg_home }}/.gnupg/gpg.conf" + mode: "0600" + owner: "{{ rootUser }}" + +- name: Copy default template for gpg key generation + become: true + ansible.builtin.template: + src: gen-key-script + dest: "{{ gpg_home }}/.gnupg/gen-key-script-{{ rootUser }}" + mode: "0600" + owner: "{{ rootUser }}" + +# Not sure what this task does, or if it's needed. +- name: List available GPG secret keys + become: true + ansible.builtin.command: "gpg --list-secret-keys --keyid-format LONG" + +# rng-tools might not be needed on newer kernel versions +- name: Install rng-tools-debian + become: true + ansible.builtin.apt: + name: rng-tools-debian + state: present + ignore_errors: true + +- name: Make sure /etc/default/rng-tools-debian exist + become: true + ansible.builtin.file: + path: /etc/default/rng-tools-debian + state: touch + +- name: Add HRNGDEVICE=/dev/urandom so we can execute rngd + become: true + ansible.builtin.lineinfile: + path: /etc/default/rng-tools-debian + line: HRNGDEVICE=/dev/urandom + insertafter: last + +- name: Generate randomness + become: true + ansible.builtin.command: "sudo /etc/init.d/rng-tools-debian restart" + ignore_errors: true + +- name: Generate gpg key + become: true + ansible.builtin.command: "sudo gpg --batch --gen-key {{ gpg_home }}/.gnupg/gen-key-script-{{ rootUser }}" diff --git a/data/ansible/gpg_key_rotation/gpg.conf.j2 b/data/ansible/gpg_key_rotation/gpg.conf.j2 new file mode 100644 index 000000000..38d375f03 --- /dev/null +++ b/data/ansible/gpg_key_rotation/gpg.conf.j2 @@ -0,0 +1,5 @@ +{{ ansible_managed | comment }} +# Prioritize stronger algorithms for new keys. +default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 BZIP2 ZLIB ZIP Uncompressed +# Use a stronger digest than the default SHA1 for certifications. +cert-digest-algo SHA512 diff --git a/data/ansible/gpg_key_rotation/gpg.yaml b/data/ansible/gpg_key_rotation/gpg.yaml new file mode 100644 index 000000000..2602ae04a --- /dev/null +++ b/data/ansible/gpg_key_rotation/gpg.yaml @@ -0,0 +1,47 @@ +--- +- name: Restart gpg-agent + become: true + ansible.builtin.command: "gpgconf --kill all" + +- name: Ensure .gnupg config directory exists with right permissions + become: true + ansible.builtin.file: + dest: "{{ gpg_home }}/.gnupg" + state: directory + mode: "0700" + owner: "{{ rootUser }}" + +# Note: matching on realname or email doesn't allow to create multiple keys. alternative? +- name: Check existing secret key + ansible.builtin.shell: "gpg --list-secret-keys | grep '{{ gpg_realname }}'" + changed_when: false + ignore_errors: true + become: true + become_user: "{{ rootUser }}" + register: gpgkeys + +- name: Check expired keys + become: true + ansible.builtin.shell: "gpg --list-keys {{ gpg_realname }} | grep 'expired'" + ignore_errors: true + failed_when: false + register: gpgExpKeys + when: gpgkeys.stdout_lines|length > 0 + +- name: Update expired + become: true + ansible.builtin.shell: 'printf "expire\n{{ gpg_expire }}\nsave\n" | gpg --batch --command-fd 0 --status-fd=2 --edit-key {{ gpg_realname }}' + when: gpgkeys.stdout_lines|length > 0 and gpgExpKeys.stdout_lines|length > 0 + +- ansible.builtin.include_tasks: gpg-gen-key.yaml + when: gpgkeys.stdout_lines|length < 1 + +- name: Get user armored public key + become: true + ansible.builtin.command: "sudo gpg --armor --output {{ gpg_pubkeyfileexport }} --export {{ gpg_useremail }}" + when: gpgkeys.stdout_lines|length < 1 or (gpgkeys.stdout_lines|length > 0 and gpgExpKeys.stdout_lines|length > 0) + +- name: After export move the key to /var/packages + become: true + ansible.builtin.command: "sudo mv {{ gpg_pubkeyfileexport }} /var/packages" + when: gpgkeys.stdout_lines|length < 1 or (gpgkeys.stdout_lines|length > 0 and gpgExpKeys.stdout_lines|length > 0) diff --git a/data/ansible/gpg_key_rotation/hosts b/data/ansible/gpg_key_rotation/hosts new file mode 100644 index 000000000..ebfedcfa8 --- /dev/null +++ b/data/ansible/gpg_key_rotation/hosts @@ -0,0 +1,2 @@ +[all] +apt ansible_host=h4.itsyscom.com ansible_port=60022 ansible_ssh_user=dan user=dan pkgAddr=192.168.122.132 diff --git a/data/ansible/gpg_key_rotation/main.yaml b/data/ansible/gpg_key_rotation/main.yaml new file mode 100644 index 000000000..b1b4bdbf0 --- /dev/null +++ b/data/ansible/gpg_key_rotation/main.yaml @@ -0,0 +1,42 @@ +--- +- hosts: apt + vars: + gpg_home: "/root" + gpg_realname: "CGRateS" + gpg_useremail: "cgrates@itsyscom.com" + gpg_pubkeyfileexport: "apt.cgrates.org.gpg.key" + + gpg_keylength: 2048 + gpg_subkeylength: 2048 + gpg_expire: 360 + + rootUser: root + + dependencies: + - reprepro + + cgrates_branch: v0.10 + distributions: + - codename: bookworm + version: 12 + - codename: bullseye + version: 11 + + tasks: + - name: Install dependencies + become: true + ansible.builtin.apt: + name: "{{ dependencies }}" + state: present + + - name: Configure reprepro + ansible.builtin.import_tasks: reprepro.yaml + + - name: Generate GPG Key + ansible.builtin.import_tasks: gpg.yaml + + - name: Resign packages with new GPG key + become: true + ansible.builtin.shell: | + reprepro -Vb /var/packages/debian export {{ cgrates_branch }}-{{ item.codename }} + with_items: "{{ distributions }}" diff --git a/data/ansible/gpg_key_rotation/options.conf.j2 b/data/ansible/gpg_key_rotation/options.conf.j2 new file mode 100644 index 000000000..6187384eb --- /dev/null +++ b/data/ansible/gpg_key_rotation/options.conf.j2 @@ -0,0 +1,3 @@ +{{ ansible_managed | comment }} +verbose +basedir /var/packages/debian diff --git a/data/ansible/gpg_key_rotation/reprepro.yaml b/data/ansible/gpg_key_rotation/reprepro.yaml new file mode 100644 index 000000000..412de6dea --- /dev/null +++ b/data/ansible/gpg_key_rotation/reprepro.yaml @@ -0,0 +1,43 @@ +--- +- name: Create debian repository base directory + become: true + ansible.builtin.file: + path: /var/packages/debian + state: directory + +- name: Create reprepro configuration directory + become: true + ansible.builtin.file: + path: /var/packages/debian/conf + state: directory + +- name: Create reprepro incoming packages directory + become: true + ansible.builtin.file: + path: /var/packages/debian/incoming + state: directory + +- name: Configure reprepro distribution settings + become: true + ansible.builtin.template: + src: distributions.conf.j2 + dest: "/var/packages/debian/conf/distributions" + mode: "0600" + owner: "{{ rootUser }}" + +- name: Configure reprepro general options + become: true + ansible.builtin.template: + src: options.conf.j2 + dest: "/var/packages/debian/conf/options" + mode: "0600" + owner: "{{ rootUser }}" + +- name: Initialize empty override file for testing distribution + become: true + ansible.builtin.copy: + content: "" + dest: /var/packages/debian/conf/override.testing + force: false + group: root + owner: root