ovpn-key 0.8 → 0.8.5
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/README.md +1 -1
- data/bin/ovpn-key +3 -3
- data/lib/functions.rb +59 -45
- data/lib/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7416051f932e40fb29c714599ad2ae7090b33dd0cf90ac31d3186993adc5a29a
|
4
|
+
data.tar.gz: 85b35e1706fd1ea6892363cb01caf734b7c6bf84614aac5a31d3d31c1f10bf8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c6baffe4fe1c9340cc4a2cff365eb82ea5a63aa4e943ea4aecd3bb629459558363f6fcd4621b97f287427a91f05562689ab4451915bf84b2dfde192970a6d1e
|
7
|
+
data.tar.gz: 4759d340ff8f701aa5f1ea2e084070dd55a9511ddd9ee0583feb6d1c51a62187661207022a6e401010f89c9435dff71df767e34bbfef5c0c42f03aec1a67e2e7
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ If you're brave, [let me know](https://github.com/chillum/ovpn-key/issues), wher
|
|
40
40
|
|
41
41
|
### Configuration
|
42
42
|
|
43
|
-
|
43
|
+
It's just a single simple YAML file named [`ovpn-key.yml`](https://github.com/chillum/ovpn-key/blob/master/defaults/ovpn-key.yml).
|
44
44
|
|
45
45
|
ovpn-key also processes `~/.ovpn-key.yml` file, for now it has only one possible setting:
|
46
46
|
```yaml
|
data/bin/ovpn-key
CHANGED
@@ -15,7 +15,9 @@ CRL_FILE = 'crl.pem'
|
|
15
15
|
SERIAL_FILE = 'serial'
|
16
16
|
|
17
17
|
options = {}
|
18
|
+
# rubocop:disable Metrics/BlockLength
|
18
19
|
OptionParser.new do |opts|
|
20
|
+
# rubocop:enable Metrics/BlockLength
|
19
21
|
opts.banner = "Usage: #{File.basename $PROGRAM_NAME} <options> [--nopass]"
|
20
22
|
opts.on('--init [directory]', 'Init a CA directory (defaults to current)') do |v|
|
21
23
|
options[:init] = v || '.'
|
@@ -44,7 +46,7 @@ OptionParser.new do |opts|
|
|
44
46
|
check_client(v)
|
45
47
|
options[:generate_zip] = v
|
46
48
|
end
|
47
|
-
opts.on(
|
49
|
+
opts.on('--revoke [name]', "Revoke a certificate (using #{CRL_FILE}) and delete it") do |v|
|
48
50
|
abort 'Please specify what certificate to revoke' unless v
|
49
51
|
options[:revoke] = v
|
50
52
|
end
|
@@ -63,7 +65,6 @@ if options[:generate_client] && options[:generate_zip]
|
|
63
65
|
# I assume that user likely wants one of them and is confused with usage
|
64
66
|
abort 'There can be only one: --client or --zip'
|
65
67
|
end
|
66
|
-
umask = File.umask 0o077
|
67
68
|
|
68
69
|
if options[:init]
|
69
70
|
unless options[:init] == '.'
|
@@ -178,7 +179,6 @@ if options[:generate_zip]
|
|
178
179
|
|
179
180
|
zip_file = File.join(File.expand_path(ZIP_DIR), "#{File.basename ovpn_file, '.ovpn'}.tblk.zip")
|
180
181
|
File.delete(zip_file) if File.exist?(zip_file)
|
181
|
-
File.umask umask
|
182
182
|
Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
|
183
183
|
zip.get_output_stream(ovpn_file) {|f|
|
184
184
|
f.write File.read(ovpn_file)
|
data/lib/functions.rb
CHANGED
@@ -26,6 +26,17 @@ def ask_password(name)
|
|
26
26
|
password
|
27
27
|
end
|
28
28
|
|
29
|
+
def unencrypt_ca_key(pass = '')
|
30
|
+
begin
|
31
|
+
OpenSSL::PKey::RSA.new File.read('ca.key'), pass
|
32
|
+
rescue OpenSSL::PKey::RSAError
|
33
|
+
# this means pass is wrong, so ask for it
|
34
|
+
OpenSSL::PKey::RSA.new File.read('ca.key'), ask_password('ca')
|
35
|
+
end
|
36
|
+
rescue OpenSSL::PKey::RSAError
|
37
|
+
retry
|
38
|
+
end
|
39
|
+
|
29
40
|
def gen_and_sign(type, certname, password)
|
30
41
|
gen_key(certname, password)
|
31
42
|
sign_key(type, certname, password)
|
@@ -39,36 +50,48 @@ def gen_key(certname, password)
|
|
39
50
|
end
|
40
51
|
|
41
52
|
# type is one of: 'ca', 'server', 'client'
|
42
|
-
# rubocop:disable Naming/MethodParameterName
|
43
53
|
def sign_key(type, cn, password)
|
44
|
-
# rubocop:enable Naming/MethodParameterName
|
45
54
|
certname = type == 'ca' ? 'ca' : cn
|
46
55
|
key = OpenSSL::PKey::RSA.new File.read("#{certname}.key"), password
|
47
|
-
|
48
|
-
|
49
|
-
File.read(SERIAL_FILE).to_i
|
50
|
-
rescue Errno::ENOENT
|
51
|
-
0
|
52
|
-
end + 1
|
56
|
+
serial = new_serial
|
57
|
+
cert = gen_cert(type, cn, key.public_key, serial)
|
53
58
|
|
59
|
+
ca_key = type == 'ca' ? key : unencrypt_ca_key
|
60
|
+
cert.sign ca_key, OpenSSL::Digest.new(DIGEST)
|
61
|
+
|
62
|
+
File.open(SERIAL_FILE, 'w') {|f| f.write serial }
|
63
|
+
File.open("#{certname}.crt", 'w') {|f| f.write cert.to_pem }
|
64
|
+
end
|
65
|
+
|
66
|
+
def gen_cert(type, cn, pubkey, serial)
|
67
|
+
cert = basic_cert(type, cn)
|
68
|
+
cert.public_key = pubkey
|
69
|
+
cert.serial = serial
|
70
|
+
|
71
|
+
customize_cert(type, cert)
|
72
|
+
end
|
73
|
+
|
74
|
+
def basic_cert(type, cn)
|
54
75
|
cert = OpenSSL::X509::Certificate.new
|
76
|
+
|
55
77
|
cert.version = 2
|
56
|
-
cert.
|
57
|
-
cert.not_before = Time.now
|
58
|
-
cert.not_after =
|
59
|
-
Time.now +
|
60
|
-
case type
|
61
|
-
when 'ca'
|
62
|
-
EXPIRE['ca']
|
63
|
-
when 'server'
|
64
|
-
EXPIRE['server']
|
65
|
-
when 'client'
|
66
|
-
EXPIRE['client']
|
67
|
-
# days to seconds
|
68
|
-
end * 86_400
|
69
|
-
cert.public_key = key.public_key
|
70
|
-
cert.subject = subj
|
78
|
+
cert.subject = OpenSSL::X509::Name.new([['CN', cn]] + REQ.to_a)
|
71
79
|
cert.issuer = OpenSSL::X509::Name.new([['CN', CN_CA]] + REQ.to_a)
|
80
|
+
cert.not_before = Time.now
|
81
|
+
cert.not_after = time_after_days(EXPIRE[type])
|
82
|
+
|
83
|
+
cert
|
84
|
+
end
|
85
|
+
|
86
|
+
def time_after_days(days)
|
87
|
+
Time.now + days * 86_400 # days to seconds
|
88
|
+
end
|
89
|
+
|
90
|
+
# rubocop:disable Metrics/MethodLength
|
91
|
+
# rubocop:disable Metrics/AbcSize
|
92
|
+
def customize_cert(type, cert)
|
93
|
+
# rubocop:enable Metrics/AbcSize
|
94
|
+
# rubocop:enable Metrics/MethodLength
|
72
95
|
|
73
96
|
ef = OpenSSL::X509::ExtensionFactory.new nil, cert
|
74
97
|
ef.issuer_certificate = cert
|
@@ -80,7 +103,6 @@ def sign_key(type, cn, password)
|
|
80
103
|
case type
|
81
104
|
when 'ca'
|
82
105
|
cert.add_extension ef.create_extension('keyUsage', 'cRLSign,keyCertSign')
|
83
|
-
cert.sign key, OpenSSL::Digest.new(DIGEST)
|
84
106
|
when 'server'
|
85
107
|
cert.add_extension ef.create_extension('keyUsage', 'keyEncipherment,digitalSignature')
|
86
108
|
cert.add_extension ef.create_extension('extendedKeyUsage', 'serverAuth')
|
@@ -88,34 +110,21 @@ def sign_key(type, cn, password)
|
|
88
110
|
cert.add_extension ef.create_extension('keyUsage', 'digitalSignature')
|
89
111
|
cert.add_extension ef.create_extension('extendedKeyUsage', 'clientAuth')
|
90
112
|
end
|
91
|
-
|
92
|
-
ca_key = begin
|
93
|
-
OpenSSL::PKey::RSA.new File.read('ca.key'), ask_password('ca')
|
94
|
-
rescue OpenSSL::PKey::RSAError
|
95
|
-
retry
|
96
|
-
end
|
97
|
-
cert.sign ca_key, OpenSSL::Digest.new(DIGEST)
|
98
|
-
end
|
99
|
-
|
100
|
-
File.open(SERIAL_FILE, 'w') {|f| f.write serial }
|
101
|
-
File.open("#{certname}.crt", 'w') {|f| f.write cert.to_pem }
|
113
|
+
cert
|
102
114
|
end
|
103
115
|
|
116
|
+
# rubocop:disable Metrics/AbcSize
|
104
117
|
def revoke(certname)
|
118
|
+
# rubocop:enable Metrics/AbcSize
|
105
119
|
crl = OpenSSL::X509::CRL.new(File.read(CRL_FILE))
|
106
120
|
cert = OpenSSL::X509::Certificate.new(File.read("#{certname}.crt"))
|
107
121
|
revoke = OpenSSL::X509::Revoked.new.tap {|rev|
|
108
122
|
rev.serial = cert.serial
|
109
123
|
rev.time = Time.now
|
110
124
|
}
|
111
|
-
crl.next_update =
|
125
|
+
crl.next_update = time_after_days(EXPIRE['crl'])
|
112
126
|
crl.add_revoked(revoke)
|
113
|
-
|
114
|
-
update_crl(crl, ask_password('ca'))
|
115
|
-
rescue OpenSSL::PKey::RSAError
|
116
|
-
retry
|
117
|
-
end
|
118
|
-
|
127
|
+
update_crl(crl, '')
|
119
128
|
%w[crt key].each {|ext| File.delete "#{certname}.#{ext}" }
|
120
129
|
end
|
121
130
|
|
@@ -128,14 +137,19 @@ def gen_crl(ca_pass)
|
|
128
137
|
end
|
129
138
|
|
130
139
|
def update_crl(crl, ca_pass)
|
131
|
-
ca_key =
|
140
|
+
ca_key = unencrypt_ca_key(ca_pass)
|
132
141
|
crl.last_update = Time.now
|
133
|
-
crl.next_update =
|
134
|
-
crl.version = crl.version + 1
|
142
|
+
crl.next_update = time_after_days(EXPIRE['crl'])
|
135
143
|
crl.sign(ca_key, OpenSSL::Digest.new(DIGEST))
|
136
144
|
File.open(CRL_FILE, 'w') {|f| f.write crl.to_pem }
|
137
145
|
end
|
138
146
|
|
147
|
+
def new_serial
|
148
|
+
File.read(SERIAL_FILE).to_i + 1
|
149
|
+
rescue Errno::ENOENT
|
150
|
+
0
|
151
|
+
end
|
152
|
+
|
139
153
|
def create_dir(name)
|
140
154
|
return if Dir.exist? name
|
141
155
|
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ovpn-key
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vasily Korytov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03-
|
11
|
+
date: 2021-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|