puppetserver-ca 1.5.0 → 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.
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