puppetserver-ca 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6675ef6328d11ddc9d47becb63063089f1eab59d
4
- data.tar.gz: f8f0e62f01297a56d238ffc7d074b6ed1300a448
2
+ SHA256:
3
+ metadata.gz: 6523b5628cc4d83aa2627326400a2fb493a18f28d7e4da4b8046eac41e09c555
4
+ data.tar.gz: 6e8cfbeb2a63ad443f22b196d9cdf2749242ef552c6376fd55b723aa699ceefd
5
5
  SHA512:
6
- metadata.gz: ce20b8b249b03b73eeeaed698723df472191269626e37ce232ddf6e5a199fbcc19e29787929efa70e4400dc7a14c38fc0ad1c62f0de1febee3845d36899b49da
7
- data.tar.gz: 37b285c14dff8b48fab045dd699771917ac12e0b3663c61ec42d94ff6773644a7311af02d792ed17241be9b180f4ff041e2d61d04bf9cf7f034eaeefa0d12fa7
6
+ metadata.gz: 82c62889b706bad66349d5efd8469969b919d8d90741c57c12827eccdedf2de80597ea923509c66de6d6f317da365d860705d556441ce817167d323ad6e80325
7
+ data.tar.gz: 72cca87e22e38e8c6b2b7975d4920057f5364c7a9499bcf30553894b9285468a0cb1d3fd93aace8974a889a0e0a0ed35f348d902139a07d0f588957e61f479f4
@@ -6,6 +6,8 @@ rvm:
6
6
  - 2.3
7
7
  - 2.4
8
8
  - 2.5
9
+ - 2.6
10
+ - 2.7
9
11
  before_install:
10
12
  gem install bundler -v 1.16.1 && (gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true)
11
13
  script:
data/Gemfile CHANGED
@@ -5,6 +5,11 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
5
5
  # Specify your gem's dependencies in puppetserver-ca.gemspec
6
6
  gemspec
7
7
 
8
- gem 'pry'
9
- gem 'pry-byebug'
10
8
  gem 'hocon', '~> 1.2', require: false
9
+ gem 'rake', '~> 13.0', require: false
10
+ gem 'rspec', '~> 3.4', require: false
11
+
12
+ group(:development, optional: true) do
13
+ gem 'pry'
14
+ gem 'pry-byebug'
15
+ end
data/README.md CHANGED
@@ -73,8 +73,26 @@ interactive prompt that will allow you to experiment.
73
73
 
74
74
  To install this gem onto your local machine, run `bundle exec rake install`.
75
75
 
