puppetserver-ca 1.11.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,6 @@ require 'puppetserver/ca/action/list'
8
8
  require 'puppetserver/ca/action/revoke'
9
9
  require 'puppetserver/ca/action/setup'
10
10
  require 'puppetserver/ca/action/sign'
11
- require 'puppetserver/ca/action/prune'
12
11
  require 'puppetserver/ca/action/migrate'
13
12
  require 'puppetserver/ca/errors'
14
13
  require 'puppetserver/ca/logger'
@@ -26,12 +25,11 @@ Manage the Private Key Infrastructure for
26
25
  Puppet Server's built-in Certificate Authority
27
26
  BANNER
28
27
 
29
- ADMIN_ACTIONS = {
28
+ INIT_ACTIONS = {
30
29
  'import' => Action::Import,
31
30
  'setup' => Action::Setup,
32
- 'enable' => Action::Enable,
33
- 'migrate' => Action::Migrate,
34
- 'prune' => Action::Prune
31
+ 'enable' => Action::Enable,
32
+ 'migrate' => Action::Migrate,
35
33
  }
36
34
 
37
35
  MAINT_ACTIONS = {
@@ -42,15 +40,15 @@ BANNER
42
40
  'sign' => Action::Sign
43
41
  }
44
42
 
45
- VALID_ACTIONS = ADMIN_ACTIONS.merge(MAINT_ACTIONS).sort.to_h
43
+ VALID_ACTIONS = INIT_ACTIONS.merge(MAINT_ACTIONS).sort.to_h
46
44
 
47
45
  ACTION_LIST = "\nAvailable Actions:\n\n" +
48
46
  " Certificate Actions (requires a running Puppet Server):\n\n" +
49
47
  MAINT_ACTIONS.map do |action, cls|
50
48
  " #{action}\t#{cls::SUMMARY}"
51
49
  end.join("\n") + "\n\n" +
52
- " Administrative Actions (requires Puppet Server to be stopped):\n\n" +
53
- ADMIN_ACTIONS.map do |action, cls|
50
+ " Initialization Actions (requires Puppet Server to be stopped):\n\n" +
51
+ INIT_ACTIONS.map do |action, cls|
54
52
  " #{action}\t#{cls::SUMMARY}"
55
53
  end.join("\n")
56
54
 
@@ -66,10 +64,8 @@ BANNER
66
64
 
67
65
 
68
66
  def self.run(cli_args = ARGV, out = STDOUT, err = STDERR)
67
+ logger = Puppetserver::Ca::Logger.new(:info, out, err)
69
68
  parser, general_options, unparsed = parse_general_inputs(cli_args)
70
- level = general_options.delete('verbose') ? :debug : :info
71
-
72
- logger = Puppetserver::Ca::Logger.new(level, out, err)
73
69
 
74
70
  if general_options['version']
75
71
  logger.inform Puppetserver::Ca::VERSION
@@ -125,9 +121,6 @@ BANNER
125
121
  opts.on('--version', 'Display the version') do |v|
126
122
  parsed['version'] = true
127
123
  end
128
- opts.on('--verbose', 'Display low-level information') do |verbose|
129
- parsed['verbose'] = true
130
- end
131
124
 
132
125
  opts.separator ACTION_OPTIONS
133
126
  opts.separator "\nSee `puppetserver ca <action> --help` for detailed info"
@@ -23,9 +23,9 @@ module Puppetserver
23
23
  # A regex describing valid formats with groups for capturing the value and units
24
24
  TTL_FORMAT = /^(\d+)(y|d|h|m|s)?$/
25
25
 
26
- def self.parse(config_path)
26
+ def self.parse(config_path, logger)
27
27
  instance = new(config_path)
28
- instance.load
28
+ instance.load({}, logger)
29
29
 
30
30
  return instance
31
31
  end
@@ -34,7 +34,7 @@ module Puppetserver
34
34
 
35
35
  def initialize(supplied_config_path = nil)
36
36
  @using_default_location = !supplied_config_path
37
- @config_path = supplied_config_path || user_specific_conf_file
37
+ @config_path = supplied_config_path || user_specific_puppet_config
38
38
 
39
39
  @settings = nil
40
40
  @errors = []
@@ -46,55 +46,45 @@ module Puppetserver
46
46
  # on Windows are unsupported.
47
47
  # Note that Puppet Server runs as the [pe-]puppet user but to
48
48
  # start/stop it you must be root.
49
- def user_specific_conf_dir
50
- @user_specific_conf_dir ||=
51
- if Puppetserver::Ca::Utils::Config.running_as_root?
52
- '/etc/puppetlabs/puppet'
53
- else
54
- "#{ENV['HOME']}/.puppetlabs/etc/puppet"
55
- end
49
+ def user_specific_puppet_confdir
50
+ @user_specific_puppet_confdir ||= Puppetserver::Ca::Utils::Config.puppet_confdir
56
51
  end
57
52
 
58
- def user_specific_conf_file
59
- user_specific_conf_dir + '/puppet.conf'
53
+ def user_specific_puppet_config
54
+ user_specific_puppet_confdir + '/puppet.conf'
60
55
  end
61
56
 
62
- def load(cli_overrides = {})
57
+ def load(cli_overrides = {}, logger)
63
58
  if explicitly_given_config_file_or_default_config_exists?
64
59
  results = parse_text(File.read(@config_path))
65
60
  end
66
61
 
67
62
  results ||= {}
68
63
  results[:main] ||= {}
69
- # The [master] config section is deprecated
70
- # We now favor [server], but support both for backwards compatibility
71
64
  results[:master] ||= {}
72
- results[:server] ||= {}
73
65
  results[:agent] ||= {}
74
66
 
75
- overrides = results[:agent].merge(results[:main]).merge(results[:master]).merge(results[:server])
67
+ overrides = results[:agent].merge(results[:main]).merge(results[:master])
76
68
  overrides.merge!(cli_overrides)
77
- if overrides[:masterport]
78
- overrides[:serverport] ||= overrides.delete(:masterport)
79
- end
80
69
 
81
- @settings = resolve_settings(overrides).freeze
70
+ @settings = resolve_settings(overrides, logger).freeze
82
71
  end
83
72
 
84
73
  def default_certname
85
- hostname = Facter.value(:hostname)
86
- domain = Facter.value(:domain)
87
- if domain and domain != ''
88
- fqdn = [hostname, domain].join('.')
89
- else
90
- fqdn = hostname
91
- end
92
- fqdn.chomp('.')
74
+ @certname ||=
75
+ hostname = Facter.value(:hostname)
76
+ domain = Facter.value(:domain)
77
+ if domain and domain != ''
78
+ fqdn = [hostname, domain].join('.')
79
+ else
80
+ fqdn = hostname
81
+ end
82
+ fqdn.chomp('.')
93
83
  end
94
84
 
95
85
  # Resolve settings from default values, with any overrides for the
96
86
  # specific settings or their dependent settings (ssldir, cadir) taken into account.
97
- def resolve_settings(overrides = {})
87
+ def resolve_settings(overrides = {}, logger)
98
88
  unresolved_setting = /\$[a-z_]+/
99
89
 
100
90
  # Returning the key for unknown keys (rather than nil) is required to
@@ -106,12 +96,12 @@ module Puppetserver
106
96
  # These need to be evaluated before we can construct their dependent
107
97
  # defaults below
108
98
  base_defaults = [
109
- [:confdir, user_specific_conf_dir],
99
+ [:confdir, user_specific_puppet_confdir],
110
100
  [:ssldir,'$confdir/ssl'],
111
101
  [:certdir, '$ssldir/certs'],
112
102
  [:certname, default_certname],
113
103
  [:server, 'puppet'],
114
- [:serverport, '8140'],
104
+ [:masterport, '8140'],
115
105
  [:privatekeydir, '$ssldir/private_keys'],
116
106
  [:publickeydir, '$ssldir/public_keys'],
117
107
  ]
@@ -129,7 +119,7 @@ module Puppetserver
129
119
  :serial => '$cadir/serial',
130
120
  :cert_inventory => '$cadir/inventory.txt',
131
121
  :ca_server => '$server',
132
- :ca_port => '$serverport',
122
+ :ca_port => '$masterport',
133
123
  :localcacert => '$certdir/ca.pem',
134
124
  :hostcrl => '$ssldir/crl.pem',
135
125
  :hostcert => '$certdir/$certname.pem',
@@ -153,9 +143,12 @@ module Puppetserver
153
143
  end
154
144
 
155
145
  cadir = find_cadir(overrides.fetch(:cadir, false),
156
- settings[:confdir])
146
+ settings[:confdir],
147
+ settings[:ssldir],
148
+ logger)
157
149
  settings[:cadir] = substitutions['$cadir'] = cadir
