summaryrefslogtreecommitdiff
path: root/lib/chef/provider/zypper_repository.rb
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2017-09-25 21:33:52 -0700
committerTim Smith <tsmith@chef.io>2017-09-28 11:04:54 -0700
commit4df19b0ac8a403c127986e4f6f5e739b8930eb7c (patch)
tree02ece044229aefd4f76ec3dd4901acb7f9b0d3f3 /lib/chef/provider/zypper_repository.rb
parented3750c1d9f8a677b891c59203e828cbfccc345e (diff)
downloadchef-4df19b0ac8a403c127986e4f6f5e739b8930eb7c.tar.gz
Use apt-like gpg key management to avoid notifications
Download the key to the cache Grab the key's fingerprint Check to see if that fingerprint is in the RPM database Add it if it's not Signed-off-by: Tim Smith <tsmith@chef.io>
Diffstat (limited to 'lib/chef/provider/zypper_repository.rb')
-rw-r--r--lib/chef/provider/zypper_repository.rb85
1 files changed, 80 insertions, 5 deletions
diff --git a/lib/chef/provider/zypper_repository.rb b/lib/chef/provider/zypper_repository.rb
index 14d592debe..a1a31d5bea 100644
--- a/lib/chef/provider/zypper_repository.rb
+++ b/lib/chef/provider/zypper_repository.rb
@@ -19,6 +19,7 @@
require "chef/resource"
require "chef/dsl/declare_resource"
require "chef/provider/noop"
+require "chef/mixin/shell_out"
require "shellwords"
class Chef
@@ -31,10 +32,9 @@ class Chef
action :create do
if new_resource.gpgautoimportkeys
- declare_resource(:execute, "import gpg key from #{new_resource.gpgkey}") do
- command "/bin/rpm --import #{new_resource.gpgkey}"
- action :nothing
- end
+ install_gpg_key(new_resource.gpgkey)
+ else
+ Chef::Log.debug("'gpgautoimportkeys' property is set to false. Skipping key import.")
end
declare_resource(:template, "/etc/zypp/repos.d/#{escaped_repo_name}.repo") do
@@ -47,7 +47,6 @@ class Chef
sensitive new_resource.sensitive
variables(config: new_resource)
mode new_resource.mode
- notifies :run, "execute[import gpg key from #{new_resource.gpgkey}]", :before if new_resource.gpgautoimportkeys
notifies :refresh, new_resource, :immediately if new_resource.refresh_cache
end
end
@@ -74,11 +73,87 @@ class Chef
end
# determine if a template file is available in the current run
+ # @param [String] path the path to the template file
+ #
# @return [Boolean] template file exists or doesn't
def template_available?(path)
!path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook_name, path)
end
+ # determine if a cookbook file is available in the run
+ # @param [String] path the path to the template file
+ #
+ # @return [Boolean] cookbook file exists or doesn't
+ def has_cookbook_file?(fn)
+ run_context.has_cookbook_file_in_cookbook?(cookbook_name, fn)
+ end
+
+ # Given the provided key URI determine what kind of chef resource we need
+ # to fetch the key
+ # @param [String] uri the uri of the gpg key (local path or http URL)
+ #
+ # @raise [Chef::Exceptions::FileNotFound] Key isn't remote or found in the current run
+ #
+ # @return [Symbol] :remote_file or :cookbook_file
+ def key_type(uri)
+ if uri.start_with?("http")
+ Chef::Log.debug("Will use :remote_file resource to cache the gpg key locally")
+ :remote_file
+ elsif has_cookbook_file?(key)
+ Chef::Log.debug("Will use :cookbook_file resource to cache the gpg key locally")
+ :cookbook_file
+ else
+ raise Chef::Exceptions::FileNotFound, "Cannot determine location of gpgkey. Must start with 'http' or be a file managed by Chef."
+ end
+ end
+
+ # is the provided key already installed
+ # @param [String] key_path the path to the key on the local filesystem
+ #
+ # @return [boolean] is the key already known by rpm
+ def key_installed?(key_path)
+ so = shell_out("rpm -qa gpg-pubkey*").run_command
+ # expected output & match: http://rubular.com/r/RdF7EcXEtb
+ status = /gpg-pubkey-#{key_fingerprint(key_path)}/.match(so.stdout)
+ Chef::Log.debug("GPG key at #{key_path} is known by rpm? #{status ? "true" : "false"}")
+ status
+ end
+
+ # extract the gpg key fingerprint from a local file
+ # @param [String] key_path the path to the key on the local filesystem
+ #
+ # @return [String] the fingerprint of the key
+ def key_fingerprint(key_path)
+ so = shell_out("gpg --with-fingerprint #{key_path}").run_command
+ # expected output and match: http://rubular.com/r/BpfMjxySQM
+ fingerprint = /pub\s*\S*\/(\S*)/.match(so.stdout)[1].downcase
+ Chef::Log.debug("GPG fingerprint of key at #{key_path} is #{fingerprint}")
+ fingerprint
+ end
+
+ # install the provided gpg key
+ # @param [String] uri the uri of the local or remote gpg key
+ def install_gpg_key(uri)
+ unless uri
+ Chef::Log.debug("'gpgkey' property not provided or set to nil. Skipping key import.")
+ return
+ end
+
+ cached_keyfile = ::File.join(Chef::Config[:file_cache_path], uri.split("/")[-1])
+
+ declare_resource(key_type(new_resource.gpgkey), cached_keyfile) do
+ source uri
+ mode "0644"
+ sensitive new_resource.sensitive
+ action :create
+ end
+
+ declare_resource(:execute, "import gpg key from #{new_resource.gpgkey}") do
+ command "/bin/rpm --import #{new_resource.gpgkey}"
+ not_if { key_installed?(cached_keyfile) }
+ action :run
+ end
+ end
end
end
end