summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThayne McCombs <thayne@lucidchart.com>2023-02-07 14:04:22 -0700
committerGitHub <noreply@github.com>2023-02-07 16:04:22 -0500
commita484732c2ab1a55d26be65c3c2260c287ef138e1 (patch)
treee4aee0700ac15128464d0a77fd228d0620847383
parentfd02b3b8b9fb75b420cba1db7c27fd60aeed85aa (diff)
downloadchef-a484732c2ab1a55d26be65c3c2260c287ef138e1.tar.gz
fix(apt_repository): Detect changes to expiration in key (#13535)
This makes it so that the apt keys are updated if the expiration of a key is updated without changing the fingerprint. See: https://gitlab.com/gitlab-cookbooks/cookbook-gitlab-runner/-/merge_requests/37/diffs#35cd6a49d9e22469db42af7a30c5f3a76487e3c7 Fixes: #13308 Signed-off-by: Thayne McCombs <thayne@lucid.co>
-rw-r--r--lib/chef/resource/apt_repository.rb22
-rw-r--r--spec/unit/provider/apt_repository_spec.rb31
2 files changed, 46 insertions, 7 deletions
diff --git a/lib/chef/resource/apt_repository.rb b/lib/chef/resource/apt_repository.rb
index 80df76ef4c..7e2ced5c92 100644
--- a/lib/chef/resource/apt_repository.rb
+++ b/lib/chef/resource/apt_repository.rb
@@ -187,6 +187,24 @@ class Chef
end.compact
end
+ # run the specified command and extract the public key ids
+ # accepts the command so it can be used to extract both the current keys
+ # and the new keys
+ # @param [Array<String>] cmd the command to run
+ #
+ # @return [Array] an array of key ids
+ def extract_public_keys_from_cmd(*cmd)
+ so = shell_out(*cmd)
+ # Sample output
+ # pub:-:4096:1:D94AA3F0EFE21092:1336774248:::-:::scSC::::::23::0:
+ so.stdout.split(/\n/).map do |t|
+ if t.match(/^pub:/)
+ f = t.split(":")
+ f.slice(0, 6).join(":")
+ end
+ end.compact
+ end
+
# validate the key against the apt keystore to see if that version is expired
# @param [String] key
#
@@ -222,8 +240,8 @@ class Chef
def no_new_keys?(file)
# Now we are using the option --with-colons that works across old os versions
# as well as the latest (16.10). This for both `apt-key` and `gpg` commands
- installed_keys = extract_fingerprints_from_cmd(*LIST_APT_KEY_FINGERPRINTS)
- proposed_keys = extract_fingerprints_from_cmd("gpg", "--with-fingerprint", "--with-colons", file)
+ installed_keys = extract_public_keys_from_cmd(*LIST_APT_KEY_FINGERPRINTS)
+ proposed_keys = extract_public_keys_from_cmd("gpg", "--with-fingerprint", "--with-colons", file)
(installed_keys & proposed_keys).sort == proposed_keys.sort
end
diff --git a/spec/unit/provider/apt_repository_spec.rb b/spec/unit/provider/apt_repository_spec.rb
index aa2fb770c7..0f5421abc2 100644
--- a/spec/unit/provider/apt_repository_spec.rb
+++ b/spec/unit/provider/apt_repository_spec.rb
@@ -82,6 +82,15 @@ C5986B4F1257FFA86632CBA746181433FBB75451
843938DF228D22F7B3742BC0D94AA3F0EFE21092}
end
+ let(:apt_public_keys) do
+ %w{
+ pub:-:1024:17:40976EAF437D05B5:2004-09-12
+ pub:-:1024:17:46181433FBB75451:2004-12-30
+ pub:-:4096:1:3B4FE6ACC0B21F32:2012-05-11
+ pub:-:4096:1:D94AA3F0EFE21092:2012-05-11
+ }
+ end
+
it "responds to load_current_resource" do
expect(provider).to respond_to(:load_current_resource)
end
@@ -113,6 +122,18 @@ C5986B4F1257FFA86632CBA746181433FBB75451
end
end
+ describe "#extract_public_keys_from_cmd" do
+ it "runs the desired command" do
+ expect(provider).to receive(:shell_out).and_return(apt_key_finger)
+ provider.extract_public_keys_from_cmd(*apt_key_finger_cmd)
+ end
+
+ it "returns a list of key fingerprints" do
+ expect(provider).to receive(:shell_out).and_return(apt_key_finger)
+ expect(provider.extract_public_keys_from_cmd(*apt_key_finger_cmd)).to eql(apt_public_keys)
+ end
+ end
+
describe "#cookbook_name" do
it "returns 'test' when the cookbook property is set" do
new_resource.cookbook("test")
@@ -122,22 +143,22 @@ C5986B4F1257FFA86632CBA746181433FBB75451
describe "#no_new_keys?" do
before do
- allow(provider).to receive(:extract_fingerprints_from_cmd).with(*apt_key_finger_cmd).and_return(apt_fingerprints)
+ allow(provider).to receive(:extract_public_keys_from_cmd).with(*apt_key_finger_cmd).and_return(apt_public_keys)
end
let(:file) { "/tmp/remote-gpg-keyfile" }
it "matches a set of keys" do
- allow(provider).to receive(:extract_fingerprints_from_cmd)
+ allow(provider).to receive(:extract_public_keys_from_cmd)
.with("gpg", "--with-fingerprint", "--with-colons", file)
- .and_return(Array(apt_fingerprints.first))
+ .and_return([apt_public_keys.first])
expect(provider.no_new_keys?(file)).to be_truthy
end
it "notices missing keys" do
- allow(provider).to receive(:extract_fingerprints_from_cmd)
+ allow(provider).to receive(:extract_public_keys_from_cmd)
.with("gpg", "--with-fingerprint", "--with-colons", file)
- .and_return(%w{ F36A89E33CC1BD0F71079007327574EE02A818DD })
+ .and_return(%w{pub:-:4096:1:871920D1991BC93C:1537196506})
expect(provider.no_new_keys?(file)).to be_falsey
end
end