76
- To release a new version, update the version number in `version.rb`, and then
77
- speak with Release Engineering.
76
+ ### Testing
77
+ To test your changes on a VM:
78
+ 1. Build the gem with your changes: `gem build puppetserver-ca.gemspec`
79
+ 1. Copy the gem to your VM: `scp puppetserver-ca-<version>.gem <your-vm>:.`
80
+ 1. Install puppetserver (FOSS) by installing the relevant release package and then installing the puppetserver package. For example:
81
+ ```
82
+ $ wget http://nightlies.puppet.com/yum/puppet6-nightly-release-el-7.noarch.rpm
83
+ $ rpm -i puppet6-nightly-release-el-7.noarch.rpm
84
+ $ yum update
85
+ $ yum install -y puppetserver
86
+ ```
87
+ 1. Restart your shell so that puppet's bin dir is on your $PATH: `exec bash`
88
+ 1. Install the gem into puppet's gem directory using puppet's gem command:
89
+ ```
90
+ $ /opt/puppetlabs/puppet/bin/gem install --install-dir "/opt/puppetlabs/puppet/lib/ruby/vendor_gems" puppetserver-ca-<version>.gem
91
+ ```
92
+ 1. To confirm that installation was successful, run `puppetserver ca --help`
93
+
94
+ ### Releasing
95
+ To release a new version, run the [release pipeline](https://jenkins-master-prod-1.delivery.puppetlabs.net/job/platform_puppetserver-ca_init-multijob_main/), which will bump the version, tag, build, and release the gem.
78
96
 
79
97
 
80
98
  ## Contributing & Support
@@ -85,7 +85,7 @@ BANNER
85
85
  return 1 if Errors.handle_with_usage(@logger, errors)
86
86
  end
87
87
 
88
- puppet = Config::Puppet.parse(config)
88
+ puppet = Config::Puppet.parse(config, @logger)
89
89
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
90
90
 
91
91
  result = clean_certs(certnames, puppet.settings)
@@ -45,7 +45,7 @@ BANNER
45
45
  end
46
46
 
47
47
  puppet = Config::Puppet.new(config_path)
48
- puppet.load
48
+ puppet.load({}, @logger)
49
49
  settings = puppet.settings
50
50
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
51
51
 
@@ -126,7 +126,7 @@ BANNER
126
126
  # Load, resolve, and validate puppet config settings
127
127
  settings_overrides = {}
128
128
  puppet = Config::Puppet.new(config_path)
129
- puppet.load(settings_overrides)
129
+ puppet.load(settings_overrides, @logger)
130
130
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
131
131
 
132
132
  # We don't want generate to respect the alt names setting, since it is usually
@@ -140,7 +140,7 @@ BANNER
140
140
  # Generate and save certs and associated keys
141
141
  if input['ca-client']
142
142
  # Refused to generate certs offfline if the CA service is running
143
- return 1 if check_server_online(puppet.settings)
143
+ return 1 if HttpClient.check_server_online(puppet.settings, @logger)
144
144
  all_passed = generate_authorized_certs(certnames, alt_names, puppet.settings, signer.digest)
145
145
  else
146
146
  all_passed = generate_certs(certnames, alt_names, puppet.settings, signer.digest, input['ttl'])
@@ -148,34 +148,6 @@ BANNER
148
148
  return all_passed ? 0 : 1
149
149
  end
150
150
 
151
- # Queries the simple status endpoint for the status of the CA service.
152
- # Returns true if it receives back a response of "running", and false if
153
- # no connection can be made, or a different response is received.
154
- def check_server_online(settings)
155
- status_url = HttpClient::URL.new('https', settings[:ca_server], settings[:ca_port], 'status', 'v1', 'simple', 'ca')
156
- begin
157
- # Generating certs offline is necessary if the master cert has been destroyed
158
- # or compromised. Since querying the status endpoint does not require a client cert, and
159
- # we commonly won't have one, don't require one for creating the connection.
160
- HttpClient.new(settings, with_client_cert: false).with_connection(status_url) do |conn|
161
- result = conn.get
162
- if result.body == "running"
163
- @logger.err "CA service is running. Please stop it before attempting to generate certs offline."
164
- true
165
- else
166
- false
167
- end
168
- end
169
- true
170
- rescue Puppetserver::Ca::ConnectionFailed => e
171
- if e.wrapped.is_a? Errno::ECONNREFUSED
172
- return false
173
- else
174
- raise e
175
- end
176
- end
177
- end
178
-
179
151
  # Certs authorized to talk to the CA API need to be signed offline,
180
152
  # in order to securely add the special auth extension.
181
153
  def generate_authorized_certs(certnames, alt_names, settings, digest)
@@ -4,6 +4,7 @@ require 'puppetserver/ca/config/puppet'
4
4
  require 'puppetserver/ca/errors'
5
5
  require 'puppetserver/ca/local_certificate_authority'
6
6
  require 'puppetserver/ca/utils/cli_parsing'
7
+ require 'puppetserver/ca/utils/config'
7
8
  require 'puppetserver/ca/utils/file_system'
8
9
  require 'puppetserver/ca/utils/signing_digest'
9
10
  require 'puppetserver/ca/x509_loader'
@@ -55,7 +56,7 @@ BANNER
55
56
  settings_overrides[:dns_alt_names] = input['subject-alt-names'] unless input['subject-alt-names'].empty?
56
57
 
57
58
  puppet = Config::Puppet.new(config_path)
58
- puppet.load(settings_overrides)
59
+ puppet.load(settings_overrides, @logger)
59
60
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
60
61
 
61
62
  # Load most secure signing digest we can for cers/crl/csr signing.
@@ -130,6 +131,8 @@ ERR
130
131
  FileSystem.write_file(location, content, 0640)
131
132
  end
132
133
 
134
+ Puppetserver::Ca::Utils::Config.symlink_to_old_cadir(settings[:cadir], settings[:confdir])
135
+
133
136
  return []
134
137
  end
135
138
 
@@ -68,7 +68,7 @@ Options:
68
68
  return 1 if Errors.handle_with_usage(@logger, errors)
69
69
  end
70
70
 
71
- puppet = Config::Puppet.parse(config)
71
+ puppet = Config::Puppet.parse(config, @logger)
72
72
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
73
73
 
74
74
  filter_names = certnames.any? \
@@ -118,20 +118,41 @@ Options:
118
118
  end
119
119
 
120
120
  def output_certs(certs)
121
- padded = 0
121
+ cert_column_width = certs.map { |c| c['name'].size }.max
122
+
122
123
  certs.each do |cert|
123
- cert_size = cert["name"].size
124
- padded = cert_size if cert_size > padded
124
+ @logger.inform(format_cert(cert, cert_column_width))
125
125
  end
126
+ end
126
127
 
127
- certs.each do |cert|
128
- # In newer versions of the CA api we return subjcet_alt_names
129
- # in addition to dns_alt_names, this field includes DNS alt
130
- # names but also IP alt names.
131
- alt_names = cert["subject_alt_names"] || cert["dns_alt_names"]
132
- @logger.inform " #{cert["name"]}".ljust(padded + 6) + " (SHA256) " + " #{cert["fingerprints"]["SHA256"]}" +
133
- (alt_names.empty? ? "" : "\talt names: #{alt_names}")
134
- end
128
+ def format_cert(cert, cert_column_width)
129
+ [
130
+ format_cert_and_sha(cert, cert_column_width),
131
+ format_alt_names(cert),
132
+ format_authorization_extensions(cert)
133
+ ].compact.join("\t")
134
+ end
135
+
136
+ def format_cert_and_sha(cert, cert_column_width)
137
+ justified_certname = cert['name'].ljust(cert_column_width + 6)
138
+ sha = cert['fingerprints']['SHA256']
139
+ " #{justified_certname} (SHA256) #{sha}"
140
+ end
141
+
142
+ def format_alt_names(cert)
143
+ # In newer versions of the CA api we return subject_alt_names
144
+ # in addition to dns_alt_names, this field includes DNS alt
145
+ # names but also IP alt names.
146
+ alt_names = cert['subject_alt_names'] || cert['dns_alt_names']
147
+ "alt names: #{alt_names}" unless alt_names.empty?
148
+ end
149
+
150
+ def format_authorization_extensions(cert)
151
+ auth_exts = cert['authorization_extensions']
152
+ return nil if auth_exts.nil? || auth_exts.empty?
153
+
154
+ values = auth_exts.map { |ext, value| "#{ext}: #{value}" }.join(', ')
155
+ "authorization extensions: [#{values}]"
135
156
  end
136
157
 
137
158
  def separate_certs(all_certs)
@@ -0,0 +1,95 @@
1
+ require 'puppetserver/ca/utils/cli_parsing'
2
+ require 'puppetserver/ca/utils/file_system'
3
+ require 'puppetserver/ca/utils/http_client'
4
+
5
+ module Puppetserver
6
+ module Ca
7
+ module Action
8
+ class Migrate
9
+ include Puppetserver::Ca::Utils
10
+ PUPPETSERVER_CA_DIR = '/etc/puppetlabs/puppetserver/ca'
11
+
12
+ SUMMARY = "Migrate the existing CA directory to /etc/puppetlabs/puppetserver/ca"
13
+ BANNER = <<-BANNER
14
+ Usage:
15
+ puppetserver ca migrate [--help]
16
+ puppetserver ca migrate [--config PATH]
17
+
18
+ Description:
19
+ Migrate an existing CA directory to /etc/puppetlabs/puppetserver/ca. This is for
20
+ upgrading from Puppet Platform 6.x to Puppet 7. Use the currently configured
21
+ puppet.conf file in your installation, or supply one using the `--config` flag.
22
+ Options:
23
+ BANNER
24
+
25
+ def initialize(logger)
26
+ @logger = logger
27
+ end
28
+
29
+ def run(input)
30
+ config_path = input['config']
31
+ puppet = Config::Puppet.new(config_path)
32
+ puppet.load({}, @logger)
33
+ return 1 if HttpClient.check_server_online(puppet.settings, @logger)
34
+
35
+ errors = FileSystem.check_for_existing_files(PUPPETSERVER_CA_DIR)
36
+ if !errors.empty?
37
+ instructions = <<-ERR
38
+ Migration will not overwrite the directory at #{PUPPETSERVER_CA_DIR}. Have you already
39
+ run this migration tool? Is this a puppet 7 installation? It is likely that you have
40
+ already successfully run the migration or do not need to run it.
41
+ ERR
42
+ errors << instructions
43
+ Errors.handle_with_usage(@logger, errors)
44
+ return 1
45
+ end
46
+
47
+ current_cadir = puppet.settings[:cadir]
48
+ if FileSystem.check_for_existing_files(current_cadir).empty?
49
+ error_message = <<-ERR
50
+ No CA dir found at #{current_cadir}. Please check the configured cadir setting in your
51
+ puppet.conf file and verify its contents.
52
+ ERR
53
+ Errors.handle_with_usage(@logger, [error_message])
54
+ return 1
55
+ end
56
+
57
+ migrate(current_cadir)
58
+
59
+ @logger.inform <<-SUCCESS_MESSAGE
60
+ CA dir successfully migrated to #{PUPPETSERVER_CA_DIR}. Symlink placed at #{current_cadir}
61
+ for backwards compatibility. The puppetserver can be safely restarted now.
62
+ SUCCESS_MESSAGE
63
+ return 0
64
+ end
65
+
66
+ def migrate(old_cadir, new_cadir=PUPPETSERVER_CA_DIR)
67
+ FileUtils.mv(old_cadir, new_cadir)
68
+ FileUtils.symlink(new_cadir, old_cadir)
69
+ end
70
+
71
+ def parse(args)
72
+ results = {}
73
+ parser = self.class.parser(results)
74
+ errors = CliParsing.parse_with_errors(parser, args)
75
+ errors_were_handled = Errors.handle_with_usage(@logger, errors, parser.help)
76
+ exit_code = errors_were_handled ? 1 : nil
77
+ return results, exit_code
78
+ end
79
+
80
+ def self.parser(parsed = {})
81
+ OptionParser.new do |opts|
82
+ opts.banner = BANNER
83
+ opts.on('--help', 'Display this command-specific help output') do |help|
84
+ parsed['help'] = true
85
+ end
86
+ opts.on('--config CONF', 'Path to puppet.conf') do |conf|
87
+ parsed['config'] = conf
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+ end
@@ -83,7 +83,7 @@ BANNER
83
83
  return 1 if Errors.handle_with_usage(@logger, errors)
84
84
  end
85
85
 
86
- puppet = Config::Puppet.parse(config)
86
+ puppet = Config::Puppet.parse(config, @logger)
87
87
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
88
88
 
89
89
  result = revoke_certs(certnames, puppet.settings)
@@ -3,6 +3,7 @@ require 'optparse'
3
3
  require 'puppetserver/ca/config/puppet'
4
4
  require 'puppetserver/ca/errors'
5
5
  require 'puppetserver/ca/local_certificate_authority'
6
+ require 'puppetserver/ca/utils/config'
6
7
  require 'puppetserver/ca/utils/cli_parsing'
7
8
  require 'puppetserver/ca/utils/file_system'
8
9
  require 'puppetserver/ca/utils/signing_digest'
@@ -55,7 +56,7 @@ BANNER
55
56
  settings_overrides[:dns_alt_names] = input['subject-alt-names'] unless input['subject-alt-names'].empty?
56
57
 
57
58
  puppet = Config::Puppet.new(config_path)
58
- puppet.load(settings_overrides)
59
+ puppet.load(settings_overrides, @logger)
59
60
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
60
61
 
61
62
  # Load most secure signing digest we can for cers/crl/csr signing.
@@ -135,6 +136,8 @@ ERR
135
136
  FileSystem.write_file(location, content, 0640)
136
137
  end
137
138
 
139
+ Puppetserver::Ca::Utils::Config.symlink_to_old_cadir(settings[:cadir], settings[:confdir])
140
+
138
141
  return []
139
142
  end
140
143
 
@@ -62,7 +62,7 @@ Options:
62
62
  return 1 if Errors.handle_with_usage(@logger, errors)
63
63
  end
64
64
 
65
- puppet = Config::Puppet.parse(config)
65
+ puppet = Config::Puppet.parse(config, @logger)
66
66
  return 1 if Errors.handle_with_usage(@logger, puppet.errors)
67
67
 
68
68
  ca = Puppetserver::Ca::CertificateAuthority.new(@logger, puppet.settings)
@@ -8,6 +8,7 @@ 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/migrate'
11
12
  require 'puppetserver/ca/errors'
12
13
  require 'puppetserver/ca/logger'
13
14
  require 'puppetserver/ca/utils/cli_parsing'
@@ -28,6 +29,7 @@ BANNER
28
29
  'import' => Action::Import,
29
30
  'setup' => Action::Setup,
30
31
  'enable' => Action::Enable,
32
+ 'migrate' => Action::Migrate,
31
33
  }
