diff --git a/README.markdown b/README.markdown index 3150e44..559a6a0 100644 --- a/README.markdown +++ b/README.markdown @@ -1214,6 +1214,22 @@ Instead, use: *Type*: statement. +#### `validate_x509_rsa_key_pair` + +Validates a PEM-formatted X.509 certificate and private key using OpenSSL. +Verifies that the certficate's signature was created from the supplied key. + +Fails catalog compilation if any value fails this check. + +Takes two arguments, the first argument must be a X.509 certificate and the +second must be an RSA private key: + + ~~~ + validate_x509_rsa_key_pair($cert, $key) + ~~~ + +*Type*: statement. + #### `values` Returns the values of a given hash. For example, given `$hash = {'a'=1, 'b'=2, 'c'=3} values($hash)` returns [1,2,3]. diff --git a/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb b/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb new file mode 100644 index 0000000..fc9f23f --- /dev/null +++ b/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb @@ -0,0 +1,47 @@ +module Puppet::Parser::Functions + + newfunction(:validate_x509_rsa_key_pair, :doc => <<-ENDHEREDOC + Validates a PEM-formatted X.509 certificate and RSA private key using + OpenSSL. Verifies that the certficate's signature was created from the + supplied key. + + Fail compilation if any value fails this check. + + validate_x509_rsa_key_pair($cert, $key) + + ENDHEREDOC + ) do |args| + + require 'openssl' + + NUM_ARGS = 2 unless defined? NUM_ARGS + + unless args.length == NUM_ARGS then + raise Puppet::ParseError, + ("validate_x509_rsa_key_pair(): wrong number of arguments (#{args.length}; must be #{NUM_ARGS})") + end + + args.each do |arg| + unless arg.is_a?(String) + raise Puppet::ParseError, "#{arg.inspect} is not a string." + end + end + + begin + cert = OpenSSL::X509::Certificate.new(args[0]) + rescue OpenSSL::X509::CertificateError => e + raise Puppet::ParseError, "Not a valid x509 certificate: #{e}" + end + + begin + key = OpenSSL::PKey::RSA.new(args[1]) + rescue OpenSSL::PKey::RSAError => e + raise Puppet::ParseError, "Not a valid RSA key: #{e}" + end + + unless cert.verify(key) + raise Puppet::ParseError, "Certificate signature does not match supplied key" + end + end + +end diff --git a/spec/functions/validate_x509_rsa_key_pair_spec.rb b/spec/functions/validate_x509_rsa_key_pair_spec.rb new file mode 100755 index 0000000..eb63310 --- /dev/null +++ b/spec/functions/validate_x509_rsa_key_pair_spec.rb @@ -0,0 +1,180 @@ +require 'spec_helper' + +describe 'validate_x509_rsa_key_pair' do + + let(:valid_cert) do + <