puppetserver-ca 0.3.1 → 0.4.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 +4 -4
- data/lib/puppetserver/ca/action/clean.rb +102 -0
- data/lib/puppetserver/ca/action/create.rb +161 -0
- data/lib/puppetserver/ca/action/generate.rb +313 -0
- data/lib/puppetserver/ca/action/import.rb +132 -0
- data/lib/puppetserver/ca/action/list.rb +132 -0
- data/lib/puppetserver/ca/action/revoke.rb +101 -0
- data/lib/puppetserver/ca/action/sign.rb +126 -0
- data/lib/puppetserver/ca/certificate_authority.rb +224 -0
- data/lib/puppetserver/ca/cli.rb +17 -16
- data/lib/puppetserver/ca/config/puppet.rb +242 -0
- data/lib/puppetserver/ca/config/puppetserver.rb +85 -0
- data/lib/puppetserver/ca/utils/cli_parsing.rb +82 -0
- data/lib/puppetserver/ca/utils/config.rb +13 -0
- data/lib/puppetserver/ca/utils/file_system.rb +90 -0
- data/lib/puppetserver/ca/utils/http_client.rb +129 -0
- data/lib/puppetserver/ca/utils/signing_digest.rb +27 -0
- data/lib/puppetserver/ca/version.rb +1 -1
- metadata +17 -17
- data/lib/puppetserver/ca/clean_action.rb +0 -157
- data/lib/puppetserver/ca/config_utils.rb +0 -11
- data/lib/puppetserver/ca/create_action.rb +0 -265
- data/lib/puppetserver/ca/generate_action.rb +0 -227
- data/lib/puppetserver/ca/import_action.rb +0 -153
- data/lib/puppetserver/ca/list_action.rb +0 -153
- data/lib/puppetserver/ca/puppet_config.rb +0 -197
- data/lib/puppetserver/ca/puppetserver_config.rb +0 -83
- data/lib/puppetserver/ca/revoke_action.rb +0 -136
- data/lib/puppetserver/ca/sign_action.rb +0 -190
- data/lib/puppetserver/ca/utils.rb +0 -80
- data/lib/puppetserver/settings/ttl_setting.rb +0 -48
- data/lib/puppetserver/utils/file_utilities.rb +0 -78
- data/lib/puppetserver/utils/http_client.rb +0 -129
- data/lib/puppetserver/utils/signing_digest.rb +0 -25
@@ -1,48 +0,0 @@
|
|
1
|
-
# A setting that represents a span of time to live, and evaluates to Numeric
|
2
|
-
# seconds to live where 0 means shortest possible time to live, a positive numeric value means time
|
3
|
-
# to live in seconds, and the symbolic entry 'unlimited' is an infinite amount of time.
|
4
|
-
#
|
5
|
-
module Puppetserver
|
6
|
-
module Settings
|
7
|
-
class TTLSetting
|
8
|
-
# How we convert from various units to seconds.
|
9
|
-
UNITMAP = {
|
10
|
-
# 365 days isn't technically a year, but is sufficient for most purposes
|
11
|
-
"y" => 365 * 24 * 60 * 60,
|
12
|
-
"d" => 24 * 60 * 60,
|
13
|
-
"h" => 60 * 60,
|
14
|
-
"m" => 60,
|
15
|
-
"s" => 1
|
16
|
-
}
|
17
|
-
|
18
|
-
# A regex describing valid formats with groups for capturing the value and units
|
19
|
-
FORMAT = /^(\d+)(y|d|h|m|s)?$/
|
20
|
-
|
21
|
-
attr_reader :errors, :munged_value
|
22
|
-
|
23
|
-
def initialize(name, setting_value)
|
24
|
-
@errors = []
|
25
|
-
@munged_value = munge(setting_value, name)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Convert the value to Numeric, parsing numeric string with units if necessary.
|
29
|
-
def munge(value, name)
|
30
|
-
case
|
31
|
-
when value.is_a?(Numeric)
|
32
|
-
if value < 0
|
33
|
-
@errors << "Invalid negative 'time to live' #{value.inspect} - did you mean 'unlimited'?"
|
34
|
-
end
|
35
|
-
value
|
36
|
-
|
37
|
-
when value == 'unlimited'
|
38
|
-
Float::INFINITY
|
39
|
-
|
40
|
-
when (value.is_a?(String) and value =~ FORMAT)
|
41
|
-
$1.to_i * UNITMAP[$2 || 's']
|
42
|
-
else
|
43
|
-
@errors << "Invalid 'time to live' format '#{value.inspect}' for parameter: #{name}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'etc'
|
3
|
-
|
4
|
-
module Puppetserver
|
5
|
-
module Utils
|
6
|
-
class FileUtilities
|
7
|
-
|
8
|
-
def self.instance
|
9
|
-
@instance ||= new
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.write_file(*args)
|
13
|
-
instance.write_file(*args)
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.ensure_dir(setting)
|
17
|
-
instance.ensure_dir(setting)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.ensure_file(location, content, mode)
|
21
|
-
if !File.exist?(location)
|
22
|
-
instance.write_file(location, content, mode)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.validate_file_paths(one_or_more_paths)
|
27
|
-
errors = []
|
28
|
-
Array(one_or_more_paths).each do |path|
|
29
|
-
if !File.exist?(path) || !File.readable?(path)
|
30
|
-
errors << "Could not read file '#{path}'"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
errors
|
35
|
-
end
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
@user, @group = find_user_and_group
|
39
|
-
end
|
40
|
-
|
41
|
-
def find_user_and_group
|
42
|
-
if !running_as_root?
|
43
|
-
return Process.euid, Process.egid
|
44
|
-
else
|
45
|
-
if pe_puppet_exists?
|
46
|
-
return 'pe-puppet', 'pe-puppet'
|
47
|
-
else
|
48
|
-
return 'puppet', 'puppet'
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def running_as_root?
|
54
|
-
!Gem.win_platform? && Process.euid == 0
|
55
|
-
end
|
56
|
-
|
57
|
-
def pe_puppet_exists?
|
58
|
-
!!(Etc.getpwnam('pe-puppet') rescue nil)
|
59
|
-
end
|
60
|
-
|
61
|
-
def write_file(path, one_or_more_objects, mode)
|
62
|
-
File.open(path, 'w', mode) do |f|
|
63
|
-
Array(one_or_more_objects).each do |object|
|
64
|
-
f.puts object.to_s
|
65
|
-
end
|
66
|
-
end
|
67
|
-
FileUtils.chown(@user, @group, path)
|
68
|
-
end
|
69
|
-
|
70
|
-
def ensure_dir(setting)
|
71
|
-
if !File.exist?(setting)
|
72
|
-
FileUtils.mkdir_p(setting, mode: 0750)
|
73
|
-
FileUtils.chown(@user, @group, setting)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,129 +0,0 @@
|
|
1
|
-
require 'openssl'
|
2
|
-
require 'net/https'
|
3
|
-
|
4
|
-
module Puppetserver
|
5
|
-
module Utils
|
6
|
-
# Utilities for doing HTTPS against the CA that wraps Net::HTTP constructs
|
7
|
-
class HttpClient
|
8
|
-
|
9
|
-
HEADERS = {
|
10
|
-
'User-Agent' => 'PuppetserverCaCli',
|
11
|
-
'Content-Type' => 'application/json',
|
12
|
-
'Accept' => 'application/json'
|
13
|
-
}
|
14
|
-
|
15
|
-
attr_reader :store
|
16
|
-
|
17
|
-
def initialize(settings)
|
18
|
-
@store = make_store(settings[:localcacert],
|
19
|
-
settings[:certificate_revocation],
|
20
|
-
settings[:hostcrl])
|
21
|
-
@cert = load_cert(settings[:hostcert])
|
22
|
-
@key = load_key(settings[:hostprivkey])
|
23
|
-
end
|
24
|
-
|
25
|
-
def load_cert(cert_path)
|
26
|
-
OpenSSL::X509::Certificate.new(File.read(cert_path))
|
27
|
-
end
|
28
|
-
|
29
|
-
def load_key(key_path)
|
30
|
-
OpenSSL::PKey.read(File.read(key_path))
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns a URI-like wrapper around CA specific urls
|
34
|
-
def make_ca_url(host, port, resource_type = nil, certname = nil)
|
35
|
-
URL.new('https', host, port, 'puppet-ca', 'v1', resource_type, certname)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Takes an instance URL (defined lower in the file), and creates a
|
39
|
-
# connection. The given block is passed our own Connection object.
|
40
|
-
# The Connection object should have HTTP verbs defined on it that take
|
41
|
-
# a body (and optional overrides). Returns whatever the block given returned.
|
42
|
-
def with_connection(url, &block)
|
43
|
-
request = ->(conn) { block.call(Connection.new(conn, url)) }
|
44
|
-
|
45
|
-
Net::HTTP.start(url.host, url.port,
|
46
|
-
use_ssl: true, cert_store: @store,
|
47
|
-
cert: @cert, key: @key,
|
48
|
-
&request)
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
# Helper class that wraps a Net::HTTP connection, a HttpClient::URL
|
53
|
-
# and defines methods named after HTTP verbs that are called on the
|
54
|
-
# saved connection, returning a Result.
|
55
|
-
class Connection
|
56
|
-
def initialize(net_http_connection, url_struct)
|
57
|
-
@conn = net_http_connection
|
58
|
-
@url = url_struct
|
59
|
-
end
|
60
|
-
|
61
|
-
def get(url_overide = nil)
|
62
|
-
url = url_overide || @url
|
63
|
-
|
64
|
-
request = Net::HTTP::Get.new(url.to_uri, HEADERS)
|
65
|
-
result = @conn.request(request)
|
66
|
-
|
67
|
-
Result.new(result.code, result.body)
|
68
|
-
end
|
69
|
-
|
70
|
-
def put(body, url_override = nil)
|
71
|
-
url = url_override || @url
|
72
|
-
|
73
|
-
request = Net::HTTP::Put.new(url.to_uri, HEADERS)
|
74
|
-
request.body = body
|
75
|
-
result = @conn.request(request)
|
76
|
-
|
77
|
-
Result.new(result.code, result.body)
|
78
|
-
end
|
79
|
-
|
80
|
-
def delete(url_override = nil)
|
81
|
-
url = url_override || @url
|
82
|
-
|
83
|
-
result = @conn.request(Net::HTTP::Delete.new(url.to_uri, HEADERS))
|
84
|
-
|
85
|
-
Result.new(result.code, result.body)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Just provide the bits of Net::HTTPResponse we care about
|
90
|
-
Result = Struct.new(:code, :body)
|
91
|
-
|
92
|
-
# Like URI, but not... maybe of suspicious value
|
93
|
-
URL = Struct.new(:protocol, :host, :port,
|
94
|
-
:endpoint, :version,
|
95
|
-
:resource_type, :resource_name) do
|
96
|
-
def full_url
|
97
|
-
protocol + '://' + host + ':' + port + '/' +
|
98
|
-
[endpoint, version, resource_type, resource_name].join('/')
|
99
|
-
end
|
100
|
-
|
101
|
-
def to_uri
|
102
|
-
URI(full_url)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def make_store(bundle, crl_usage, crls = nil)
|
107
|
-
store = OpenSSL::X509::Store.new
|
108
|
-
store.purpose = OpenSSL::X509::PURPOSE_ANY
|
109
|
-
store.add_file(bundle)
|
110
|
-
|
111
|
-
if crl_usage != :ignore
|
112
|
-
|
113
|
-
flags = OpenSSL::X509::V_FLAG_CRL_CHECK
|
114
|
-
if crl_usage == :chain
|
115
|
-
flags |= OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
|
116
|
-
end
|
117
|
-
|
118
|
-
store.flags = flags
|
119
|
-
delimiter = /-----BEGIN X509 CRL-----.*?-----END X509 CRL-----/m
|
120
|
-
File.read(crls).scan(delimiter).each do |crl|
|
121
|
-
store.add_crl(OpenSSL::X509::CRL.new(crl))
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
store
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Puppetserver
|
2
|
-
module Utils
|
3
|
-
class SigningDigest
|
4
|
-
|
5
|
-
attr_reader :errors, :digest
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@errors = []
|
9
|
-
if OpenSSL::Digest.const_defined?('SHA256')
|
10
|
-
@digest = OpenSSL::Digest::SHA256.new
|
11
|
-
elsif OpenSSL::Digest.const_defined?('SHA1')
|
12
|
-
@digest = OpenSSL::Digest::SHA1.new
|
13
|
-
elsif OpenSSL::Digest.const_defined?('SHA512')
|
14
|
-
@digest = OpenSSL::Digest::SHA512.new
|
15
|
-
elsif OpenSSL::Digest.const_defined?('SHA384')
|
16
|
-
@digest = OpenSSL::Digest::SHA384.new
|
17
|
-
elsif OpenSSL::Digest.const_defined?('SHA224')
|
18
|
-
@digest = OpenSSL::Digest::SHA224.new
|
19
|
-
else
|
20
|
-
@errors << "Error: No FIPS 140-2 compliant digest algorithm in OpenSSL::Digest"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|