cfn-vpn 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +75 -0
- data/LICENSE.txt +21 -0
- data/README.md +74 -0
- data/Rakefile +2 -0
- data/cfn-vpn.gemspec +48 -0
- data/exe/cfn-vpn +4 -0
- data/lib/cfnvpn.rb +26 -0
- data/lib/cfnvpn/acm.rb +49 -0
- data/lib/cfnvpn/certificates.rb +55 -0
- data/lib/cfnvpn/cfhighlander.rb +49 -0
- data/lib/cfnvpn/clientvpn.rb +36 -0
- data/lib/cfnvpn/cloudformation.rb +75 -0
- data/lib/cfnvpn/config.rb +77 -0
- data/lib/cfnvpn/init.rb +93 -0
- data/lib/cfnvpn/log.rb +38 -0
- data/lib/cfnvpn/ssm.rb +50 -0
- data/lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt +14 -0
- data/lib/cfnvpn/version.rb +4 -0
- metadata +231 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4e3b6334f24037b79137a09d3d93325a2513162f4e151b1e565875e74352aac7
|
4
|
+
data.tar.gz: d0e7e304876a4bcccab2b082fc8c298f8fc74b0769b4eb9338fdc98b5d5842a1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c75ae0f97eb239c6db309b98d09d5b08a688bde621aa5f23b091face28fab3737369d67d6d40c9f13e7615ba8f58c4ee3553fe24a55715ac0282f889b72946fd
|
7
|
+
data.tar.gz: d543e66f8ce62534e64de754d09be061c4a92b50bff6d8ddfbd0f8df03a48f830217c501024986e8810e4f2a300fa503a9631efb7ad0cb4a22c6c47019456df6
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
sudo: required
|
2
|
+
dist: trusty
|
3
|
+
language: ruby
|
4
|
+
rvm:
|
5
|
+
- 2.5
|
6
|
+
script:
|
7
|
+
- bundle install
|
8
|
+
- gem build cfn-vpn.gemspec
|
9
|
+
- gem install cfn-vpn-*.gem
|
10
|
+
- cfn-vpn help
|
11
|
+
deploy:
|
12
|
+
provider: rubygems
|
13
|
+
api_key: "${RUBYGEMS_API_KEY}"
|
14
|
+
gem: cfn-vpn
|
15
|
+
on:
|
16
|
+
all_branches: true
|
17
|
+
condition: $TRAVIS_BRANCH =~ ^develop|master && $TRAVIS_EVENT_TYPE =~ ^push|api$ && $TRAVIS_REPO_SLUG == "base2services/aws-client-vpn"
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cfn-vpn (0.1.0)
|
5
|
+
aws-sdk-acm (~> 1, < 2)
|
6
|
+
aws-sdk-cloudformation (~> 1, < 2)
|
7
|
+
aws-sdk-ec2 (~> 1.95, < 2)
|
8
|
+
aws-sdk-ssm (~> 1, < 2)
|
9
|
+
cfhighlander (~> 0.9, < 1)
|
10
|
+
cfndsl (~> 0.17, < 1)
|
11
|
+
thor (~> 0.20)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
aws-eventstream (1.0.3)
|
17
|
+
aws-partitions (1.176.0)
|
18
|
+
aws-sdk-acm (1.23.0)
|
19
|
+
aws-sdk-core (~> 3, >= 3.56.0)
|
20
|
+
aws-sigv4 (~> 1.1)
|
21
|
+
aws-sdk-cloudformation (1.23.0)
|
22
|
+
aws-sdk-core (~> 3, >= 3.56.0)
|
23
|
+
aws-sigv4 (~> 1.1)
|
24
|
+
aws-sdk-core (3.56.0)
|
25
|
+
aws-eventstream (~> 1.0, >= 1.0.2)
|
26
|
+
aws-partitions (~> 1.0)
|
27
|
+
aws-sigv4 (~> 1.1)
|
28
|
+
jmespath (~> 1.0)
|
29
|
+
aws-sdk-ec2 (1.95.0)
|
30
|
+
aws-sdk-core (~> 3, >= 3.56.0)
|
31
|
+
aws-sigv4 (~> 1.1)
|
32
|
+
aws-sdk-kms (1.22.0)
|
33
|
+
aws-sdk-core (~> 3, >= 3.56.0)
|
34
|
+
aws-sigv4 (~> 1.1)
|
35
|
+
aws-sdk-s3 (1.43.0)
|
36
|
+
aws-sdk-core (~> 3, >= 3.56.0)
|
37
|
+
aws-sdk-kms (~> 1)
|
38
|
+
aws-sigv4 (~> 1.1)
|
39
|
+
aws-sdk-ssm (1.50.0)
|
40
|
+
aws-sdk-core (~> 3, >= 3.56.0)
|
41
|
+
aws-sigv4 (~> 1.1)
|
42
|
+
aws-sigv4 (1.1.0)
|
43
|
+
aws-eventstream (~> 1.0, >= 1.0.2)
|
44
|
+
cfhighlander (0.9.0)
|
45
|
+
aws-sdk-cloudformation (~> 1, < 2)
|
46
|
+
aws-sdk-core (~> 3, < 4)
|
47
|
+
aws-sdk-ec2 (~> 1, < 2)
|
48
|
+
aws-sdk-s3 (~> 1, < 2)
|
49
|
+
cfndsl (~> 0.16, < 1)
|
50
|
+
duplicate (~> 1.1)
|
51
|
+
git (~> 1.4, < 2)
|
52
|
+
highline (>= 1.7.10, < 1.8)
|
53
|
+
netaddr (~> 1.5, >= 1.5.1)
|
54
|
+
rubyzip (>= 1.2.1, < 2)
|
55
|
+
thor (~> 0.20, < 1)
|
56
|
+
cfndsl (0.17.0)
|
57
|
+
duplicate (1.1.1)
|
58
|
+
git (1.5.0)
|
59
|
+
highline (1.7.10)
|
60
|
+
jmespath (1.4.0)
|
61
|
+
netaddr (1.5.1)
|
62
|
+
rake (10.5.0)
|
63
|
+
rubyzip (1.2.3)
|
64
|
+
thor (0.20.3)
|
65
|
+
|
66
|
+
PLATFORMS
|
67
|
+
ruby
|
68
|
+
|
69
|
+
DEPENDENCIES
|
70
|
+
bundler (~> 2.0)
|
71
|
+
cfn-vpn!
|
72
|
+
rake (~> 10.0)
|
73
|
+
|
74
|
+
BUNDLED WITH
|
75
|
+
2.0.1
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Guslington
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# CfnVpn
|
2
|
+
|
3
|
+
Manages the resources required to create a client vpn in AWS.
|
4
|
+
Uses cloudformation to manage the state of the vpn resources.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Install `cfn-vpn` gem
|
9
|
+
|
10
|
+
```bash
|
11
|
+
gem install cfn-vpn
|
12
|
+
```
|
13
|
+
|
14
|
+
Install [docker](https://docs.docker.com/install/)
|
15
|
+
|
16
|
+
Docker is required to generate the certificates required for the client vpn.
|
17
|
+
The gem uses [openvpn/easy-rsa](https://github.com/OpenVPN/easy-rsa) project in [base2/aws-client-vpn](https://hub.docker.com/r/base2/aws-client-vpn) dokcer image.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### help
|
22
|
+
|
23
|
+
Displays all possible commands
|
24
|
+
|
25
|
+
```bash
|
26
|
+
Commands:
|
27
|
+
cfn-vpn --version, -v # print the version
|
28
|
+
cfn-vpn help [COMMAND] # Describe available commands or one specific command
|
29
|
+
cfn-vpn init [name] --server-cn=SERVER_CN --subnet-id=SUBNET_ID # Ciinabox configuration initialization
|
30
|
+
```
|
31
|
+
|
32
|
+
### init
|
33
|
+
|
34
|
+
Initialises a new client vpn and creates all required resources to get it running.
|
35
|
+
|
36
|
+
```bash
|
37
|
+
Usage:
|
38
|
+
cfn-vpn init [name] --server-cn=SERVER_CN --subnet-id=SUBNET_ID
|
39
|
+
|
40
|
+
Options:
|
41
|
+
p, [--profile=PROFILE] # AWS Profile
|
42
|
+
r, [--region=REGION] # AWS Region
|
43
|
+
--server-cn=SERVER_CN # server certificate common name
|
44
|
+
[--client-cn=CLIENT_CN] # client certificate common name
|
45
|
+
--subnet-id=SUBNET_ID # subnet id to associate your vpn with
|
46
|
+
[--cidr=CIDR] # cidr from which to assign client IP addresses
|
47
|
+
# Default: 10.250.0.0/16
|
48
|
+
|
49
|
+
Ciinabox configuration initialization
|
50
|
+
```
|
51
|
+
|
52
|
+
### config
|
53
|
+
|
54
|
+
Downloads the opvn config file for the client vpn
|
55
|
+
|
56
|
+
```bash
|
57
|
+
Usage:
|
58
|
+
cfn-vpn config [name]
|
59
|
+
|
60
|
+
Options:
|
61
|
+
[--profile=PROFILE] # AWS Profile
|
62
|
+
[--region=REGION] # AWS Region
|
63
|
+
# Default: ap-southeast-2
|
64
|
+
|
65
|
+
Ciinabox configuration initialization
|
66
|
+
```
|
67
|
+
|
68
|
+
## Contributing
|
69
|
+
|
70
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/base2services/aws-client-vpn.
|
71
|
+
|
72
|
+
## License
|
73
|
+
|
74
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/cfn-vpn.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "cfnvpn/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cfn-vpn"
|
8
|
+
spec.version = CfnVpn::VERSION
|
9
|
+
spec.authors = ["Guslington"]
|
10
|
+
spec.email = ["guslington@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{creates and manages resources for the aws client vpn}
|
13
|
+
spec.description = %q{creates and manages resources for the aws client vpn}
|
14
|
+
spec.homepage = "https://github.com/base2services/aws-client-vpn"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata["allowed_push_host"] = 'https://rubygems.org'
|
21
|
+
|
22
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
spec.metadata["source_code_uri"] = "https://github.com/base2services/aws-client-vpn"
|
24
|
+
else
|
25
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
26
|
+
"public gem pushes."
|
27
|
+
end
|
28
|
+
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
|
+
end
|
34
|
+
spec.bindir = "exe"
|
35
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
|
+
spec.require_paths = ["lib"]
|
37
|
+
|
38
|
+
spec.add_dependency "thor", "~> 0.20"
|
39
|
+
spec.add_dependency 'cfhighlander', '~> 0.9', '<1'
|
40
|
+
spec.add_dependency 'cfndsl', '~> 0.17', '<1'
|
41
|
+
spec.add_runtime_dependency 'aws-sdk-ec2', '~> 1.95', '<2'
|
42
|
+
spec.add_runtime_dependency 'aws-sdk-acm', '~> 1', '<2'
|
43
|
+
spec.add_runtime_dependency 'aws-sdk-ssm', '~> 1', '<2'
|
44
|
+
spec.add_runtime_dependency 'aws-sdk-cloudformation', '~> 1', '<2'
|
45
|
+
|
46
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
47
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
48
|
+
end
|
data/exe/cfn-vpn
ADDED
data/lib/cfnvpn.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'cfnvpn/version'
|
3
|
+
require 'cfnvpn/init'
|
4
|
+
require 'cfnvpn/config'
|
5
|
+
|
6
|
+
module CfnVpn
|
7
|
+
class Cli < Thor
|
8
|
+
|
9
|
+
map %w[--version -v] => :__print_version
|
10
|
+
desc "--version, -v", "print the version"
|
11
|
+
def __print_version
|
12
|
+
puts CfnVpn::VERSION
|
13
|
+
end
|
14
|
+
|
15
|
+
# Initializes ciinabox configuration
|
16
|
+
register CfnVpn::Init, 'init', 'init [name]', 'Ciinabox configuration initialization'
|
17
|
+
tasks["init"].options = CfnVpn::Init.class_options
|
18
|
+
|
19
|
+
register CfnVpn::Config, 'config', 'config [name]', 'Ciinabox configuration initialization'
|
20
|
+
tasks["config"].options = CfnVpn::Config.class_options
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# Aws.config[:retry_limit] = if ENV.key? 'CFNVPN_AWS_RETRY_LIMIT' then (ENV['CFNVPN_AWS_RETRY_LIMIT'].to_i) else 10 end
|
25
|
+
|
26
|
+
end
|
data/lib/cfnvpn/acm.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'aws-sdk-acm'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module CfnVpn
|
5
|
+
class Acm
|
6
|
+
|
7
|
+
def initialize(region,cert_dir)
|
8
|
+
@client = Aws::ACM::Client.new(region: region)
|
9
|
+
@cert_dir = cert_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def import_certificate(cert,key,ca)
|
13
|
+
cert_body = load_certificate(cert)
|
14
|
+
key_body = load_certificate(key)
|
15
|
+
ca_body = load_certificate(ca)
|
16
|
+
|
17
|
+
resp = @client.import_certificate({
|
18
|
+
certificate: cert_body,
|
19
|
+
private_key: key_body,
|
20
|
+
certificate_chain: ca_body
|
21
|
+
})
|
22
|
+
return resp.certificate_arn
|
23
|
+
end
|
24
|
+
|
25
|
+
def tag_certificate(arn,name,type,cfnvpn_name)
|
26
|
+
@client.add_tags_to_certificate({
|
27
|
+
certificate_arn: arn,
|
28
|
+
tags: [
|
29
|
+
{ key: "Name", value: name },
|
30
|
+
{ key: "cfnvpn:name", value: cfnvpn_name },
|
31
|
+
{ key: "cfnvpn:certificate:type", value: type }
|
32
|
+
]
|
33
|
+
})
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_certificate(cert)
|
37
|
+
File.read("#{@cert_dir}/#{cert}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def certificate_exists?(name)
|
41
|
+
return true
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_certificate(name)
|
45
|
+
return 'arn'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'cfnvpn/acm'
|
3
|
+
require 'cfnvpn/ssm'
|
4
|
+
require 'cfnvpn/log'
|
5
|
+
|
6
|
+
module CfnVpn
|
7
|
+
class Certificates
|
8
|
+
include CfnVpn::Log
|
9
|
+
|
10
|
+
def initialize(build_dir,cfnvpn_name)
|
11
|
+
@cfnvpn_name = cfnvpn_name
|
12
|
+
@config_dir = "#{build_dir}/config"
|
13
|
+
@cert_dir = "#{build_dir}/certificates"
|
14
|
+
FileUtils.mkdir_p(@cert_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate(server_cn,client_cn)
|
18
|
+
cmd = ["docker", "run", "-it", "--rm"]
|
19
|
+
cmd << "-e EASYRSA_REQ_CN=#{server_cn}"
|
20
|
+
cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
|
21
|
+
cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
22
|
+
cmd << "base2/aws-client-vpn:3.0.5"
|
23
|
+
return `#{cmd.join(' ')}`
|
24
|
+
end
|
25
|
+
|
26
|
+
def upload_certificates(region,cert,type,cn=nil)
|
27
|
+
cn = cn.nil? ? cert : cn
|
28
|
+
acm = CfnVpn::Acm.new(region, @cert_dir)
|
29
|
+
arn = acm.import_certificate("#{cert}.crt", "#{cert}.key", "ca.crt")
|
30
|
+
Log.logger.debug "Uploaded #{type} certificate to ACM #{arn}"
|
31
|
+
acm.tag_certificate(arn,cn,type,@cfnvpn_name)
|
32
|
+
return arn
|
33
|
+
end
|
34
|
+
|
35
|
+
def store_certificate(region,cert)
|
36
|
+
ssm = CfnVpn::SSM.new(@cfnvpn_name, region, @cert_dir)
|
37
|
+
ssm.put_parameter(cert)
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_certificate(cert_body,name,force)
|
41
|
+
file = "#{@config_dir}/#{name}"
|
42
|
+
if File.file?(file)
|
43
|
+
if force
|
44
|
+
Log.logger.warn "overriding existing #{name}"
|
45
|
+
File.write(file, cert_body)
|
46
|
+
else
|
47
|
+
Log.logger.info "#{name} already exists"
|
48
|
+
end
|
49
|
+
else
|
50
|
+
File.write(file, cert_body)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'aws-sdk-ec2'
|
2
|
+
require 'cfnvpn/log'
|
3
|
+
|
4
|
+
module CfnVpn
|
5
|
+
class ClientVpn
|
6
|
+
include CfnVpn::Log
|
7
|
+
|
8
|
+
def initialize(name,region)
|
9
|
+
@client = Aws::EC2::Client.new(region: region)
|
10
|
+
@name = name
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_endpoint()
|
14
|
+
resp = @client.describe_client_vpn_endpoints({
|
15
|
+
filters: [{ name: "tag:cfnvpn:name", values: [@name] }]
|
16
|
+
})
|
17
|
+
if resp.client_vpn_endpoints.empty?
|
18
|
+
Log.logger.error "unable to find endpoint with tag Key: cfnvpn:name with Value: #{@name}"
|
19
|
+
raise "Unable to find client vpn"
|
20
|
+
end
|
21
|
+
resp.client_vpn_endpoints.first
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_endpoint_id()
|
25
|
+
return get_endpoint().client_vpn_endpoint_id
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_config(endpoint_id)
|
29
|
+
resp = @client.export_client_vpn_client_configuration({
|
30
|
+
client_vpn_endpoint_id: endpoint_id
|
31
|
+
})
|
32
|
+
return resp.client_configuration
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'aws-sdk-cloudformation'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'cfnvpn/version'
|
4
|
+
require 'cfnvpn/log'
|
5
|
+
|
6
|
+
module CfnVpn
|
7
|
+
class Cloudformation
|
8
|
+
include CfnVpn::Log
|
9
|
+
|
10
|
+
def initialize(region,name)
|
11
|
+
@name = name
|
12
|
+
@stack_name = "#{@name}-cfnvpn"
|
13
|
+
@client = Aws::CloudFormation::Client.new(region: region)
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: check for REVIEW_IN_PROGRESS
|
17
|
+
def does_cf_stack_exist()
|
18
|
+
begin
|
19
|
+
resp = @client.describe_stacks({
|
20
|
+
stack_name: @stack_name,
|
21
|
+
})
|
22
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
return resp.size > 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_change_set_type()
|
29
|
+
return does_cf_stack_exist() ? 'UPDATE' : 'CREATE'
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_change_set(template_path)
|
33
|
+
change_set_name = "#{@stack_name}-#{CfnVpn::CHANGE_SET_VERSION}"
|
34
|
+
change_set_type = get_change_set_type()
|
35
|
+
template_body = File.read(template_path)
|
36
|
+
Log.logger.debug "Creating changeset"
|
37
|
+
change_set = @client.create_change_set({
|
38
|
+
stack_name: @stack_name,
|
39
|
+
template_body: template_body,
|
40
|
+
tags: [
|
41
|
+
{
|
42
|
+
key: "cfnvpn:version",
|
43
|
+
value: CfnVpn::VERSION,
|
44
|
+
},
|
45
|
+
{
|
46
|
+
key: "cfnvpn:name",
|
47
|
+
value: @name,
|
48
|
+
}
|
49
|
+
],
|
50
|
+
change_set_name: change_set_name,
|
51
|
+
change_set_type: change_set_type
|
52
|
+
})
|
53
|
+
return change_set, change_set_type
|
54
|
+
end
|
55
|
+
|
56
|
+
def wait_for_changeset(change_set_id)
|
57
|
+
Log.logger.debug "Waiting for changeset to be created"
|
58
|
+
@client.wait_until :change_set_create_complete, change_set_name: change_set_id
|
59
|
+
end
|
60
|
+
|
61
|
+
def execute_change_set(change_set_id)
|
62
|
+
Log.logger.debug "Executing the changeset"
|
63
|
+
stack = @client.execute_change_set({
|
64
|
+
change_set_name: change_set_id
|
65
|
+
})
|
66
|
+
end
|
67
|
+
|
68
|
+
def wait_for_execute(change_set_type)
|
69
|
+
waiter = change_set_type == 'CREATE' ? :stack_create_complete : :stack_update_complete
|
70
|
+
Log.logger.info "Waiting for changeset to #{change_set_type}"
|
71
|
+
resp = @client.wait_until waiter, stack_name: @stack_name
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'cfnvpn/clientvpn'
|
2
|
+
require 'cfnvpn/ssm'
|
3
|
+
require 'cfnvpn/log'
|
4
|
+
|
5
|
+
module CfnVpn
|
6
|
+
class Config < Thor::Group
|
7
|
+
include Thor::Actions
|
8
|
+
include CfnVpn::Log
|
9
|
+
|
10
|
+
argument :name
|
11
|
+
|
12
|
+
class_option :profile, desc: 'AWS Profile'
|
13
|
+
class_option :region, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
14
|
+
class_option :force, default: false, type: :boolean, desc: 'AWS Region'
|
15
|
+
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
16
|
+
|
17
|
+
def self.source_root
|
18
|
+
File.dirname(__FILE__)
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_loglevel
|
22
|
+
Log.logger.level = Logger::DEBUG if @options['verbose']
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_config_directory
|
26
|
+
@home_dir = "#{ENV['HOME']}/.cfnvpn/#{@name}"
|
27
|
+
@config_dir = "#{@home_dir}/config"
|
28
|
+
Log.logger.debug("Creating config directory #{@config_dir}")
|
29
|
+
FileUtils.mkdir_p(@config_dir)
|
30
|
+
end
|
31
|
+
|
32
|
+
def download_config
|
33
|
+
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
34
|
+
@endpoint_id = vpn.get_endpoint_id()
|
35
|
+
Log.logger.info "downloading client config for #{@endpoint_id}"
|
36
|
+
@config = vpn.get_config(@endpoint_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def download_certificate
|
40
|
+
ssm = CfnVpn::SSM.new(@name,@options['region'],@home_dir)
|
41
|
+
cert_body = ssm.get_parameter("#{@name}.crt")
|
42
|
+
if cert_body
|
43
|
+
cert = CfnVpn::Certificates.new(@home_dir,@name)
|
44
|
+
cert.write_certificate(cert_body,"#{@name}.crt",@options['force'])
|
45
|
+
Log.logger.info "downloaded client certificate #{@name}.crt"
|
46
|
+
else
|
47
|
+
Log.logger.error "unable to find client certificate #{@name}.crt"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def download_key
|
52
|
+
ssm = CfnVpn::SSM.new(@name,@options['region'],@home_dir)
|
53
|
+
cert_body = ssm.get_parameter("#{@name}.key")
|
54
|
+
if cert_body
|
55
|
+
cert = CfnVpn::Certificates.new(@home_dir,@name)
|
56
|
+
cert.write_certificate(cert_body,"#{@name}.key",@options['force'])
|
57
|
+
Log.logger.info "downloaded client key #{@name}.key"
|
58
|
+
else
|
59
|
+
Log.logger.error "unable to find client certificate #{@name}.crt"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def alter_config
|
64
|
+
string = (0...8).map { (65 + rand(26)).chr.downcase }.join
|
65
|
+
@config.sub!(@endpoint_id, "#{string}.#{@endpoint_id}")
|
66
|
+
@config.concat("\n\ncert #{@config_dir}/#{@name}.crt")
|
67
|
+
@config.concat("\nkey #{@config_dir}/#{@name}.key\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
def write_config
|
71
|
+
config_file = "#{@config_dir}/#{@name}.ovpn"
|
72
|
+
File.write(config_file, @config)
|
73
|
+
Log.logger.info "downloaded client config #{config_file}"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
data/lib/cfnvpn/init.rb
ADDED
@@ -0,0 +1,93 @@
|
|
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
|
+
|
10
|
+
module CfnVpn
|
11
|
+
class Init < Thor::Group
|
12
|
+
include Thor::Actions
|
13
|
+
include CfnVpn::Log
|
14
|
+
|
15
|
+
argument :name
|
16
|
+
|
17
|
+
class_option :profile, aliases: :p, desc: 'AWS Profile'
|
18
|
+
class_option :region, aliases: :r, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
19
|
+
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
20
|
+
|
21
|
+
class_option :server_cn, required: true, desc: 'server certificate common name'
|
22
|
+
class_option :client_cn, desc: 'client certificate common name'
|
23
|
+
|
24
|
+
class_option :subnet_id, required: true, desc: 'subnet id to associate your vpn with'
|
25
|
+
class_option :cidr, default: '10.250.0.0/16', desc: 'cidr from which to assign client IP addresses'
|
26
|
+
|
27
|
+
def self.source_root
|
28
|
+
File.dirname(__FILE__)
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_loglevel
|
32
|
+
Log.logger.level = Logger::DEBUG if @options['verbose']
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_build_directory
|
36
|
+
@build_dir = "#{ENV['HOME']}/.cfnvpn/#{@name}"
|
37
|
+
Log.logger.debug "creating directory #{@build_dir}"
|
38
|
+
FileUtils.mkdir_p(@build_dir)
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize_config
|
42
|
+
@config = {}
|
43
|
+
@config['subnet_id'] = @options['subnet_id']
|
44
|
+
@config['cidr'] = @options['cidr']
|
45
|
+
end
|
46
|
+
|
47
|
+
def stack_exist
|
48
|
+
@cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
49
|
+
if @cfn.does_cf_stack_exist()
|
50
|
+
Log.logger.error "#{@name}-cfnvpn stack already exists in this account in region #{@options['region']}"
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# create certificates
|
56
|
+
def generate_server_certificates
|
57
|
+
Log.logger.info "Generating certificates using openvpn easy-rsa"
|
58
|
+
cert = CfnVpn::Certificates.new(@build_dir,@name)
|
59
|
+
@client_cn = @options['client_cn'] ? @options['client_cn'] : "#{@name}.#{@options['server_cn']}"
|
60
|
+
Log.logger.debug cert.generate(@options['server_cn'],@client_cn)
|
61
|
+
end
|
62
|
+
|
63
|
+
def upload_certificates
|
64
|
+
cert = CfnVpn::Certificates.new(@build_dir,@name)
|
65
|
+
@config['server_cert_arn'] = cert.upload_certificates(@options['region'],'server','server',@options['server_cn'])
|
66
|
+
@config['client_cert_arn'] = cert.upload_certificates(@options['region'],@client_cn,'client')
|
67
|
+
cert.store_certificate(@options['region'],"#{@client_cn}.crt")
|
68
|
+
cert.store_certificate(@options['region'],"#{@client_cn}.key")
|
69
|
+
end
|
70
|
+
|
71
|
+
def deploy_vpn
|
72
|
+
template('templates/cfnvpn.cfhighlander.rb.tt', "#{@build_dir}/#{@name}.cfhighlander.rb", @config)
|
73
|
+
Log.logger.debug "Generating cloudformation from #{@build_dir}/#{@name}.cfhighlander.rb"
|
74
|
+
cfhl = CfnVpn::CfHiglander.new(@options['region'],@name,@config,@build_dir)
|
75
|
+
template_path = cfhl.render()
|
76
|
+
Log.logger.debug "Cloudformation template #{template_path} generated and validated"
|
77
|
+
Log.logger.info "Launching cloudformation stack #{@name}-cfnvpn in #{@options['region']}"
|
78
|
+
cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
79
|
+
change_set, change_set_type = cfn.create_change_set(template_path)
|
80
|
+
cfn.wait_for_changeset(change_set.id)
|
81
|
+
cfn.execute_change_set(change_set.id)
|
82
|
+
cfn.wait_for_execute(change_set_type)
|
83
|
+
Log.logger.debug "Changeset #{change_set_type} complete"
|
84
|
+
end
|
85
|
+
|
86
|
+
def finish
|
87
|
+
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
88
|
+
@endpoint_id = vpn.get_endpoint_id()
|
89
|
+
Log.logger.info "Client VPN #{@endpoint_id} created. Run `cfn-vpn config #{@name}` to setup the client config"
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
data/lib/cfnvpn/log.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module CfnVpn
|
4
|
+
module Log
|
5
|
+
|
6
|
+
def self.colors
|
7
|
+
@colors ||= {
|
8
|
+
ERROR: 31, # red
|
9
|
+
WARN: 33, # yellow
|
10
|
+
INFO: 0,
|
11
|
+
DEBUG: 32 # grenn
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.logger
|
16
|
+
if @logger.nil?
|
17
|
+
@logger = Logger.new(STDOUT)
|
18
|
+
@logger.level = Logger::INFO
|
19
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
20
|
+
"\e[#{colors[severity.to_sym]}m#{severity}: - #{msg}\e[0m\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@logger
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.logger=(logger)
|
27
|
+
@logger = logger
|
28
|
+
end
|
29
|
+
|
30
|
+
levels = %w(debug info warn error fatal)
|
31
|
+
levels.each do |level|
|
32
|
+
define_method("#{level.to_sym}") do |msg|
|
33
|
+
self.logger.send(level, msg)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/cfnvpn/ssm.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'aws-sdk-ssm'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'cfnvpn/log'
|
4
|
+
|
5
|
+
module CfnVpn
|
6
|
+
class SSM
|
7
|
+
include CfnVpn::Log
|
8
|
+
|
9
|
+
def initialize(name,region,cert_dir)
|
10
|
+
@name = name
|
11
|
+
@cert_dir = cert_dir
|
12
|
+
@path_prefix = "/cfnvpn/#{@name}"
|
13
|
+
@client = Aws::SSM::Client.new(region: region)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_parameter(cert)
|
17
|
+
begin
|
18
|
+
resp = @client.get_parameter({
|
19
|
+
name: "#{@path_prefix}/#{cert}",
|
20
|
+
with_decryption: true
|
21
|
+
})
|
22
|
+
rescue Aws::SSM::Errors::ParameterNotFound
|
23
|
+
Log.logger.debug("Parameter #{@path_prefix}/#{cert} not found")
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
Log.logger.debug("found parameter #{@path_prefix}/#{cert}")
|
27
|
+
return resp.parameter.value
|
28
|
+
end
|
29
|
+
|
30
|
+
def put_parameter(cert)
|
31
|
+
certificate = File.read("#{@cert_dir}/#{cert}")
|
32
|
+
Log.logger.debug("Reading certificate #{@cert_dir}/#{cert}")
|
33
|
+
ext = cert.split('.').last
|
34
|
+
@client.put_parameter({
|
35
|
+
name: "#{@path_prefix}/#{@name}.#{ext}",
|
36
|
+
description: "cfn-vpn #{@name} #{cert}",
|
37
|
+
value: certificate,
|
38
|
+
type: "SecureString",
|
39
|
+
overwrite: false,
|
40
|
+
tags: [
|
41
|
+
{ key: "cfnvpn:name", value: @name },
|
42
|
+
{ key: "cfnvpn:certificate", value: cert }
|
43
|
+
],
|
44
|
+
tier: "Advanced",
|
45
|
+
})
|
46
|
+
Log.logger.info("Stored #{cert} in ssm parameter #{@path_prefix}/#{@name}.#{ext}")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
CfhighlanderTemplate do
|
2
|
+
|
3
|
+
Parameters do
|
4
|
+
ComponentParam 'EnvironmentName', '<%= @name %>'
|
5
|
+
end
|
6
|
+
|
7
|
+
Component template: 'client-vpn', name: 'vpn', render: Inline do
|
8
|
+
parameter name: 'AssociationSubnetId', value: '<%= @config['subnet_id'] %>'
|
9
|
+
parameter name: 'ClientCidrBlock', value: '<%= @config['cidr'] %>'
|
10
|
+
parameter name: 'ClientCertificateArn', value: '<%= @config['client_cert_arn'] %>'
|
11
|
+
parameter name: 'ServerCertificateArn', value: '<%= @config['server_cert_arn'] %>'
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cfn-vpn
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Guslington
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.20'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.20'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: cfhighlander
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.9'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '1'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.9'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: cfndsl
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.17'
|
54
|
+
- - "<"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '1'
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0.17'
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: aws-sdk-ec2
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '1.95'
|
74
|
+
- - "<"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '1.95'
|
84
|
+
- - "<"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '2'
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: aws-sdk-acm
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - "~>"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1'
|
94
|
+
- - "<"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2'
|
97
|
+
type: :runtime
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1'
|
104
|
+
- - "<"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '2'
|
107
|
+
- !ruby/object:Gem::Dependency
|
108
|
+
name: aws-sdk-ssm
|
109
|
+
requirement: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - "~>"
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '1'
|
114
|
+
- - "<"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '2'
|
117
|
+
type: :runtime
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '1'
|
124
|
+
- - "<"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '2'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: aws-sdk-cloudformation
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - "~>"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '1'
|
134
|
+
- - "<"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '2'
|
137
|
+
type: :runtime
|
138
|
+
prerelease: false
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '1'
|
144
|
+
- - "<"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '2'
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: bundler
|
149
|
+
requirement: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '2.0'
|
154
|
+
type: :development
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '2.0'
|
161
|
+
- !ruby/object:Gem::Dependency
|
162
|
+
name: rake
|
163
|
+
requirement: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '10.0'
|
168
|
+
type: :development
|
169
|
+
prerelease: false
|
170
|
+
version_requirements: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - "~>"
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '10.0'
|
175
|
+
description: creates and manages resources for the aws client vpn
|
176
|
+
email:
|
177
|
+
- guslington@gmail.com
|
178
|
+
executables:
|
179
|
+
- cfn-vpn
|
180
|
+
extensions: []
|
181
|
+
extra_rdoc_files: []
|
182
|
+
files:
|
183
|
+
- ".gitignore"
|
184
|
+
- ".travis.yml"
|
185
|
+
- Gemfile
|
186
|
+
- Gemfile.lock
|
187
|
+
- LICENSE.txt
|
188
|
+
- README.md
|
189
|
+
- Rakefile
|
190
|
+
- cfn-vpn.gemspec
|
191
|
+
- exe/cfn-vpn
|
192
|
+
- lib/cfnvpn.rb
|
193
|
+
- lib/cfnvpn/acm.rb
|
194
|
+
- lib/cfnvpn/certificates.rb
|
195
|
+
- lib/cfnvpn/cfhighlander.rb
|
196
|
+
- lib/cfnvpn/clientvpn.rb
|
197
|
+
- lib/cfnvpn/cloudformation.rb
|
198
|
+
- lib/cfnvpn/config.rb
|
199
|
+
- lib/cfnvpn/init.rb
|
200
|
+
- lib/cfnvpn/log.rb
|
201
|
+
- lib/cfnvpn/ssm.rb
|
202
|
+
- lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt
|
203
|
+
- lib/cfnvpn/version.rb
|
204
|
+
homepage: https://github.com/base2services/aws-client-vpn
|
205
|
+
licenses:
|
206
|
+
- MIT
|
207
|
+
metadata:
|
208
|
+
allowed_push_host: https://rubygems.org
|
209
|
+
homepage_uri: https://github.com/base2services/aws-client-vpn
|
210
|
+
source_code_uri: https://github.com/base2services/aws-client-vpn
|
211
|
+
post_install_message:
|
212
|
+
rdoc_options: []
|
213
|
+
require_paths:
|
214
|
+
- lib
|
215
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - ">="
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '0'
|
225
|
+
requirements: []
|
226
|
+
rubyforge_project:
|
227
|
+
rubygems_version: 2.7.6
|
228
|
+
signing_key:
|
229
|
+
specification_version: 4
|
230
|
+
summary: creates and manages resources for the aws client vpn
|
231
|
+
test_files: []
|