Reputation: 481
Before apt-key
was deprecated, I was using Ansible playbooks to add and update keys in my servers. At the moment, apt-key
no longer updates the keys. In few searches, I found that I need to use gpg
now. However, I have many servers and I don't want to do this manually for each one of them. Is there a way to manage my keyrings with gpg
with Ansible?
Here are my Ansible tasks, with deprecated apt-key
:
- apt_key:
url: "https://packages.treasuredata.com/GPG-KEY-td-agent"
state: present
- apt_repository:
repo: "deb http://packages.treasuredata.com/3/ubuntu/{{ ansible_distribution_release }}/ {{ ansible_distribution_release }} contrib"
state: present
filename: "treasure-data" # Name of the pre-compiled fluentd-agent
I tried apt-key update
but it is not working for me. If a key already exists but it is expired, it doesn't update it anymore.
Upvotes: 38
Views: 36629
Reputation: 419
In short, you need to put the GPG key with the correct extension into a separate directory that is not searched by default, and point your repository configuration at that specific file.
For more info on why you need a separate directory, see this answer to "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead".
Warning: apt
will not accept ASCII GPG keys saved with .gpg extension.
You can verify whether you have the old ASCII GPG format(.asc) or the newer binary GPG format(.gpg) via file
:
# file elastic-old.gpg
elastic-old.gpg: PGP public key block Public-Key (old)
# file elastic.gpg
elastic.gpg: PGP/GPG key public ring (v4) created Mon Sep 16 17:07:54 2013 RSA (Encrypt or Sign) 2048 bits MPI=0xd70ed6cd267c5b3e...
If your key is the old format, you can either use the .asc extension, or you can optionally de-armor it via gpg --dearmor elastic.gpg
into the new binary format and use the .gpg extension.
The de-armor step is annoying for ansible automation, so I suggest you just use whatever format upstream provides as is.
On Ubuntu 22.04, there's a folder you're expected to use that is not preloaded - /etc/apt/keyrings
- or you can create your own directory and use that.
As for the Ansible part, you can use get_url
or file
to push the GPG key onto the system, and then use apt_repository
like before to add the repo, with the addition of specifying the keyring.
Using the binary GPG format with .gpg
- name: Add Example GPG key
ansible.builtin.get_url:
url: https://example.com/example.gpg
dest: /etc/apt/keyrings/example.gpg
mode: '0644'
force: true
Or using the .asc extension if upstream still hasn't switched over yet
- name: Add Example GPG key
ansible.builtin.get_url:
url: https://example.com/example.gpg
dest: /etc/apt/keyrings/example.asc
mode: '0644'
force: true
Then you can define your repository via apt_repository module like before.
- name: Add Example repo
ansible.builtin.apt_repository:
filename: example-repo
repo: 'deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/packages/8.x/apt stable main'
Keep in mind that apt_repository uses the old .list
format instead of the new DEB822 compliant .sources
format.
If you want/need to use the newer DEB822 format and you happen to be running Ansible 2.15 or newer, you should use the deb822_repository module.
If you are stuck using older Ansible core, you can template it yourself similarly to this:
tasks/main.yaml
- name: Add Elastic repo
notify: apt update force
ansible.builtin.template:
src: repo.j2
dest: /etc/apt/sources.list.d/elastic-8.x.sources
mode: '0644'
vars:
repo_name: Example PPA
repo_uris: https://example.com/packages/8.x/apt
repo_suites: stable
repo_components: main
repo_signed_by: /etc/apt/keyrings/example.gpg
templates/repo.j2
X-Repolib-Name: {{ repo_name }}
Types: deb
URIs: {{ repo_uris }}
Suites: {{ repo_suites }}
{% if repo_components is defined %}
Components: {{ repo_components }}
{% endif %}
Signed-By: {{ repo_signed_by }}
Upvotes: 23
Reputation: 153
Created a takeoff on the above contents that utilizes set_fact. Makes it easier to copy / paste to other needs using the same code.
Supply 3 vars and your off and running. I've inserted the sm- prefix just so I can clearly see my script put them there and not any other process.
- set_fact:
repoid: nginx
repo_key_url: https://nginx.org/keys/nginx_signing.key
repo_sources_list_url: "http://nginx.org/packages/ubuntu {{ os_release_name }} nginx"
- name: nginx repo - add gpg key as asc so apparmor fix not needed
get_url:
url: "{{ repo_key_url }}"
dest: /etc/apt/keyrings/sm-{{ repoid }}.asc
mode: '0644'
force: true
- name: nginx repo - add to sources.list.d
apt_repository:
filename: sm-{{repoid}}-repository
repo: 'deb [signed-by=/etc/apt/keyrings/sm-{{ repoid }}.asc] {{ repo_sources_list_url }}'
state: present
Upvotes: 0
Reputation: 2440
To expand a bit on @geerlingguy's comment regarding using the .asc
extension, this is how I ended up adding the repository for Telegraf. Take note of the use of influxdb.asc
in both the get_url
and apt_repository
tasks.
- name: Install InfluxDB key
get_url:
url: https://repos.influxdata.com/influxdb.key
dest: /etc/apt/trusted.gpg.d/influxdb.asc
- name: Add InfluxDB repository
apt_repository:
repo: "deb [signed-by=/etc/apt/trusted.gpg.d/influxdb.asc] https://repos.influxdata.com/debian stable main"
state: present
update_cache: yes
- name: Install telegraf
package:
name: telegraf
state: present
You can completely bypass the gpg --dearmor
step with this method.
Upvotes: 12