puppetserver-ca 1.5.0 → 1.9.1

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: 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