cfn-vpn 1.4.5 → 1.5.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 +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
|