158
150
 
151
+
159
152
  dependent_defaults.each do |setting_name, default_value|
160
153
  setting_value = overrides.fetch(setting_name, default_value)
161
154
  settings[setting_name] = setting_value
@@ -218,17 +211,29 @@ module Puppetserver
218
211
 
219
212
  private
220
213
 
221
- def find_cadir(configured_cadir, confdir)
214
+
215
+ def find_cadir(configured_cadir, confdir, ssldir, logger)
216
+ warning = 'The cadir is currently configured to be inside the ' +
217
+ '%{ssldir} directory. This config setting and the directory ' +
218
+ 'location will not be used in a future version of puppet. ' +
219
+ 'Please run the puppetserver ca tool to migrate out from the ' +
220
+ 'puppet confdir to the /etc/puppetlabs/puppetserver/ca directory. ' +
221
+ 'Use `puppetserver ca migrate --help` for more info.'
222
+
222
223
  if configured_cadir
224
+ if configured_cadir.start_with?(ssldir)
225
+ logger.warn(warning % {ssldir: ssldir})
226
+ end
223
227
  configured_cadir
228
+
224
229
  else
225
230
  old_cadir = Puppetserver::Ca::Utils::Config.old_default_cadir(confdir)
226
231
  new_cadir = Puppetserver::Ca::Utils::Config.new_default_cadir(confdir)
