puppetserver-ca 1.11.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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