diff options
author | Ken Barber <ken@bob.sh> | 2011-08-14 03:47:32 +0200 |
---|---|---|
committer | Ken Barber <ken@bob.sh> | 2011-08-17 16:36:59 +0200 |
commit | 9b912d028fe1a2622ec61a56b1f0774ef3c9f43b (patch) | |
tree | 56c1be57410b1c1e6532b03c42cda4e1602ffd08 | |
parent | 33887f9be50c4fd94bbd08d7c00d9b3d97e29d21 (diff) |
(#8925) Added new function called 'get_certificate' for retrieving
certificates from a CA (or locally).
This function works by either obtaining the file locally
or remotely based on Puppets configuration.
Also added get_pubkey which wraps get_certificate and extracts the
public key.
23 files changed, 503 insertions, 0 deletions
diff --git a/lib/puppet/parser/functions/get_certificate.rb b/lib/puppet/parser/functions/get_certificate.rb new file mode 100644 index 0000000..66baba6 --- /dev/null +++ b/lib/puppet/parser/functions/get_certificate.rb @@ -0,0 +1,89 @@ +module Puppet::Parser::Functions + newfunction(:get_certificate, :type => :rvalue, :doc => <<-EOS +Returns the public certificate of the given CN from the local or remote Puppet +CA. + +Usage is: + + get_certificate($cn, $options) + +The first argument $cn is a valid CN for the certificate you wish to +return. A CN is usually the hostname of a machine in Puppet. You can view all available +certificates using the facility: + + puppet cert --list --all + +On the main CA or puppetmaster. + +The second argument $options allows the user to define a hash of options to +pass to the function. + +The options and descriptions are: + +* *conn_timeout*: Adjust timeout for remote CA connectivity (in seconds). Default is 7. + EOS + ) do |arguments| + + # Make sure we have enough arguments + if not (1..2).include?(arguments.size) then + raise(Puppet::ParseError, "get_certificate(): Wrong number of arguments " + + "given (#{arguments.size} for 1 or 2)") + end + + # Obtain arguments and set defaults + cn = arguments[0] + options = arguments[1] ||= {} + options[:conn_timeout] = 7 if !options.has_key?(:conn_timeout) + + # Validation of arguments + if not (cn.is_a?(String) and cn.match(/^[a-zA-Z0-9@_\-\.]+$/)) then + raise(Puppet::ParseError, 'get_certificate(): CN name must be a valid string. Hashes and Arrays are not valid') + end + if not (1..600).include?(options[:conn_timeout]) then + raise(Puppet::ParseError, "get_certificate(): The option 'conn_timeout' must be an integer between 1 and 600") + end + + # Get and return certificate using file or rest + if Puppet[:ca] == true then + # Get the certificate locally if we are acting as a CA + # TODO: wrap: puppet certificate --render-as s --ca-location remote find ken@bob.sh + ssl_cert_path = Puppet[:signeddir] + "/" + cn + ".pem" + if FileTest.exists?(ssl_cert_path) then + cert = File.open(ssl_cert_path,"r") + return cert.read + end + else + # Obtain the certificate from the CA if its remote + # TODO: wrap: puppet certificate --render-as s --ca-location local find ken@bob.sh + require 'net/http' + require 'net/https' + + http = Net::HTTP.new(Puppet[:ca_server], Puppet[:ca_port]) + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + + begin + res = timeout(options[:conn_timeout]) do + http.start {|h| + h.get("/production/certificate/#{cn}", { "Accept" => "s" }) + } + end + rescue Timeout::Error + raise(Puppet::Error, "Transaction timed out when connecting to #{Puppet[:ca_server]}:#{Puppet[:ca_port]}. Check your CA is running and that your ca_server and ca_port settings are correct on the machine this function ran on.") + rescue Errno::ECONNREFUSED + raise(Puppet::Error, "Connection refused when connecting to #{Puppet[:ca_server]}:#{Puppet[:ca_port]}. Check your CA is running and that your ca_server and ca_port settings are correct on the machine this function ran on.") + end + + case res.code + when "200" + return res.body if res.body + when "404" + return :undef + else + raise(Puppet::Error, "Error with REST call: #{res.code}") + end + end + + :undef + end +end diff --git a/lib/puppet/parser/functions/get_pubkey.rb b/lib/puppet/parser/functions/get_pubkey.rb new file mode 100644 index 0000000..744b9df --- /dev/null +++ b/lib/puppet/parser/functions/get_pubkey.rb @@ -0,0 +1,25 @@ +module Puppet::Parser::Functions + newfunction(:get_pubkey, :type => :rvalue, :doc => <<-EOS +Gets a public key given a CN. This function accepts all the same +parameters as get_certificate(), but instead returns the public +key portion of the certificate. + +See get_certificate() for a more complete list of options available. +EOS + ) do |arguments| + + # Wrap the get_certificate method + method = Puppet::Parser::Functions.function(:get_certificate) + cert_text = send(method, arguments) + + require 'openssl' + + if cert_text == :undef then + return :undef + else + cert = OpenSSL::X509::Certificate.new(cert_text) + pubkey = cert.public_key + return pubkey.to_s + end + end +end diff --git a/spec/fixtures/master_config/.gitignore b/spec/fixtures/master_config/.gitignore new file mode 100644 index 0000000..7d4e912 --- /dev/null +++ b/spec/fixtures/master_config/.gitignore @@ -0,0 +1,2 @@ +manifests/ +var/ diff --git a/spec/fixtures/master_config/auth.conf b/spec/fixtures/master_config/auth.conf new file mode 100644 index 0000000..aecb32e --- /dev/null +++ b/spec/fixtures/master_config/auth.conf @@ -0,0 +1,4 @@ +path /certificate/ +auth no +method find +allow * diff --git a/spec/fixtures/master_config/ssl/ca/ca_crl.pem b/spec/fixtures/master_config/ssl/ca/ca_crl.pem new file mode 100644 index 0000000..90c7a03 --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/ca_crl.pem @@ -0,0 +1,8 @@ +-----BEGIN X509 CRL----- +MIH5MGQCAQEwDQYJKoZIhvcNAQEFBQAwIjEgMB4GA1UEAwwXUHVwcGV0IENBOiBw +dXBwZXRtYXN0ZXIXDTExMDgxMzIwMDAwOFoXDTE2MDgxMTIwMDAwOFqgDjAMMAoG +A1UdFAQDAgEAMA0GCSqGSIb3DQEBBQUAA4GBACBHLkJD4RvEV75ak8w468Kq7r5p +s87Fzs0Vj2fgqH/3GPoazwBD4R0TvqMb+NUuF0WnipexdQQRjaiERmqX9aIhRjRA +vs4ItdoxAvcgCzWs6cYm/e4SAAqY5lipfJqd+aRlQgzWaj6WDbFMVEKvqMXqM5wU +gGQRYVnXHbohA+/I +-----END X509 CRL----- diff --git a/spec/fixtures/master_config/ssl/ca/ca_crt.pem b/spec/fixtures/master_config/ssl/ca/ca_crt.pem new file mode 100644 index 0000000..7910b2b --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/ca_crt.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIBATANBgkqhkiG9w0BAQUFADAiMSAwHgYDVQQDDBdQdXBw +ZXQgQ0E6IHB1cHBldG1hc3RlcjAeFw0xMTA4MTIyMDAwMDhaFw0xNjA4MTAyMDAw +MDhaMCIxIDAeBgNVBAMMF1B1cHBldCBDQTogcHVwcGV0bWFzdGVyMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDA6rbkI3p/YmrjE5ZNwuCPRfqUtywnBHqClp2o +nBgqrBZiKitxAmdEH4lidGA9AbiNnBiMh0fC4s5sKAUZUjPjv1I7VBqrueYWKnKP +1IBuggaJDoUQysj73XxPUnfFiuBuDVO+FEjLCrbB7WCfdli3KuueUJjHbcLyUh0n +o2ceMwIDAQABo3kwdzA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1YnkvT3BlblNT +TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUB14U4FLr4JVibAmnV+n+kw85ck4wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4GBAAZ3wF7R8DDhhT31OGQ/A+/F3L59nStqvW7AD7EabrTDPPNOVcvt/las +oi4MXiBuGPgS/xg+n4YBREaaYoF8BcGx5YMPY1XOPS0DItnDl44Wd+eHraD69kLl +l/4pPMlE5PQ21o82dph3i6B1E5zwLxhMXzh1mfvDcCIMmRdVobQm +-----END CERTIFICATE----- diff --git a/spec/fixtures/master_config/ssl/ca/ca_key.pem b/spec/fixtures/master_config/ssl/ca/ca_key.pem new file mode 100644 index 0000000..d073e22 --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/ca_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDA6rbkI3p/YmrjE5ZNwuCPRfqUtywnBHqClp2onBgqrBZiKitx +AmdEH4lidGA9AbiNnBiMh0fC4s5sKAUZUjPjv1I7VBqrueYWKnKP1IBuggaJDoUQ +ysj73XxPUnfFiuBuDVO+FEjLCrbB7WCfdli3KuueUJjHbcLyUh0no2ceMwIDAQAB +AoGAdJRieXNHL3uWBCtuBQfjFDHBv+UBdYKrVgcWtzG9GOxtilzZa618Ihq8txaE +odlMYacW3rVRlF/jRlDY4/hdChKO0PwffYzMmMklora8knG4Epi3LbMsVYCpbmvr +AYNKkvAnTbSF/PQMq8hTRnRf8cL8KU6e0uFFiOfx0pc+YyECQQDyod+VtRiOxWM1 +/FE2eZpihibAiB0HV9VJuXW23WwKh2fIqHs2oQXzjvzjiDV+LiZu51L21hQQcAeH +hMrNWRI/AkEAy4ulVjGybS0FqCvOX8UllJZBkN2z266HRag5a90TG0a0PEb0L+5Y +3rokNTZAzxdrCxkHaLRXQ9PE7b3c/1CPDQJAWNeW491swZJbMoBSSG0cb6kJdYQh +hPfPXHBxPuUy02QjR2ERxL4PTNB1nubYF3zUi9VeFo3qyN4Mk722+Jv9xwJADK8j +Gn/2Un9fvt8b+TPb56qFY3WtY584psqY6XPZYPXC/Y6eYO5Fc3u+DeLXnxAih4qD +v66dUYi82OPgBbkLcQJBAIFwHWNgrDZqSp8KBOldRUdwt2MkG3QzRiMziP8DczXF +xvdxH+AHPWl7yzOLas/kgx23ozQZcTzNqFjDmnSrJZQ= +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/master_config/ssl/ca/ca_pub.pem b/spec/fixtures/master_config/ssl/ca/ca_pub.pem new file mode 100644 index 0000000..2ba33aa --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/ca_pub.pem @@ -0,0 +1,5 @@ +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAMDqtuQjen9iauMTlk3C4I9F+pS3LCcEeoKWnaicGCqsFmIqK3ECZ0Qf +iWJ0YD0BuI2cGIyHR8LizmwoBRlSM+O/UjtUGqu55hYqco/UgG6CBokOhRDKyPvd +fE9Sd8WK4G4NU74USMsKtsHtYJ92WLcq655QmMdtwvJSHSejZx4zAgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/spec/fixtures/master_config/ssl/ca/inventory.txt b/spec/fixtures/master_config/ssl/ca/inventory.txt new file mode 100644 index 0000000..51ed4af --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/inventory.txt @@ -0,0 +1,5 @@ +# Inventory of signed certificates +# SERIAL NOT_BEFORE NOT_AFTER SUBJECT +0x0001 2011-08-12T20:00:08GMT 2016-08-10T20:00:08GMT /CN=Puppet CA: puppetmaster +0x0002 2011-08-12T20:00:08GMT 2016-08-10T20:00:08GMT /CN=puppetmaster +0x0003 2011-08-12T20:01:09GMT 2016-08-10T20:01:09GMT /CN=bob@mydomain.com diff --git a/spec/fixtures/master_config/ssl/ca/private/ca.pass b/spec/fixtures/master_config/ssl/ca/private/ca.pass new file mode 100644 index 0000000..234a5b9 --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/private/ca.pass @@ -0,0 +1 @@ +[Ie3rqTiZfur`@gLW5<P
\ No newline at end of file diff --git a/spec/fixtures/master_config/ssl/ca/serial b/spec/fixtures/master_config/ssl/ca/serial new file mode 100644 index 0000000..9df46a8 --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/serial @@ -0,0 +1 @@ +0004
\ No newline at end of file diff --git a/spec/fixtures/master_config/ssl/ca/signed/bob@mydomain.com.pem b/spec/fixtures/master_config/ssl/ca/signed/bob@mydomain.com.pem new file mode 100644 index 0000000..a649c8d --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/signed/bob@mydomain.com.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICVDCCAb2gAwIBAgIBAzANBgkqhkiG9w0BAQUFADAiMSAwHgYDVQQDDBdQdXBw +ZXQgQ0E6IHB1cHBldG1hc3RlcjAeFw0xMTA4MTIyMDAxMDlaFw0xNjA4MTAyMDAx +MDlaMBsxGTAXBgNVBAMMEGJvYkBteWRvbWFpbi5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBAL7+Idbd+eohxCXVXcICvo1IaqAzyjezWxfxMxoBF4mjdvwY +9RalRM5jItm9ThVwLMezcISYSNPI42Y70+9XIK/3f6OxnSMoB7kDKX9MvcbZkRAt +OfxDeWmAun+PXuH87VN1r7sViRSSB2dIxB3qjF1HNhAm0ocmSW+sZ3eul2lpAgMB +AAGjgaAwgZ0wOAYJYIZIAYb4QgENBCsWKVB1cHBldCBSdWJ5L09wZW5TU0wgR2Vu +ZXJhdGVkIENlcnRpZmljYXRlMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFFyA8pjL ++VkeCZHDRYCzKjzT4Cr9MAsGA1UdDwQEAwIFoDAnBgNVHSUEIDAeBggrBgEFBQcD +AQYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4GBAExa0zqinr4P +6ZmYOYxNtS1d+8YQdzjJXOnlXUURhERHfKMjvvJ125MO9i4TRF/isetRKz2w0OfO +Vfsdio9PSJf2Fh+/1V2r5eSvLbVenRwFnvyv/u/39ukQNbX5YSwXsl9QcWhqwtwF +dL1eEwuy2xmfxX6ZZRPDFDrideAtTEJy +-----END CERTIFICATE----- diff --git a/spec/fixtures/master_config/ssl/ca/signed/puppetmaster.pem b/spec/fixtures/master_config/ssl/ca/signed/puppetmaster.pem new file mode 100644 index 0000000..df900fc --- /dev/null +++ b/spec/fixtures/master_config/ssl/ca/signed/puppetmaster.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAiMSAwHgYDVQQDDBdQdXBw +ZXQgQ0E6IHB1cHBldG1hc3RlcjAeFw0xMTA4MTIyMDAwMDhaFw0xNjA4MTAyMDAw +MDhaMBcxFTATBgNVBAMMDHB1cHBldG1hc3RlcjCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEAzxm4O4OlcihWLbNHboKEmQ9cGlsG1vs0nkFtjLeF6eyi4cV6n8Af +1OacZV9aqzK8MrBQvYrpbpap2/kFSWx3vbhUVDz5ynsNzhu2Jt914XaJEcDmpDMU +UwQ+pg7JCSHocW2JilofAZdC1HrefLc570yYwxS//U/cw6N5MnskS2ECAwEAAaOB +oDCBnTA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1YnkvT3BlblNTTCBHZW5lcmF0 +ZWQgQ2VydGlmaWNhdGUwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUYSrVz684wuDJ +3awwcfFxMZGPkNQwCwYDVR0PBAQDAgWgMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwQwDQYJKoZIhvcNAQEFBQADgYEAEL5ZXS5TVzaI56HH +RhcGFLnvfl2BldsPuVuE5H6fqegRUyLpH7mXHCBt1Zn3IlUUdMLHOump4UHVjw/B +QPk6ihVjWcBTCU8xu4hKj54MixZFFIo2sJveMVdfIJ3lTQTmRpTHpIU7hYHwP46q +hLWywdpCBvhCxpK0YSi4FSDiYQ8= +-----END CERTIFICATE----- diff --git a/spec/fixtures/master_config/ssl/certs/bob@mydomain.com.pem b/spec/fixtures/master_config/ssl/certs/bob@mydomain.com.pem new file mode 100644 index 0000000..a649c8d --- /dev/null +++ b/spec/fixtures/master_config/ssl/certs/bob@mydomain.com.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICVDCCAb2gAwIBAgIBAzANBgkqhkiG9w0BAQUFADAiMSAwHgYDVQQDDBdQdXBw +ZXQgQ0E6IHB1cHBldG1hc3RlcjAeFw0xMTA4MTIyMDAxMDlaFw0xNjA4MTAyMDAx +MDlaMBsxGTAXBgNVBAMMEGJvYkBteWRvbWFpbi5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBAL7+Idbd+eohxCXVXcICvo1IaqAzyjezWxfxMxoBF4mjdvwY +9RalRM5jItm9ThVwLMezcISYSNPI42Y70+9XIK/3f6OxnSMoB7kDKX9MvcbZkRAt +OfxDeWmAun+PXuH87VN1r7sViRSSB2dIxB3qjF1HNhAm0ocmSW+sZ3eul2lpAgMB +AAGjgaAwgZ0wOAYJYIZIAYb4QgENBCsWKVB1cHBldCBSdWJ5L09wZW5TU0wgR2Vu +ZXJhdGVkIENlcnRpZmljYXRlMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFFyA8pjL ++VkeCZHDRYCzKjzT4Cr9MAsGA1UdDwQEAwIFoDAnBgNVHSUEIDAeBggrBgEFBQcD +AQYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4GBAExa0zqinr4P +6ZmYOYxNtS1d+8YQdzjJXOnlXUURhERHfKMjvvJ125MO9i4TRF/isetRKz2w0OfO +Vfsdio9PSJf2Fh+/1V2r5eSvLbVenRwFnvyv/u/39ukQNbX5YSwXsl9QcWhqwtwF +dL1eEwuy2xmfxX6ZZRPDFDrideAtTEJy +-----END CERTIFICATE----- diff --git a/spec/fixtures/master_config/ssl/certs/ca.pem b/spec/fixtures/master_config/ssl/certs/ca.pem new file mode 100644 index 0000000..7910b2b --- /dev/null +++ b/spec/fixtures/master_config/ssl/certs/ca.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIBATANBgkqhkiG9w0BAQUFADAiMSAwHgYDVQQDDBdQdXBw +ZXQgQ0E6IHB1cHBldG1hc3RlcjAeFw0xMTA4MTIyMDAwMDhaFw0xNjA4MTAyMDAw +MDhaMCIxIDAeBgNVBAMMF1B1cHBldCBDQTogcHVwcGV0bWFzdGVyMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDA6rbkI3p/YmrjE5ZNwuCPRfqUtywnBHqClp2o +nBgqrBZiKitxAmdEH4lidGA9AbiNnBiMh0fC4s5sKAUZUjPjv1I7VBqrueYWKnKP +1IBuggaJDoUQysj73XxPUnfFiuBuDVO+FEjLCrbB7WCfdli3KuueUJjHbcLyUh0n +o2ceMwIDAQABo3kwdzA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1YnkvT3BlblNT +TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUB14U4FLr4JVibAmnV+n+kw85ck4wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4GBAAZ3wF7R8DDhhT31OGQ/A+/F3L59nStqvW7AD7EabrTDPPNOVcvt/las +oi4MXiBuGPgS/xg+n4YBREaaYoF8BcGx5YMPY1XOPS0DItnDl44Wd+eHraD69kLl +l/4pPMlE5PQ21o82dph3i6B1E5zwLxhMXzh1mfvDcCIMmRdVobQm +-----END CERTIFICATE----- diff --git a/spec/fixtures/master_config/ssl/certs/puppetmaster.pem b/spec/fixtures/master_config/ssl/certs/puppetmaster.pem new file mode 100644 index 0000000..df900fc --- /dev/null +++ b/spec/fixtures/master_config/ssl/certs/puppetmaster.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAiMSAwHgYDVQQDDBdQdXBw +ZXQgQ0E6IHB1cHBldG1hc3RlcjAeFw0xMTA4MTIyMDAwMDhaFw0xNjA4MTAyMDAw +MDhaMBcxFTATBgNVBAMMDHB1cHBldG1hc3RlcjCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEAzxm4O4OlcihWLbNHboKEmQ9cGlsG1vs0nkFtjLeF6eyi4cV6n8Af +1OacZV9aqzK8MrBQvYrpbpap2/kFSWx3vbhUVDz5ynsNzhu2Jt914XaJEcDmpDMU +UwQ+pg7JCSHocW2JilofAZdC1HrefLc570yYwxS//U/cw6N5MnskS2ECAwEAAaOB +oDCBnTA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1YnkvT3BlblNTTCBHZW5lcmF0 +ZWQgQ2VydGlmaWNhdGUwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUYSrVz684wuDJ +3awwcfFxMZGPkNQwCwYDVR0PBAQDAgWgMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwQwDQYJKoZIhvcNAQEFBQADgYEAEL5ZXS5TVzaI56HH +RhcGFLnvfl2BldsPuVuE5H6fqegRUyLpH7mXHCBt1Zn3IlUUdMLHOump4UHVjw/B +QPk6ihVjWcBTCU8xu4hKj54MixZFFIo2sJveMVdfIJ3lTQTmRpTHpIU7hYHwP46q +hLWywdpCBvhCxpK0YSi4FSDiYQ8= +-----END CERTIFICATE----- diff --git a/spec/fixtures/master_config/ssl/crl.pem b/spec/fixtures/master_config/ssl/crl.pem new file mode 100644 index 0000000..90c7a03 --- /dev/null +++ b/spec/fixtures/master_config/ssl/crl.pem @@ -0,0 +1,8 @@ +-----BEGIN X509 CRL----- +MIH5MGQCAQEwDQYJKoZIhvcNAQEFBQAwIjEgMB4GA1UEAwwXUHVwcGV0IENBOiBw +dXBwZXRtYXN0ZXIXDTExMDgxMzIwMDAwOFoXDTE2MDgxMTIwMDAwOFqgDjAMMAoG +A1UdFAQDAgEAMA0GCSqGSIb3DQEBBQUAA4GBACBHLkJD4RvEV75ak8w468Kq7r5p +s87Fzs0Vj2fgqH/3GPoazwBD4R0TvqMb+NUuF0WnipexdQQRjaiERmqX9aIhRjRA +vs4ItdoxAvcgCzWs6cYm/e4SAAqY5lipfJqd+aRlQgzWaj6WDbFMVEKvqMXqM5wU +gGQRYVnXHbohA+/I +-----END X509 CRL----- diff --git a/spec/fixtures/master_config/ssl/private_keys/bob@mydomain.com.pem b/spec/fixtures/master_config/ssl/private_keys/bob@mydomain.com.pem new file mode 100644 index 0000000..dcf753a --- /dev/null +++ b/spec/fixtures/master_config/ssl/private_keys/bob@mydomain.com.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC+/iHW3fnqIcQl1V3CAr6NSGqgM8o3s1sX8TMaAReJo3b8GPUW +pUTOYyLZvU4VcCzHs3CEmEjTyONmO9PvVyCv93+jsZ0jKAe5Ayl/TL3G2ZEQLTn8 +Q3lpgLp/j17h/O1Tda+7FYkUkgdnSMQd6oxdRzYQJtKHJklvrGd3rpdpaQIDAQAB +AoGAWlPwhyFWd9/eV5JQlFgd7M3J99hmk+9Ubr9ZTrwjeKoBtPrMtxgUsZN7QQVh +74us8gmwdlVbZCZHPeufsTtAroYX9lru3he0oopn82Revc9OYll8hHoXjpLlhJyz +G40e1DQ5wO0z1WKxAiMvR06i56z03nCgJYp5RzVIx6As0bECQQD1HHuEHZU69C64 +NnDLlokoCMxs/zgjO/oFJbuit63vOc/Ua6oCciEt6xaxUUzVUcOK4VEcjwBKifiK +ua2Z7ZANAkEAx3owTktjSU2RleIE6aZq7gfgC2ZAjHiIwtFRq573dfCfbj1b2wKk +8GBudLsXNLZEEgJwJofljjXPAcPAebSLzQJBAM0hVCGCHITlHEBgl09aoViW3HaP +tSyPojMym/CWpgMiL9OHcxVu7GOgbjJhZtrT/cE5xgcPil/XTeDTefzrevUCQEW0 +X+7sDwzNa0M50Meo3JLC87poB8ROVlPleymCiiyPYdbO4Cs+2E4bFF38Bpbn3g+B +BJmiQUgZa3XNZpPg0D0CQGJocWKoiWBUcZSbEAaJtBCG+CO+Z8QQP62RpiiYck4W +VMn3s3fSS8cLdl65jSLM/dXA6YWZlwT/7Vl46ooGdDQ= +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/master_config/ssl/private_keys/puppetmaster.pem b/spec/fixtures/master_config/ssl/private_keys/puppetmaster.pem new file mode 100644 index 0000000..4de4dd2 --- /dev/null +++ b/spec/fixtures/master_config/ssl/private_keys/puppetmaster.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDPGbg7g6VyKFYts0dugoSZD1waWwbW+zSeQW2Mt4Xp7KLhxXqf +wB/U5pxlX1qrMrwysFC9iululqnb+QVJbHe9uFRUPPnKew3OG7Ym33XhdokRwOak +MxRTBD6mDskJIehxbYmKWh8Bl0LUet58tznvTJjDFL/9T9zDo3kyeyRLYQIDAQAB +AoGAIseQ9v2uxTMc9ePLtTVaC1JXB14OEgBx37nhKeaQKK7C0+OUKkvbjKeF0Ehp +M6L7lA+kH5C6jwXiVLzHNINwwDAqgx+n2O73BjKbqXSVNmdwirX+7nlqVKP6lR+E +xGYn3MMQhZe956qGJffHbEPQB3dx0mzIcvXSWCTwWaPfTgECQQD4gbARjcSiirGi +1GA8hMGzdkozt9yb2hbiF79NMGN/wbdYe4FxrmnzGkKXEBvkUFPlGu7GkEwNDtkF +3MqpsBbxAkEA1VhnLYoPpIDxupJRclwBFxEOBFQ3pkgA5/kxayoeAYLoiMRU6mfE +bhtA8lWoV9BFNvzVCSFS3Yvb1sXLgWrbcQJAfuu9wTlm9J1hnIhbno0vYTlJLKD7 +S55XkaIPUp0kNFv8CHUL58Ps2PzQhdb0Z+ee8aSPz1pjfUfYD+Z0m7YUAQJBAIvn +ohnB/MoS6PJBe3m0Dd7zhy6dj7TSaQ22Y4r0HqM9FoKBxXHGRJEz/B4uv+t+H7WU +jZukJ7QzQCISqYaf7XECQQCbmDO/lv8qdmLfApN2v1H7t9R7tXhEm8jK7OLZsoAT +QAwCPYh7YRnhpFE0gMUncg+lVu3CTrXtlBRDRgF68Lhx +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/master_config/ssl/public_keys/bob@mydomain.com.pem b/spec/fixtures/master_config/ssl/public_keys/bob@mydomain.com.pem new file mode 100644 index 0000000..3d46da5 --- /dev/null +++ b/spec/fixtures/master_config/ssl/public_keys/bob@mydomain.com.pem @@ -0,0 +1,5 @@ +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAL7+Idbd+eohxCXVXcICvo1IaqAzyjezWxfxMxoBF4mjdvwY9RalRM5j +Itm9ThVwLMezcISYSNPI42Y70+9XIK/3f6OxnSMoB7kDKX9MvcbZkRAtOfxDeWmA +un+PXuH87VN1r7sViRSSB2dIxB3qjF1HNhAm0ocmSW+sZ3eul2lpAgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/spec/fixtures/master_config/ssl/public_keys/puppetmaster.pem b/spec/fixtures/master_config/ssl/public_keys/puppetmaster.pem new file mode 100644 index 0000000..24c6361 --- /dev/null +++ b/spec/fixtures/master_config/ssl/public_keys/puppetmaster.pem @@ -0,0 +1,5 @@ +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAM8ZuDuDpXIoVi2zR26ChJkPXBpbBtb7NJ5BbYy3hensouHFep/AH9Tm +nGVfWqsyvDKwUL2K6W6Wqdv5BUlsd724VFQ8+cp7Dc4btibfdeF2iRHA5qQzFFME +PqYOyQkh6HFtiYpaHwGXQtR63ny3Oe9MmMMUv/1P3MOjeTJ7JEthAgMBAAE= +-----END RSA PUBLIC KEY----- diff --git a/spec/unit/puppet/parser/functions/get_certficiate_spec.rb b/spec/unit/puppet/parser/functions/get_certficiate_spec.rb new file mode 100755 index 0000000..2f5b583 --- /dev/null +++ b/spec/unit/puppet/parser/functions/get_certficiate_spec.rb @@ -0,0 +1,158 @@ +#!/usr/bin/env rspec + +require 'spec_helper' +require 'net/http' +require 'thread' +require 'fileutils' + +describe "the get_certificate function" do + include PuppetSpec::Files + + before :all do + @sslcert = File.read("spec/master_config/ssl/ca/signed/bob@mydomain.com.pem") + + Puppet::Parser::Functions.autoloader.loadall + end + + before :each do + @scope = Puppet::Parser::Scope.new + end + + it "should exist" do + Puppet::Parser::Functions.function("get_certificate").should == "function_get_certificate" + end + + it "should raise a ParseError if there is less than 1 argument" do + lambda { @scope.function_get_certificate([]) }.should(raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if the argument is empty" do + lambda { @scope.function_get_certificate([""]) }.should(raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if the argument contains strange characters" do + lambda { @scope.function_get_certificate(["%^&"]) }.should(raise_error(Puppet::ParseError)) + end + + it "should return a valid certificate if CA is local" do + Puppet[:ca] = true + Puppet[:signeddir] = "spec/master_config/ssl/ca/signed/" + result = @scope.function_get_certificate(["bob@mydomain.com"]) + result.should(eq(@sslcert)) + end + + it "should throw an error if CN is missing and CA is local" do + Puppet[:ca] = true + Puppet[:signeddir] = "spec/master_config/ssl/ca/signed/" + result = @scope.function_get_certificate(["missing@mydomain.com"]) + result.should(eq(:undef)) + end + + it "should return a valid certificate if CA is remote" do + Puppet[:ca] = false + Puppet[:ssldir] = "spec/master_config/ssl" + Puppet[:certname] = "puppetmaster" + + # Mock return + require 'ostruct' + http = OpenStruct.new + http.body = @sslcert + http.code = "200" + + # Intercept http start call + Net::HTTP.any_instance.expects(:start).returns(http) + + result = @scope.function_get_certificate(["bob@mydomain.com"]) + result.should(eq(@sslcert)) + end + + it "should throw an error if CN doesn't exist and CA is remote (stubbed)" do + Puppet[:ca] = false + Puppet[:ssldir] = "spec/master_config/ssl" + Puppet[:certname] = "puppetmaster" + + # Mock return + require 'ostruct' + http = OpenStruct.new + http.code = "404" + + # Intercept http start call + Net::HTTP.any_instance.expects(:start).returns(http) + + result = @scope.function_get_certificate(["missing@mydomain.com"]) + result.should(eq(:undef)) + end + + describe "real puppetmaster" do + before :all do + # Prepare fixture for puppetmaster + @master_tmp = tmpdir("get_certificate") + "/master_config" + FileUtils.cp_r("spec/master_config",@master_tmp) + + # Fork and start a puppetmaster + master_config = [ + "--config=/dev/null", + "--logdest=#{@master_tmp}/var/log/logfile", + "--confdir=#{@master_tmp}", + "--no-daemonize", + "--masterport=9354", + "--bindaddress=127.0.0.1", + "--vardir=#{@master_tmp}/var", + "--ssldir=#{@master_tmp}/ssl", + "--certname=puppetmaster", + "--user=#{ENV["USER"]}", +# "--debug", + ] + @master = Process.fork do + cmd = Puppet::Util::CommandLine.new("master", master_config) + Puppet::Plugins.on_application_intialization(:application_object => cmd) + app = Puppet::Application.find("master").new(cmd) + app.run + end + + # Wait 1 second for puppetmatser setup + # TODO: must be a better wait to check if master + # is listening first before proceeding. + sleep 1 + + Puppet::Parser::Functions.autoloader.loadall + end + + before :each do + # Standard puppet setup for each test + Puppet[:ca] = false + Puppet[:ssldir] = "#{@master_tmp}/ssl" + Puppet[:certname] = "puppetmaster" + Puppet[:ca_port] = "9354" + Puppet[:ca_server] = "127.0.0.1" + end + + after :all do + # Kill and reap puppetmaster + Process.kill("TERM", @master) + Process.wait(@master) + end + + it "should return a valid certificate if CA is remote" do + result = @scope.function_get_certificate(["bob@mydomain.com"]) + result.should(eq(@sslcert)) + end + + it "should throw an error if CN doesn't exist and CA is remote" do + result = @scope.function_get_certificate(["missing@mydomain.com"]) + result.should(eq(:undef)) + end + + it "should throw a connection refused message if CA is not running on port" do + Puppet[:ca_port] = "65111" + lambda { @scope.function_get_certificate(["missing@mydomain.com"]) }.should(raise_error(Puppet::Error)) + end + + it "should raise an exception if connection to CA times out" do + Puppet[:ca_server] = "10.254.254.254" + lambda { @scope.function_get_certificate(["missing@mydomain.com", { :conn_timeout => 1}]) }.should(raise_error(Puppet::Error)) + end + + end + +end diff --git a/spec/unit/puppet/parser/functions/get_pubkey_spec.rb b/spec/unit/puppet/parser/functions/get_pubkey_spec.rb new file mode 100755 index 0000000..e4cdd9f --- /dev/null +++ b/spec/unit/puppet/parser/functions/get_pubkey_spec.rb @@ -0,0 +1,54 @@ +#!/usr/bin/env rspec + +require 'spec_helper' +require 'net/http' +require 'thread' +require 'fileutils' + +describe "the get_pubkey function" do + include PuppetSpec::Files + + before :all do + Puppet::Parser::Functions.autoloader.loadall + end + + before :each do + @scope = Puppet::Parser::Scope.new + end + + it "should exist" do + Puppet::Parser::Functions.function("get_pubkey").should == "function_get_pubkey" + end + + it "should raise a ParseError if there is less than 1 argument" do + lambda { @scope.function_get_pubkey([]) }.should(raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if the argument is empty" do + lambda { @scope.function_get_pubkey([""]) }.should(raise_error(Puppet::ParseError)) + end + + it "should raise a ParseError if the argument contains strange characters" do + lambda { @scope.function_get_pubkey(["%^&"]) }.should(raise_error(Puppet::ParseError)) + end + + it "should return a valid certificate if CA is local" do + Puppet[:ca] = true + Puppet[:signeddir] = "spec/master_config/ssl/ca/signed/" + result = @scope.function_get_pubkey(["bob@mydomain.com"]) + result.should(eq(<<-EOS)) +-----BEGIN RSA PUBLIC KEY----- +MIGJAoGBAL7+Idbd+eohxCXVXcICvo1IaqAzyjezWxfxMxoBF4mjdvwY9RalRM5j +Itm9ThVwLMezcISYSNPI42Y70+9XIK/3f6OxnSMoB7kDKX9MvcbZkRAtOfxDeWmA +un+PXuH87VN1r7sViRSSB2dIxB3qjF1HNhAm0ocmSW+sZ3eul2lpAgMBAAE= +-----END RSA PUBLIC KEY----- +EOS + end + + it "should throw an error if CN is missing and CA is local" do + Puppet[:ca] = true + Puppet[:signeddir] = "spec/master_config/ssl/ca/signed/" + result = @scope.function_get_pubkey(["missing@mydomain.com"]) + result.should(eq(:undef)) + end +end |