ovpn-key 0.7.1 → 0.7.7

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: da769c59267c3c1bc605a2da314d55b0599e56de6e48dc25ef17ea56ed1af960
4
- data.tar.gz: eb106210d91f8e5ba367d20d94e72e74f27e1a53a8abd3cf58cf61fc7580f0fb
3
+ metadata.gz: 13681f4cf8c6abc0badce3feceacf4ce489daab4ff9ea7b177bdca7c3fe983ed
4
+ data.tar.gz: 621ad232db5032b90b1b631f7765dc15aca7b8131465bb2658408c13a7c1d8b0
5
5
  SHA512:
6
- metadata.gz: 44b34a49e1730f3c9bff11022fa63e8cf1426c85a6f737c84b68cafa50be8c4e05110202d40dc1e1bfbfda36d29df02003b6ebd07c489fa21a76dcd8afea8d94
7
- data.tar.gz: c4370cde04518bc151c64f2fb329718d68eed360080987807ed201103d55f999a84b0fcfd4d96634bc1124e96f419956b2c497046ab9bf957e55590e2882724c
6
+ metadata.gz: cc2d031bd9f8a595fa1efd862c2e5e371643928d34c7d7398db179466b655e48d412dd5494cfc6d705e614114846acbcce717b1117026df685bac5a4eb6e65b7
7
+ data.tar.gz: d31fd3d8936ab9bbd94daed1db9f2334925e073dfb9319d6d96aabfa1db566bd2f340144dd0190ee27ee2652d64ef70d59e6c0a6a1c63af6392dfdba0191073e
data/README.md CHANGED
@@ -12,9 +12,12 @@ It supports encrypting `.key` files with a passphrase (there is an option to dis
12
12
 
13
13
  It can be used with a non-self signed CA, just place your `ca.key` and `ca.crt` in the keys directory and skip the `--ca` step.
14
14
 
15
- It can be used to manage a non-OpenVPN CA, in that case `--zip` step will be useless, but all others will work.
15
+ It can be used to manage a non-OpenVPN CA, in that case `--zip` and `--static` steps will be useless, but all others will work.
16
16
 
17
- For now it should be considered experimental and rather undocumented.
17
+ OpenVPN static keys are supported partially, as they should be used for `tls-auth`/`tls-crypt` only.
18
+ Please note that they are not encrypted regardless of `--nopass` option.
19
+
20
+ For now this utility should be considered experimental and rather undocumented.
18
21
  If you're brave, [let me know](https://github.com/chillum/ovpn-key/issues), where the problems are.
19
22
 
20
23
  ### Installation
@@ -26,12 +29,14 @@ If you're brave, [let me know](https://github.com/chillum/ovpn-key/issues), wher
26
29
 
27
30
  1. `ovpn-key --init`
28
31
  2. edit `ovpn-key.yml` and `openssl.ini`
29
- 3. `ovpn-key --ca --dh --server --nopass`
30
- 4. `ovpn-key --client somebody`
31
- 5. `ovpn-key --revoke somebody`
32
- 6. add a file with `.ovpn` extension to the directory
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
33
38
  it should contain every setting except for `cert` and `key`
34
- 7. `ovpn-key --zip somebody-else`
39
+ 9. `ovpn-key --zip somebody-else [--nopass]`
35
40
 
36
41
  ### Configuration
37
42
 
data/bin/ovpn-key CHANGED
@@ -1,76 +1,82 @@
1
1
  #! /usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require 'optparse'
3
5
  require 'fileutils'
4
6
  require 'yaml'
5
7
  require 'zip'
6
- require_relative '../lib/version.rb'
7
- require_relative '../lib/functions.rb'
8
+ require_relative '../lib/version'
9
+ require_relative '../lib/functions'
8
10
 
9
11
  SSL_CONF = 'openssl.ini'
10
12
  APP_CONF = 'ovpn-key.yml'
11
13
 
12
14
  options = {}
13
15
  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 : "."
16
+ opts.banner = "Usage: #{File.basename $PROGRAM_NAME} <options> [--nopass]"
17
+ opts.on('--init [directory]', 'Init a CA directory (defaults to current)') do |v|
18
+ options[:init] = v || '.'
17
19
  end
18
- opts.on("--ca", "Generate a CA (ca.crt)") do |v|
20
+ opts.on('--ca', 'Generate a CA (ca.crt)') do |v|
19
21
  check_crt('ca')
20
22
  options[:generate_ca] = v
21
23
  end
22
- opts.on("--dh", "Generate a DH keyfile (dh.pem)") do |v|
23
- # it's safe to rewrite this file
24
+ opts.on('--dh', 'Generate a DH keyfile (dh.pem)') do |v|
25
+ # it's safe to overwrite this file
24
26
  options[:generate_dh] = v
25
27
  end
26
- opts.on("--server [name]", "Generate a server key (defaults to 'server')") do |v|
27
- options[:generate_server] = v ? v : "server"
28
+ opts.on('--static', 'Generate OpenVPN static key (ta.key)') do |v|
29
+ options[:generate_static] = v
30
+ check_crt('ta')
31
+ end
32
+ opts.on('--server [name]', "Generate a server key (defaults to 'server')") do |v|
33
+ options[:generate_server] = v || 'server'
28
34
  check_crt(options[:generate_server])
29
35
  end
30
- opts.on("--client [name]", "Generate a client key and sign it") do |v|
36
+ opts.on('--client [name]', 'Generate a client key and sign it') do |v|
31
37
  check_client(v)
32
38
  options[:generate_client] = v
33
39
  end
34
- opts.on("--zip [name]", "Ditto plus pack it to ZIP with OpenVPN config") do |v|
40
+ opts.on('--zip [name]', 'Ditto plus pack it to ZIP with OpenVPN config') do |v|
35
41
  check_client(v)
36
42
  options[:generate_zip] = v
37
43
  end
38
- opts.on("--revoke [name]", "Revoke a certificate (using crl.pem) and delete it") do |v|
39
- abort "Please specify what certificate to revoke" unless v
44
+ opts.on('--revoke [name]', 'Revoke a certificate (using crl.pem) and delete it') do |v|
45
+ abort 'Please specify what certificate to revoke' unless v
40
46
  options[:revoke] = v
41
47
  end
42
- opts.on("--nopass", "Don't protect .key files with a password") do |v|
48
+ opts.on('--nopass', "Don't protect .key files with a password") do |v|
43
49
  options[:no_password] = v
44
50
  end
45
51
  end.parse!
46
- if ARGV.length > 0
47
- abort "Error: invalid args: #{ARGV.join ' '}\nSee `#{File.basename $0} -h` for help"
52
+ if ARGV.length.positive?
53
+ abort "Error: invalid args: #{ARGV.join ' '}\nSee `#{File.basename $PROGRAM_NAME} -h` for help"
48
54
  end
49
- unless options[:init] || options[:generate_ca] || options[:generate_dh] || options[:generate_server] \
50
- || options[:generate_client] || options[:generate_zip] || options[:revoke]
51
- abort "See `#{File.basename $0} -h` for usage"
55
+ unless options[:init] || options[:generate_ca] || options[:generate_dh] || options[:generate_static] \
56
+ || options[:generate_server] || options[:generate_client] || options[:generate_zip] || options[:revoke]
57
+ abort "See `#{File.basename $PROGRAM_NAME} -h` for usage"
52
58
  end
53
- if options[:generate_client] and options[:generate_zip]
59
+ if options[:generate_client] && options[:generate_zip]
54
60
  # I assume that user likely wants one of them and is confused with usage
55
- abort "There can be only one: --client or --zip"
61
+ abort 'There can be only one: --client or --zip'
56
62
  end
57
- File.umask 0077
63
+ umask = File.umask 0o077
58
64
 
59
65
  if options[:init]
60
66
  unless options[:init] == '.'
61
67
  create_dir options[:init]
62
68
  Dir.chdir options[:init]
63
69
  end
64
- ['certs', 'meta'].each {|dir| create_dir dir}
70
+ %w[certs meta].each {|dir| create_dir dir}
65
71
  ['meta/index.txt', 'meta/index.txt.attr', 'meta/serial', SSL_CONF, APP_CONF].each {|file|
66
72
  unless File.exist? file
67
73
  FileUtils.copy_file(File.expand_path("defaults/#{file}", "#{__dir__}/.."), "./#{file}")
68
74
  puts "Created file: #{file}"
69
75
  end
70
76
  }
71
- elsif !File.exist? 'ovpn-key.yml'
77
+ elsif !File.exist? APP_CONF
72
78
  begin
73
- rc = YAML.load_file(File.expand_path '~/.ovpn-key.yml')
79
+ rc = YAML.load_file(File.expand_path("~/.#{APP_CONF}"))
74
80
  rescue Errno::ENOENT
75
81
  # no configuration file in home directory is not an error
76
82
  end
@@ -80,23 +86,28 @@ end
80
86
  begin
81
87
  settings = YAML.load_file(APP_CONF)
82
88
  rescue Errno::ENOENT
83
- abort "Run `#{File.basename $0} --init` before generating certificates"
89
+ abort "Run `#{File.basename $PROGRAM_NAME} --init` before generating certificates"
84
90
  end
85
91
  ZIP_DIR = settings['zip_dir'] || '~'
92
+ OPENVPN = settings['openvpn'] || 'openvpn'
86
93
  OPENSSL = settings['openssl'] || 'openssl'
87
- KEY_SIZE = settings['key_size'] || 2048
88
94
  ENCRYPT = settings['encrypt'] || 'aes128'
95
+ KEY_SIZE = settings['key_size'] || 2048
96
+ CA_DAYS = settings['ca_days'] || 3650
89
97
  CN_CA = settings['ca_name'] || 'Certification Authority'
90
98
  REQ = settings['details']
91
99
 
92
100
  if options[:generate_ca]
93
- gen_key('ca', 'ca', options[:no_password])
101
+ gen_key('ca', options[:no_password])
94
102
  sign_key('ca', 'ca', CN_CA)
95
103
  gen_crl
96
104
  end
97
105
  if options[:generate_dh]
98
106
  exe "#{OPENSSL} dhparam -out dh.pem #{KEY_SIZE}"
99
107
  end
108
+ if options[:generate_static]
109
+ exe "#{OPENVPN} --genkey --secret ta.key"
110
+ end
100
111
  if options[:generate_server]
101
112
  gen_and_sign('server', options[:generate_server], options[:no_password])
102
113
  end
@@ -109,27 +120,29 @@ if options[:generate_zip]
109
120
  when 1
110
121
  ovpn_file = ovpn_files.first
111
122
  when 0
112
- abort "No .ovpn file in current directory, please add one"
123
+ abort 'No .ovpn file in current directory, please add one'
113
124
  else
114
- abort "More than one .ovpn files in current directory, aborting"
125
+ abort 'More than one .ovpn files in current directory, aborting'
115
126
  end
116
127
 
117
128
  gen_and_sign('client', options[:generate_zip], options[:no_password])
118
129
 
119
130
  zip_file = File.join(File.expand_path(ZIP_DIR), "#{File.basename ovpn_file, '.ovpn'}.tblk.zip")
120
131
  File.delete(zip_file) if File.exist?(zip_file)
132
+ File.umask umask
121
133
  Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
122
134
  zip.get_output_stream(ovpn_file) {|f|
123
135
  File.open(ovpn_file).each {|line| f.write line}
124
136
  f.write "cert #{options[:generate_zip]}.crt\nkey #{options[:generate_zip]}.key\n"
125
137
  }
126
- [ 'ca.crt', "#{options[:generate_zip]}.crt", "#{options[:generate_zip]}.key"].each {|i|
138
+ ['ca.crt', "#{options[:generate_zip]}.crt", "#{options[:generate_zip]}.key"].each {|i|
127
139
  zip.add(i, i)
128
140
  }
141
+ zip.add('ta.key', 'ta.key') if File.exist? 'ta.key'
129
142
  end
130
143
  end
131
144
  if options[:revoke]
132
145
  exe "#{OPENSSL} ca -revoke '#{options[:revoke]}.crt' -config #{SSL_CONF}"
133
146
  gen_crl
134
- ['crt', 'key'].each {|ext| File.delete "#{options[:revoke]}.#{ext}"}
147
+ %w[crt key].each {|ext| File.delete "#{options[:revoke]}.#{ext}"}
135
148
  end
data/defaults/meta/serial CHANGED
@@ -1 +1 @@
1
- 01
1
+ 00
data/defaults/openssl.ini CHANGED
@@ -1,7 +1,6 @@
1
1
  [req]
2
2
  default_md = sha256
3
3
  distinguished_name = dn.ovpn
4
- days = 3650
5
4
 
6
5
  [dn.ovpn]
7
6
  CN = Certificate name (required)
@@ -1,6 +1,8 @@
1
1
  zip_dir: '~'
2
+ openvpn: openvpn
2
3
  openssl: openssl
3
- key_size: 2048
4
4
  encrypt: aes128
5
+ key_size: 2048
6
+ ca_days: 3650
5
7
  ca_name: Certification Authority
6
8
  details: /C=US/ST=CA/L=San Francisco/O=Dva Debila/OU=OpenVPN
data/lib/functions.rb CHANGED
@@ -1,34 +1,36 @@
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
14
+ def exe(cmd)
13
15
  system(cmd) or 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
+ def gen_and_sign(type, certname, no_password)
19
+ gen_key(certname, no_password)
18
20
  sign_key(type, certname, certname)
19
21
  end
20
22
 
21
- def gen_key type, certname, no_password
23
+ def gen_key(certname, no_password)
22
24
  if no_password
23
- exe "#{OPENSSL} genrsa -out '#{certname}.key' #{KEY_SIZE} -config #{SSL_CONF} -extensions ext.#{type}"
25
+ exe "#{OPENSSL} genrsa -out '#{certname}.key' #{KEY_SIZE}"
24
26
  else
25
- exe "#{OPENSSL} genrsa -#{ENCRYPT} -out '#{certname}.key' #{KEY_SIZE} -config #{SSL_CONF} -extensions ext.#{type}"
27
+ exe "#{OPENSSL} genrsa -#{ENCRYPT} -out '#{certname}.key' #{KEY_SIZE}"
26
28
  end
27
29
  end
28
30
 
29
- def sign_key type, certname, cn
31
+ def sign_key(type, certname, cn)
30
32
  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}"
33
+ exe "#{OPENSSL} req -new -x509 -key '#{certname}.key' -out '#{certname}.crt' -config #{SSL_CONF} -subj '/CN=#{cn}#{REQ}' -extensions ext.#{type} -days #{CA_DAYS}"
32
34
  else
33
35
  exe "#{OPENSSL} req -new -key '#{certname}.key' -out '#{certname}.csr' -config #{SSL_CONF} -subj '/CN=#{cn}#{REQ}' -extensions ext.#{type}"
34
36
  exe "#{OPENSSL} ca -in '#{certname}.csr' -out '#{certname}.crt' -config #{SSL_CONF} -extensions ext.#{type} -batch"
@@ -40,9 +42,9 @@ def gen_crl
40
42
  exe "#{OPENSSL} ca -gencrl -out crl.pem -config #{SSL_CONF}"
41
43
  end
42
44
 
43
- def create_dir name
44
- unless Dir.exist? name
45
- Dir.mkdir name
46
- puts "Created directory: #{name}"
47
- end
45
+ def create_dir(name)
46
+ return if Dir.exist? name
47
+
48
+ Dir.mkdir name
49
+ puts "Created directory: #{name}"
48
50
  end
data/lib/version.rb CHANGED
@@ -1 +1,3 @@
1
- ::Version = '0.7.1'
1
+ # frozen_string_literal: true
2
+
3
+ ::VERSION = '0.7.7'
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.1
4
+ version: 0.7.7
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-08-09 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,16 +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'
27
- description: ''
28
- email: vasily.korytov@icloud.com
26
+ version: '2.0'
27
+ description: Generates and revokes certificates, also packs them to ZIP files with
28
+ OpenVPN configuration
29
+ email: v.korytov@outlook.com
29
30
  executables:
30
31
  - ovpn-key
31
32
  extensions: []
@@ -45,7 +46,7 @@ homepage: https://github.com/chillum/ovpn-key
45
46
  licenses:
46
47
  - Apache-2.0
47
48
  metadata: {}
48
- post_install_message:
49
+ post_install_message:
49
50
  rdoc_options: []
50
51
  require_paths:
51
52
  - lib
@@ -53,16 +54,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
54
  requirements:
54
55
  - - ">="
55
56
  - !ruby/object:Gem::Version
56
- version: '2.0'
57
+ version: '2.4'
57
58
  required_rubygems_version: !ruby/object:Gem::Requirement
58
59
  requirements:
59
60
  - - ">="
60
61
  - !ruby/object:Gem::Version
61
62
  version: '0'
62
63
  requirements: []
63
- rubyforge_project:
64
- rubygems_version: 2.7.6
65
- signing_key:
64
+ rubygems_version: 3.2.3
65
+ signing_key:
66
66
  specification_version: 4
67
67
  summary: Key management utility for OpenVPN
68
68
  test_files: []