diff options
| author | Dominic Maraglia <dominic@puppetlabs.com> | 2011-08-03 15:43:20 -0700 |
|---|---|---|
| committer | Dominic Maraglia <dominic@puppetlabs.com> | 2011-08-03 15:43:20 -0700 |
| commit | e45f08bf1fef8842554ca0d8cb6fb13711e888e7 (patch) | |
| tree | 9bb476a0fe381d53060abc1f1c240cf1291b2ee4 /lib/puppet/face | |
| parent | a97c86e7d01384aa06f5d4d69da427fc355aebe7 (diff) | |
| parent | c833fde370d43023f52c8f2e11fd77e720d0f577 (diff) | |
Merge branch 'master' of github.com:puppetlabs/puppet
Diffstat (limited to 'lib/puppet/face')
| -rw-r--r-- | lib/puppet/face/ca.rb | 233 | ||||
| -rw-r--r-- | lib/puppet/face/certificate.rb | 26 | ||||
| -rw-r--r-- | lib/puppet/face/certificate_request.rb | 20 | ||||
| -rw-r--r-- | lib/puppet/face/certificate_revocation_list.rb | 12 | ||||
| -rw-r--r-- | lib/puppet/face/status.rb | 1 |
5 files changed, 263 insertions, 29 deletions
diff --git a/lib/puppet/face/ca.rb b/lib/puppet/face/ca.rb new file mode 100644 index 000000000..e643530f0 --- /dev/null +++ b/lib/puppet/face/ca.rb @@ -0,0 +1,233 @@ +require 'puppet/face' + +Puppet::Face.define(:ca, '0.1.0') do + copyright "Puppet Labs", 2011 + license "Apache 2 license; see COPYING" + + summary "Local Puppet Certificate Authority management." + + description <<TEXT +This provides local management of the Puppet Certificate Authority. + +You can use this subcommand to sign outstanding certificate requests, list +and manage local certificates, and inspect the state of the CA. +TEXT + + action :list do + summary "List certificates and/or certificate requests." + + description <<-end +This will list the current certificates and certificate signing requests +in the Puppet CA. You will also get the fingerprint, and any certificate +verification failure reported. + end + + option "--[no-]all" do + summary "Include all certificates and requests." + end + + option "--[no-]pending" do + summary "Include pending certificate signing requests." + end + + option "--[no-]signed" do + summary "Include signed certificates." + end + + option "--subject PATTERN" do + summary "Only list if the subject matches PATTERN." + + description <<TEXT +Only include certificates or requests where subject matches PATTERN. + +PATTERN is interpreted as a regular expression, allowing complex +filtering of the content. +TEXT + end + + when_invoked do |options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + pattern = options[:subject].nil? ? nil : + Regexp.new(options[:subject], Regexp::IGNORECASE) + + pending = options[:pending].nil? ? options[:all] : options[:pending] + signed = options[:signed].nil? ? options[:all] : options[:signed] + + # By default we list pending, so if nothing at all was requested... + unless pending or signed then pending = true end + + hosts = [] + + pending and hosts += ca.waiting? + signed and hosts += ca.list + + pattern and hosts = hosts.select {|hostname| pattern.match hostname } + + hosts.sort.map {|host| Puppet::SSL::Host.new(host) } + end + + when_rendering :console do |hosts| + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + length = hosts.map{|x| x.name.length }.max + 1 + + hosts.map do |host| + name = host.name.ljust(length) + if host.certificate_request then + " #{name} (#{host.certificate_request.fingerprint})" + else + begin + ca.verify(host.certificate) + "+ #{name} (#{host.certificate.fingerprint})" + rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => e + "- #{name} (#{host.certificate.fingerprint}) (#{e.to_s})" + end + end + end.join("\n") + end + end + + action :destroy do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + ca.destroy host + end + end + + action :revoke do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.revoke host + rescue ArgumentError => e + # This is a bit naff, but it makes the behaviour consistent with the + # destroy action. The underlying tools could be nicer for that sort + # of thing; they have fairly inconsistent reporting of failures. + raise unless e.to_s =~ /Could not find a serial number for / + "Nothing was revoked" + end + end + end + + action :generate do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.generate host + rescue RuntimeError => e + if e.to_s =~ /already has a requested certificate/ + "#{host} already has a certificate request; use sign instead" + else + raise + end + rescue ArgumentError => e + if e.to_s =~ /A Certificate already exists for / + "#{host} already has a certificate" + else + raise + end + end + end + end + + action :sign do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.sign host + rescue ArgumentError => e + if e.to_s =~ /Could not find certificate request/ + e.to_s + else + raise + end + end + end + end + + action :print do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + ca.print host + end + end + + action :fingerprint do + option "--digest ALGORITHM" do + summary "The hash algorithm to use when displaying the fingerprint" + end + + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + # I want the default from the CA, not to duplicate it, but passing + # 'nil' explicitly means that we don't get that. This works... + if options.has_key? :digest + ca.fingerprint host, options[:digest] + else + ca.fingerprint host + end + rescue ArgumentError => e + raise unless e.to_s =~ /Could not find a certificate or csr for/ + nil + end + end + end + + action :verify do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.verify host + { :host => host, :valid => true } + rescue ArgumentError => e + raise unless e.to_s =~ /Could not find a certificate for/ + { :host => host, :valid => false, :error => e.to_s } + rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => e + { :host => host, :valid => false, :error => e.to_s } + end + end + + when_rendering :console do |value| + if value[:valid] + nil + else + "Could not verify #{value[:host]}: #{value[:error]}" + end + end + end +end diff --git a/lib/puppet/face/certificate.rb b/lib/puppet/face/certificate.rb index 9a306da37..8019b6bea 100644 --- a/lib/puppet/face/certificate.rb +++ b/lib/puppet/face/certificate.rb @@ -6,7 +6,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do license "Apache 2 license; see COPYING" summary "Provide access to the CA for certificate management." - description <<-'EOT' + description <<-EOT This subcommand interacts with a local or remote Puppet certificate authority. Currently, its behavior is not a full superset of `puppet cert`; specifically, it is unable to mimic puppet cert's "clean" option, @@ -15,8 +15,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do EOT option "--ca-location LOCATION" do + required summary "Which certificate authority to use (local or remote)." - description <<-'EOT' + description <<-EOT Whether to act on the local certificate authority or one provided by a remote puppet master. Allowed values are 'local' and 'remote.' @@ -24,6 +25,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do EOT before_action do |action, args, options| + unless [:remote, :local, :only].include? options[:ca_location].to_sym + raise ArgumentError, "Valid values for ca-location are 'remote', 'local', 'only'." + end Puppet::SSL::Host.ca_location = options[:ca_location].to_sym end end @@ -32,7 +36,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do summary "Generate a new certificate signing request." arguments "<host>" returns "Nothing." - description <<-'EOT' + description <<-EOT Generates and submits a certificate signing request (CSR) for the specified host. This CSR will then have to be signed by a user with the proper authorization on the certificate authority. @@ -41,7 +45,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do primarily useful for requesting certificates for individual users and external applications. EOT - examples <<-'EOT' + examples <<-EOT Request a certificate for "somenode" from the site's CA: $ puppet certificate generate somenode.puppetlabs.lan --ca-location remote @@ -56,7 +60,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do action :list do summary "List all certificate signing requests." - returns <<-'EOT' + returns <<-EOT An array of #inspect output from CSR objects. This output is currently messy, but does contain the names of nodes requesting certificates. This action returns #inspect strings even when used @@ -73,10 +77,10 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do action :sign do summary "Sign a certificate signing request for HOST." arguments "<host>" - returns <<-'EOT' + returns <<-EOT A string that appears to be (but isn't) an x509 certificate. EOT - examples <<-'EOT' + examples <<-EOT Sign somenode.puppetlabs.lan's certificate: $ puppet certificate sign somenode.puppetlabs.lan --ca-location remote @@ -93,9 +97,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do find = get_action(:find) find.summary "Retrieve a certificate." find.arguments "<host>" - find.returns <<-'EOT' - An x509 SSL certificate. You will usually want to render this as a - string (--render-as s). + find.render_as = :s + find.returns <<-EOT + An x509 SSL certificate. Note that this action has a side effect of caching a copy of the certificate in Puppet's `ssldir`. @@ -105,7 +109,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do destroy.summary "Delete a certificate." destroy.arguments "<host>" destroy.returns "Nothing." - destroy.description <<-'EOT' + destroy.description <<-EOT Deletes a certificate. This action currently only works on the local CA. EOT diff --git a/lib/puppet/face/certificate_request.rb b/lib/puppet/face/certificate_request.rb index 774821f12..cf342d51a 100644 --- a/lib/puppet/face/certificate_request.rb +++ b/lib/puppet/face/certificate_request.rb @@ -5,7 +5,7 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do license "Apache 2 license; see COPYING" summary "Manage certificate requests." - description <<-'EOT' + description <<-EOT This subcommand retrieves and submits certificate signing requests (CSRs). EOT @@ -15,14 +15,12 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do find = get_action(:find) find.summary "Retrieve a single CSR." find.arguments "<host>" - find.returns <<-'EOT' + find.render_as = :s + find.returns <<-EOT A single certificate request. When used from the Ruby API, returns a Puppet::SSL::CertificateRequest object. - - RENDERING ISSUES: In most cases, you will want to render this as a string - ('--render-as s'). EOT - find.examples <<-'EOT' + find.examples <<-EOT Retrieve a single CSR from the puppet master's CA: $ puppet certificate_request find somenode.puppetlabs.lan --terminus rest @@ -31,10 +29,10 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do search = get_action(:search) search.summary "Retrieve all outstanding CSRs." search.arguments "<dummy_text>" - search.returns <<-'EOT' - A list of certificate requests; be sure to to render this as a string - ('--render-as s'). When used from the Ruby API, returns an array of - Puppet::SSL::CertificateRequest objects. + search.render_as = :s + search.returns <<-EOT + A list of certificate requests. When used from the Ruby API, returns an + array of Puppet::SSL::CertificateRequest objects. EOT search.short_description <<-EOT Retrieves all outstanding certificate signing requests. Due to a known bug, @@ -44,7 +42,7 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do Although this action always returns all CSRs, it requires a dummy search key; this is a known bug. EOT - search.examples <<-'EOT' + search.examples <<-EOT Retrieve all CSRs from the local CA (similar to 'puppet cert list'): $ puppet certificate_request search x --terminus ca diff --git a/lib/puppet/face/certificate_revocation_list.rb b/lib/puppet/face/certificate_revocation_list.rb index f58368f75..022323b29 100644 --- a/lib/puppet/face/certificate_revocation_list.rb +++ b/lib/puppet/face/certificate_revocation_list.rb @@ -5,7 +5,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do license "Apache 2 license; see COPYING" summary "Manage the list of revoked certificates." - description <<-'EOT' + description <<-EOT This subcommand is primarily for retrieving the certificate revocation list from the CA. EOT @@ -13,12 +13,10 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do find = get_action(:find) find.summary "Retrieve the certificate revocation list." find.arguments "<dummy_text>" - find.returns <<-'EOT' + find.render_as = :s + find.returns <<-EOT The certificate revocation list. When used from the Ruby API: returns an OpenSSL::X509::CRL object. - - RENDERING ISSUES: this should usually be rendered as a string - ('--render-as s'). EOT find.short_description <<-EOT Retrieves the certificate revocation list. Due to a known bug, this action @@ -28,7 +26,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do Although this action always returns the CRL from the specified terminus, it requires a dummy argument; this is a known bug. EOT - find.examples <<-'EXAMPLES' + find.examples <<-EXAMPLES Retrieve a copy of the puppet master's CRL: $ puppet certificate_revocation_list find crl --terminus rest @@ -38,7 +36,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do destroy.summary "Delete the certificate revocation list." destroy.arguments "<dummy_text>" destroy.returns "Nothing." - destroy.description <<-'EOT' + destroy.description <<-EOT Deletes the certificate revocation list. This cannot be done over REST, but it is possible to delete the locally cached copy or the local CA's copy of the CRL. diff --git a/lib/puppet/face/status.rb b/lib/puppet/face/status.rb index bdb0c4d26..e8c87e98d 100644 --- a/lib/puppet/face/status.rb +++ b/lib/puppet/face/status.rb @@ -12,6 +12,7 @@ Puppet::Indirector::Face.define(:status, '0.0.1') do get_action(:search).summary "Invalid for this subcommand." find = get_action(:find) + find.default = true find.summary "Check status of puppet master server." find.arguments "<dummy_text>" find.returns <<-'EOT' |
