puppetserver-ca 1.5.0 → 1.9.1

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: 6b557070928191df64bd5c16ffe5f523953056da761ba306f6601c422bf442e2
4
+ data.tar.gz: 0cb7ba011bd18b86a8842922d1b7c673754f1bacdcf25f3e80182bae237cde24
5
5
  SHA512:
6
- metadata.gz: ce20b8b249b03b73eeeaed698723df472191269626e37ce232ddf6e5a199fbcc19e29787929efa70e4400dc7a14c38fc0ad1c62f0de1febee3845d36899b49da
7
- data.tar.gz: 37b285c14dff8b48fab045dd699771917ac12e0b3663c61ec42d94ff6773644a7311af02d792ed17241be9b180f4ff041e2d61d04bf9cf7f034eaeefa0d12fa7
6
+ metadata.gz: 4dc1a23d03d22196b32f6dc6af78033c2600c1b1afac7f7d50df6b2abe56ed44197b07aafb76e9a95e5916cbc21464b5b1ce30cd6cfb74d81793206b04be7224
7
+ data.tar.gz: 06390ed9834caebe8b3847dc349d9a1af887086cd1ffee0ba774148c7da2c4c6e1055b4349e505e6cb67856315b325dff4f0f72502112e2628f34fb064c68457
@@ -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_1.x/), which will bump the version, tag, build, and release the gem.
78
96
 
79
97
 
80
98
  ## Contributing & Support
@@ -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)
@@ -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,103 @@
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
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
+ # Ensure the symlink has the same ownership as the actual cadir.
70
+ # This requires using `FileUtils.chown` rather than `File.chown`, as
71
+ # the latter will update the ownership of the target rather than the
72
+ # link itself.
73
+ # Symlink permissions are ignored in favor of the target's permissions,
74
+ # so we don't have to change those.
75
+ cadir = File.stat(new_cadir)
76
+ FileUtils.chown(cadir.uid, cadir.gid, old_cadir)
77
+ end
78
+
79
+ def parse(args)
80
+ results = {}
81
+ parser = self.class.parser(results)
82
+ errors = CliParsing.parse_with_errors(parser, args)
83
+ errors_were_handled = Errors.handle_with_usage(@logger, errors, parser.help)
84
+ exit_code = errors_were_handled ? 1 : nil
85
+ return results, exit_code
86
+ end
87
+
88
+ def self.parser(parsed = {})
89
+ OptionParser.new do |opts|
90
+ opts.banner = BANNER
91
+ opts.on('--help', 'Display this command-specific help output') do |help|
92
+ parsed['help'] = true
93
+ end
94
+ opts.on('--config CONF', 'Path to puppet.conf') do |conf|
95
+ parsed['config'] = conf
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+ end
@@ -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 = {
@@ -66,10 +66,13 @@ module Puppetserver
66
66
 
67
67
  results ||= {}
68
68
  results[:main] ||= {}
69
+ # The [master] config section is deprecated
70
+ # We now favor [server], but support both for backwards compatibility
69
71
  results[:master] ||= {}
72
+ results[:server] ||= {}
70
73
  results[:agent] ||= {}
71
74
 
72
- overrides = results[:agent].merge(results[:main]).merge(results[:master])
75
+ overrides = results[:agent].merge(results[:main]).merge(results[:master]).merge(results[:server])
73
76
  overrides.merge!(cli_overrides)
74
77
 
75
78
  @settings = resolve_settings(overrides).freeze
@@ -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
 
@@ -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 "Puppetserver 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 = "1.9.1"
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: 1.9.1
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-12-09 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