227
-
228
- if File.exist?("#{new_cadir}/ca_crt.pem")
229
- new_cadir
230
- else
232
+ if File.exist?(old_cadir) && !File.symlink?(old_cadir)
233
+ logger.warn(warning % {ssldir: ssldir})
231
234
  old_cadir
235
+ else
236
+ new_cadir
232
237
  end
233
238
  end
234
239
  end
@@ -279,7 +284,7 @@ module Puppetserver
279
284
  end
280
285
 
281
286
  if settings.dig(:server_list, 0, 1) &&
282
- settings[:ca_port] == '$serverport'
287
+ settings[:ca_port] == '$masterport'
283
288
 
284
289
  settings[:ca_port] = settings.dig(:server_list, 0, 1)
285
290
  end
@@ -58,10 +58,10 @@ module Puppetserver
58
58
  @errors = []
59
59
  end
60
60
 
61
- # If both the private and public keys exist for a server then we want
61
+ # If both the private and public keys exist for a master then we want
62
62
  # to honor them here, if only one key exists we want to surface an error,
63
63
  # and if neither exist we generate a new key. This logic is necessary for
64
- # proper bootstrapping for certain server workflows.
64
+ # proper bootstrapping for certain master workflows.
65
65
  def create_private_key(keylength, private_path = '', public_path = '')
66
66
  if File.exists?(private_path) && File.exists?(public_path)
67
67
  return OpenSSL::PKey.read(File.read(private_path))
@@ -20,7 +20,7 @@ module Puppetserver
20
20
 
