cfn-vpn 0.5.1 → 1.1.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/.github/workflows/build-gem.yml +25 -0
- data/.github/workflows/release-gem.yml +31 -0
- data/.github/workflows/release-image.yml +33 -0
- data/Gemfile.lock +30 -38
- data/README.md +1 -247
- data/cfn-vpn.gemspec +3 -2
- data/docs/README.md +44 -0
- data/docs/certificate-users.md +89 -0
- data/docs/getting-started.md +87 -0
- data/docs/modifying.md +67 -0
- data/docs/routes.md +82 -0
- data/docs/scheduling.md +32 -0
- data/docs/sessions.md +27 -0
- data/lib/cfnvpn.rb +31 -27
- data/lib/cfnvpn/{client.rb → actions/client.rb} +5 -6
- data/lib/cfnvpn/{embedded.rb → actions/embedded.rb} +15 -15
- data/lib/cfnvpn/actions/init.rb +130 -0
- data/lib/cfnvpn/actions/modify.rb +149 -0
- data/lib/cfnvpn/actions/params.rb +73 -0
- data/lib/cfnvpn/{revoke.rb → actions/revoke.rb} +6 -6
- data/lib/cfnvpn/actions/routes.rb +144 -0
- data/lib/cfnvpn/{sessions.rb → actions/sessions.rb} +5 -5
- data/lib/cfnvpn/{share.rb → actions/share.rb} +10 -10
- data/lib/cfnvpn/actions/subnets.rb +78 -0
- data/lib/cfnvpn/certificates.rb +5 -5
- data/lib/cfnvpn/clientvpn.rb +34 -68
- data/lib/cfnvpn/compiler.rb +23 -0
- data/lib/cfnvpn/config.rb +34 -78
- data/lib/cfnvpn/{cloudformation.rb → deployer.rb} +47 -19
- data/lib/cfnvpn/log.rb +26 -26
- data/lib/cfnvpn/s3.rb +4 -4
- data/lib/cfnvpn/string.rb +29 -0
- data/lib/cfnvpn/templates/helper.rb +14 -0
- data/lib/cfnvpn/templates/vpn.rb +344 -0
- data/lib/cfnvpn/version.rb +1 -1
- metadata +55 -22
- data/lib/cfnvpn/cfhighlander.rb +0 -49
- data/lib/cfnvpn/init.rb +0 -109
- data/lib/cfnvpn/modify.rb +0 -103
- data/lib/cfnvpn/routes.rb +0 -84
- data/lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt +0 -27
data/lib/cfnvpn/cfhighlander.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'cfhighlander.publisher'
|
2
|
-
require 'cfhighlander.factory'
|
3
|
-
require 'cfhighlander.validator'
|
4
|
-
|
5
|
-
require 'cfnvpn/version'
|
6
|
-
|
7
|
-
module CfnVpn
|
8
|
-
class CfHiglander
|
9
|
-
|
10
|
-
def initialize(region, name, config, output_dir)
|
11
|
-
@component_name = name
|
12
|
-
@region = region
|
13
|
-
@config = config
|
14
|
-
@cfn_output_format = 'yaml'
|
15
|
-
ENV['CFHIGHLANDER_WORKDIR'] = output_dir
|
16
|
-
end
|
17
|
-
|
18
|
-
def render()
|
19
|
-
component = load_component(@component_name)
|
20
|
-
compiled = compile_component(component)
|
21
|
-
validate_component(component,compiled.cfn_template_paths)
|
22
|
-
cfn_template_paths = compiled.cfn_template_paths
|
23
|
-
return cfn_template_paths.select { |path| path.match(@component_name) }.first
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def load_component(component_name)
|
29
|
-
factory = Cfhighlander::Factory::ComponentFactory.new
|
30
|
-
component = factory.loadComponentFromTemplate(component_name)
|
31
|
-
component.config = @config
|
32
|
-
component.version = CfnVpn::VERSION
|
33
|
-
component.load()
|
34
|
-
return component
|
35
|
-
end
|
36
|
-
|
37
|
-
def compile_component(component)
|
38
|
-
component_compiler = Cfhighlander::Compiler::ComponentCompiler.new(component)
|
39
|
-
component_compiler.compileCloudFormation(@cfn_output_format)
|
40
|
-
return component_compiler
|
41
|
-
end
|
42
|
-
|
43
|
-
def validate_component(component,template_paths)
|
44
|
-
component_validator = Cfhighlander::Cloudformation::Validator.new(component)
|
45
|
-
component_validator.validate(template_paths, @cfn_output_format)
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
data/lib/cfnvpn/init.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'thor'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'cfnvpn/cloudformation'
|
4
|
-
require 'cfnvpn/certificates'
|
5
|
-
require 'cfnvpn/cfhighlander'
|
6
|
-
require 'cfnvpn/cloudformation'
|
7
|
-
require 'cfnvpn/log'
|
8
|
-
require 'cfnvpn/clientvpn'
|
9
|
-
require 'cfnvpn/globals'
|
10
|
-
|
11
|
-
module CfnVpn
|
12
|
-
class Init < Thor::Group
|
13
|
-
include Thor::Actions
|
14
|
-
include CfnVpn::Log
|
15
|
-
|
16
|
-
argument :name
|
17
|
-
|
18
|
-
class_option :profile, aliases: :p, desc: 'AWS Profile'
|
19
|
-
class_option :region, aliases: :r, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
20
|
-
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
21
|
-
|
22
|
-
class_option :server_cn, required: true, desc: 'server certificate common name'
|
23
|
-
class_option :client_cn, desc: 'client certificate common name'
|
24
|
-
class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker'
|
25
|
-
class_option :bucket, required: true, desc: 's3 bucket'
|
26
|
-
|
27
|
-
class_option :subnet_id, required: true, desc: 'subnet id to associate your vpn with'
|
28
|
-
class_option :cidr, default: '10.250.0.0/16', desc: 'cidr from which to assign client IP addresses'
|
29
|
-
class_option :dns_servers, desc: 'DNS Servers to push to clients.'
|
30
|
-
|
31
|
-
class_option :split_tunnel, type: :boolean, default: false, desc: 'only push routes to the client on the vpn endpoint'
|
32
|
-
class_option :internet_route, type: :boolean, default: true, desc: 'create a default route to the internet'
|
33
|
-
class_option :protocol, type: :string, default: 'udp', enum: ['udp','tcp'], desc: 'set the protocol for the vpn connections'
|
34
|
-
|
35
|
-
|
36
|
-
def self.source_root
|
37
|
-
File.dirname(__FILE__)
|
38
|
-
end
|
39
|
-
|
40
|
-
def set_loglevel
|
41
|
-
Log.logger.level = Logger::DEBUG if @options['verbose']
|
42
|
-
end
|
43
|
-
|
44
|
-
def create_build_directory
|
45
|
-
@build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}"
|
46
|
-
Log.logger.debug "creating directory #{@build_dir}"
|
47
|
-
FileUtils.mkdir_p(@build_dir)
|
48
|
-
end
|
49
|
-
|
50
|
-
def initialize_config
|
51
|
-
@config = {}
|
52
|
-
@config['parameters'] = {}
|
53
|
-
@config['parameters']['EnvironmentName'] = @name
|
54
|
-
@config['parameters']['AssociationSubnetId'] = @options['subnet_id']
|
55
|
-
@config['parameters']['ClientCidrBlock'] = @options['cidr']
|
56
|
-
@config['parameters']['DnsServers'] = @options['dns_servers']
|
57
|
-
@config['parameters']['SplitTunnel'] = @options['split_tunnel'].to_s
|
58
|
-
@config['parameters']['InternetRoute'] = @options['internet_route'].to_s
|
59
|
-
@config['parameters']['Protocol'] = @options['protocol']
|
60
|
-
@config['template_version'] = '0.2.0'
|
61
|
-
end
|
62
|
-
|
63
|
-
def stack_exist
|
64
|
-
@cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
65
|
-
if @cfn.does_cf_stack_exist()
|
66
|
-
Log.logger.error "#{@name}-cfnvpn stack already exists in this account in region #{@options['region']}"
|
67
|
-
exit 1
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# create certificates
|
72
|
-
def generate_server_certificates
|
73
|
-
Log.logger.info "Generating certificates using openvpn easy-rsa"
|
74
|
-
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
75
|
-
@client_cn = @options['client_cn'] ? @options['client_cn'] : "client-vpn.#{@options['server_cn']}"
|
76
|
-
cert.generate_ca(@options['server_cn'],@client_cn)
|
77
|
-
end
|
78
|
-
|
79
|
-
def upload_certificates
|
80
|
-
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
81
|
-
@config['parameters']['ServerCertificateArn'] = cert.upload_certificates(@options['region'],'server','server',@options['server_cn'])
|
82
|
-
@config['parameters']['ClientCertificateArn'] = cert.upload_certificates(@options['region'],@client_cn,'client')
|
83
|
-
s3 = CfnVpn::S3.new(@options['region'],@options['bucket'],@name)
|
84
|
-
s3.store_object("#{@build_dir}/certificates/ca.tar.gz")
|
85
|
-
end
|
86
|
-
|
87
|
-
def deploy_vpn
|
88
|
-
template('templates/cfnvpn.cfhighlander.rb.tt', "#{@build_dir}/#{@name}.cfhighlander.rb", @config, force: true)
|
89
|
-
Log.logger.debug "Generating cloudformation from #{@build_dir}/#{@name}.cfhighlander.rb"
|
90
|
-
cfhl = CfnVpn::CfHiglander.new(@options['region'],@name,@config,@build_dir)
|
91
|
-
template_path = cfhl.render()
|
92
|
-
Log.logger.debug "Cloudformation template #{template_path} generated and validated"
|
93
|
-
Log.logger.info "Launching cloudformation stack #{@name}-cfnvpn in #{@options['region']}"
|
94
|
-
cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
95
|
-
change_set, change_set_type = cfn.create_change_set(template_path, @config['parameters'])
|
96
|
-
cfn.wait_for_changeset(change_set.id)
|
97
|
-
cfn.execute_change_set(change_set.id)
|
98
|
-
cfn.wait_for_execute(change_set_type)
|
99
|
-
Log.logger.debug "Changeset #{change_set_type} complete"
|
100
|
-
end
|
101
|
-
|
102
|
-
def finish
|
103
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
104
|
-
@endpoint_id = vpn.get_endpoint_id()
|
105
|
-
Log.logger.info "Client VPN #{@endpoint_id} created. Run `cfn-vpn config #{@name}` to setup the client config"
|
106
|
-
end
|
107
|
-
|
108
|
-
end
|
109
|
-
end
|
data/lib/cfnvpn/modify.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'thor'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'cfnvpn/cloudformation'
|
4
|
-
require 'cfnvpn/certificates'
|
5
|
-
require 'cfnvpn/cfhighlander'
|
6
|
-
require 'cfnvpn/cloudformation'
|
7
|
-
require 'cfnvpn/log'
|
8
|
-
require 'cfnvpn/clientvpn'
|
9
|
-
require 'cfnvpn/globals'
|
10
|
-
|
11
|
-
module CfnVpn
|
12
|
-
class Modify < Thor::Group
|
13
|
-
include Thor::Actions
|
14
|
-
include CfnVpn::Log
|
15
|
-
|
16
|
-
argument :name
|
17
|
-
|
18
|
-
class_option :profile, aliases: :p, desc: 'AWS Profile'
|
19
|
-
class_option :region, aliases: :r, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
20
|
-
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
21
|
-
|
22
|
-
class_option :subnet_id, desc: 'subnet id to associate your vpn with'
|
23
|
-
class_option :cidr, desc: 'cidr from which to assign client IP addresses'
|
24
|
-
class_option :dns_servers, desc: 'DNS Servers to push to clients.'
|
25
|
-
|
26
|
-
class_option :split_tunnel, type: :boolean, desc: 'only push routes to the client on the vpn endpoint'
|
27
|
-
class_option :internet_route, type: :boolean, desc: 'create a default route to the internet'
|
28
|
-
class_option :protocol, type: :string, enum: ['udp','tcp'], desc: 'set the protocol for the vpn connections'
|
29
|
-
|
30
|
-
def self.source_root
|
31
|
-
File.dirname(__FILE__)
|
32
|
-
end
|
33
|
-
|
34
|
-
def set_loglevel
|
35
|
-
Log.logger.level = Logger::DEBUG if @options['verbose']
|
36
|
-
end
|
37
|
-
|
38
|
-
def create_build_directory
|
39
|
-
@build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}"
|
40
|
-
Log.logger.debug "creating directory #{@build_dir}"
|
41
|
-
FileUtils.mkdir_p(@build_dir)
|
42
|
-
end
|
43
|
-
|
44
|
-
def initialize_config
|
45
|
-
@config = {}
|
46
|
-
@config['parameters'] = {}
|
47
|
-
@config['parameters']['AssociationSubnetId'] = @options['subnet_id'] unless @options['subnet_id'].nil?
|
48
|
-
@config['parameters']['ClientCidrBlock'] = @options['cidr'] unless @options['cidr'].nil?
|
49
|
-
@config['parameters']['DnsServers'] = @options['dns_servers'] unless @options['dns_servers'].nil?
|
50
|
-
@config['parameters']['SplitTunnel'] = @options['split_tunnel'].to_s unless @options['split_tunnel'].nil?
|
51
|
-
@config['parameters']['InternetRoute'] = @options['internet_route'].to_s unless @options['internet_route'].nil?
|
52
|
-
@config['parameters']['Protocol'] = @options['protocol'] unless @options['protocol'].nil?
|
53
|
-
@config['template_version'] = '0.2.0'
|
54
|
-
end
|
55
|
-
|
56
|
-
def stack_exist
|
57
|
-
@cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
58
|
-
if !@cfn.does_cf_stack_exist()
|
59
|
-
Log.logger.error "#{@name}-cfnvpn stack doesn't exists in this account in region #{@options['region']}\n Try running `cfn-vpn init #{@name}` to setup the stack"
|
60
|
-
exit 1
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def deploy_vpn
|
65
|
-
template('templates/cfnvpn.cfhighlander.rb.tt', "#{@build_dir}/#{@name}.cfhighlander.rb", @config, force: true)
|
66
|
-
Log.logger.debug "Generating cloudformation from #{@build_dir}/#{@name}.cfhighlander.rb"
|
67
|
-
cfhl = CfnVpn::CfHiglander.new(@options['region'],@name,@config,@build_dir)
|
68
|
-
template_path = cfhl.render()
|
69
|
-
Log.logger.debug "Cloudformation template #{template_path} generated and validated"
|
70
|
-
|
71
|
-
Log.logger.info "Modifying cloudformation stack #{@name}-cfnvpn in #{@options['region']}"
|
72
|
-
cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
73
|
-
change_set, change_set_type = cfn.create_change_set(template_path,@config['parameters'])
|
74
|
-
cfn.wait_for_changeset(change_set.id)
|
75
|
-
changes = cfn.get_change_set(change_set.id)
|
76
|
-
|
77
|
-
Log.logger.warn("The following changes to the cfnvpn stack will be made")
|
78
|
-
changes.changes.each do |change|
|
79
|
-
Log.logger.warn("ID: #{change.resource_change.logical_resource_id} Action: #{change.resource_change.action}")
|
80
|
-
change.resource_change.details.each do |details|
|
81
|
-
Log.logger.warn("Name: #{details.target.name} Attribute: #{details.target.attribute} Cause: #{details.causing_entity}")
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
continue = yes? "Continue?", :green
|
86
|
-
if !continue
|
87
|
-
Log.logger.error("Cancelled cfn-vpn modifiy #{@name}")
|
88
|
-
exit 1
|
89
|
-
end
|
90
|
-
|
91
|
-
cfn.execute_change_set(change_set.id)
|
92
|
-
cfn.wait_for_execute(change_set_type)
|
93
|
-
Log.logger.debug "Changeset #{change_set_type} complete"
|
94
|
-
end
|
95
|
-
|
96
|
-
def finish
|
97
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
98
|
-
@endpoint_id = vpn.get_endpoint_id()
|
99
|
-
Log.logger.info "Client VPN #{@endpoint_id} modified."
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
end
|
data/lib/cfnvpn/routes.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
require 'thor'
|
2
|
-
require 'cfnvpn/log'
|
3
|
-
require 'cfnvpn/s3'
|
4
|
-
require 'cfnvpn/globals'
|
5
|
-
|
6
|
-
module CfnVpn
|
7
|
-
class Routes < Thor::Group
|
8
|
-
include Thor::Actions
|
9
|
-
include CfnVpn::Log
|
10
|
-
|
11
|
-
argument :name
|
12
|
-
|
13
|
-
class_option :profile, aliases: :p, desc: 'AWS Profile'
|
14
|
-
class_option :region, aliases: :r, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
15
|
-
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
16
|
-
|
17
|
-
class_option :add, desc: 'add cidr to route through the client vpn'
|
18
|
-
class_option :del, desc: 'delete cidr route from the client vpn'
|
19
|
-
class_option :desc, desc: 'description of the route'
|
20
|
-
|
21
|
-
def self.source_root
|
22
|
-
File.dirname(__FILE__)
|
23
|
-
end
|
24
|
-
|
25
|
-
def set_loglevel
|
26
|
-
Log.logger.level = Logger::DEBUG if @options['verbose']
|
27
|
-
end
|
28
|
-
|
29
|
-
def set_directory
|
30
|
-
@build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}"
|
31
|
-
end
|
32
|
-
|
33
|
-
def add_route
|
34
|
-
if !@options['add'].nil?
|
35
|
-
if @options['desc'].nil?
|
36
|
-
Log.logger.error "--desc option must be provided if adding a new route"
|
37
|
-
exit 1
|
38
|
-
end
|
39
|
-
|
40
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
41
|
-
|
42
|
-
if vpn.route_exists?(@options['add'])
|
43
|
-
Log.logger.error "route #{@options['add']} already exists in the client vpn"
|
44
|
-
exit 1
|
45
|
-
end
|
46
|
-
|
47
|
-
Log.logger.info "Adding new route for #{@options['add']}"
|
48
|
-
vpn.add_route(@options['add'],@options['desc'])
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def del_route
|
53
|
-
if !@options['del'].nil?
|
54
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
55
|
-
|
56
|
-
if !vpn.route_exists?(@options['del'])
|
57
|
-
Log.logger.error "route #{@options['del']} doesn't exist in the client vpn"
|
58
|
-
exit 1
|
59
|
-
end
|
60
|
-
delete = yes? "Delete route #{@options['del']}?", :yellow
|
61
|
-
if delete
|
62
|
-
Log.logger.info "Deleting route for #{@options['del']}"
|
63
|
-
vpn.del_route(@options['del'])
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def get_routes
|
69
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
70
|
-
@routes = vpn.get_routes()
|
71
|
-
end
|
72
|
-
|
73
|
-
def display_routes
|
74
|
-
rows = @routes.collect do |s|
|
75
|
-
[ s.destination_cidr, s.description, s.status.code, s.target_subnet, s.type, s.origin ]
|
76
|
-
end
|
77
|
-
table = Terminal::Table.new(
|
78
|
-
:headings => ['Route', 'Description', 'Status', 'Target', 'Type', 'Origin'],
|
79
|
-
:rows => rows)
|
80
|
-
puts table
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
CfhighlanderTemplate do
|
2
|
-
|
3
|
-
Parameters do
|
4
|
-
ComponentParam 'EnvironmentName'
|
5
|
-
ComponentParam 'AssociationSubnetId'
|
6
|
-
ComponentParam 'ClientCidrBlock'
|
7
|
-
ComponentParam 'DnsServers'
|
8
|
-
ComponentParam 'SplitTunnel'
|
9
|
-
ComponentParam 'InternetRoute'
|
10
|
-
ComponentParam 'Protocol'
|
11
|
-
ComponentParam 'ServerCertificateArn'
|
12
|
-
ComponentParam 'ClientCertificateArn'
|
13
|
-
end
|
14
|
-
|
15
|
-
Component template: 'client-vpn@<%= @config['template_version'] %>', name: 'vpn', render: Inline do
|
16
|
-
parameter name: 'EnvironmentName', value: Ref('EnvironmentName')
|
17
|
-
parameter name: 'AssociationSubnetId', value: Ref('AssociationSubnetId')
|
18
|
-
parameter name: 'ClientCidrBlock', value: Ref('ClientCidrBlock')
|
19
|
-
parameter name: 'DnsServers', value: Ref('DnsServers')
|
20
|
-
parameter name: 'SplitTunnel', value: Ref('SplitTunnel')
|
21
|
-
parameter name: 'InternetRoute', value: Ref('InternetRoute')
|
22
|
-
parameter name: 'Protocol', value: Ref('Protocol')
|
23
|
-
parameter name: 'ServerCertificateArn', value: Ref('ServerCertificateArn')
|
24
|
-
parameter name: 'ClientCertificateArn', value: Ref('ClientCertificateArn')
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|