Implement usage of multiple GPG keys in repofiles, get keys from keys.datadoghq.com
MODIFY
attributes/default.rb
attributes/default.rb
@@ -160,7 +160,7 @@ default['datadog']['aptrepo_retries'] = 4
default['datadog']['aptrepo_use_backup_keyserver'] = false
default['datadog']['aptrepo_keyserver'] = 'hkp://keyserver.ubuntu.com:80'
default['datadog']['aptrepo_backup_keyserver'] = 'hkp://pool.sks-keyservers.net:80'
-default['datadog']['yumrepo_gpgkey'] = "#{yum_protocol}://yum.datadoghq.com/DATADOG_RPM_KEY.public"
+default['datadog']['yumrepo_gpgkey'] = "#{yum_protocol}://keys.datadoghq.com/DATADOG_RPM_KEY.public"
default['datadog']['yumrepo_proxy'] = nil
default['datadog']['yumrepo_proxy_username'] = nil
default['datadog']['yumrepo_proxy_password'] = nil
@@ -173,8 +173,10 @@ default['datadog']['windows_agent_installer_prefix'] = nil
# Location of additional rpm gpg keys to import. In the future the rpm packages
# of the Agent will be signed with this key.
-default['datadog']['yumrepo_gpgkey_new_e09422b3'] = "#{yum_protocol}://yum.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public"
-default['datadog']['yumrepo_gpgkey_new_fd4bf915'] = "#{yum_protocol}://yum.datadoghq.com/DATADOG_RPM_KEY_20200908.public"
+# DATADOG_RPM_KEY_CURRENT always contains the key that is used to sign repodata and latest packages
+default['datadog']['yumrepo_gpgkey_new_current'] = "#{yum_protocol}://keys.datadoghq.com/DATADOG_RPM_KEY_CURRENT.public"
+default['datadog']['yumrepo_gpgkey_new_e09422b3'] = "#{yum_protocol}://keys.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public"
+default['datadog']['yumrepo_gpgkey_new_fd4bf915'] = "#{yum_protocol}://keys.datadoghq.com/DATADOG_RPM_KEY_FD4BF915.public"
# Windows Agent Blacklist
# Attribute to enforce silent failures on agent installs when attempting to install a

