summaryrefslogtreecommitdiff
path: root/code/environments/production/modules/certregen/lib
diff options
context:
space:
mode:
authorMike Gabriel <mike.gabriel@das-netzwerkteam.de>2022-02-08 11:51:10 +0100
committerMike Gabriel <mike.gabriel@das-netzwerkteam.de>2022-02-08 11:51:10 +0100
commit74e2687fa98ea5ba25fbe07c038253d1fc14584e (patch)
treea390be820f6b3bd91f849acb41415d610e41b186 /code/environments/production/modules/certregen/lib
parent49c9d906fd74f51484977736d78f16095d4f1a69 (diff)
downloadpuppet.KATH-74e2687fa98ea5ba25fbe07c038253d1fc14584e.tar.gz
puppet.KATH-74e2687fa98ea5ba25fbe07c038253d1fc14584e.tar.bz2
puppet.KATH-74e2687fa98ea5ba25fbe07c038253d1fc14584e.zip
code/environments/production/modules: Drop certregen module again.
Diffstat (limited to 'code/environments/production/modules/certregen/lib')
-rw-r--r--code/environments/production/modules/certregen/lib/facter/has_puppet.rb10
-rw-r--r--code/environments/production/modules/certregen/lib/facter/hostcrl.rb4
-rw-r--r--code/environments/production/modules/certregen/lib/facter/localcacert.rb4
-rw-r--r--code/environments/production/modules/certregen/lib/puppet/application/certregen.rb4
-rw-r--r--code/environments/production/modules/certregen/lib/puppet/face/certregen.rb205
-rw-r--r--code/environments/production/modules/certregen/lib/puppet/feature/chloride.rb3
-rw-r--r--code/environments/production/modules/certregen/lib/puppet/functions/is_classified_with.rb9
-rw-r--r--code/environments/production/modules/certregen/lib/puppet/parser/functions/is_classified_with.rb4
-rw-r--r--code/environments/production/modules/certregen/lib/puppet_x/certregen/ca.rb137
-rw-r--r--code/environments/production/modules/certregen/lib/puppet_x/certregen/certificate.rb42
-rw-r--r--code/environments/production/modules/certregen/lib/puppet_x/certregen/crl.rb56
-rw-r--r--code/environments/production/modules/certregen/lib/puppet_x/certregen/util.rb27
12 files changed, 0 insertions, 505 deletions
diff --git a/code/environments/production/modules/certregen/lib/facter/has_puppet.rb b/code/environments/production/modules/certregen/lib/facter/has_puppet.rb
deleted file mode 100644
index 05f2e80..0000000
--- a/code/environments/production/modules/certregen/lib/facter/has_puppet.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-Facter.add(:has_puppet) do
- setcode do
- begin
- require 'puppet'
- true
- rescue LoadError
- false
- end
- end
-end
diff --git a/code/environments/production/modules/certregen/lib/facter/hostcrl.rb b/code/environments/production/modules/certregen/lib/facter/hostcrl.rb
deleted file mode 100644
index 1d69a66..0000000
--- a/code/environments/production/modules/certregen/lib/facter/hostcrl.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Facter.add(:hostcrl) do
- confine :has_puppet => true
- setcode { Puppet[:hostcrl] }
-end
diff --git a/code/environments/production/modules/certregen/lib/facter/localcacert.rb b/code/environments/production/modules/certregen/lib/facter/localcacert.rb
deleted file mode 100644
index 278ca8b..0000000
--- a/code/environments/production/modules/certregen/lib/facter/localcacert.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Facter.add(:localcacert) do
- confine :has_puppet => true
- setcode { Puppet[:localcacert] }
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet/application/certregen.rb b/code/environments/production/modules/certregen/lib/puppet/application/certregen.rb
deleted file mode 100644
index 73d6ca2..0000000
--- a/code/environments/production/modules/certregen/lib/puppet/application/certregen.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'puppet/application/face_base'
-
-class Puppet::Application::Certregen < Puppet::Application::FaceBase
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet/face/certregen.rb b/code/environments/production/modules/certregen/lib/puppet/face/certregen.rb
deleted file mode 100644
index 24c4b30..0000000
--- a/code/environments/production/modules/certregen/lib/puppet/face/certregen.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-require 'puppet/face'
-require 'puppet_x/certregen/ca'
-require 'puppet_x/certregen/certificate'
-require 'puppet_x/certregen/crl'
-require 'puppet/feature/chloride'
-
-Puppet::Face.define(:certregen, '0.1.0') do
- copyright "Puppet", 2016
- summary "Regenerate the Puppet CA and client certificates"
-
- description <<-EOT
- This subcommand provides tools for monitoring the health of the Puppet CA, regenerating
- expiring CA certificates, and remediation for expired CA certificates.
- EOT
-
- action(:ca) do
- summary "Refresh the Puppet CA certificate and CRL"
-
- option('--ca_serial SERIAL') do
- summary 'The serial number (in hexadecimal) of the CA to rotate.'
- end
-
- when_invoked do |opts|
- cert = Puppet::Face[:certregen, :current].cacert(:ca_serial => opts[:ca_serial])
- crl = Puppet::Face[:certregen, :current].crl()
- [cert, crl]
- end
-
- when_rendering :console do |(cert, crl)|
- "CA expiration is now #{cert.content.not_after}\n" + \
- "CRL next update is now #{crl.content.next_update}"
- end
- end
-
- action(:cacert) do
- summary "Regenerate the Puppet CA certificate"
-
- description <<-EOT
- This subcommand generates a new CA certificate that can replace the existing CA certificate.
- The new CA certificate uses the same subject as the current CA certificate and reuses the
- key pair associated with the current CA certificate, so all certificates signed by the old
- CA certificate will remain valid.
- EOT
-
- option('--ca_serial SERIAL') do
- summary 'The serial number (in hexadecimal) of the CA to rotate.'
- end
-
- when_invoked do |opts|
- ca = PuppetX::Certregen::CA.setup
-
- current_ca_serial = ca.host.certificate.content.serial.to_s(16)
- if opts[:ca_serial].nil?
- raise "The serial number of the CA certificate to rotate must be provided. If you " \
- "are sure that you want to rotate the CA certificate, rerun this command with " \
- "--ca_serial #{current_ca_serial}"
- elsif opts[:ca_serial] != current_ca_serial
- raise "The serial number of the current CA certificate (#{current_ca_serial}) "\
- "does not match the serial number given on the command line (#{opts[:ca_serial]}). "\
- "If you are sure that you want to rotate the CA certificate, rerun this command with "\
- "--ca_serial #{current_ca_serial}"
- end
-
- PuppetX::Certregen::CA.backup
- PuppetX::Certregen::CA.regenerate(ca)
- Puppet::SSL::Certificate.indirection.find(Puppet::SSL::CA_NAME)
- end
-
- when_rendering(:console) do |cert|
- "CA expiration is now #{cert.content.not_after}"
- end
- end
-
- action(:crl) do
- summary 'Update the lastUpdate and nextUpdate field for the CA CRL'
-
- when_invoked do |opts|
- ca = PuppetX::Certregen::CA.setup
- PuppetX::Certregen::CRL.refresh(ca)
- end
-
- when_rendering(:console) do |crl|
- "CRL next update is now #{crl.content.next_update}"
- end
- end
-
- action(:healthcheck) do
- summary "Check for expiring certificates"
-
- description <<-EOT
- This subcommand checks for certificates that are nearing or past expiration.
- EOT
-
- option('--all') do
- summary "Report certificate expiry for all nodes, including nodes that aren't near expiration."
- end
-
- when_invoked do |opts|
- ca = PuppetX::Certregen::CA.setup
-
- certs = Puppet::SSL::Certificate.indirection.search('*').select do |cert|
- opts[:all] || PuppetX::Certregen::Certificate.expiring?(cert)
- end
-
- cacert = ca.host.certificate
- certs << cacert if (opts[:all] || PuppetX::Certregen::Certificate.expiring?(cacert))
-
- certs.sort { |a, b| a.content.not_after <=> b.content.not_after }
- end
-
- when_rendering :console do |certs|
- if certs.empty?
- "No certificates are approaching expiration."
- else
- certs.map do |cert|
- str = "#{cert.name.inspect} #{cert.digest.to_s}\n"
- expiry = PuppetX::Certregen::Certificate.expiry(cert)
- str << "Status: #{expiry[:status]}\n"
- str << "Expiration date: #{expiry[:expiration_date]}\n"
- if expiry[:expires_in]
- str << "Expires in: #{expiry[:expires_in]}\n"
- end
- str
- end
- end
- end
-
- when_rendering :pson do |certs|
- certs.map do |cert|
- {
- :name => cert.name,
- :digest => cert.digest.to_s,
- :expiry => PuppetX::Certregen::Certificate.expiry(cert)
- }
- end
- end
-
- when_rendering :yaml do |certs|
- certs.map do |cert|
- {
- :name => cert.name,
- :digest => cert.digest.to_s,
- :expiry => PuppetX::Certregen::Certificate.expiry(cert)
- }
- end
- end
- end
-
- action(:redistribute) do
- summary "Redistribute the regenerated CA certificate and CRL to nodes in PuppetDB"
-
- description <<-EOT
- Redistribute the regenerated CA certificate and CRL to active nodes in PuppetDB. This command is
- only necessary if the CA certificate is expired and a new CA certificate needs to be manually
- distributed via SSH.
-
- This subcommand depends on the `chloride` gem, which is not included with this Puppet face.
-
- Distributing the CA certificate via SSH requires either a private ssh key (given by the
- `--ssh_key_file` flag) or entering the password when prompted. If password auth is used,
- the `highline` gem should be installed so that the entered password is not echoed to the
- terminal.
- EOT
-
- option('--username USER') do
- summary "The username to use when logging into the remote machine"
- end
-
- option('--ssh_key_file FILE') do
- summary "The SSH key file to use for authentication"
- default_to { "~/.ssh/id_rsa" }
- end
-
- when_invoked do |opts|
- unless Puppet.features.chloride?
- raise "Unable to distribute CA certificate: the chloride gem is not available."
- end
-
- config = {}
-
- config.merge!(username: opts[:username]) if opts[:username]
- config.merge!(ssh_key_file: File.expand_path(opts[:ssh_key_file])) if opts[:ssh_key_file]
-
- ca = PuppetX::Certregen::CA.setup
- cacert = ca.host.certificate
- if PuppetX::Certregen::Certificate.expiring?(cacert)
- Puppet.err "Refusing to distribute CA certificate: certificate is pending expiration."
- exit 1
- end
-
- rv = {succeeded: [], failed: []}
- PuppetX::Certregen::CA.certnames.each do |certname|
- begin
- PuppetX::Certregen::CA.distribute(certname, config)
- rv[:succeeded] << certname
- rescue => e
- Puppet.log_exception(e)
- rv[:failed] << certname
- end
- end
-
- rv
- end
- end
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet/feature/chloride.rb b/code/environments/production/modules/certregen/lib/puppet/feature/chloride.rb
deleted file mode 100644
index ea777cb..0000000
--- a/code/environments/production/modules/certregen/lib/puppet/feature/chloride.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-require 'puppet/util/feature'
-
-Puppet.features.add(:chloride, libs: 'chloride')
diff --git a/code/environments/production/modules/certregen/lib/puppet/functions/is_classified_with.rb b/code/environments/production/modules/certregen/lib/puppet/functions/is_classified_with.rb
deleted file mode 100644
index 0f6d54b..0000000
--- a/code/environments/production/modules/certregen/lib/puppet/functions/is_classified_with.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-Puppet::Functions.create_function(:is_classified_with) do
- dispatch :is_classified_with do
- param 'String', :str
- end
-
- def is_classified_with(str)
- closure_scope.find_global_scope.compiler.node.classes.keys.include?(str.to_s)
- end
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet/parser/functions/is_classified_with.rb b/code/environments/production/modules/certregen/lib/puppet/parser/functions/is_classified_with.rb
deleted file mode 100644
index 1e17887..0000000
--- a/code/environments/production/modules/certregen/lib/puppet/parser/functions/is_classified_with.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Puppet::Parser::Functions::newfunction(:is_classified_with, :arity => 1,
- :type => :rvalue) do |(str)|
- compiler.node.classes.keys.include?(str)
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet_x/certregen/ca.rb b/code/environments/production/modules/certregen/lib/puppet_x/certregen/ca.rb
deleted file mode 100644
index c9e7457..0000000
--- a/code/environments/production/modules/certregen/lib/puppet_x/certregen/ca.rb
+++ /dev/null
@@ -1,137 +0,0 @@
-require 'securerandom'
-require 'shellwords'
-
-require 'puppet'
-require 'puppet/util/execution'
-require 'puppet/util/package'
-
-require 'puppet/feature/chloride'
-
-module PuppetX
- module Certregen
- module CA
- module_function
-
- def setup
- Puppet::SSL::Host.ca_location = :only
- Puppet.settings.preferred_run_mode = "master"
-
- if !Puppet::SSL::CertificateAuthority.ca?
- raise "Unable to set up CA: this node is not a CA server."
- end
-
- if Puppet::SSL::Certificate.indirection.find('ca').nil?
- raise "Unable to set up CA: the CA certificate is not present."
- end
-
- Puppet::SSL::CertificateAuthority.instance
- end
-
- def backup
- cacert_backup_path = File.join(Puppet[:cadir], "ca_crt.#{Time.now.to_i}.pem")
- Puppet.notice("Backing up current CA certificate to #{cacert_backup_path}")
- FileUtils.cp(Puppet[:cacert], cacert_backup_path)
- end
-
- # Generate an updated CA certificate with the same subject as the existing CA certificate
- # and synchronize the new CA certificate with the local CA certificate.
- def regenerate(ca, cert = Puppet::SSL::Certificate.indirection.find("ca"))
- Puppet[:ca_name] = cert.content.subject.to_a[0][1]
-
- request = Puppet::SSL::CertificateRequest.new(Puppet::SSL::Host::CA_NAME)
- request.generate(ca.host.key)
- PuppetX::Certregen::CA.sign(ca, Puppet::SSL::CA_NAME,
- {allow_dns_alt_names: false, self_signing_csr: request})
- FileUtils.cp(Puppet[:cacert], Puppet[:localcacert])
- end
-
- # Copy the current CA certificate and CRL to the given host.
- #
- # @note Only Linux systems are supported and requires that the localcacert/hostcrl setting on the
- # given host is the default path.
- #
- # @param [String] hostname The host to copy the CA cert to
- # @param [Hash] config the Chloride host config
- # @return [void]
- def distribute(hostname, config)
- host = Chloride::Host.new(hostname, config)
- host.ssh_connect
-
- Puppet.debug("SSH status for #{hostname}: #{host.ssh_status}")
-
- log_events = lambda do |event|
- event.data[:messages].each do |data|
- Puppet.info "[#{data.severity}:#{data.hostname}]: #{data.message.inspect}"
- end
- end
-
- distribute_cacert(host, log_events)
- distribute_crl(host, log_events)
- end
-
- def distribute_cacert(host, blk)
- src = Puppet[:cacert]
- dst ='/etc/puppetlabs/puppet/ssl/certs/ca.pem' # @todo: query node for localcacert
- distribute_file(host, src, dst, blk)
- end
-
- def distribute_crl(host, blk)
- src = Puppet[:cacrl]
- dst ='/etc/puppetlabs/puppet/ssl/crl.pem' # @todo: query node for hostcrl
- distribute_file(host, src, dst, blk)
- end
-
- def distribute_file(host, src, dst, blk)
- tmp = "#{File.basename(src)}.tmp.#{SecureRandom.uuid}"
-
- copy_action = Chloride::Action::FileCopy.new(to_host: host, from: src, to: tmp)
- copy_action.go(&blk)
- if copy_action.success?
- Puppet.info "Copied #{src} to #{host.hostname}:#{tmp}"
- else
- raise "Failed to copy #{src} to #{host.hostname}:#{tmp}: #{copy_action.status}"
- end
-
- move_action = Chloride::Action::Execute.new(host: host, cmd: "cp #{tmp} #{dst}", sudo: true)
- move_action.go(&blk)
-
- if move_action.success?
- Puppet.info "Updated #{host.hostname}:#{dst}"
- else
- raise "Failed to copy #{tmp} to #{host.hostname}:#{dst}"
- end
-
- end
-
-
- # Enumerate Puppet nodes without relying on PuppetDB
- #
- # If the Puppet CA certificate has expired we cannot rely on PuppetDB working
- # or being able to connect to Postgres via the network. In order to access
- # this information while the CA is in a degraded state we perform the query
- # directly via a local psql call.
- def certnames
- psql = '/opt/puppetlabs/server/bin/psql -d pe-puppetdb --pset format=unaligned --pset t=on -c %s'
- query = 'SELECT certname FROM certnames WHERE deactivated IS NULL AND expired IS NULL;'
- cmd = psql % Shellwords.escape(query)
- Puppet::Util::Execution.execute(cmd,
- uid: 'pe-postgres',
- gid: 'pe-postgres').split("\n")
-
- end
-
- # Abstract API changes for CA cert signing
- #
- # @param ca [Puppet::SSL::CertificateAuthority]
- # @param hostname [String]
- # @param options [Hash<Symbol, Object>]
- def sign(ca, hostname, options)
- if Puppet::Util::Package.versioncmp(Puppet::PUPPETVERSION, "4.6.0") != -1
- ca.sign(hostname, options)
- else
- ca.sign(hostname, options[:allow_dns_alt_names], options[:self_signing_csr])
- end
- end
- end
- end
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet_x/certregen/certificate.rb b/code/environments/production/modules/certregen/lib/puppet_x/certregen/certificate.rb
deleted file mode 100644
index 56ad970..0000000
--- a/code/environments/production/modules/certregen/lib/puppet_x/certregen/certificate.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require 'puppet_x/certregen/util'
-
-module PuppetX
- module Certregen
- module Certificate
- module_function
-
- # @param cert [Puppet::SSL::Certificate]
- # @return [Hash<Symbol, String>]
- def expiry(cert)
- if cert.content.not_after < Time.now
- status = :expired
- elsif expiring?(cert)
- status = :expiring
- else
- status = :ok
- end
-
- data = {
- :status => status,
- :expiration_date => cert.content.not_after
- }
-
- if status != :expired
- data[:expires_in] = PuppetX::Certregen::Util.duration(cert.content.not_after - Time.now)
- end
-
- data
- end
-
- # Is this certificate expiring or expired?
- #
- # @param cert [Puppet::SSL::Certificate]
- # @param percent [Integer]
- def expiring?(cert, percent = 10)
- remaining = cert.content.not_after - Time.now
- lifetime = cert.content.not_after - (cert.content.not_before + 86400)
- remaining / lifetime < (percent / 100.0)
- end
- end
- end
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet_x/certregen/crl.rb b/code/environments/production/modules/certregen/lib/puppet_x/certregen/crl.rb
deleted file mode 100644
index e82f929..0000000
--- a/code/environments/production/modules/certregen/lib/puppet_x/certregen/crl.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'fileutils'
-require 'openssl'
-
-module PuppetX
- module Certregen
- # @api private
- # @see {Puppet::SSL::CertificateRevocationList}
- module CRL
- module_function
-
- FIVE_YEARS = 5 * 365*24*60*60
-
- def refresh(ca)
- crl = ca.crl
- crl_content = crl.content
- update_to_next_crl_number(crl_content)
- update_valid_time_range_to_start_at(crl_content, Time.now)
- sign_with(crl_content, ca.host.key.content)
- Puppet::SSL::CertificateRevocationList.indirection.save(crl)
- FileUtils.cp(Puppet[:cacrl], Puppet[:hostcrl])
- Puppet::SSL::CertificateRevocationList.indirection.find("ca")
- end
-
- # @api private
- def update_valid_time_range_to_start_at(crl_content, time)
- # The CRL is not valid if the time of checking == the time of last_update.
- # So to have it valid right now we need to say that it was updated one second ago.
- crl_content.last_update = time - 1
- crl_content.next_update = time + FIVE_YEARS
- end
-
- # @api private
- def update_to_next_crl_number(crl_content)
- crl_content.extensions = with_next_crl_number_from(crl_content, crl_content.extensions)
- end
-
- # @api private
- def with_next_crl_number_from(crl_content, existing_extensions)
- existing_crl_num = existing_extensions.find { |e| e.oid == 'crlNumber' }
- new_crl_num = existing_crl_num ? existing_crl_num.value.to_i + 1 : 0
- extensions_without_crl_num = existing_extensions.reject { |e| e.oid == 'crlNumber' }
- extensions_without_crl_num + [crl_number_of(new_crl_num)]
- end
-
- # @api private
- def crl_number_of(number)
- OpenSSL::X509::Extension.new('crlNumber', OpenSSL::ASN1::Integer(number))
- end
-
- # @api private
- def sign_with(crl_content, cakey)
- crl_content.sign(cakey, OpenSSL::Digest::SHA1.new)
- end
- end
- end
-end
diff --git a/code/environments/production/modules/certregen/lib/puppet_x/certregen/util.rb b/code/environments/production/modules/certregen/lib/puppet_x/certregen/util.rb
deleted file mode 100644
index e21298a..0000000
--- a/code/environments/production/modules/certregen/lib/puppet_x/certregen/util.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module PuppetX
- module Certregen
- module Util
- module_function
-
- def duration(epoch)
- seconds = epoch.to_i
- minutes = (epoch / 60).to_i; seconds %= 60 if minutes > 0
- hours = (minutes / 60).to_i; minutes %= 60 if hours > 0
- days = (hours / 24).to_i; hours %= 24 if days > 0
- years = (days / 365).to_i; days %= 365 if years > 0
-
- list = []
- list << "#{years} #{pluralize('year', years)}" if years > 0
- list << "#{days} #{pluralize('day', days)}" if days > 0
- list << "#{hours} #{pluralize('hour', hours)}" if hours > 0
- list << "#{minutes} #{pluralize('minute', minutes)}" if minutes > 0
- list << "#{seconds} #{pluralize('second', seconds)}" if seconds > 0
- list.join(", ")
- end
-
- def pluralize(str, count)
- count == 1 ? str : str + 's'
- end
- end
- end
-end