kybus-ssl 0.1.0 → 0.2.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/bin/kybssl +90 -0
- data/lib/kybus/ssl/certificate.rb +1 -1
- data/lib/kybus/ssl/cli/add_ca.rb +37 -0
- data/lib/kybus/ssl/cli/add_certificate.rb +37 -0
- data/lib/kybus/ssl/cli/base_command.rb +44 -0
- data/lib/kybus/ssl/cli/build.rb +0 -0
- data/lib/kybus/ssl/cli/init.rb +191 -0
- data/lib/kybus/ssl/cli/revoke_certificate.rb +0 -0
- data/lib/kybus/ssl/cli.rb +6 -0
- data/lib/kybus/ssl/configuration.rb +13 -4
- data/lib/kybus/ssl/inventory.rb +6 -1
- data/lib/kybus/ssl/revocation_list.rb +2 -0
- data/lib/kybus/ssl/version.rb +1 -1
- metadata +29 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa8499e77ca6b86352e3e7bcbcd89080419ff5ebf9122b681aecbb189ef3bbd4
|
4
|
+
data.tar.gz: 52d7ec328216a409462fbf398c6d99eea73dd0db08e847d9d6a4b30b15affcb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3b5bce4e64ac747d0738b560cf0c0a5a853ca0fe843b8860baf72a1960644bebd397ff61f6fc6710fdf6f336a49e02ca662803277c89e8fc7be52f633dc1f00
|
7
|
+
data.tar.gz: 73a58d32976e8b016eec3986c1f0e7a4939a364237769b7fa9e76e88ae8b4e615fe96313b50b2bce1c551c318763678dc2c01432c993d79d891bb1193f55e79a
|
data/bin/kybssl
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'optimist'
|
2
|
+
require 'yaml'
|
3
|
+
require './lib/kybus/ssl/cli'
|
4
|
+
|
5
|
+
def run_init(opts)
|
6
|
+
Kybus::SSL::CLI::Init.new(opts).run
|
7
|
+
end
|
8
|
+
|
9
|
+
def run_add_ca(opts)
|
10
|
+
Kybus::SSL::CLI::AddCA.new(opts).run
|
11
|
+
end
|
12
|
+
|
13
|
+
def run_add_certificate(opts)
|
14
|
+
Kybus::SSL::CLI::AddCertificate.new(opts).run
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_revoke_certificate(opts); end
|
18
|
+
|
19
|
+
def run_build(opts); end
|
20
|
+
|
21
|
+
# Define expected commands and options
|
22
|
+
commands = %i[init add_ca add_certificate revoke_certificate build]
|
23
|
+
cmd = ARGV.shift&.to_sym || :help
|
24
|
+
abort "Invalid command. Valid commands are: #{commands.join(', ')}" unless commands.include?(cmd)
|
25
|
+
|
26
|
+
def global_params(context, cmd)
|
27
|
+
context.instance_eval do
|
28
|
+
opt :pki_file, 'PKI File', type: :string, required: true
|
29
|
+
opt :team, 'Organization Unit name', type: :string, required: cmd == :init
|
30
|
+
opt :country, 'Organization Unit name', type: :string, required: cmd == :init
|
31
|
+
opt :state, 'Organization Unit name', type: :string, required: cmd == :init
|
32
|
+
opt :city, 'Organization Unit name', type: :string, required: cmd == :init
|
33
|
+
opt :organization, 'Organization Unit name', type: :string, required: cmd == :init
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
opts = case cmd
|
38
|
+
when :init
|
39
|
+
Optimist.options do
|
40
|
+
banner 'Usage: kybssl init [options]'
|
41
|
+
opt :outputdir, 'Output Directory', type: :string, default: 'pki'
|
42
|
+
opt :force, 'Overwrite file if it already exists', type: :bool, default: false
|
43
|
+
global_params(self, cmd)
|
44
|
+
end
|
45
|
+
when :add_ca
|
46
|
+
Optimist.options do
|
47
|
+
banner 'Usage: kybssl add-ca [options]'
|
48
|
+
opt :caname, 'CA Name', type: :string, required: true
|
49
|
+
opt :name, 'Common Name', type: :string, required: true
|
50
|
+
opt :expiration, 'Validity Years', type: :integer, default: 10
|
51
|
+
opt :keysize, 'Key Size', type: :integer, default: 2048
|
52
|
+
opt :parent, 'Parent CA', type: :string, default: 'root'
|
53
|
+
global_params(self, cmd)
|
54
|
+
end
|
55
|
+
when :add_certificate
|
56
|
+
Optimist.options do
|
57
|
+
banner 'Usage: kybssl add-certificate [options]'
|
58
|
+
opt :name, 'Common Name', type: :string, required: true
|
59
|
+
opt :email, 'User Email', type: :string, require: true
|
60
|
+
opt :dns, 'Server DNS', type: :string
|
61
|
+
opt :ca, 'CA Name', type: :string, required: true
|
62
|
+
opt :expiration, 'Validity Years', type: :integer, default: 5
|
63
|
+
opt :type, 'Type of certificate client|server', type: :string, default: 'client'
|
64
|
+
global_params(self, cmd)
|
65
|
+
end
|
66
|
+
when :revoke_certificate
|
67
|
+
Optimist.options do
|
68
|
+
banner 'Usage: kybssl revoke-certificate [options]'
|
69
|
+
opt :serial, 'Certificate Serial', type: :string, required: true
|
70
|
+
global_params(self, cmd)
|
71
|
+
end
|
72
|
+
when :build
|
73
|
+
Optimist.options do
|
74
|
+
banner 'Usage: kybssl build [options]'
|
75
|
+
global_params(self, cmd)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
case cmd
|
80
|
+
when :init
|
81
|
+
run_init(opts)
|
82
|
+
when :add_ca
|
83
|
+
run_add_ca(opts)
|
84
|
+
when :add_certificate
|
85
|
+
run_add_certificate(opts)
|
86
|
+
when :revoke_certificate
|
87
|
+
run_revoke_certificate(opts)
|
88
|
+
when :build
|
89
|
+
run_build(opts)
|
90
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module SSL
|
5
|
+
module CLI
|
6
|
+
class AddCA < BaseCommand
|
7
|
+
def run
|
8
|
+
load_template
|
9
|
+
update_yaml_file
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def update_yaml_file
|
15
|
+
new_ca = {
|
16
|
+
caname: @opts[:caname],
|
17
|
+
name: @opts[:name],
|
18
|
+
expiration: @opts[:expiration],
|
19
|
+
key_size: @opts[:key_size],
|
20
|
+
parent: @opts[:parent] || 'root',
|
21
|
+
serial: next_serial,
|
22
|
+
extensions: {
|
23
|
+
basicConstraints: {
|
24
|
+
details: 'CA:true, pathlen:0',
|
25
|
+
critical: true
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
@template['certificate_descriptions']['authorities']['certificates'] << new_ca
|
31
|
+
|
32
|
+
save_template
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module SSL
|
5
|
+
module CLI
|
6
|
+
class AddCertificate < BaseCommand
|
7
|
+
def run
|
8
|
+
load_template
|
9
|
+
update_yaml_file
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def update_yaml_file
|
15
|
+
new_certificate = {
|
16
|
+
parent: @opts[:ca],
|
17
|
+
name: @opts[:name],
|
18
|
+
expiration: @opts[:expiration],
|
19
|
+
key_size: @opts[:key_size],
|
20
|
+
serial: next_serial,
|
21
|
+
organization: @opts[:org],
|
22
|
+
team: @opts[:team],
|
23
|
+
country: @opts[:country],
|
24
|
+
city: @opts[:city],
|
25
|
+
state: @opts[:state],
|
26
|
+
email: @opts[:email],
|
27
|
+
revoked: false
|
28
|
+
}.compact
|
29
|
+
|
30
|
+
@template['certificate_descriptions']['clients']['certificates'] << new_certificate
|
31
|
+
|
32
|
+
save_template
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module SSL
|
5
|
+
module CLI
|
6
|
+
class BaseCommand
|
7
|
+
def initialize(opts)
|
8
|
+
@opts = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def transform_keys_recursively(hash)
|
12
|
+
hash.each_with_object({}) do |(key, value), new_hash|
|
13
|
+
new_key = key.is_a?(Symbol) ? key.to_s : key
|
14
|
+
new_value = if value.is_a?(Hash)
|
15
|
+
transform_keys_recursively(value)
|
16
|
+
elsif value.is_a?(Array)
|
17
|
+
value.map { |v| transform_keys_recursively(v) }
|
18
|
+
else
|
19
|
+
value
|
20
|
+
end
|
21
|
+
new_hash[new_key] = new_value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_template
|
26
|
+
@template = YAML.load_file(@opts[:pki_file])
|
27
|
+
end
|
28
|
+
|
29
|
+
def save_template
|
30
|
+
@template = transform_keys_recursively(@template)
|
31
|
+
File.write(@opts[:pki_file], @template.to_yaml)
|
32
|
+
end
|
33
|
+
|
34
|
+
def next_serial
|
35
|
+
@template['serial_counter'] += 1
|
36
|
+
end
|
37
|
+
|
38
|
+
def pki_file_exist?
|
39
|
+
File.file?(@opts[:pki_file])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
File without changes
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_command'
|
4
|
+
|
5
|
+
module Kybus
|
6
|
+
module SSL
|
7
|
+
module CLI
|
8
|
+
class Init < BaseCommand
|
9
|
+
def build_default_config
|
10
|
+
@template = {
|
11
|
+
serial_counter: 3,
|
12
|
+
certificate_descriptions: {
|
13
|
+
defaults: certificate_defaults,
|
14
|
+
authorities: default_authorities,
|
15
|
+
clients: default_clients_config,
|
16
|
+
servers: default_servers_config
|
17
|
+
}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_certificate_extensions
|
22
|
+
{
|
23
|
+
subjectKeyIdentifier: {
|
24
|
+
details: 'hash',
|
25
|
+
critical: false
|
26
|
+
},
|
27
|
+
authorityKeyIdentifier: {
|
28
|
+
details: 'keyid:always',
|
29
|
+
critical: false
|
30
|
+
},
|
31
|
+
basicConstraints: {
|
32
|
+
details: 'CA:false',
|
33
|
+
critical: false
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def certificate_defaults
|
39
|
+
{
|
40
|
+
saving_directory: @opts[:outputdir],
|
41
|
+
country: @opts[:country],
|
42
|
+
state: @opts[:state],
|
43
|
+
city: @opts[:city],
|
44
|
+
organization: @opts[:organization],
|
45
|
+
team: @opts[:team],
|
46
|
+
key_size: @opts[:key_size],
|
47
|
+
expiration: 5,
|
48
|
+
extensions: default_certificate_extensions
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def root_ca
|
53
|
+
{
|
54
|
+
name: "#{@opts[:organization]} Root CA",
|
55
|
+
expiration: 20,
|
56
|
+
serial: 1,
|
57
|
+
key_size: 4096,
|
58
|
+
ca: 'root',
|
59
|
+
parent: 'root'
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def servers_ca
|
64
|
+
{
|
65
|
+
name: "#{@opts[:organization]} Servers CA",
|
66
|
+
parent: 'root',
|
67
|
+
expiration: 10,
|
68
|
+
serial: 2,
|
69
|
+
ca: 'servers',
|
70
|
+
key_size: 2048,
|
71
|
+
extensions: {
|
72
|
+
basicConstraints: {
|
73
|
+
details: 'CA:true, pathlen:0',
|
74
|
+
critical: true
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def clients_ca
|
81
|
+
{
|
82
|
+
name: "#{@opts[:organization]} Clients CA",
|
83
|
+
parent: 'root',
|
84
|
+
expiration: 10,
|
85
|
+
serial: 3,
|
86
|
+
ca: 'clients',
|
87
|
+
key_size: 2048,
|
88
|
+
extensions: {
|
89
|
+
basicConstraints: {
|
90
|
+
details: 'CA:true, pathlen:0',
|
91
|
+
critical: true
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def default_authorities
|
98
|
+
{
|
99
|
+
defaults: {
|
100
|
+
parent: 'root',
|
101
|
+
extensions: {
|
102
|
+
basicConstraints: {
|
103
|
+
details: 'CA:true',
|
104
|
+
critical: true
|
105
|
+
},
|
106
|
+
keyUsage: {
|
107
|
+
details: 'Digital Signature, keyCertSign, cRLSign',
|
108
|
+
critical: true
|
109
|
+
}
|
110
|
+
}
|
111
|
+
},
|
112
|
+
certificates: [root_ca, servers_ca, clients_ca]
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def default_servers_config
|
117
|
+
{
|
118
|
+
defaults: {
|
119
|
+
parent: 'servers',
|
120
|
+
extensions: {
|
121
|
+
'Netscape Cert Type': {
|
122
|
+
details: 'SSL Server',
|
123
|
+
critical: false
|
124
|
+
},
|
125
|
+
'Netscape Comment': {
|
126
|
+
details: 'Server certificate',
|
127
|
+
critical: false
|
128
|
+
},
|
129
|
+
keyUsage: {
|
130
|
+
details: 'Digital Signature, Key Encipherment',
|
131
|
+
critical: true
|
132
|
+
},
|
133
|
+
extendedKeyUsage: {
|
134
|
+
details: 'TLS Web Server Authentication',
|
135
|
+
critical: false
|
136
|
+
},
|
137
|
+
authorityKeyIdentifier: {
|
138
|
+
details: 'keyid, issuer:always',
|
139
|
+
critical: false
|
140
|
+
},
|
141
|
+
subjectAltName: {
|
142
|
+
details: '$dns',
|
143
|
+
critical: false
|
144
|
+
}
|
145
|
+
}
|
146
|
+
},
|
147
|
+
certificates: []
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
def default_clients_config
|
152
|
+
{
|
153
|
+
defaults: {
|
154
|
+
parent: 'clients',
|
155
|
+
extensions: {
|
156
|
+
'Netscape Cert Type': {
|
157
|
+
details: 'SSL Client, S/MIME',
|
158
|
+
critical: false
|
159
|
+
},
|
160
|
+
'Netscape Comment': {
|
161
|
+
details: 'Client certificate',
|
162
|
+
critical: false
|
163
|
+
},
|
164
|
+
keyUsage: {
|
165
|
+
details: 'Digital Signature, Non Repudiation, Key Encipherment',
|
166
|
+
critical: true
|
167
|
+
},
|
168
|
+
extendedKeyUsage: {
|
169
|
+
details: 'TLS Web Client Authentication, E-mail Protection',
|
170
|
+
critical: false
|
171
|
+
},
|
172
|
+
subjectAltName: {
|
173
|
+
details: '$email',
|
174
|
+
critical: false
|
175
|
+
}
|
176
|
+
},
|
177
|
+
team: @opts[:team]
|
178
|
+
},
|
179
|
+
certificates: []
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
def run
|
184
|
+
abort 'File already exists. Use --force to overwrite.' if pki_file_exist? && !@opts[:force]
|
185
|
+
build_default_config
|
186
|
+
save_template
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
File without changes
|
@@ -26,8 +26,8 @@ module Kybus
|
|
26
26
|
|
27
27
|
def subject_string
|
28
28
|
"/C=#{@config['country']}/ST=#{@config['state']}" \
|
29
|
-
|
30
|
-
|
29
|
+
"/L=#{@config['city']}/O=#{@config['organization']}" \
|
30
|
+
"/OU=#{@config['team']}/CN=#{@config['name']}"
|
31
31
|
end
|
32
32
|
|
33
33
|
def configure_cert_details!(cert)
|
@@ -35,14 +35,23 @@ module Kybus
|
|
35
35
|
cert.serial = @config['serial']
|
36
36
|
cert.subject = OpenSSL::X509::Name.parse(subject_string)
|
37
37
|
cert.not_before = Time.now
|
38
|
-
cert.not_after = cert.not_before + ONE_YEAR * @config['expiration']
|
38
|
+
cert.not_after = cert.not_before + (ONE_YEAR * @config['expiration'])
|
39
|
+
end
|
40
|
+
|
41
|
+
def apply_placeholders(description)
|
42
|
+
if description.include?('$')
|
43
|
+
description.gsub('$email', "email:#{@config['email']}").gsub('$dns', "DNS:#{@config['dns']}")
|
44
|
+
else
|
45
|
+
description
|
46
|
+
end
|
39
47
|
end
|
40
48
|
|
41
49
|
def configure_extensions!(cert, extension_factory)
|
42
50
|
@config['extensions'].each do |name, details|
|
51
|
+
applied_description = apply_placeholders(details['details'])
|
43
52
|
extension = extension_factory.create_extension(
|
44
53
|
name,
|
45
|
-
|
54
|
+
applied_description,
|
46
55
|
details['critical']
|
47
56
|
)
|
48
57
|
cert.add_extension(extension)
|
data/lib/kybus/ssl/inventory.rb
CHANGED
@@ -47,6 +47,8 @@ module Kybus
|
|
47
47
|
# configurations.
|
48
48
|
class SubInventory
|
49
49
|
def initialize(configs, inventory)
|
50
|
+
raise 'Nil config' if configs.nil?
|
51
|
+
|
50
52
|
defaults = configs['defaults']
|
51
53
|
@parent = inventory
|
52
54
|
@certificates = configs['certificates'].map do |cert|
|
@@ -64,7 +66,10 @@ module Kybus
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def ca(name)
|
67
|
-
@certificates.find { |cert| cert.ca_name == name }
|
69
|
+
ca = @certificates.find { |cert| cert.ca_name == name }
|
70
|
+
raise "CA #{name} not found" if ca.nil?
|
71
|
+
|
72
|
+
ca
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
data/lib/kybus/ssl/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kybus-ssl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gilberto Vargas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: optimist
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: minitest
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,12 +111,21 @@ dependencies:
|
|
97
111
|
description: Package for creating self signed certificates for development purpose
|
98
112
|
email:
|
99
113
|
- tachoguitar@gmail.com
|
100
|
-
executables:
|
114
|
+
executables:
|
115
|
+
- kybssl
|
101
116
|
extensions: []
|
102
117
|
extra_rdoc_files: []
|
103
118
|
files:
|
119
|
+
- bin/kybssl
|
104
120
|
- lib/kybus/ssl.rb
|
105
121
|
- lib/kybus/ssl/certificate.rb
|
122
|
+
- lib/kybus/ssl/cli.rb
|
123
|
+
- lib/kybus/ssl/cli/add_ca.rb
|
124
|
+
- lib/kybus/ssl/cli/add_certificate.rb
|
125
|
+
- lib/kybus/ssl/cli/base_command.rb
|
126
|
+
- lib/kybus/ssl/cli/build.rb
|
127
|
+
- lib/kybus/ssl/cli/init.rb
|
128
|
+
- lib/kybus/ssl/cli/revoke_certificate.rb
|
106
129
|
- lib/kybus/ssl/configuration.rb
|
107
130
|
- lib/kybus/ssl/inventory.rb
|
108
131
|
- lib/kybus/ssl/revocation_list.rb
|
@@ -110,7 +133,8 @@ files:
|
|
110
133
|
homepage: https://github.com/KueskiEngineering/ruby-kybus-server
|
111
134
|
licenses:
|
112
135
|
- MIT
|
113
|
-
metadata:
|
136
|
+
metadata:
|
137
|
+
rubygems_mfa_required: 'true'
|
114
138
|
post_install_message:
|
115
139
|
rdoc_options: []
|
116
140
|
require_paths:
|
@@ -126,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
150
|
- !ruby/object:Gem::Version
|
127
151
|
version: '0'
|
128
152
|
requirements: []
|
129
|
-
rubygems_version: 3.
|
153
|
+
rubygems_version: 3.5.14
|
130
154
|
signing_key:
|
131
155
|
specification_version: 4
|
132
156
|
summary: Kybus SSL tools
|