21
21
  CLI_AUTH_EXT_OID = "1.3.6.1.4.1.34380.1.3.39"
22
22
 
23
- SERVER_EXTENSIONS = [
23
+ MASTER_EXTENSIONS = [
24
24
  ["basicConstraints", "CA:FALSE", true],
25
25
  ["nsComment", "Puppet Server Internal Certificate", false],
26
26
  ["authorityKeyIdentifier", "keyid:always", false],
@@ -132,23 +132,23 @@ module Puppetserver
132
132
  time.strftime('%Y-%m-%dT%H:%M:%S%Z')
133
133
  end
134
134
 
135
- def create_server_cert
136
- server_cert = nil
137
- server_key = @host.create_private_key(@settings[:keylength],
135
+ def create_master_cert
136
+ master_cert = nil
137
+ master_key = @host.create_private_key(@settings[:keylength],
138
138
  @settings[:hostprivkey],
139
139
  @settings[:hostpubkey])
140
- if server_key
141
- server_csr = @host.create_csr(name: @settings[:certname], key: server_key)
140
+ if master_key
141
+ master_csr = @host.create_csr(name: @settings[:certname], key: master_key)
142
142
  if @settings[:subject_alt_names].empty?
143
143
  alt_names = "DNS:puppet, DNS:#{@settings[:certname]}"
144
144
  else
145
145
  alt_names = @settings[:subject_alt_names]
146
146
  end
147
147
 
148
- server_cert = sign_authorized_cert(server_csr, alt_names)
148
+ master_cert = sign_authorized_cert(master_csr, alt_names)
149
149
  end
150
150
 
151
- return server_key, server_cert
151
+ return master_key, master_cert
152
152
  end
153
153
 
154
154
  def sign_authorized_cert(csr, alt_names = '')
@@ -176,7 +176,7 @@ module Puppetserver
176
176
  end
177
177
 
178
178
  def add_authorized_extensions(cert, ef)
179
- SERVER_EXTENSIONS.each do |ext|
179
+ MASTER_EXTENSIONS.each do |ext|
180
180
  extension = ef.create_extension(*ext)
181
181
  cert.add_extension(extension)
182
182
  end
@@ -13,16 +13,8 @@ module Puppetserver
13
13
  @err = err
14
14
  end
15
15
 
16
- def level
17
- @level
18
- end
19
-
20
- def debug?
21
- return @level >= LEVELS[:debug]
22
- end
23
-
24
16
  def debug(text)
25
- if debug?
17
+ if @level >= LEVELS[:debug]
26
18
  @out.puts(text)
27
19
  end
28
20
  end
@@ -1,3 +1,5 @@
1
+ require 'puppetserver/ca/utils/file_system'
2
+
1
3
  module Puppetserver
2
4
  module Ca
3
5
  module Utils
@@ -31,6 +33,10 @@ module Puppetserver
31
33
  File.join(File.dirname(puppet_confdir), 'puppetserver')
32
34
  end
33
35
 
36
+ def self.default_ssldir(confdir = puppet_confdir)
37
+ File.join(confdir, 'ssl')
38
+ end
39
+
34
40
  def self.old_default_cadir(confdir = puppet_confdir)
35
41
  File.join(confdir, 'ssl', 'ca')
36
42
  end
@@ -38,6 +44,17 @@ module Puppetserver
38
44
  def self.new_default_cadir(confdir = puppet_confdir)
39
45
  File.join(puppetserver_confdir(confdir), 'ca')
40
46
  end
47
+
48
+ def self.symlink_to_old_cadir(current_cadir, puppet_confdir)
49
+ old_cadir = old_default_cadir(puppet_confdir)
50
+ new_cadir = new_default_cadir(puppet_confdir)
51
+ return if current_cadir != new_cadir
52
+ # This is only run on setup/import, so there should be no files in the
53
+ # old cadir, so it should be safe to forcibly remove it (which we need
54
+ # to do in order to create a symlink).
55
+ Puppetserver::Ca::Utils::FileSystem.forcibly_symlink(new_cadir, old_cadir)
56
+ end
57
+
41
58
  end
42
59
  end
43
60
  end
@@ -50,6 +50,11 @@ module Puppetserver
50
50
  errors
51
51
  end
52
52
 
53
+ def self.forcibly_symlink(source, link_target)
54
+ FileUtils.remove_dir(link_target, true)
55
+ FileUtils.symlink(source, link_target)
56
+ end
57
+
53
58
  def initialize
54
59
  @user, @group = find_user_and_group
55
60
  end
@@ -1,6 +1,5 @@
1
1
  require 'net/https'
2
2
  require 'openssl'
3
- require 'uri'
4
3
 
5
4
  require 'puppetserver/ca/errors'
6
5
 
@@ -20,8 +19,7 @@ module Puppetserver
20
19
 
21
20
  # Not all connections require a client cert to be present.
22
21
  # For example, when querying the status endpoint.
23
- def initialize(logger, settings, with_client_cert: true)
24
- @logger = logger
22
+ def initialize(settings, with_client_cert: true)
25
23
  @store = make_store(settings[:localcacert],
26
24
  settings[:certificate_revocation],
27
25
  settings[:hostcrl])
@@ -52,7 +50,7 @@ module Puppetserver
52
50
  # The Connection object should have HTTP verbs defined on it that take
53
51
  # a body (and optional overrides). Returns whatever the block given returned.
54
52
  def with_connection(url, &block)
55
- request = ->(conn) { block.call(Connection.new(conn, url, @logger)) }
53
+ request = ->(conn) { block.call(Connection.new(conn, url)) }
56
54
 
57
55
  begin
58
56
  Net::HTTP.start(url.host, url.port,
@@ -87,30 +85,25 @@ module Puppetserver
87
85
  # and defines methods named after HTTP verbs that are called on the
88
86
  # saved connection, returning a Result.
89
87
  class Connection
90
- def initialize(net_http_connection, url_struct, logger)
88
+ def initialize(net_http_connection, url_struct)
91
89
  @conn = net_http_connection
92
90
  @url = url_struct
93
- @logger = logger
94
91
  end
95
92
 
96
93
  def get(url_overide = nil, headers = {})
97
94
  url = url_overide || @url
98
95
  headers = DEFAULT_HEADERS.merge(headers)
99
96
 
100
- @logger.debug("Making a GET request at #{url.full_url}")
101
-
102
97
  request = Net::HTTP::Get.new(url.to_uri, headers)
103
98
  result = @conn.request(request)
104
- Result.new(result.code, result.body)
105
99
 
100
+ Result.new(result.code, result.body)
106
101
  end
107
102
 
108
103
  def put(body, url_override = nil, headers = {})
109
104
  url = url_override || @url
110
105
  headers = DEFAULT_HEADERS.merge(headers)
111
106
 
112
- @logger.debug("Making a PUT request at #{url.full_url}")
113
-
114
107
  request = Net::HTTP::Put.new(url.to_uri, headers)
115
108
  request.body = body
116
109
  result = @conn.request(request)
@@ -122,8 +115,6 @@ module Puppetserver
122
115
  url = url_override || @url
123
116
  headers = DEFAULT_HEADERS.merge(headers)
124
117
 
125
- @logger.debug("Making a DELETE request at #{url.full_url}")
126
-
127
118
  result = @conn.request(Net::HTTP::Delete.new(url.to_uri, headers))
128
119
 
129
120
  Result.new(result.code, result.body)
@@ -136,13 +127,10 @@ module Puppetserver
136
127
  # Like URI, but not... maybe of suspicious value
137
128
  URL = Struct.new(:protocol, :host, :port,
138
129
  :endpoint, :version,
139
- :resource_type, :resource_name, :query) do
130
+ :resource_type, :resource_name) do
140
131
  def full_url
141
- url = protocol + '://' + host + ':' + port + '/' +
142
- [endpoint, version, resource_type, resource_name].join('/')
143
-
144
- url = url + "?" + URI.encode_www_form(query) unless query.nil? || query.empty?
145
- return url
132
+ protocol + '://' + host + ':' + port + '/' +
133
+ [endpoint, version, resource_type, resource_name].join('/')
146
134
  end
147
135
 
148
136
  def to_uri
@@ -178,15 +166,15 @@ module Puppetserver
178
166
  def self.check_server_online(settings, logger)
179
167
  status_url = URL.new('https', settings[:ca_server], settings[:ca_port], 'status', 'v1', 'simple', 'ca')
180
168
  begin
181
- # Generating certs offline is necessary if the server cert has been destroyed
169
+ # Generating certs offline is necessary if the master cert has been destroyed
182
170
  # or compromised. Since querying the status endpoint does not require a client cert, and
183
171
  # we commonly won't have one, don't require one for creating the connection.
184
172
  # Additionally, we want to ensure the server is stopped before migrating the CA dir to
185
173
  # avoid issues with writing to the CA dir and moving it.
186
- self.new(logger, settings, with_client_cert: false).with_connection(status_url) do |conn|
174
+ self.new(settings, with_client_cert: false).with_connection(status_url) do |conn|
187
175
  result = conn.get
188
176
  if result.body == "running"
189
- logger.err "Puppetserver service is running. Please stop it before attempting to run this command."
177
+ logger.err "CA service is running. Please stop it before attempting to run this command."
190
178
  true
191
179
  else
192
180
  false
@@ -1,5 +1,5 @@
1
1
  module Puppetserver
2
2
  module Ca
3
- VERSION = "1.11.7"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppetserver-ca
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.7
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-11 00:00:00.000000000 Z
11
+ date: 2020-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: facter
@@ -100,7 +100,6 @@ files:
100
100
  - lib/puppetserver/ca/action/import.rb
101
101
  - lib/puppetserver/ca/action/list.rb
102
102
  - lib/puppetserver/ca/action/migrate.rb
103
- - lib/puppetserver/ca/action/prune.rb
104
103
  - lib/puppetserver/ca/action/revoke.rb
105
104
  - lib/puppetserver/ca/action/setup.rb
106
105
  - lib/puppetserver/ca/action/sign.rb
@@ -140,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
139
  - !ruby/object:Gem::Version
141
140
  version: '0'
142
141
  requirements: []
143
- rubygems_version: 3.0.9
142
+ rubygems_version: 3.0.8
144
143
  signing_key:
145
144
  specification_version: 4
146
145
  summary: A simple CLI tool for interacting with Puppet Server's Certificate Authority
@@ -1,137 +0,0 @@
1
- require 'optparse'
2
- require 'openssl'
3
- require 'set'
4
- require 'puppetserver/ca/errors'
5
- require 'puppetserver/ca/utils/cli_parsing'
6
- require 'puppetserver/ca/utils/file_system'
7
- require 'puppetserver/ca/utils/config'
8
- require 'puppetserver/ca/x509_loader'
9
-
10
- module Puppetserver
11
- module Ca
12
- module Action
13
- class Prune
14
- include Puppetserver::Ca::Utils
15
-
16
- SUMMARY = "Prune the local CRL on disk to remove any duplicated certificates"
17
- BANNER = <<-BANNER
18
- Usage:
19
- puppetserver ca prune [--help]
20
- puppetserver ca prune [--config]
21
-
22
- Description:
23
- Prune the list of revoked certificates of any duplication within it. This command
24
- will only prune the CRL issued by Puppet's CA cert.
25
-
26
- Options:
27
- BANNER
28
-
29
- def initialize(logger)
30
- @logger = logger
31
- end
32
-
33
- def run(inputs)
34
- config_path = inputs['config']
35
- exit_code = 0
36
-
37
- # Validate the config path.
38
- if config_path
39
- errors = FileSystem.validate_file_paths(config_path)
40
- return 1 if Errors.handle_with_usage(@logger, errors)
41
- end
42
-
43
- # Validate puppet config setting.
44
- puppet = Config::Puppet.new(config_path)
45
- puppet.load(logger: @logger)
46
- return 1 if Errors.handle_with_usage(@logger, puppet.errors)
47
-
48
- # Validate that we are offline
49
- return 1 if HttpClient.check_server_online(puppet.settings, @logger)
50
-
51
- # Getting the CRL(s)
52
- loader = X509Loader.new(puppet.settings[:cacert], puppet.settings[:cakey], puppet.settings[:cacrl])
53
-
54
- verified_crls = loader.crls.select { |crl| crl.verify(loader.key) }
55
-
56
- if verified_crls.length == 1
57
- puppet_crl = verified_crls.first
58
- @logger.inform("Total number of certificates found in Puppet's CRL is: #{puppet_crl.revoked.length}.")
59
- number_of_removed_duplicates = prune_CRL(puppet_crl)
60
-
61
- if number_of_removed_duplicates > 0
62
- update_pruned_CRL(puppet_crl, loader.key)
63
- FileSystem.write_file(puppet.settings[:cacrl], loader.crls, 0644)
64
- @logger.inform("Removed #{number_of_removed_duplicates} duplicated certs from Puppet's CRL.")
65
- else
66
- @logger.inform("No duplicate revocations found in the CRL.")
67
- end
68
- else
69
- @logger.err("Could not identify Puppet's CRL. Aborting prune action.")
70
- exit_code = 1
71
- end
72
-
73
- return exit_code
74
- end
75
-
76
- def prune_CRL(crl)
77
- number_of_removed_duplicates = 0
78
-
79
- existed_serial_number = Set.new()
80
- revoked_list = crl.revoked
81
- @logger.debug("Pruning duplicate entries in CRL for issuer " \
82
- "#{crl.issuer.to_s(OpenSSL::X509::Name::RFC2253)}") if @logger.debug?
83
-
84
- revoked_list.delete_if do |revoked|
85
- if existed_serial_number.add?(revoked.serial)
86
- false
87
- else
88
- number_of_removed_duplicates += 1
89
- @logger.debug("Removing duplicate of #{revoked.serial}, " \
90
- "revoked on #{revoked.time}\n") if @logger.debug?
91
- true
92
- end
93
- end
94
- crl.revoked=(revoked_list)
95
-
96
- return number_of_removed_duplicates
97
- end
98
-
99
- def update_pruned_CRL(crl, pkey)
100
- number_ext, other_ext = crl.extensions.partition{ |ext| ext.oid == "crlNumber" }
101
- number_ext.each do |crl_number|
102
- updated_crl_number = OpenSSL::BN.new(crl_number.value) + OpenSSL::BN.new(1)
103
- crl_number.value=(OpenSSL::ASN1::Integer(updated_crl_number))
104
- end
105
- crl.extensions=(number_ext + other_ext)
106
- crl.sign(pkey, OpenSSL::Digest::SHA256.new)
107
- end
108
-
109
- def self.parser(parsed = {})
110
- OptionParser.new do |opts|
111
- opts.banner = BANNER
112
- opts.on('--help', 'Display this command-specific help output') do |help|
113
- parsed['help'] = true
114
- end
115
- opts.on('--config CONF', 'Path to the puppet.conf file on disk') do |conf|
116
- parsed['config'] = conf
117
- end
118
- end
119
- end
120
-
121
- def parse(args)
122
- results = {}
123
- parser = self.class.parser(results)
124
- errors = CliParsing.parse_with_errors(parser, args)
125
- errors_were_handled = Errors.handle_with_usage(@logger, errors, parser.help)
126
-
127
- if errors_were_handled
128
- exit_code = 1
129
- else
130
- exit_code = nil
131
- end
132
- return results, exit_code
133
- end
134
- end
135
- end
136
- end
137
- end