MODIFY
recipes/repository.rb
recipes/repository.rb
@@ -31,10 +31,12 @@ agent_major_version = Chef::Datadog.agent_major_version(node)
apt_gpg_key = 'D75CEA17048B9ACBF186794B32637D44F14F620E'
other_apt_gpg_keys = ['A2923DFF56EDA6E76E55E492D3A80E30382E94DE']
+# DATADOG_RPM_KEY_CURRENT always contains the key that is used to sign repodata and latest packages
# DATADOG_RPM_KEY_E09422B3.public expires in 2022
-# DATADOG_RPM_KEY_20200908.public expires in 2024
-rpm_gpg_keys = [['DATADOG_RPM_KEY_E09422B3.public', 'e09422b3', 'A4C0 B90D 7443 CF6E 4E8A A341 F106 8E14 E094 22B3'],
- ['DATADOG_RPM_KEY_20200908.public', 'fd4bf915', 'C655 9B69 0CA8 82F0 23BD F3F6 3F4D 1729 FD4B F915']]
+# DATADOG_RPM_KEY_FD4BF915.public expires in 2024
+rpm_gpg_keys = [['DATADOG_RPM_KEY_CURRENT.public', 'current', ''],
+ ['DATADOG_RPM_KEY_E09422B3.public', 'e09422b3', 'A4C0 B90D 7443 CF6E 4E8A A341 F106 8E14 E094 22B3'],
+ ['DATADOG_RPM_KEY_FD4BF915.public', 'fd4bf915', 'C655 9B69 0CA8 82F0 23BD F3F6 3F4D 1729 FD4B F915']]
# Local file name of the key
rpm_gpg_keys_name = 0
@@ -113,6 +115,8 @@ when 'rhel', 'fedora', 'amazon'
remote_file "remote_file_#{rpm_gpg_key[rpm_gpg_keys_name]}" do
path key_local_path
source node['datadog']["yumrepo_gpgkey_new_#{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]}"]
+ # note that for the "current" key, this will fine, because there's never going to be
+ # gpg-pubkey-current entry in the RPM database
not_if "rpm -q gpg-pubkey-#{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]}" # (key already imported)
notifies :run, "execute[rpm-import datadog key #{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]}]", :immediately
end
@@ -123,7 +127,7 @@ when 'rhel', 'fedora', 'amazon'
# Import key if fingerprint matches
execute "rpm-import datadog key #{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]}" do
command "rpm --import #{key_local_path}"
- only_if "gpg --dry-run --quiet --with-fingerprint #{key_local_path} | grep '#{rpm_gpg_key[rpm_gpg_keys_full_fingerprint]}' || gpg --dry-run --import --import-options import-show #{key_local_path} | grep '#{gpg_key_fingerprint_without_space}'"
+ only_if "gpg --dry-run --quiet --with-fingerprint #{key_local_path} | grep '#{rpm_gpg_key[rpm_gpg_keys_full_fingerprint]}' || gpg --dry-run --import --import-options import-show #{key_local_path} | grep '#{gpg_key_fingerprint_without_space}' || [ #{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]} = \"current\" ]"
action :nothing
end
end
@@ -145,13 +149,14 @@ when 'rhel', 'fedora', 'amazon'
# Add YUM repository
yumrepo_gpgkeys = []
- if agent_major_version < 7
- yumrepo_gpgkeys.push(node['datadog']['yumrepo_gpgkey'])
- else
+ if agent_major_version > 5
rpm_gpg_keys.each do |rpm_gpg_key|
yumrepo_gpgkeys.push(node['datadog']["yumrepo_gpgkey_new_#{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]}"])
end
end
+ # yum/dnf go through entries in the order in which they're set in the repofile;
+ # add the old key last so it doesn't get imported at all if a newer key can be used
+ yumrepo_gpgkeys.push(node['datadog']['yumrepo_gpgkey']) if agent_major_version < 7
yum_repository 'datadog' do
description 'datadog'
@@ -183,7 +188,7 @@ when 'suse'
# Import key if fingerprint matches
execute "rpm-import datadog key #{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]}" do
command "rpm --import #{new_key_local_path}"
- only_if "gpg --dry-run --quiet --with-fingerprint #{new_key_local_path} | grep '#{rpm_gpg_key[rpm_gpg_keys_full_fingerprint]}' || gpg --dry-run --import --import-options import-show #{new_key_local_path} | grep '#{gpg_key_fingerprint_without_space}'"
+ only_if "gpg --dry-run --quiet --with-fingerprint #{new_key_local_path} | grep '#{rpm_gpg_key[rpm_gpg_keys_full_fingerprint]}' || gpg --dry-run --import --import-options import-show #{new_key_local_path} | grep '#{gpg_key_fingerprint_without_space}' || [ #{rpm_gpg_key[rpm_gpg_keys_short_fingerprint]} = \"current\" ]"
action :nothing
end
end
@@ -221,7 +226,7 @@ when 'suse'
zypper_repository 'datadog' do
description 'datadog'
baseurl baseurl
- gpgkey agent_major_version < 7 ? node['datadog']['yumrepo_gpgkey'] : node['datadog']["yumrepo_gpgkey_new_#{rpm_gpg_keys[0][rpm_gpg_keys_short_fingerprint]}"]
+ gpgkey agent_major_version < 6 ? node['datadog']['yumrepo_gpgkey'] : node['datadog']['yumrepo_gpgkey_new_current']
gpgautoimportkeys false
gpgcheck false
action :create

