ovpn-key 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/NOTICE +15 -0
- data/README.md +46 -0
- data/bin/ovpn-key +133 -0
- data/defaults/meta/index.txt +0 -0
- data/defaults/meta/index.txt.attr +1 -0
- data/defaults/meta/serial +1 -0
- data/defaults/openssl.ini +49 -0
- data/defaults/ovpn-key.yml +6 -0
- data/lib/functions.rb +38 -0
- data/lib/version.rb +1 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 87d20925cbb4231873b06d213c5cb1b3e47f428d5c349449288b778b0b1fcf38
|
4
|
+
data.tar.gz: fbd4b0f7700bc6c103728b412478a0cbaf7adb5c80cbefa7178ccc00abb9e47b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e90c6313d933c5298c9c170b7eedeb06fbe5045575aae3dd985c6aad38bb6e7a6b83d2375247d5946bab40aa408c057b18e9d2a1fa474f04fbd60929f8d0db0
|
7
|
+
data.tar.gz: b9d7a14f848837c59c6810985211d9f43c89a7d79b5a4d7bd4305c84f60bf3c3adf119178eb3836c2d9ea56e562235cdf7264201e8e4aaa2b49920df05e59f25
|
data/NOTICE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ovpn-key: https://github.com/chillum/ovpn-key
|
2
|
+
|
3
|
+
Copyright 2018 Vasily Korytov
|
4
|
+
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
you may not use this software except in compliance with the License.
|
7
|
+
You may obtain a copy of the License at
|
8
|
+
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
See the License for the specific language governing permissions and
|
15
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
## ovpn-key: key management for OpenVPN [![Gem Version](https://badge.fury.io/rb/ovpn-key.svg)](http://badge.fury.io/rb/ovpn-key)
|
2
|
+
|
3
|
+
This utility is designed as [easy-rsa](https://github.com/OpenVPN/easy-rsa) replacement suitable for one exact use case.
|
4
|
+
|
5
|
+
It's basically a wrapper around `openssl` to:
|
6
|
+
* create a self-signed CA
|
7
|
+
* create client and server certificates and pack them to ZIP files along with the OpenVPN config
|
8
|
+
* revoke the certificates
|
9
|
+
* create a DH keyfile
|
10
|
+
|
11
|
+
It supports encrypting `.key` files with a passphrase (there is an option to disable that).
|
12
|
+
|
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
|
+
|
15
|
+
For now it should be considered experimental and rather undocumented.
|
16
|
+
If you're brave, [let me know](https://github.com/chillum/ovpn-key/issues), where the problems are.
|
17
|
+
|
18
|
+
### Installation
|
19
|
+
|
20
|
+
1. Get [Ruby](https://www.ruby-lang.org/en/documentation/installation/)
|
21
|
+
2. Run `gem install ovpn-key`
|
22
|
+
|
23
|
+
### Usage
|
24
|
+
|
25
|
+
1. `ovpn-key --init`
|
26
|
+
2. edit `ovpn-key.yml` and `openssl.ini`
|
27
|
+
3. `ovpn-key --ca --dh --server --nopass`
|
28
|
+
4. add a file with `.ovpn` extension to the directory
|
29
|
+
it should contain every setting except for `cert` and `key`
|
30
|
+
5. `ovpn-key --client somebody`
|
31
|
+
6. `ovpn-key --revoke somebody`
|
32
|
+
|
33
|
+
### Configuration
|
34
|
+
|
35
|
+
Most of configuration is done in `open-vpn.key` and `openssl.ini` files in the directory.
|
36
|
+
|
37
|
+
ovpn-key also processes `~/.ovpn-key.yml` file, for now it has only one possible setting:
|
38
|
+
```yaml
|
39
|
+
dir: ~/some/path
|
40
|
+
```
|
41
|
+
|
42
|
+
This setting is used as a default directory if:
|
43
|
+
1. current directory does not have a `ovpn-key.yml`
|
44
|
+
2. `--init` is not specified
|
45
|
+
|
46
|
+
If you specify the default directory, you don't need to travel to it every time you want to launch `ovpn-key`, i.e. you can use it from your home directory or any other, as long as requirements above are met.
|
data/bin/ovpn-key
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'yaml'
|
5
|
+
require 'zip'
|
6
|
+
require_relative '../lib/version.rb'
|
7
|
+
require_relative '../lib/functions.rb'
|
8
|
+
|
9
|
+
SSL_CONF = 'openssl.ini'
|
10
|
+
APP_CONF = 'ovpn-key.yml'
|
11
|
+
|
12
|
+
options = {}
|
13
|
+
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
|
+
if v
|
17
|
+
options[:init] = v
|
18
|
+
else
|
19
|
+
options[:init] = "."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
opts.on("--ca", "Generate a CA (ca.crt)") do |v|
|
23
|
+
check_crt('ca')
|
24
|
+
options[:generate_ca] = v
|
25
|
+
end
|
26
|
+
opts.on("--dh", "Generate a DH keyfile (dh.pem)") do |v|
|
27
|
+
options[:generate_dh] = v
|
28
|
+
end
|
29
|
+
opts.on("--server [name]", "Generate a server key (defaults to 'server')") do |v|
|
30
|
+
if v
|
31
|
+
options[:generate_server] = v
|
32
|
+
else
|
33
|
+
options[:generate_server] = "server"
|
34
|
+
end
|
35
|
+
check_crt(options[:generate_server])
|
36
|
+
end
|
37
|
+
opts.on("--client [name]", "Generate a client key and pack it to ZIP") do |v|
|
38
|
+
abort "Error: client should have an alphanumeric name" unless v
|
39
|
+
check_crt(v)
|
40
|
+
options[:generate_client] = v
|
41
|
+
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
|
44
|
+
options[:revoke] = v
|
45
|
+
end
|
46
|
+
opts.on("--nopass", "Don't protect .key files with a password") do |v|
|
47
|
+
options[:no_password] = v
|
48
|
+
end
|
49
|
+
end.parse!
|
50
|
+
if ARGV.length > 0
|
51
|
+
abort "Error: invalid args: #{ARGV.join ' '}\nSee `#{File.basename $0} -h` for help"
|
52
|
+
end
|
53
|
+
unless options[:init] || options[:generate_ca] || options[:generate_dh] \
|
54
|
+
|| options[:generate_server] || options[:generate_client] || options[:revoke]
|
55
|
+
abort "See `#{File.basename $0} -h` for usage"
|
56
|
+
end
|
57
|
+
File.umask 0077
|
58
|
+
|
59
|
+
if options[:init]
|
60
|
+
unless options[:init] == '.'
|
61
|
+
create_dir options[:init]
|
62
|
+
Dir.chdir options[:init]
|
63
|
+
end
|
64
|
+
['certs', 'meta'].each {|dir| create_dir dir}
|
65
|
+
['meta/index.txt', 'meta/index.txt.attr', 'meta/serial', SSL_CONF, APP_CONF].each {|file|
|
66
|
+
unless File.exist? file
|
67
|
+
FileUtils.copy_file(File.expand_path("defaults/#{file}", "#{__dir__}/.."), "./#{file}")
|
68
|
+
puts "Created file: #{file}"
|
69
|
+
end
|
70
|
+
}
|
71
|
+
elsif !File.exist? 'ovpn-key.yml'
|
72
|
+
begin
|
73
|
+
rc = YAML.load_file(File.expand_path '~/.ovpn-key.yml')
|
74
|
+
rescue Errno::ENOENT
|
75
|
+
end
|
76
|
+
Dir.chdir File.expand_path(rc['dir']) if rc && rc['dir']
|
77
|
+
end
|
78
|
+
|
79
|
+
begin
|
80
|
+
settings = YAML.load_file(APP_CONF)
|
81
|
+
rescue Errno::ENOENT
|
82
|
+
abort "Run `#{File.basename $0} --init` before generating certificates"
|
83
|
+
end
|
84
|
+
ZIP_DIR = settings['zip_dir'] || '~'
|
85
|
+
OPENSSL = settings['openssl'] || 'openssl'
|
86
|
+
KEY_SIZE = settings['key_size'] || 2048
|
87
|
+
ENCRYPT = settings['encrypt'] || 'aes128'
|
88
|
+
REQ = settings['req']
|
89
|
+
CN_CA = settings['cn_ca'] || 'Certification Authority'
|
90
|
+
|
91
|
+
if options[:generate_ca]
|
92
|
+
genrsa('ca', 'ca', options[:no_password])
|
93
|
+
req('ca', 'ca', CN_CA)
|
94
|
+
gen_crl
|
95
|
+
end
|
96
|
+
if options[:generate_dh]
|
97
|
+
exe "#{OPENSSL} dhparam -out dh.pem #{KEY_SIZE}"
|
98
|
+
end
|
99
|
+
if options[:generate_server]
|
100
|
+
genrsa('server', options[:generate_server], options[:no_password])
|
101
|
+
req('server', options[:generate_server], options[:generate_server])
|
102
|
+
end
|
103
|
+
if options[:generate_client]
|
104
|
+
ovpn_files = Dir['*.ovpn']
|
105
|
+
case ovpn_files.length
|
106
|
+
when 1
|
107
|
+
ovpn_file = ovpn_files.first
|
108
|
+
when 0
|
109
|
+
abort "No .ovpn file in current directory, please add one"
|
110
|
+
else
|
111
|
+
abort "More than one .ovpn files in current directory, aborting"
|
112
|
+
end
|
113
|
+
|
114
|
+
genrsa('client', options[:generate_client], options[:no_password])
|
115
|
+
req('client', options[:generate_client], options[:generate_client])
|
116
|
+
|
117
|
+
zip_file = File.join(File.expand_path(ZIP_DIR), "#{File.basename ovpn_file, '.ovpn'}.tblk.zip")
|
118
|
+
File.delete(zip_file) if File.exist?(zip_file)
|
119
|
+
Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
|
120
|
+
zip.get_output_stream(ovpn_file) {|f|
|
121
|
+
File.open(ovpn_file).each {|line| f.write line}
|
122
|
+
f.write "cert #{options[:generate_client]}.crt\nkey #{options[:generate_client]}.key\n"
|
123
|
+
}
|
124
|
+
[ 'ca.crt', "#{options[:generate_client]}.crt", "#{options[:generate_client]}.key"].each {|i|
|
125
|
+
zip.add(i, i)
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
if options[:revoke]
|
130
|
+
exe "#{OPENSSL} ca -revoke '#{options[:revoke]}.crt' -config #{SSL_CONF}"
|
131
|
+
gen_crl
|
132
|
+
['crt', 'key'].each {|ext| File.delete "#{options[:revoke]}.#{ext}"}
|
133
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
unique_subject = yes
|
@@ -0,0 +1 @@
|
|
1
|
+
01
|
@@ -0,0 +1,49 @@
|
|
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
|
data/lib/functions.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
def check_crt filename
|
2
|
+
['key', 'crt'].each {|ext|
|
3
|
+
abort "#{filename}.#{ext} already exists, exiting" if File.exist? "#{filename}.#{ext}"
|
4
|
+
}
|
5
|
+
end
|
6
|
+
|
7
|
+
def exe cmd
|
8
|
+
system(cmd) or abort "error executing: #{cmd}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def genrsa type, certname, no_password
|
12
|
+
if no_password
|
13
|
+
exe "#{OPENSSL} genrsa -out '#{certname}.key' #{KEY_SIZE} -config #{SSL_CONF} -extensions ext.#{type}"
|
14
|
+
else
|
15
|
+
exe "#{OPENSSL} genrsa -#{ENCRYPT} -out '#{certname}.key' #{KEY_SIZE} -config #{SSL_CONF} -extensions ext.#{type}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def req type, certname, cn
|
20
|
+
if certname == 'ca'
|
21
|
+
exe "#{OPENSSL} req -new -x509 -key '#{certname}.key' -out '#{certname}.crt' -config #{SSL_CONF} -subj '/CN=#{cn}#{REQ}' -extensions ext.#{type}"
|
22
|
+
else
|
23
|
+
exe "#{OPENSSL} req -new -key '#{certname}.key' -out '#{certname}.csr' -config #{SSL_CONF} -subj '/CN=#{cn}#{REQ}' -extensions ext.#{type}"
|
24
|
+
exe "#{OPENSSL} ca -in '#{certname}.csr' -out '#{certname}.crt' -config #{SSL_CONF} -extensions ext.#{type} -batch"
|
25
|
+
File.delete "#{certname}.csr"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def gen_crl
|
30
|
+
exe "#{OPENSSL} ca -gencrl -out crl.pem -config #{SSL_CONF}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_dir name
|
34
|
+
unless Dir.exist? name
|
35
|
+
Dir.mkdir name
|
36
|
+
puts "Created directory: #{name}"
|
37
|
+
end
|
38
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
::Version = '0.4'
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ovpn-key
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.4'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vasily Korytov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rubyzip
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.2'
|
27
|
+
description: ''
|
28
|
+
email: vasily.korytov@icloud.com
|
29
|
+
executables:
|
30
|
+
- ovpn-key
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- NOTICE
|
35
|
+
- README.md
|
36
|
+
- bin/ovpn-key
|
37
|
+
- defaults/meta/index.txt
|
38
|
+
- defaults/meta/index.txt.attr
|
39
|
+
- defaults/meta/serial
|
40
|
+
- defaults/openssl.ini
|
41
|
+
- defaults/ovpn-key.yml
|
42
|
+
- lib/functions.rb
|
43
|
+
- lib/version.rb
|
44
|
+
homepage: https://github.com/chillum/ovpn-key
|
45
|
+
licenses:
|
46
|
+
- Apache-2.0
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '2.0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.7.6
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Key management utility for OpenVPN
|
68
|
+
test_files: []
|