ovpn-key 0.7.3 → 0.8.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
2
  SHA256:
3
- metadata.gz: f3c5c58642f5c151172f602aa1b0182ecf8f45239b5de9c03aca65e9923e2b15
4
- data.tar.gz: b19dbc262c6a83c41f01152b90583afb09a9823a3b4689938ba455429ecba4b8
3
+ metadata.gz: 314eca1d302d14375dbba738bbd66ffcc29bd00d5b77e45705a415e9aadbd5aa
4
+ data.tar.gz: '042730556841b7e05cf523bf57d9a57b7b987d12e15e1308b110fafbf5ab3dac'
5
5
  SHA512:
6
- metadata.gz: a4f9f7bad183e3b5360dfc4e1d70320a7fcaa2ed2590060cf6f86049a1a3789308a4036d6dae2d10feaf304df657677cb42019cbd8efcfc376575680066c1a12
7
- data.tar.gz: 3b03ffa591731f274e90ed97be56fcce4c1a196c2384f8347f52d2c13e554754d2533b653d485656aa79b00cad1c2fa950c9b96f79a9c7fdbc2429b17d375006
6
+ metadata.gz: 82736489c4feba97e504de91c939c3cdb074a988effa3972f07a7e2e674cbdac81af8a1ad7ae89f17c2fa35ed8afa69dbfaaf7bb504baac4ea971ed04aabd824
7
+ data.tar.gz: 7f8d4f05ec4d4a64c4231e4d575a69c7d6bc03180b6538ed2542486792692ff24145ab058644b6bdce50570ed627a8177b38a8837743c7ac4faa031cfbd89099
data/NOTICE CHANGED
@@ -1,6 +1,6 @@
1
1
  ovpn-key: https://github.com/chillum/ovpn-key
2
2
 
3
- Copyright 2018 Vasily Korytov
3
+ Copyright 2018-2021 Vasily Korytov
4
4
 
5
5
  Licensed under the Apache License, Version 2.0 (the "License");