32
34
 
33
35
  MAINT_ACTIONS = {
@@ -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,20 +46,15 @@ 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
@@ -72,7 +67,7 @@ module Puppetserver
72
67
  overrides = results[:agent].merge(results[:main]).merge(results[:master])
73
68
  overrides.merge!(cli_overrides)
74
69
 
75
- @settings = resolve_settings(overrides).freeze
70
+ @settings = resolve_settings(overrides, logger).freeze
76
71
  end
77
72
 
78
73
  def default_certname
@@ -89,7 +84,7 @@ module Puppetserver
89
84
 
90
85
  # Resolve settings from default values, with any overrides for the
91
86
  # specific settings or their dependent settings (ssldir, cadir) taken into account.
92
- def resolve_settings(overrides = {})
87
+ def resolve_settings(overrides = {}, logger)
93
88
  unresolved_setting = /\$[a-z_]+/
94
89
 
95
90
  # Returning the key for unknown keys (rather than nil) is required to
@@ -101,9 +96,8 @@ module Puppetserver
101
96
  # These need to be evaluated before we can construct their dependent
102
97
  # defaults below
103
98
  base_defaults = [
104
- [:confdir, user_specific_conf_dir],
99
+ [:confdir, user_specific_puppet_confdir],
105
100
  [:ssldir,'$confdir/ssl'],
106
- [:cadir, '$ssldir/ca'],
107
101
  [:certdir, '$ssldir/certs'],
108
102
  [:certname, default_certname],
109
103
  [:server, 'puppet'],
@@ -148,6 +142,13 @@ module Puppetserver
148
142
  settings[setting_name] = substitutions[substitution_name] = subbed_value
149
143
  end
150
144
 
145
+ cadir = find_cadir(overrides.fetch(:cadir, false),
146
+ settings[:confdir],
147
+ settings[:ssldir],
148
+ logger)
149
+ settings[:cadir] = substitutions['$cadir'] = cadir
150
+
151
+
151
152
  dependent_defaults.each do |setting_name, default_value|
152
153
  setting_value = overrides.fetch(setting_name, default_value)
153
154
  settings[setting_name] = setting_value
@@ -210,6 +211,33 @@ module Puppetserver
210
211
 
211
212
  private
212
213
 
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
+
223
+ if configured_cadir
224
+ if configured_cadir.start_with?(ssldir)
225
+ logger.warn(warning % {ssldir: ssldir})
226
+ end
227
+ configured_cadir
228
+
229
+ else
230
+ old_cadir = Puppetserver::Ca::Utils::Config.old_default_cadir(confdir)
231
+ new_cadir = Puppetserver::Ca::Utils::Config.new_default_cadir(confdir)
232
+ if File.exist?(old_cadir) && !File.symlink?(old_cadir)
233
+ logger.warn(warning % {ssldir: ssldir})
234
+ old_cadir
235
+ else
236
+ new_cadir
237
+ end
238
+ end
239
+ end
240
+
213
241
  def explicitly_given_config_file_or_default_config_exists?
214
242
  !@using_default_location || File.exist?(@config_path)
215
243
  end
@@ -47,6 +47,7 @@ module Puppetserver
47
47
  'pp_cloudplatform' => "1.3.6.1.4.1.34380.1.1.23",
48
48
  'pp_apptier' => "1.3.6.1.4.1.34380.1.1.24",
49
49
  'pp_hostname' => "1.3.6.1.4.1.34380.1.1.25",
50
+ 'pp_owner' => "1.3.6.1.4.1.34380.1.1.26",
50
51
  'pp_authorization' => "1.3.6.1.4.1.34380.1.3.1",
51
52
  'pp_auth_role' => "1.3.6.1.4.1.34380.1.3.13"}
52
53
 
@@ -1,3 +1,5 @@
1
+ require 'puppetserver/ca/utils/file_system'
2
+
1
3
  module Puppetserver
2
4
  module Ca
3
5
  module Utils
@@ -19,6 +21,40 @@ module Puppetserver
19
21
  end.sort.uniq.join(", ")
20
22
  end
21
23
 
24
+ def self.puppet_confdir
25
+ if running_as_root?
26
+ '/etc/puppetlabs/puppet'
27
+ else
28
+ "#{ENV['HOME']}/.puppetlabs/etc/puppet"
29
+ end
30
+ end
31
+
32
+ def self.puppetserver_confdir(puppet_confdir)
33
+ File.join(File.dirname(puppet_confdir), 'puppetserver')
34
+ end
35
+
36
+ def self.default_ssldir(confdir = puppet_confdir)
37
+ File.join(confdir, 'ssl')
38
+ end
39
+
40
+ def self.old_default_cadir(confdir = puppet_confdir)
41
+ File.join(confdir, 'ssl', 'ca')
42
+ end
43
+
44
+ def self.new_default_cadir(confdir = puppet_confdir)
45
+ File.join(puppetserver_confdir(confdir), 'ca')
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
+
22
58
  end
23
59
  end
24
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
@@ -159,6 +159,36 @@ module Puppetserver
159
159
 
160
160
  store
161
161
  end
162
+
163
+ # Queries the simple status endpoint for the status of the CA service.
164
+ # Returns true if it receives back a response of "running", and false if
165
+ # no connection can be made, or a different response is received.
166
+ def self.check_server_online(settings, logger)
167
+ status_url = URL.new('https', settings[:ca_server], settings[:ca_port], 'status', 'v1', 'simple', 'ca')
168
+ begin
169
+ # Generating certs offline is necessary if the master cert has been destroyed
170
+ # or compromised. Since querying the status endpoint does not require a client cert, and
171
+ # we commonly won't have one, don't require one for creating the connection.
172
+ # Additionally, we want to ensure the server is stopped before migrating the CA dir to
173
+ # avoid issues with writing to the CA dir and moving it.
174
+ self.new(settings, with_client_cert: false).with_connection(status_url) do |conn|
175
+ result = conn.get
176
+ if result.body == "running"
177
+ logger.err "CA service is running. Please stop it before attempting to run this command."
178
+ true
179
+ else
180
+ false
181
+ end
182
+ end
183
+ rescue Puppetserver::Ca::ConnectionFailed => e
184
+ if e.wrapped.is_a? Errno::ECONNREFUSED
185
+ return false
186
+ else
187
+ raise e
188
+ end
189
+ end
190
+ end
191
+
162
192
  end
163
193
  end
164
194
  end
@@ -1,5 +1,5 @@
1
1
  module Puppetserver
2
2
  module Ca
3
- VERSION = "1.5.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_runtime_dependency "facter", [">= 2.0.1", "< 4"]
23
+ spec.add_runtime_dependency "facter", [">= 2.0.1", "< 5"]
24
24
 
25
25
  spec.add_development_dependency "bundler", ">= 1.16"
26
- spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rake", ">= 12.3.3"
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
28
  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.5.0
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: 2019-12-02 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
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 2.0.1
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '4'
22
+ version: '5'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 2.0.1
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '4'
32
+ version: '5'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: bundler
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -48,16 +48,16 @@ dependencies:
48
48
  name: rake
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '10.0'
53
+ version: 12.3.3
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '10.0'
60
+ version: 12.3.3
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rspec
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -99,6 +99,7 @@ files:
99
99
  - lib/puppetserver/ca/action/generate.rb
100
100
  - lib/puppetserver/ca/action/import.rb
101
101
  - lib/puppetserver/ca/action/list.rb
102
+ - lib/puppetserver/ca/action/migrate.rb
102
103
  - lib/puppetserver/ca/action/revoke.rb
103
104
  - lib/puppetserver/ca/action/setup.rb
104
105
  - lib/puppetserver/ca/action/sign.rb
@@ -138,8 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
139
  - !ruby/object:Gem::Version
139
140
  version: '0'
140
141
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 2.5.1
142
+ rubygems_version: 3.0.8
143
143
  signing_key:
144
144
  specification_version: 4
145
145
  summary: A simple CLI tool for interacting with Puppet Server's Certificate Authority