MODIFY
spec/repository_spec.rb
spec/repository_spec.rb
@@ -52,7 +52,22 @@ describe 'datadog::repository' do
end
it 'installs gnupg E09422B3' do
- expect(chef_run).to install_package('gnupg') if chef_run.node['packages']['gnupg2'].nil?
+ epect(chef_run).to install_package('gnupg') if chef_run.node['packages']['gnupg2'].nil?
+ end
+
+ it 'downloads the current RPM key' do
+ expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_CURRENT.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_CURRENT.public'))
+ end
+
+ it 'notifies the GPG key install if a new one is downloaded CURRENT' do
+ keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_CURRENT.public')
+ expect(keyfile_r).to notify('execute[rpm-import datadog key current]')
+ .to(:run).immediately
+ end
+
+ it 'execute[rpm-import datadog key *] by default CURRENT' do
+ keyfile_exec_r = chef_run.execute('rpm-import datadog key current')
+ expect(keyfile_exec_r).to do_nothing
end
it 'downloads the new RPM key E09422B3' do
@@ -73,7 +88,7 @@ describe 'datadog::repository' do
# Key FD4BF915 (2020-09-08)
it 'sets the yumrepo_gpgkey_new attribute fd4bf915' do
expect(chef_run.node['datadog']['yumrepo_gpgkey_new_fd4bf915']).to match(
- /DATADOG_RPM_KEY_20200908.public/
+ /DATADOG_RPM_KEY_FD4BF915.public/
)
end
@@ -82,11 +97,11 @@ describe 'datadog::repository' do
end
it 'downloads the new RPM key fd4bf915' do
- expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_20200908.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_20200908.public'))
+ expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_FD4BF915.public'))
end
it 'notifies the GPG key install if a new one is downloaded fd4bf915' do
- keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_20200908.public')
+ keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public')
expect(keyfile_r).to notify('execute[rpm-import datadog key fd4bf915]')
.to(:run).immediately
end
@@ -97,9 +112,13 @@ describe 'datadog::repository' do
end
# prefer HTTPS on boxes that support TLS1.2
- it 'sets up a yum repo E09422B3 and 20200908' do
+ it 'sets up a yum repo E09422B3 and FD4BF915' do
expect(chef_run).to create_yum_repository('datadog').with(
- gpgkey: ['https://yum.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public', 'https://yum.datadoghq.com/DATADOG_RPM_KEY_20200908.public']
+ gpgkey: [
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY_CURRENT.public',
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public',
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY_FD4BF915.public',
+ ]
)
end
end
@@ -142,7 +161,7 @@ describe 'datadog::repository' do
# Key FD4BF915 (2020-09-08)
it 'sets the yumrepo_gpgkey_new attribute fd4bf915' do
expect(chef_run.node['datadog']['yumrepo_gpgkey_new_fd4bf915']).to match(
- /DATADOG_RPM_KEY_20200908.public/
+ /DATADOG_RPM_KEY_FD4BF915.public/
)
end
@@ -151,11 +170,11 @@ describe 'datadog::repository' do
end
it 'downloads the new RPM key fd4bf915' do
- expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_20200908.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_20200908.public'))
+ expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_FD4BF915.public'))
end
it 'notifies the GPG key install if a new one is downloaded fd4bf915' do
- keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_20200908.public')
+ keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public')
expect(keyfile_r).to notify('execute[rpm-import datadog key fd4bf915]')
.to(:run).immediately
end
@@ -168,7 +187,12 @@ describe 'datadog::repository' do
# prefer HTTPS on boxes that support TLS1.2
it 'sets up a yum repo' do
expect(chef_run).to create_yum_repository('datadog').with(
- gpgkey: ['https://yum.datadoghq.com/DATADOG_RPM_KEY.public']
+ gpgkey: [
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY_CURRENT.public',
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public',
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY_FD4BF915.public',
+ 'https://keys.datadoghq.com/DATADOG_RPM_KEY.public',
+ ]
)
end
end
@@ -211,7 +235,7 @@ describe 'datadog::repository' do
# Key FD4BF915 (2020-09-08)
it 'sets the yumrepo_gpgkey_new attribute fd4bf915' do
expect(chef_run.node['datadog']['yumrepo_gpgkey_new_fd4bf915']).to match(
- /DATADOG_RPM_KEY_20200908.public/
+ /DATADOG_RPM_KEY_FD4BF915.public/
)
end
@@ -220,11 +244,11 @@ describe 'datadog::repository' do
end
it 'downloads the new RPM key fd4bf915' do
- expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_20200908.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_20200908.public'))
+ expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_FD4BF915.public'))
end
it 'notifies the GPG key install if a new one is downloaded fd4bf915' do
- keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_20200908.public')
+ keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public')
expect(keyfile_r).to notify('execute[rpm-import datadog key fd4bf915]')
.to(:run).immediately
end
@@ -238,7 +262,93 @@ describe 'datadog::repository' do
# https://github.com/DataDog/chef-datadog/blob/v2.8.1/attributes/default.rb#L85-L91
it 'sets up a yum repo' do
expect(chef_run).to create_yum_repository('datadog').with(
- gpgkey: ['http://yum.datadoghq.com/DATADOG_RPM_KEY.public']
+ gpgkey: [
+ 'http://keys.datadoghq.com/DATADOG_RPM_KEY_CURRENT.public',
+ 'http://keys.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public',
+ 'http://keys.datadoghq.com/DATADOG_RPM_KEY_FD4BF915.public',
+ 'http://keys.datadoghq.com/DATADOG_RPM_KEY.public',
+ ]
+ )
+ end
+ end
+ end
+
+ context 'suseiods' do
+ # SUSE 12.5 is one of the versions for which we want to generate gpgkey=
+ # entry in repofile with one value; ensure this stays true even if
+ # https://github.com/chef/chef/issues/11090 (specifying multiple values for
+ # gpgkey= entry) is implemented and used here in the future
+ context 'suse 12.5, agent 6' do
+ cached(:chef_run) do
+ ChefSpec::SoloRunner.new(
+ platform: 'suse', version: '12.5'
+ ) do |node|
+ node.normal['datadog'] = { 'agent_major_version' => '6' }
+ end.converge(described_recipe)
+ end
+
+ # Key E09422B3
+ it 'sets the yumrepo_gpgkey_new attribute E09422B3' do
+ expect(chef_run.node['datadog']['yumrepo_gpgkey_new_e09422b3']).to match(
+ /DATADOG_RPM_KEY_E09422B3.public/
+ )
+ end
+
+ it 'downloads the new RPM key E09422B3' do
+ expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_E09422B3.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_E09422B3.public'))
+ end
+
+ it 'notifies the GPG key install if a new one is downloaded E09422B3' do
+ keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_E09422B3.public')
+ expect(keyfile_r).to notify('execute[rpm-import datadog key e09422b3]')
+ .to(:run).immediately
+ end
+
+ it 'doesn\'t execute[rpm-import datadog key *] by default E09422B3' do
+ keyfile_exec_r = chef_run.execute('rpm-import datadog key e09422b3')
+ expect(keyfile_exec_r).to do_nothing
+ end
+
+ # Key FD4BF915 (2020-09-08)
+ it 'sets the yumrepo_gpgkey_new attribute fd4bf915' do
+ expect(chef_run.node['datadog']['yumrepo_gpgkey_new_fd4bf915']).to match(
+ /DATADOG_RPM_KEY_FD4BF915.public/
+ )
+ end
+
+ it 'downloads the new RPM key fd4bf915' do
+ expect(chef_run).to create_remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY_FD4BF915.public'))
+ end
+
+ it 'notifies the GPG key install if a new one is downloaded fd4bf915' do
+ keyfile_r = chef_run.remote_file('remote_file_DATADOG_RPM_KEY_FD4BF915.public')
+ expect(keyfile_r).to notify('execute[rpm-import datadog key fd4bf915]')
+ .to(:run).immediately
+ end
+
+ it 'doesn\'t execute[rpm-import datadog key *] by default fd4bf915' do
+ keyfile_exec_r = chef_run.execute('rpm-import datadog key fd4bf915')
+ expect(keyfile_exec_r).to do_nothing
+ end
+
+ it 'downloads the old RPM key 4172a230' do
+ expect(chef_run).to create_remote_file('DATADOG_RPM_KEY.public').with(path: ::File.join(Chef::Config[:file_cache_path], 'DATADOG_RPM_KEY.public'))
+ end
+
+ it 'notifies the GPG key install if the old key is downloaded 4172a230' do
+ keyfile_r = chef_run.remote_file('DATADOG_RPM_KEY.public')
+ expect(keyfile_r).to notify('execute[rpm-import datadog key 4172a230]')
+ .to(:run).immediately
+ end
+
+ it 'doesn\'t execute[rpm-import datadog key *] by default 4172a230' do
+ keyfile_exec_r = chef_run.execute('rpm-import datadog key 4172a230')
+ expect(keyfile_exec_r).to do_nothing
+ end
+
+ it 'sets up a yum repo' do
+ expect(chef_run).to create_zypper_repository('datadog').with(
+ gpgkey: 'https://keys.datadoghq.com/DATADOG_RPM_KEY_CURRENT.public'
)
end
end

MODIFY
spec/spec_helper.rb
spec/spec_helper.rb
@@ -27,8 +27,10 @@ RSpec.configure do |config|
stub_command('apt-cache policy datadog-agent-base | grep "Installed: (none)"').and_return(false)
# recipes/repository.rb
+ stub_command('rpm -q gpg-pubkey-current').and_return(false)
stub_command('rpm -q gpg-pubkey-e09422b3').and_return(false)
stub_command('rpm -q gpg-pubkey-fd4bf915').and_return(false)
+ stub_command('rpm -q gpg-pubkey-4172a230').and_return(false)
stub_command('apt-key adv --list-public-keys --with-fingerprint --with-colons | grep 382E94DE | grep pub').and_return(false)
end

Implement usage of multiple GPG keys in repofiles, get keys from keys.datadoghq.com (#782)