From f588f2651a68c5863aac7dac910d96bbc7531ef9 Mon Sep 17 00:00:00 2001 From: tphoney Date: Fri, 6 Mar 2015 16:14:40 +0000 Subject: [PATCH] initial commit for gpg key checking better attempt at gpg version checking adding in key length warning removing version check, adding key check adding tests clean up the code small changes use commands documentation updates --- README.md | 2 +- lib/puppet/provider/apt_key/apt_key.rb | 13 +++++++++ lib/puppet/type/apt_key.rb | 3 +++ spec/acceptance/apt_key_provider_spec.rb | 34 ++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c06e17..45e9052 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The apt module provides a simple interface for managing Apt source, key, and def The apt module automates obtaining and installing software packages on \*nix systems. -**Note**: While this module allows the use of short keys, **we urge you NOT to use short keys**, as they pose a serious security issue by opening you up to collision attacks. +**Note**: While this module allows the use of short keys, **warnings are thrown if a full fingerprint is not used**, as they pose a serious security issue by opening you up to collision attacks. ## Setup diff --git a/lib/puppet/provider/apt_key/apt_key.rb b/lib/puppet/provider/apt_key/apt_key.rb index 67a8aa0..687c995 100644 --- a/lib/puppet/provider/apt_key/apt_key.rb +++ b/lib/puppet/provider/apt_key/apt_key.rb @@ -16,6 +16,7 @@ Puppet::Type.type(:apt_key).provide(:apt_key) do confine :osfamily => :debian defaultfor :osfamily => :debian commands :apt_key => 'apt-key' + commands :gpg => '/usr/bin/gpg' def self.instances cli_args = ['adv','--list-keys', '--with-colons', '--fingerprint'] @@ -136,6 +137,18 @@ Puppet::Type.type(:apt_key).provide(:apt_key) do file = Tempfile.new('apt_key') file.write content file.close + #confirm that the fingerprint from the file, matches the long key that is in the manifest + if name.size == 40 + if File.executable? command(:gpg) + extracted_key = execute(["#{command(:gpg)} --with-fingerprint --with-colons #{file.path} | awk -F: '/^fpr:/ { print $10 }'"], :failonfail => false) + extracted_key = extracted_key.chomp + if extracted_key != name + fail ("The id in your manifest #{resource[:name]} and the fingerprint from content/source do not match. Please check there is not an error in the id or check the content/source is legitimate.") + end + else + warning ('/usr/bin/gpg cannot be found for verification of the id.') + end + end file.path end diff --git a/lib/puppet/type/apt_key.rb b/lib/puppet/type/apt_key.rb index 70825ac..7130496 100644 --- a/lib/puppet/type/apt_key.rb +++ b/lib/puppet/type/apt_key.rb @@ -23,6 +23,9 @@ Puppet::Type.newtype(:apt_key) do if self[:content] and self[:source] fail('The properties content and source are mutually exclusive.') end + if self[:id].length < 40 + warning('The id should be a full fingerprint (40 characters), see README.') + end end newparam(:id, :namevar => true) do diff --git a/spec/acceptance/apt_key_provider_spec.rb b/spec/acceptance/apt_key_provider_spec.rb index 24277d2..1f703c9 100644 --- a/spec/acceptance/apt_key_provider_spec.rb +++ b/spec/acceptance/apt_key_provider_spec.rb @@ -520,4 +520,38 @@ ugVIB2pi+8u84f+an4Hml4xlyijgYu05pqNvnLRyJDLd61hviLC8GYU= end end end + + describe 'fingerprint validation against source/content' do + context 'fingerprint in id matches fingerprint from remote key' do + it 'works' do + pp = <<-EOS + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}', + ensure => 'present', + source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_failures => true) + end + end + + context 'fingerprint in id does NOT match fingerprint from remote key' do + it 'works' do + pp = <<-EOS + apt_key { 'puppetlabs': + id => '47B320EB4C7C375AA9DAE1A01054B7A24BD6E666', + ensure => 'present', + source => 'https://#{PUPPETLABS_APT_URL}/#{PUPPETLABS_GPG_KEY_FILE}', + } + EOS + + apply_manifest(pp, :expect_failures => true) do |r| + expect(r.stderr).to match(/do not match/) + end + end + end + end + end -- 2.32.3