6
6
  you may not use this software except in compliance with the License.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This utility is designed as [easy-rsa](https://github.com/OpenVPN/easy-rsa) replacement suitable for one exact use case.
4
4
 
5
- It's basically a wrapper around `openssl` to:
5
+ It's basically a wrapper around OpenSSL API to:
6
6
  * create a self-signed CA
7
7
  * create client and server certificates and pack them to ZIP files along with the OpenVPN config
8
8
  * revoke the certificates
@@ -28,14 +28,15 @@ If you're brave, [let me know](https://github.com/chillum/ovpn-key/issues), wher
28
28
  ### Usage
29
29
 
30
30
  1. `ovpn-key --init`
31
- 2. edit `ovpn-key.yml` and `openssl.ini`
32
- 3. `ovpn-key --ca --dh --server --nopass`
33
- 4. `ovpn-key --client somebody [--nopass]`
34
- 5. `ovpn-key --revoke somebody`
35
- 6. add a file with `.ovpn` extension to the directory
31
+ 2. edit `ovpn-key.yml`
32
+ 3. `ovpn-key --ca --dh`
33
+ 4. `ovpn-key --server --nopass`
34
+ 5. `ovpn-key --client somebody [--nopass]`
35
+ 6. `ovpn-key --revoke somebody`
36
+ 7. `ovpn-key --static` (generates `ta.key`)
37
+ 8. add a file with `.ovpn` extension to the directory
36
38
  it should contain every setting except for `cert` and `key`
37
- 7. `ovpn-key --zip somebody-else [--nopass]`
38
- 8. `ovpn-key --static` (generates `ta.key`)
39
+ 9. `ovpn-key --zip somebody-else [--nopass]`
39
40
 
40
41
  ### Configuration
41
42
 
data/bin/ovpn-key CHANGED
@@ -1,80 +1,82 @@
1
- #! /usr/bin/env ruby
2
- require 'optparse'
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
3
+
3
4
  require 'fileutils'
5
+ require 'io/console'
6
+ require 'openssl'
7
+ require 'optparse'
4
8
  require 'yaml'
5
9
  require 'zip'
6
- require_relative '../lib/version.rb'
7
- require_relative '../lib/functions.rb'
10
+ require_relative '../lib/version'
11
+ require_relative '../lib/functions'
8
12
 
9
- SSL_CONF = 'openssl.ini'
10
13
  APP_CONF = 'ovpn-key.yml'
14
+ CRL_FILE = 'crl.pem'
15
+ SERIAL_FILE = 'serial'
11
16
 
12
17
  options = {}
13
18
  OptionParser.new do |opts|
14
- opts.banner = "Usage: #{File.basename $0} <options> [--nopass]"
15
- opts.on("--init [directory]", "Init a CA directory (defaults to current)") do |v|
16
- options[:init] = v ? v : "."
19
+ opts.banner = "Usage: #{File.basename $PROGRAM_NAME} <options> [--nopass]"
20
+ opts.on('--init [directory]', 'Init a CA directory (defaults to current)') do |v|
21
+ options[:init] = v || '.'
17
22
  end
18
- opts.on("--ca", "Generate a CA (ca.crt)") do |v|
23
+ opts.on('--ca', 'Generate a CA (ca.crt)') do |v|
19
24
  check_crt('ca')
20
25
  options[:generate_ca] = v
21
26
  end
22
- opts.on("--dh", "Generate a DH keyfile (dh.pem)") do |v|
27
+ opts.on('--dh', 'Generate a DH keyfile (dh.pem)') do |v|
23
28
  # it's safe to overwrite this file
24
29
  options[:generate_dh] = v
25
30
  end
26
- opts.on("--static [name]", "Generate OpenVPN static key (defaults to 'ta')") do |v|
27
- options[:generate_static] = v ? v : "ta"
28
- check_crt(options[:generate_static])
31
+ opts.on('--static', 'Generate OpenVPN static key (ta.key)') do |v|
32
+ options[:generate_static] = v
33
+ check_crt('ta')
29
34
  end
30
- opts.on("--server [name]", "Generate a server key (defaults to 'server')") do |v|
31
- options[:generate_server] = v ? v : "server"
35
+ opts.on('--server [name]', "Generate a server key (defaults to 'server')") do |v|
36
+ options[:generate_server] = v || 'server'
32
37
  check_crt(options[:generate_server])
33
38
  end
34
- opts.on("--client [name]", "Generate a client key and sign it") do |v|
39
+ opts.on('--client [name]', 'Generate a client key and sign it') do |v|
35
40
  check_client(v)
36
41
  options[:generate_client] = v
37
42
  end
38
- opts.on("--zip [name]", "Ditto plus pack it to ZIP with OpenVPN config") do |v|
43
+ opts.on('--zip [name]', 'Ditto plus pack it to ZIP with OpenVPN config') do |v|
39
44
  check_client(v)
40
45
  options[:generate_zip] = v
41
46
  end
42
- opts.on("--revoke [name]", "Revoke a certificate (using crl.pem) and delete it") do |v|
43
- abort "Please specify what certificate to revoke" unless v
47
+ opts.on('--revoke [name]', "Revoke a certificate (using #{CRL_FILE}) and delete it") do |v|
48
+ abort 'Please specify what certificate to revoke' unless v
44
49
  options[:revoke] = v
45
50
  end
46
- opts.on("--nopass", "Don't protect .key files with a password") do |v|
51
+ opts.on('--nopass', "Don't protect .key files with a password") do |v|
47
52
  options[:no_password] = v
48
53
  end
49
54
  end.parse!
50
- if ARGV.length > 0
51
- abort "Error: invalid args: #{ARGV.join ' '}\nSee `#{File.basename $0} -h` for help"
55
+ if ARGV.length.positive?
56
+ abort "Error: invalid args: #{ARGV.join ' '}\nSee `#{File.basename $PROGRAM_NAME} -h` for help"
52
57
  end
53
58
  unless options[:init] || options[:generate_ca] || options[:generate_dh] || options[:generate_static] \
54
59
  || options[:generate_server] || options[:generate_client] || options[:generate_zip] || options[:revoke]
55
- abort "See `#{File.basename $0} -h` for usage"
60
+ abort "See `#{File.basename $PROGRAM_NAME} -h` for usage"
56
61
  end
57
- if options[:generate_client] and options[:generate_zip]
62
+ if options[:generate_client] && options[:generate_zip]
58
63
  # I assume that user likely wants one of them and is confused with usage
59
- abort "There can be only one: --client or --zip"
64
+ abort 'There can be only one: --client or --zip'
60
65
  end
61
- umask = File.umask 0077
66
+ umask = File.umask 0o077
62
67
 
63
68
  if options[:init]
64
69
  unless options[:init] == '.'
65
70
  create_dir options[:init]
66
71
  Dir.chdir options[:init]
67
72
  end
68
- ['certs', 'meta'].each {|dir| create_dir dir}
69
- ['meta/index.txt', 'meta/index.txt.attr', 'meta/serial', SSL_CONF, APP_CONF].each {|file|
70
- unless File.exist? file
71
- FileUtils.copy_file(File.expand_path("defaults/#{file}", "#{__dir__}/.."), "./#{file}")
72
- puts "Created file: #{file}"
73
- end
74
- }
73
+ unless File.exist? APP_CONF
74
+ FileUtils.copy_file(File.expand_path("defaults/#{APP_CONF}", "#{__dir__}/.."), "./#{APP_CONF}")
75
+ puts "Created file: #{APP_CONF}"
76
+ end
75
77
  elsif !File.exist? APP_CONF
76
78
  begin
77
- rc = YAML.load_file(File.expand_path "~/.#{APP_CONF}")
79
+ rc = YAML.load_file(File.expand_path("~/.#{APP_CONF}"))
78
80
  rescue Errno::ENOENT
79
81
  # no configuration file in home directory is not an error
80
82
  end
@@ -84,32 +86,82 @@ end
84
86
  begin
85
87
  settings = YAML.load_file(APP_CONF)
86
88
  rescue Errno::ENOENT
87
- abort "Run `#{File.basename $0} --init` before generating certificates"
89
+ abort "Run `#{File.basename $PROGRAM_NAME} --init` before generating certificates"
88
90
  end
89
91
  ZIP_DIR = settings['zip_dir'] || '~'
90
92
  OPENVPN = settings['openvpn'] || 'openvpn'
91
- OPENSSL = settings['openssl'] || 'openssl'
92
- KEY_SIZE = settings['key_size'] || 2048
93
93
  ENCRYPT = settings['encrypt'] || 'aes128'
94
+ DIGEST = settings['digest'] || 'sha256'
95
+ KEY_SIZE = settings['key_size'] || 2048
94
96
  CN_CA = settings['ca_name'] || 'Certification Authority'
95
- REQ = settings['details']
97
+
98
+ unless settings['ca_days'].nil?
99
+ if settings['expire'].nil?
100
+ puts 'Migrating pre-0.8 configuration to new format: ca_days'
101
+ puts "WARNING: if you tweaked `default_days` or `default_days_crl` in #{SSL_CONF}, edit #{APP_CONF}"
102
+ File.open(APP_CONF, 'a') do |f|
103
+ f.write "# ca_days is not used anymore, you can remove it\nexpire:\n"
104
+ f.write " ca: #{settings['ca_days']}\n crl: 3650\n server: 3650\n client: 3650\n"
105
+ end
106
+ else
107
+ puts "WARNING: `ca_days` setting is deprecated, remove it from #{APP_CONF}"
108
+ end
109
+ end
110
+
111
+ settings['expire'] ||= {}
112
+ settings['expire']['ca'] ||= settings['ca_days'] || 3650
113
+ settings['expire']['crl'] ||= 3650
114
+ settings['expire']['server'] ||= 3650
115
+ settings['expire']['client'] ||= 3650
116
+ EXPIRE = settings['expire']
117
+
118
+ if settings['x509'].nil? && !settings['details'].nil?
119
+ puts 'Migrating pre-0.8 configuration to new format: details'
120
+ REQ = OpenSSL::X509::Name.parse(settings['details']).to_a
121
+ File.open(APP_CONF, 'a') do |f|
122
+ f.write "# details is not used anymore, you can remove it\nx509:\n"
123
+ REQ.map {|i, j| f.write " #{i}: #{j}\n" }
124
+ end
125
+ else
126
+ REQ = settings['x509']
127
+ puts "WARNING: `details` section is deprecated, remove it from #{APP_CONF}" unless settings['details'].nil?
128
+ end
129
+ if settings['openssl']
130
+ puts "WARNING: `openssl` setting is deprecated, remove it from #{APP_CONF}"
131
+ end
132
+
133
+ if !File.exist?(SERIAL_FILE) && File.exist?('meta/serial')
134
+ FileUtils.copy_file('meta/serial', SERIAL_FILE)
135
+ puts 'Copied meta/serial to serial'
136
+ end
137
+ %w[certs meta].each {|dir|
138
+ puts "WARNING: #{dir} directory is not used anymore. you can remove it" if File.exist? dir
139
+ }
140
+ if File.exist? 'openssl.ini'
141
+ puts 'WARNING: openssl.ini file is not used anymore. you can remove it'
142
+ end
96
143
 
97
144
  if options[:generate_ca]
98
- gen_key('ca', 'ca', options[:no_password])
99
- sign_key('ca', 'ca', CN_CA)
100
- gen_crl
145
+ ca_pass = options[:no_password] ? nil : ask_password('ca')
146
+ gen_key('ca', ca_pass)
147
+ sign_key('ca', CN_CA, ca_pass)
148
+ gen_crl(ca_pass)
101
149
  end
102
150
  if options[:generate_dh]
103
- exe "#{OPENSSL} dhparam -out dh.pem #{KEY_SIZE}"
151
+ File.open('dh.pem', 'w') do |f|
152
+ print 'Generating dh.pem. This will take a while'
153
+ f.write OpenSSL::PKey::DH.new(KEY_SIZE)
154
+ puts '. Done'
155
+ end
104
156
  end
105
157
  if options[:generate_static]
106
- exe "#{OPENVPN} --genkey --secret '#{options[:generate_static]}.key'"
158
+ exe "#{OPENVPN} --genkey --secret ta.key"
107
159
  end
108
160
  if options[:generate_server]
109
- gen_and_sign('server', options[:generate_server], options[:no_password])
161
+ gen_and_sign('server', options[:generate_server], options[:no_password] ? nil : ask_password(options[:generate_server]))
110
162
  end
111
163
  if options[:generate_client]
112
- gen_and_sign('client', options[:generate_client], options[:no_password])
164
+ gen_and_sign('client', options[:generate_client], options[:no_password] ? nil : ask_password(options[:generate_client]))
113
165
  end
114
166
  if options[:generate_zip]
115
167
  ovpn_files = Dir['*.ovpn']
@@ -117,29 +169,27 @@ if options[:generate_zip]
117
169
  when 1
118
170
  ovpn_file = ovpn_files.first
119
171
  when 0
120
- abort "No .ovpn file in current directory, please add one"
172
+ abort 'No .ovpn file in current directory, please add one'
121
173
  else
122
- abort "More than one .ovpn files in current directory, aborting"
174
+ abort 'More than one .ovpn files in current directory, aborting'
123
175
  end
124
176
 
125
- gen_and_sign('client', options[:generate_zip], options[:no_password])
177
+ gen_and_sign('client', options[:generate_zip], options[:no_password] ? nil : ask_password(options[:generate_zip]))
126
178
 
127
179
  zip_file = File.join(File.expand_path(ZIP_DIR), "#{File.basename ovpn_file, '.ovpn'}.tblk.zip")
128
180
  File.delete(zip_file) if File.exist?(zip_file)
129
181
  File.umask umask
130
182
  Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
131
183
  zip.get_output_stream(ovpn_file) {|f|
132
- File.open(ovpn_file).each {|line| f.write line}
184
+ f.write File.read(ovpn_file)
133
185
  f.write "cert #{options[:generate_zip]}.crt\nkey #{options[:generate_zip]}.key\n"
134
186
  }
135
- [ 'ca.crt', "#{options[:generate_zip]}.crt", "#{options[:generate_zip]}.key"].each {|i|
187
+ ['ca.crt', "#{options[:generate_zip]}.crt", "#{options[:generate_zip]}.key"].each {|i|
136
188
  zip.add(i, i)
137
189
  }
138
- # TODO: include TLS key if specified in config with tls-auth/tls-crypt
190
+ zip.add('ta.key', 'ta.key') if File.exist? 'ta.key'
139
191
  end
140
192
  end
141
193
  if options[:revoke]
142
- exe "#{OPENSSL} ca -revoke '#{options[:revoke]}.crt' -config #{SSL_CONF}"
143
- gen_crl
144
- ['crt', 'key'].each {|ext| File.delete "#{options[:revoke]}.#{ext}"}
194
+ revoke(options[:revoke])
145
195
  end
@@ -1,7 +1,17 @@
1
1
  zip_dir: '~'
2
2
  openvpn: openvpn
3
- openssl: openssl
3
+ encrypt: AES128
4
+ digest: SHA256
4
5
  key_size: 2048
5
- encrypt: aes128
6
+ expire: # days
7
+ ca: 3650
8
+ crl: 3650
9
+ server: 3650
10
+ client: 3650
6
11
  ca_name: Certification Authority
7
- details: /C=US/ST=CA/L=San Francisco/O=Dva Debila/OU=OpenVPN
12
+ x509:
13
+ C: US
14
+ ST: CA
15
+ L: San Francisco
16
+ O: Dva Debila
17
+ OU: OpenVPN
data/lib/functions.rb CHANGED
@@ -1,48 +1,144 @@
1
- def check_crt filename
2
- ['key', 'crt'].each {|ext|
1
+ # frozen_string_literal: true
2
+
3
+ def check_crt(filename)
4
+ %w[key crt].each {|ext|
3
5
  abort "#{filename}.#{ext} already exists, exiting" if File.exist? "#{filename}.#{ext}"
4
6
  }
5
7
  end
6
8
 
7
- def check_client name
8
- abort "Error: client should have an alphanumeric name" unless name
9
+ def check_client(name)
10
+ abort 'Error: client should have an alphanumeric name' unless name
9
11
  check_crt(name)
10
12
  end
11
13
 
12
- def exe cmd
13
- system(cmd) or abort "error executing: #{cmd}"
14
+ def exe(cmd)
15
+ system(cmd) || abort("error executing: #{cmd}")
14
16
  end
15
17
 
16
- def gen_and_sign type, certname, no_password
17
- gen_key(type, certname, no_password)
18
- sign_key(type, certname, certname)
18
+ def ask_password(name)
19
+ password = ''
20
+ loop do
21
+ print "Enter password for #{name}.key: "
22
+ password = $stdin.noecho(&:gets).chomp
23
+ puts # trailing newline
24
+ break unless password.empty?
25
+ end
26
+ password
19
27
  end
20
28
 
21
- def gen_key type, certname, no_password
22
- if no_password
23
- exe "#{OPENSSL} genrsa -out '#{certname}.key' #{KEY_SIZE}"
24
- else
25
- exe "#{OPENSSL} genrsa -#{ENCRYPT} -out '#{certname}.key' #{KEY_SIZE}"
26
- end
29
+ def gen_and_sign(type, certname, password)
30
+ gen_key(certname, password)
31
+ sign_key(type, certname, password)
27
32
  end
28
33
 
29
- def sign_key type, certname, cn
30
- if certname == 'ca'
31
- exe "#{OPENSSL} req -new -x509 -key '#{certname}.key' -out '#{certname}.crt' -config #{SSL_CONF} -subj '/CN=#{cn}#{REQ}' -extensions ext.#{type}"
32
- else
33
- exe "#{OPENSSL} req -new -key '#{certname}.key' -out '#{certname}.csr' -config #{SSL_CONF} -subj '/CN=#{cn}#{REQ}' -extensions ext.#{type}"
34
- exe "#{OPENSSL} ca -in '#{certname}.csr' -out '#{certname}.crt' -config #{SSL_CONF} -extensions ext.#{type} -batch"
35
- File.delete "#{certname}.csr"
34
+ def gen_key(certname, password)
35
+ key = OpenSSL::PKey::RSA.new(KEY_SIZE)
36
+ File.open("#{certname}.key", 'w') do |f|
37
+ f.write password ? key.to_pem(OpenSSL::Cipher.new(ENCRYPT), password) : key
36
38
  end
37
39
  end
38
40
 
39
- def gen_crl
40
- exe "#{OPENSSL} ca -gencrl -out crl.pem -config #{SSL_CONF}"
41
+ # type is one of: 'ca', 'server', 'client'
42
+ # rubocop:disable Naming/MethodParameterName
43
+ def sign_key(type, cn, password)
44
+ # rubocop:enable Naming/MethodParameterName
45
+ certname = type == 'ca' ? 'ca' : cn
46
+ key = OpenSSL::PKey::RSA.new File.read("#{certname}.key"), password
47
+ subj = OpenSSL::X509::Name.new([['CN', cn]] + REQ.to_a)
48
+ serial = begin
49
+ File.read(SERIAL_FILE).to_i
50
+ rescue Errno::ENOENT
51
+ 0
52
+ end + 1
53
+
54
+ cert = OpenSSL::X509::Certificate.new
55
+ cert.version = 2
56
+ cert.serial = serial
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
71
+ cert.issuer = OpenSSL::X509::Name.new([['CN', CN_CA]] + REQ.to_a)
72
+
73
+ ef = OpenSSL::X509::ExtensionFactory.new nil, cert
74
+ ef.issuer_certificate = cert
75
+
76
+ cert.add_extension ef.create_extension('subjectKeyIdentifier', 'hash')
77
+ cert.add_extension ef.create_extension('authorityKeyIdentifier', 'keyid,issuer:always')
78
+ cert.add_extension ef.create_extension('basicConstraints', type == 'ca' ? 'CA:true' : 'CA:false')
79
+
80
+ case type
81
+ when 'ca'
82
+ cert.add_extension ef.create_extension('keyUsage', 'cRLSign,keyCertSign')
83
+ cert.sign key, OpenSSL::Digest.new(DIGEST)
84
+ when 'server'
85
+ cert.add_extension ef.create_extension('keyUsage', 'keyEncipherment,digitalSignature')
86
+ cert.add_extension ef.create_extension('extendedKeyUsage', 'serverAuth')
87
+ when 'client'
88
+ cert.add_extension ef.create_extension('keyUsage', 'digitalSignature')
89
+ cert.add_extension ef.create_extension('extendedKeyUsage', 'clientAuth')
90
+ end
91
+ unless type == 'ca'
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 }
41
102
  end
42
103
 
43
- def create_dir name
44
- unless Dir.exist? name
45
- Dir.mkdir name
46
- puts "Created directory: #{name}"
104
+ def revoke(certname)
105
+ crl = OpenSSL::X509::CRL.new(File.read(CRL_FILE))
106
+ cert = OpenSSL::X509::Certificate.new(File.read("#{certname}.crt"))
107
+ revoke = OpenSSL::X509::Revoked.new.tap {|rev|
108
+ rev.serial = cert.serial
109
+ rev.time = Time.now
110
+ }
111
+ crl.next_update = Time.now + EXPIRE['crl'] * 86_400 # days to seconds
112
+ crl.add_revoked(revoke)
113
+ begin
114
+ update_crl(crl, ask_password('ca'))
115
+ rescue OpenSSL::PKey::RSAError
116
+ retry
47
117
  end
118
+
119
+ %w[crt key].each {|ext| File.delete "#{certname}.#{ext}" }
120
+ end
121
+
122
+ def gen_crl(ca_pass)
123
+ return if File.exist? CRL_FILE
124
+
125
+ crl = OpenSSL::X509::CRL.new
126
+ crl.issuer = OpenSSL::X509::Name.new([['CN', CN_CA]] + REQ.to_a)
127
+ update_crl(crl, ca_pass)
128
+ end
129
+
130
+ def update_crl(crl, ca_pass)
131
+ ca_key = OpenSSL::PKey::RSA.new File.read('ca.key'), ca_pass
132
+ crl.last_update = Time.now
133
+ crl.next_update = Time.now + EXPIRE['crl'] * 86_400 # days to seconds
134
+ crl.version = crl.version + 1
135
+ crl.sign(ca_key, OpenSSL::Digest.new(DIGEST))
136
+ File.open(CRL_FILE, 'w') {|f| f.write crl.to_pem }
137
+ end
138
+
139
+ def create_dir(name)
140
+ return if Dir.exist? name
141
+
142
+ Dir.mkdir name
143
+ puts "Created directory: #{name}"
48
144
  end
data/lib/version.rb CHANGED
@@ -1 +1,3 @@
1
- ::Version = '0.7.3'
1
+ # frozen_string_literal: true
2
+
3
+ ::VERSION = '0.8.1'
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: 0.7.3
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasily Korytov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-03 00:00:00.000000000 Z
11
+ date: 2021-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -16,17 +16,17 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.2'
26
+ version: '2.0'
27
27
  description: Generates and revokes certificates, also packs them to ZIP files with
28
28
  OpenVPN configuration
29
- email: vasily.korytov@icloud.com
29
+ email: v.korytov@outlook.com
30
30
  executables:
31
31
  - ovpn-key
32
32
  extensions: []
@@ -35,10 +35,6 @@ files:
35
35
  - NOTICE
36
36
  - README.md
37
37
  - bin/ovpn-key
38
- - defaults/meta/index.txt
39
- - defaults/meta/index.txt.attr
40
- - defaults/meta/serial
41
- - defaults/openssl.ini
42
38
  - defaults/ovpn-key.yml
43
39
  - lib/functions.rb
44
40
  - lib/version.rb
@@ -46,7 +42,7 @@ homepage: https://github.com/chillum/ovpn-key
46
42
  licenses:
47
43
  - Apache-2.0
48
44
  metadata: {}
49
- post_install_message:
45
+ post_install_message:
50
46
  rdoc_options: []
51
47
  require_paths:
52
48
  - lib
@@ -54,16 +50,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
50
  requirements:
55
51
  - - ">="
56
52
  - !ruby/object:Gem::Version
57
- version: '2.0'
53
+ version: '2.4'
58
54
  required_rubygems_version: !ruby/object:Gem::Requirement
59
55
  requirements:
60
56
  - - ">="
61
57
  - !ruby/object:Gem::Version
62
58
  version: '0'
63
59
  requirements: []
64
- rubyforge_project:
65
- rubygems_version: 2.7.7
66
- signing_key:
60
+ rubygems_version: 3.2.3
61
+ signing_key:
67
62
  specification_version: 4
68
63
  summary: Key management utility for OpenVPN
69
64
  test_files: []
File without changes
@@ -1 +0,0 @@
1
- unique_subject = yes
data/defaults/meta/serial DELETED
@@ -1 +0,0 @@
1
- 01
data/defaults/openssl.ini DELETED
@@ -1,49 +0,0 @@
1
- [req]
2
- default_md = sha256
3
- distinguished_name = dn.ovpn
4
- days = 3650
5
-
6
- [dn.ovpn]
7
- CN = Certificate name (required)
8
-
9
- [ca]
10
- default_ca = ca.ovpn
11
-
12
- [ca.ovpn]
13
- default_md = sha256
14
- private_key = ca.key
15
- certificate = ca.crt
16
- database = meta/index.txt
17
- serial = meta/serial
18
- crl = crl.pem
19
- policy = policy.ovpn
20
- # create this directory if changing this value
21
- new_certs_dir = certs
22
- default_days = 3650
23
- default_crl_days = 3650
24
- subjectKeyIdentifier = hash
25
- authorityKeyIdentifier = keyid,issuer:always
26
-
27
- [ext.ca]
28
- basicConstraints = CA:true
29
-
30
- [ext.server]
31
- basicConstraints = CA:false
32
- nsCertType = server
33
- extendedKeyUsage = serverAuth
34
- keyUsage = digitalSignature, keyEncipherment
35
-
36
- [ext.client]
37
- basicConstraints = CA:false
38
- extendedKeyUsage = clientAuth
39
- keyUsage = digitalSignature
40
-
41
- [policy.ovpn]
42
- commonName = supplied
43
- countryName = optional
44
- stateOrProvinceName = optional
45
- localityName = optional
46
- organizationName = optional
47
- organizationalUnitName = optional
48
- name = optional
49
- emailAddress = optional