File: //usr/lib/ruby/site_ruby/1.8/puppet/face/certificate.rb
require 'puppet/indirector/face'
require 'puppet/ssl/host'
Puppet::Indirector::Face.define(:certificate, '0.0.1') do
copyright "Puppet Labs", 2011
license "Apache 2 license; see COPYING"
summary "Provide access to the CA for certificate management."
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,
and its "generate" action submits a CSR rather than creating a
signed certificate.
EOT
option "--ca-location LOCATION" do
required
summary "Which certificate authority to use (local or remote)."
description <<-EOT
Whether to act on the local certificate authority or one provided by a
remote puppet master. Allowed values are 'local' and 'remote.'
This option is required.
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
action :generate do
summary "Generate a new certificate signing request."
arguments "<host>"
returns "Nothing."
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.
Puppet agent usually handles CSR submission automatically. This action is
primarily useful for requesting certificates for individual users and
external applications.
EOT
examples <<-EOT
Request a certificate for "somenode" from the site's CA:
$ puppet certificate generate somenode.puppetlabs.lan --ca-location remote
EOT
# Duplicate the option here explicitly to distinguish if it was passed arg
# us vs. set in the config file.
option "--dns-alt-names NAMES" do
summary "Additional DNS names to add to the certificate request"
description Puppet.settings.setting(:dns_alt_names).desc
end
when_invoked do |name, options|
host = Puppet::SSL::Host.new(name)
# We have a weird case where we have --dns_alt_names from Puppet, but
# this option is --dns-alt-names. Until we can get rid of --dns-alt-names
# or do a global tr('-', '_'), we have to support both.
# In supporting both, we'll use Puppet[:dns_alt_names] if specified on
# command line. We'll use options[:dns_alt_names] if specified on
# command line. If both specified, we'll fail.
# jeffweiss 17 april 2012
global_setting_from_cli = Puppet.settings.set_by_cli?(:dns_alt_names) == true
raise ArgumentError, "Can't specify both --dns_alt_names and --dns-alt-names" if options[:dns_alt_names] and global_setting_from_cli
options[:dns_alt_names] = Puppet[:dns_alt_names] if global_setting_from_cli
# If dns_alt_names are specified via the command line, we will always add
# them. Otherwise, they will default to the config file setting iff this
# cert is for the host we're running on.
host.generate_certificate_request(:dns_alt_names => options[:dns_alt_names])
end
end
action :list do
summary "List all certificate signing requests."
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
from the Ruby API.
EOT
when_invoked do |options|
Puppet::SSL::Host.indirection.search("*", {
:for => :certificate_request,
}).map { |h| h.inspect }
end
end
action :sign do
summary "Sign a certificate signing request for HOST."
arguments "<host>"
returns <<-EOT
A string that appears to be (but isn't) an x509 certificate.
EOT
examples <<-EOT
Sign somenode.puppetlabs.lan's certificate:
$ puppet certificate sign somenode.puppetlabs.lan --ca-location remote
EOT
option("--[no-]allow-dns-alt-names") do
summary "Whether or not to accept DNS alt names in the certificate request"
end
when_invoked do |name, options|
host = Puppet::SSL::Host.new(name)
if Puppet::SSL::Host.ca_location == :remote
if options[:allow_dns_alt_names]
raise ArgumentError, "--allow-dns-alt-names may not be specified with a remote CA"
end
host.desired_state = 'signed'
Puppet::SSL::Host.indirection.save(host)
else
# We have to do this case manually because we need to specify
# allow_dns_alt_names.
unless ca = Puppet::SSL::CertificateAuthority.instance
raise ArgumentError, "This process is not configured as a certificate authority"
end
ca.sign(name, options[:allow_dns_alt_names])
end
end
end
# Indirector action doc overrides
find = get_action(:find)
find.summary "Retrieve a certificate."
find.arguments "<host>"
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`.
EOT
destroy = get_action(:destroy)
destroy.summary "Delete a certificate."
destroy.arguments "<host>"
destroy.returns "Nothing."
destroy.description <<-EOT
Deletes a certificate. This action currently only works on the local CA.
EOT
get_action(:search).summary "Invalid for this subcommand."
get_action(:save).summary "Invalid for this subcommand."
get_action(:save).description "Invalid for this subcommand."
end