cfn-vpn 1.4.5 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build-gem.yml +7 -4
- data/.github/workflows/release-gem.yml +4 -4
- data/.github/workflows/release-image.yml +1 -1
- data/Dockerfile +9 -8
- data/Gemfile.lock +1 -1
- data/docs/README.md +2 -1
- data/docs/certificate-renewal.md +69 -0
- data/docs/certificate-users.md +7 -0
- data/docs/routes.md +3 -1
- data/lib/cfnvpn/acm.rb +20 -11
- data/lib/cfnvpn/actions/client.rb +2 -1
- data/lib/cfnvpn/actions/init.rb +2 -1
- data/lib/cfnvpn/actions/renew_certificate.rb +141 -0
- data/lib/cfnvpn/certificates.rb +77 -6
- data/lib/cfnvpn/version.rb +1 -1
- data/lib/cfnvpn.rb +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03a0a38a10b42f88181de0fe2dc2954d4724f70515fcc3eb529f5a148ff17025
|
4
|
+
data.tar.gz: fb22c0da59f79dcf2b5175b31bb0b5c1cbf731568e3c99dc5de85bebe50f0240
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 424241bf23dd636c2c3930e7475d6840dbd110421160c517fd23b66e08306183f6f398dde96ce3fb595f7bbe3852e1dcb40a45f2a750a00c4f61a76698277217
|
7
|
+
data.tar.gz: 8d06e2135f609be0b36bf8672bdc1f8d88bf1d31213763741592cd0f511060c925ce872e5081c30c1ad8a09e4465cc49249a652cd3c360a879da310f05a7d7e1
|
@@ -11,15 +11,18 @@ jobs:
|
|
11
11
|
runs-on: ubuntu-latest
|
12
12
|
|
13
13
|
steps:
|
14
|
-
- uses: actions/checkout@
|
15
|
-
|
16
|
-
|
14
|
+
- uses: actions/checkout@v3
|
15
|
+
|
16
|
+
- name: Set up ruby 2.7
|
17
|
+
uses: ruby/setup-ruby@v1
|
17
18
|
with:
|
18
|
-
ruby-version: 2.
|
19
|
+
ruby-version: 2.7
|
20
|
+
|
19
21
|
- name: rspec
|
20
22
|
run: |
|
21
23
|
gem install rspec
|
22
24
|
rspec
|
25
|
+
|
23
26
|
- name: build gem
|
24
27
|
run: |
|
25
28
|
gem build cfn-vpn.gemspec
|
@@ -11,12 +11,12 @@ jobs:
|
|
11
11
|
|
12
12
|
steps:
|
13
13
|
- name: Check out the repo
|
14
|
-
uses: actions/checkout@
|
14
|
+
uses: actions/checkout@v3
|
15
15
|
|
16
|
-
- name: Set up
|
17
|
-
uses:
|
16
|
+
- name: Set up ruby 2.7
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
18
|
with:
|
19
|
-
ruby-version: 2.7
|
19
|
+
ruby-version: 2.7
|
20
20
|
|
21
21
|
- name: rspec
|
22
22
|
run: |
|
data/Dockerfile
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
-
FROM ruby:2.7
|
1
|
+
FROM ruby:2.7
|
2
2
|
|
3
|
-
RUN
|
4
|
-
|
5
|
-
|
3
|
+
RUN apt-get update -qq \
|
4
|
+
&& apt-get install -qqy \
|
5
|
+
easy-rsa \
|
6
|
+
git \
|
6
7
|
&& ln -s /usr/share/easy-rsa/easyrsa /usr/bin/
|
7
8
|
|
8
9
|
ENV EASYRSA=/usr/share/easy-rsa
|
9
10
|
ENV EASYRSA_BATCH=yes
|
10
11
|
|
11
|
-
ARG CFNVPN_VERSION="
|
12
|
+
ARG CFNVPN_VERSION="1.5.0"
|
12
13
|
|
13
14
|
COPY . /src
|
14
15
|
|
@@ -17,9 +18,9 @@ WORKDIR /src
|
|
17
18
|
RUN gem build cfn-vpn.gemspec \
|
18
19
|
&& gem install cfn-vpn-${CFNVPN_VERSION}.gem \
|
19
20
|
&& rm -rf /src
|
20
|
-
|
21
|
-
RUN addgroup
|
22
|
-
adduser
|
21
|
+
|
22
|
+
RUN addgroup --gid 1000 cfnvpn && \
|
23
|
+
adduser --home /home/cfnvpn --uid 1000 --disabled-password --gecos GECOS --gid 1000 cfnvpn
|
23
24
|
|
24
25
|
USER cfnvpn
|
25
26
|
|
data/Gemfile.lock
CHANGED
data/docs/README.md
CHANGED
@@ -43,4 +43,5 @@ For further information on the authentication types please visit https://docs.aw
|
|
43
43
|
5. [Stop and Start Client-VPN](scheduling.md)
|
44
44
|
6. [Managing Sessions](sessions.md)
|
45
45
|
7. [Slack Notifications](slack-notifications.md)
|
46
|
-
8. [YAML Configuration](yaml-config.md)
|
46
|
+
8. [YAML Configuration](yaml-config.md)
|
47
|
+
9. [Certificate Renewal](certificate-renewal.md)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Certificate Renewal
|
2
|
+
|
3
|
+
To update the client certificate you can use the `renew` command.
|
4
|
+
|
5
|
+
```sh
|
6
|
+
Usage:
|
7
|
+
cfn-vpn renew [name]
|
8
|
+
|
9
|
+
Options:
|
10
|
+
r, [--region=REGION] # AWS Region
|
11
|
+
# Default: ap-southeast-2
|
12
|
+
[--verbose], [--no-verbose] # set log level to debug
|
13
|
+
[--easyrsa-local], [--no-easyrsa-local] # run the easyrsa executable from your local rather than from docker
|
14
|
+
[--certificate-expiry=CERTIFICATE_EXPIRY] # value in days for when the server certificates expire, defaults to 825 days
|
15
|
+
[--rebuild], [--no-rebuild] # generates new certificates from the existing CA for certiciate type VPNs
|
16
|
+
[--bucket=BUCKET] # s3 bucket, if not set one will be generated for you
|
17
|
+
```
|
18
|
+
|
19
|
+
## Certificate Authenticated VPN
|
20
|
+
|
21
|
+
When renewing the server and client certificates for the Client VPN there are 2 options [renew](#renew) or [rebuild](#rebuild).
|
22
|
+
|
23
|
+
In both cases the Client VPN is recreated along with a new vpn endpoint which means once the update is complete each client must [update their config](#updating-client-config) to point to the new VPN endpoint.
|
24
|
+
|
25
|
+
The Update process can take as long as 1-2 hours.
|
26
|
+
|
27
|
+
### renew
|
28
|
+
|
29
|
+
This is the default option and should be used
|
30
|
+
|
31
|
+
```sh
|
32
|
+
cfn-vpn renew [name] --bucket [s3-bucket]
|
33
|
+
```
|
34
|
+
|
35
|
+
### rebuild
|
36
|
+
|
37
|
+
This creates new certificates and should only be used if renew doesn't work.
|
38
|
+
|
39
|
+
```sh
|
40
|
+
cfn-vpn renew [name] --bucket [s3-bucket] --rebuild
|
41
|
+
```
|
42
|
+
|
43
|
+
### Updating Client Config
|
44
|
+
|
45
|
+
Once the VPN has been updated you will need to retrieve the new vpn endpoint such as
|
46
|
+
|
47
|
+
```
|
48
|
+
*.cvpn-endpoint-<id>.prod.clientvpn.<aws-region>.amazonaws.com
|
49
|
+
```
|
50
|
+
|
51
|
+
Replace the endpoint value in each of the clients opvn configs and reimport them into the vpn client.
|
52
|
+
|
53
|
+
```
|
54
|
+
remote kdipkcte.cvpn-endpoint-<replace-id>.prod.clientvpn.<aws-region>.amazonaws.com 443
|
55
|
+
```
|
56
|
+
|
57
|
+
## VPNs Using Federated Access
|
58
|
+
|
59
|
+
run the renew command with the default options
|
60
|
+
|
61
|
+
```sh
|
62
|
+
cfn-vpn renew [name] --bucket [s3-bucket]
|
63
|
+
```
|
64
|
+
|
65
|
+
This will recreate the vpn with the updated server certificate.
|
66
|
+
|
67
|
+
This process can take 1-2 hours.
|
68
|
+
|
69
|
+
Once complete users will need to log into the self service portal and download new copies of the client config and import them into their vpn client.
|
data/docs/certificate-users.md
CHANGED
@@ -11,6 +11,13 @@ It will be bundled into a tar and stored encrypted in your provided s3 bucket.
|
|
11
11
|
cfn-vpn client myvpn --client-cn user1 --bucket mybucket
|
12
12
|
```
|
13
13
|
|
14
|
+
## Short Term Client
|
15
|
+
|
16
|
+
By default the expiry of client certificate is 825 days. You can shorten this value with the `--certificate-expiry` flag specify a int value in days for how long you want the certificate to stay valid.
|
17
|
+
|
18
|
+
```
|
19
|
+
cfn-vpn client myvpn --client-cn user1 --bucket mybucket --certificate-expiry 7
|
20
|
+
```
|
14
21
|
|
15
22
|
## Revoke a user
|
16
23
|
|
data/docs/routes.md
CHANGED
@@ -40,6 +40,8 @@ routes:
|
|
40
40
|
|
41
41
|
Dynamic DNS routes takes a dns endpoint and will query the record every 5 minutes to see if the IPs have changed and update the routes in the vpn route table.
|
42
42
|
|
43
|
+
**NOTE** This should not be used for cloutfront endpoints
|
44
|
+
|
43
45
|
#### CLI Commands
|
44
46
|
|
45
47
|
new route run the routes command along with the `--dns` option
|
@@ -193,4 +195,4 @@ aws service-quotas request-service-quota-increase --service-code ec2 --quota-cod
|
|
193
195
|
|
194
196
|
```sh
|
195
197
|
aws service-quotas request-service-quota-increase --service-code ec2 --quota-code L-9A1BC94B --desired-value [value]
|
196
|
-
```
|
198
|
+
```
|
data/lib/cfnvpn/acm.rb
CHANGED
@@ -23,13 +23,15 @@ module CfnVpn
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def tag_certificate(arn,name,type,cfnvpn_name)
|
26
|
+
tags = [
|
27
|
+
{ key: "Name", value: name },
|
28
|
+
{ key: "cfnvpn:name", value: cfnvpn_name },
|
29
|
+
{ key: "cfnvpn:certificate:type", value: type }
|
30
|
+
]
|
31
|
+
|
26
32
|
@client.add_tags_to_certificate({
|
27
33
|
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
|
-
]
|
34
|
+
tags: tags
|
33
35
|
})
|
34
36
|
end
|
35
37
|
|
@@ -37,13 +39,20 @@ module CfnVpn
|
|
37
39
|
File.read("#{@cert_dir}/#{cert}")
|
38
40
|
end
|
39
41
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
42
|
+
def get_certificate_tags(certificate_arn,key=nil)
|
43
|
+
resp = @client.list_tags_for_certificate({
|
44
|
+
certificate_arn: certificate_arn
|
45
|
+
})
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
if key.nil?
|
48
|
+
return resp.tags
|
49
|
+
else
|
50
|
+
resp.tags.each do |tag|
|
51
|
+
return tag.value if tag.key == key
|
52
|
+
end
|
47
53
|
|
54
|
+
raise "no tag key #{key} matched the certificate #{certificate_arn}"
|
55
|
+
end
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
@@ -17,6 +17,7 @@ module CfnVpn::Actions
|
|
17
17
|
class_option :bucket, desc: 's3 bucket', required: true
|
18
18
|
class_option :client_cn, desc: 'client certificate common name', required: true
|
19
19
|
class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker'
|
20
|
+
class_option :certificate_expiry, type: :string, desc: 'value in days for when the client certificates expire, defaults to 825 days'
|
20
21
|
|
21
22
|
def self.source_root
|
22
23
|
File.dirname(__FILE__)
|
@@ -37,7 +38,7 @@ module CfnVpn::Actions
|
|
37
38
|
s3.get_object("#{@cert_dir}/ca.tar.gz")
|
38
39
|
CfnVpn::Log.logger.info "Generating new client certificate #{@options['client_cn']} using openvpn easy-rsa"
|
39
40
|
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
40
|
-
CfnVpn::Log.logger.debug cert.generate_client(@options['client_cn'])
|
41
|
+
CfnVpn::Log.logger.debug cert.generate_client(@options['client_cn'],@options['certificate_expiry'])
|
41
42
|
s3.store_object("#{@cert_dir}/#{@options['client_cn']}.tar.gz")
|
42
43
|
end
|
43
44
|
|
data/lib/cfnvpn/actions/init.rb
CHANGED
@@ -21,6 +21,7 @@ module CfnVpn::Actions
|
|
21
21
|
class_option :server_cn, required: true, desc: 'server certificate common name'
|
22
22
|
class_option :client_cn, desc: 'client certificate common name'
|
23
23
|
class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker'
|
24
|
+
class_option :certificate_expiry, type: :string, desc: 'value in days for when the server certificates expire, defaults to 825 days'
|
24
25
|
class_option :bucket, desc: 's3 bucket, if not set one will be generated for you'
|
25
26
|
|
26
27
|
class_option :subnet_ids, required: true, type: :array, desc: 'subnet id to associate your vpn with'
|
@@ -115,7 +116,7 @@ module CfnVpn::Actions
|
|
115
116
|
CfnVpn::Log.logger.info "Generating certificates using openvpn easy-rsa"
|
116
117
|
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
117
118
|
@client_cn = @options['client_cn'] ? @options['client_cn'] : "client-vpn.#{@options['server_cn']}"
|
118
|
-
cert.generate_ca(@options['server_cn'],@client_cn)
|
119
|
+
cert.generate_ca(@options['server_cn'],@client_cn,@options['certificate_expiry'])
|
119
120
|
end
|
120
121
|
|
121
122
|
def upload_certificates
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'cfnvpn/deployer'
|
4
|
+
require 'cfnvpn/certificates'
|
5
|
+
require 'cfnvpn/compiler'
|
6
|
+
require 'cfnvpn/log'
|
7
|
+
require 'cfnvpn/clientvpn'
|
8
|
+
require 'cfnvpn/globals'
|
9
|
+
require 'cfnvpn/s3_bucket'
|
10
|
+
require 'cfnvpn/acm'
|
11
|
+
|
12
|
+
module CfnVpn::Actions
|
13
|
+
class RenewCertificate < Thor::Group
|
14
|
+
include Thor::Actions
|
15
|
+
|
16
|
+
argument :name
|
17
|
+
|
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 :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker'
|
22
|
+
class_option :certificate_expiry, type: :string, desc: 'value in days for when the server certificates expire, defaults to 825 days'
|
23
|
+
class_option :rebuild, type: :boolean, default: false, desc: 'generates new certificates from the existing CA for certiciate type VPNs'
|
24
|
+
class_option :bucket, desc: 's3 bucket, if not set one will be generated for you'
|
25
|
+
|
26
|
+
def self.source_root
|
27
|
+
File.dirname(__FILE__)
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_loglevel
|
31
|
+
CfnVpn::Log.logger.level = Logger::DEBUG if @options['verbose']
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_build_directory
|
35
|
+
@build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}"
|
36
|
+
CfnVpn::Log.logger.debug "creating directory #{@build_dir}"
|
37
|
+
FileUtils.mkdir_p(@build_dir)
|
38
|
+
@cert_dir = "#{@build_dir}/certificates"
|
39
|
+
FileUtils.mkdir_p(@cert_dir)
|
40
|
+
end
|
41
|
+
|
42
|
+
def stack_exist
|
43
|
+
@deployer = CfnVpn::Deployer.new(@options['region'],@name)
|
44
|
+
if !@deployer.does_cf_stack_exist()
|
45
|
+
CfnVpn::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"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize_config
|
51
|
+
@config = CfnVpn::Config.get_config(@options['region'], @name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_client_cn
|
55
|
+
@client_cn = nil
|
56
|
+
if @config[:type] == 'certificate'
|
57
|
+
acm = CfnVpn::Acm.new(@options['region'], @cert_dir)
|
58
|
+
@client_cn = acm.get_certificate_tags(@config[:client_cert_arn],'Name')
|
59
|
+
CfnVpn::Log.logger.info "Client CN #{@client_cn}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def renew_certificates
|
64
|
+
if @config[:type] == 'certificate'
|
65
|
+
s3 = CfnVpn::S3.new(@options['region'],@options['bucket'],@name)
|
66
|
+
s3.get_object("#{@cert_dir}/ca.tar.gz")
|
67
|
+
|
68
|
+
if @options['rebuild']
|
69
|
+
CfnVpn::Log.logger.info "rebuilding server and #{@client_cn} certificates"
|
70
|
+
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
71
|
+
cert.rebuild(@config[:server_cn],@client_cn,@options['certificate_expiry'])
|
72
|
+
else
|
73
|
+
CfnVpn::Log.logger.info "renewing server and #{@client_cn} certificates"
|
74
|
+
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
75
|
+
cert.renew(@config[:server_cn],@client_cn,@options['certificate_expiry'])
|
76
|
+
end
|
77
|
+
else
|
78
|
+
CfnVpn::Log.logger.info "recreating server and #{@client_cn} certificates with a new CA"
|
79
|
+
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
80
|
+
cert.generate_ca(@options['server_cn'],@options['certificate_expiry'])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def upload_certificates
|
85
|
+
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
86
|
+
@config[:server_cert_arn] = cert.upload_certificates(@options['region'],'server','server',@config[:server_cn])
|
87
|
+
if @config[:type] == 'certificate'
|
88
|
+
# we only need the server certificate to ACM if it is a SAML federated client vpn
|
89
|
+
@config[:client_cert_arn] = cert.upload_certificates(@options['region'],@client_cn,'client')
|
90
|
+
# and only need to upload the certs to s3 if using certificate authenitcation
|
91
|
+
s3 = CfnVpn::S3.new(@options['region'],@config[:bucket],@name)
|
92
|
+
s3.store_object("#{@build_dir}/certificates/ca.tar.gz")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def deploy_vpn
|
97
|
+
compiler = CfnVpn::Compiler.new(@name, @config)
|
98
|
+
template_body = compiler.compile
|
99
|
+
CfnVpn::Log.logger.info "Creating cloudformation changeset for stack #{@name}-cfnvpn in #{@options['region']}"
|
100
|
+
change_set, change_set_type = @deployer.create_change_set(template_body: template_body)
|
101
|
+
@deployer.wait_for_changeset(change_set.id)
|
102
|
+
changeset_response = @deployer.get_change_set(change_set.id)
|
103
|
+
|
104
|
+
changes = {"Add" => [], "Modify" => [], "Remove" => []}
|
105
|
+
change_colours = {"Add" => "green", "Modify" => 'yellow', "Remove" => 'red'}
|
106
|
+
|
107
|
+
changeset_response.changes.each do |change|
|
108
|
+
action = change.resource_change.action
|
109
|
+
changes[action].push([
|
110
|
+
change.resource_change.logical_resource_id,
|
111
|
+
change.resource_change.resource_type,
|
112
|
+
change.resource_change.replacement ? change.resource_change.replacement : 'N/A',
|
113
|
+
change.resource_change.details.collect {|detail| detail.target.name }.join(' , ')
|
114
|
+
])
|
115
|
+
end
|
116
|
+
|
117
|
+
changes.each do |type, rows|
|
118
|
+
next if !rows.any?
|
119
|
+
puts "\n"
|
120
|
+
table = Terminal::Table.new(
|
121
|
+
:title => type,
|
122
|
+
:headings => ['Logical Resource Id', 'Resource Type', 'Replacement', 'Changes'],
|
123
|
+
:rows => rows)
|
124
|
+
puts table.to_s.send(change_colours[type])
|
125
|
+
end
|
126
|
+
|
127
|
+
CfnVpn::Log.logger.info "Cloudformation changeset changes:"
|
128
|
+
puts "\n"
|
129
|
+
continue = yes? "Continue?", :green
|
130
|
+
if !continue
|
131
|
+
CfnVpn::Log.logger.info("Cancelled cfn-vpn modifiy #{@name}")
|
132
|
+
exit 1
|
133
|
+
end
|
134
|
+
|
135
|
+
@deployer.execute_change_set(change_set.id)
|
136
|
+
@deployer.wait_for_execute(change_set_type)
|
137
|
+
CfnVpn::Log.logger.info "Changeset #{change_set_type} complete"
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
data/lib/cfnvpn/certificates.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
require '
|
2
|
+
require 'time'
|
3
3
|
require 'cfnvpn/acm'
|
4
4
|
require 'cfnvpn/s3'
|
5
5
|
require 'cfnvpn/log'
|
@@ -28,19 +28,25 @@ module CfnVpn
|
|
28
28
|
FileUtils.mkdir_p(@pki_dir)
|
29
29
|
end
|
30
30
|
|
31
|
-
def generate_ca(server_cn,client_cn)
|
31
|
+
def generate_ca(server_cn,client_cn,expiry=nil)
|
32
|
+
opts = ""
|
33
|
+
unless expiry.nil?
|
34
|
+
opts += "--days=#{expiry}"
|
35
|
+
end
|
36
|
+
|
32
37
|
if @easyrsa_local
|
33
38
|
ENV["EASYRSA_REQ_CN"] = server_cn
|
34
39
|
ENV["EASYRSA_PKI"] = @pki_dir
|
35
40
|
system("easyrsa init-pki")
|
36
41
|
system("easyrsa build-ca nopass")
|
37
|
-
system("easyrsa build-server-full server nopass")
|
38
|
-
system("easyrsa build-client-full #{client_cn} nopass")
|
42
|
+
system("easyrsa #{opts} build-server-full server nopass")
|
43
|
+
system("easyrsa #{opts} build-client-full #{client_cn} nopass")
|
39
44
|
FileUtils.cp(["#{@pki_dir}/ca.crt", "#{@pki_dir}/issued/server.crt", "#{@pki_dir}/private/server.key", "#{@pki_dir}/issued/#{client_cn}.crt", "#{@pki_dir}/private/#{client_cn}.key"], @cert_dir)
|
40
45
|
system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/")
|
41
46
|
else
|
42
47
|
@docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}"
|
43
48
|
@docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
|
49
|
+
@docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\""
|
44
50
|
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
45
51
|
@docker_cmd << @easyrsa_image
|
46
52
|
@docker_cmd << "sh -c 'create-ca'"
|
@@ -48,14 +54,20 @@ module CfnVpn
|
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
51
|
-
def generate_client(client_cn)
|
57
|
+
def generate_client(client_cn,expiry=nil)
|
58
|
+
opts = ""
|
59
|
+
unless expiry.nil?
|
60
|
+
opts += "--days=#{expiry}"
|
61
|
+
end
|
62
|
+
|
52
63
|
if @easyrsa_local
|
53
64
|
ENV["EASYRSA_PKI"] = @pki_dir
|
54
65
|
system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}")
|
55
|
-
system("easyrsa build-client-full #{client_cn} nopass")
|
66
|
+
system("easyrsa #{opts} build-client-full #{client_cn} nopass")
|
56
67
|
system("tar czfv #{@cert_dir}/#{client_cn}.tar.gz -C #{@build_dir} pki/issued/#{client_cn}.crt pki/private/#{client_cn}.key pki/reqs/#{client_cn}.req")
|
57
68
|
else
|
58
69
|
@docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
|
70
|
+
@docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\""
|
59
71
|
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
60
72
|
@docker_cmd << @easyrsa_image
|
61
73
|
@docker_cmd << "sh -c 'create-client'"
|
@@ -63,6 +75,65 @@ module CfnVpn
|
|
63
75
|
end
|
64
76
|
end
|
65
77
|
|
78
|
+
def renew(server_cn,client_cn,expiry=nil)
|
79
|
+
opts = ""
|
80
|
+
unless expiry.nil?
|
81
|
+
opts += "--days=#{expiry}"
|
82
|
+
end
|
83
|
+
|
84
|
+
if @easyrsa_local
|
85
|
+
ENV["EASYRSA_REQ_CN"] = server_cn
|
86
|
+
ENV["EASYRSA_PKI"] = @pki_dir
|
87
|
+
system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}")
|
88
|
+
system("easyrsa #{opts} renew server nopass")
|
89
|
+
system("easyrsa #{opts} renew #{client_cn} nopass")
|
90
|
+
FileUtils.cp(["#{@pki_dir}/ca.crt", "#{@pki_dir}/issued/server.crt", "#{@pki_dir}/private/server.key", "#{@pki_dir}/issued/#{client_cn}.crt", "#{@pki_dir}/private/#{client_cn}.key"], @cert_dir)
|
91
|
+
system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/")
|
92
|
+
else
|
93
|
+
@docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}"
|
94
|
+
@docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
|
95
|
+
@docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\""
|
96
|
+
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
97
|
+
@docker_cmd << @easyrsa_image
|
98
|
+
@docker_cmd << "sh -c 'renew'"
|
99
|
+
CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def rebuild(server_cn,client_cn,expiry=nil)
|
104
|
+
timestamp = Time.now.getutc.to_i
|
105
|
+
opts = ""
|
106
|
+
unless expiry.nil?
|
107
|
+
opts += "--days=#{expiry}"
|
108
|
+
end
|
109
|
+
|
110
|
+
if @easyrsa_local
|
111
|
+
ENV["EASYRSA_REQ_CN"] = server_cn
|
112
|
+
ENV["EASYRSA_PKI"] = @pki_dir
|
113
|
+
system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}")
|
114
|
+
|
115
|
+
FileUtils.mv("#{@pki_dir}/reqs/server.req", "#{@pki_dir}/reqs/server.req.bak-#{timestamp}")
|
116
|
+
FileUtils.mv("#{@pki_dir}/issued/server.crt", "#{@pki_dir}/issued/server.req.bak-#{timestamp}")
|
117
|
+
FileUtils.mv("#{@pki_dir}/private/server.key", "#{@pki_dir}/private/server.req.bak-#{timestamp}")
|
118
|
+
FileUtils.mv("#{@pki_dir}/reqs/#{client_cn}.req", "#{@pki_dir}/reqs/#{client_cn}.req.bak-#{timestamp}")
|
119
|
+
FileUtils.mv("#{@pki_dir}/issued/#{client_cn}.crt", "#{@pki_dir}/issued/#{client_cn}.req.bak-#{timestamp}")
|
120
|
+
FileUtils.mv("#{@pki_dir}/private/#{client_cn}.key", "#{@pki_dir}/private/#{client_cn}.req.bak-#{timestamp}")
|
121
|
+
|
122
|
+
system("easyrsa #{opts} build-server-full server nopass")
|
123
|
+
system("easyrsa #{opts} build-client-full #{client_cn} nopass")
|
124
|
+
FileUtils.cp(["#{@pki_dir}/ca.crt", "#{@pki_dir}/issued/server.crt", "#{@pki_dir}/private/server.key", "#{@pki_dir}/issued/#{client_cn}.crt", "#{@pki_dir}/private/#{client_cn}.key"], @cert_dir)
|
125
|
+
system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/")
|
126
|
+
else
|
127
|
+
@docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}"
|
128
|
+
@docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
|
129
|
+
@docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\""
|
130
|
+
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
131
|
+
@docker_cmd << @easyrsa_image
|
132
|
+
@docker_cmd << "sh -c 'rebuild'"
|
133
|
+
CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
66
137
|
def revoke_client(client_cn)
|
67
138
|
if @easyrsa_local
|
68
139
|
ENV["EASYRSA_PKI"] = @pki_dir
|
data/lib/cfnvpn/version.rb
CHANGED
data/lib/cfnvpn.rb
CHANGED
@@ -10,6 +10,7 @@ require 'cfnvpn/actions/share'
|
|
10
10
|
require 'cfnvpn/actions/embedded'
|
11
11
|
require 'cfnvpn/actions/subnets'
|
12
12
|
require 'cfnvpn/actions/params'
|
13
|
+
require 'cfnvpn/actions/renew_certificate'
|
13
14
|
|
14
15
|
module CfnVpn
|
15
16
|
class Cli < Thor
|
@@ -23,6 +24,9 @@ module CfnVpn
|
|
23
24
|
register CfnVpn::Actions::Init, 'init', 'init [name]', 'Create a AWS Client VPN'
|
24
25
|
tasks["init"].options = CfnVpn::Actions::Init.class_options
|
25
26
|
|
27
|
+
register CfnVpn::Actions::RenewCertificate, 'renew', 'renew [name]', 'Renews a Server and Client certificates from the existing CA'
|
28
|
+
tasks["renew"].options = CfnVpn::Actions::RenewCertificate.class_options
|
29
|
+
|
26
30
|
register CfnVpn::Actions::Modify, 'modify', 'modify [name]', 'Modify your AWS Client VPN'
|
27
31
|
tasks["modify"].options = CfnVpn::Actions::Modify.class_options
|
28
32
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfn-vpn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guslington
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -240,6 +240,7 @@ files:
|
|
240
240
|
- Rakefile
|
241
241
|
- cfn-vpn.gemspec
|
242
242
|
- docs/README.md
|
243
|
+
- docs/certificate-renewal.md
|
243
244
|
- docs/certificate-users.md
|
244
245
|
- docs/getting-started.md
|
245
246
|
- docs/modifying.md
|
@@ -256,6 +257,7 @@ files:
|
|
256
257
|
- lib/cfnvpn/actions/init.rb
|
257
258
|
- lib/cfnvpn/actions/modify.rb
|
258
259
|
- lib/cfnvpn/actions/params.rb
|
260
|
+
- lib/cfnvpn/actions/renew_certificate.rb
|
259
261
|
- lib/cfnvpn/actions/revoke.rb
|
260
262
|
- lib/cfnvpn/actions/routes.rb
|
261
263
|
- lib/cfnvpn/actions/sessions.rb
|