diff --git a/.github/workflows/build-gem.yml b/.github/workflows/build-gem.yml index 72f8193..d8ff219 100644 --- a/.github/workflows/build-gem.yml +++ b/.github/workflows/build-gem.yml @@ -11,15 +11,18 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: set up ruby 2.6 - uses: actions/setup-ruby@v1 + - uses: actions/checkout@v3 + + - name: Set up ruby 2.7 + uses: ruby/setup-ruby@v1 with: - ruby-version: 2.6.x + ruby-version: 2.7 + - name: rspec run: | gem install rspec rspec + - name: build gem run: | gem build cfn-vpn.gemspec \ No newline at end of file diff --git a/.github/workflows/release-gem.yml b/.github/workflows/release-gem.yml index 39244fb..1b49f4a 100644 --- a/.github/workflows/release-gem.yml +++ b/.github/workflows/release-gem.yml @@ -11,12 +11,12 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - - name: Set up Ruby 2.7 - uses: actions/setup-ruby@v1 + - name: Set up ruby 2.7 + uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7.x + ruby-version: 2.7 - name: rspec run: | diff --git a/.github/workflows/release-image.yml b/.github/workflows/release-image.yml index 6f57743..c0efda5 100644 --- a/.github/workflows/release-image.yml +++ b/.github/workflows/release-image.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 diff --git a/Dockerfile b/Dockerfile index 7d47ee0..bf7bee8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,15 @@ -FROM ruby:2.7-alpine +FROM ruby:2.7 -RUN apk add --no-cache easy-rsa git \ - # Hack until easy-rsa 3.0.7 is released https://github.com/OpenVPN/easy-rsa/issues/261 - && sed -i 's/^RANDFILE\s*=\s\$ENV.*/#&/' /usr/share/easy-rsa/openssl-easyrsa.cnf \ +RUN apt-get update -qq \ + && apt-get install -qqy \ + easy-rsa \ + git \ && ln -s /usr/share/easy-rsa/easyrsa /usr/bin/ ENV EASYRSA=/usr/share/easy-rsa ENV EASYRSA_BATCH=yes -ARG CFNVPN_VERSION="0.5.0" +ARG CFNVPN_VERSION="1.5.0" COPY . /src @@ -17,9 +18,9 @@ WORKDIR /src RUN gem build cfn-vpn.gemspec \ && gem install cfn-vpn-${CFNVPN_VERSION}.gem \ && rm -rf /src - -RUN addgroup -g 1000 cfnvpn && \ - adduser -D -u 1000 -G cfnvpn cfnvpn + +RUN addgroup --gid 1000 cfnvpn && \ + adduser --home /home/cfnvpn --uid 1000 --disabled-password --gecos GECOS --gid 1000 cfnvpn USER cfnvpn diff --git a/Gemfile.lock b/Gemfile.lock index 6a809af..fd40ff0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - cfn-vpn (1.4.3) + cfn-vpn (1.5.0) aws-sdk-acm (~> 1, < 2) aws-sdk-cloudformation (~> 1, < 2) aws-sdk-ec2 (~> 1.95, < 2) diff --git a/docs/README.md b/docs/README.md index 39203ec..be2a15b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -43,4 +43,5 @@ For further information on the authentication types please visit https://docs.aw 5. [Stop and Start Client-VPN](scheduling.md) 6. [Managing Sessions](sessions.md) 7. [Slack Notifications](slack-notifications.md) -8. [YAML Configuration](yaml-config.md) \ No newline at end of file +8. [YAML Configuration](yaml-config.md) +9. [Certificate Renewal](certificate-renewal.md) \ No newline at end of file diff --git a/docs/certificate-renewal.md b/docs/certificate-renewal.md new file mode 100644 index 0000000..0bca8e1 --- /dev/null +++ b/docs/certificate-renewal.md @@ -0,0 +1,69 @@ +# Certificate Renewal + +To update the client certificate you can use the `renew` command. + +```sh +Usage: + cfn-vpn renew [name] + +Options: + r, [--region=REGION] # AWS Region + # Default: ap-southeast-2 + [--verbose], [--no-verbose] # set log level to debug + [--easyrsa-local], [--no-easyrsa-local] # run the easyrsa executable from your local rather than from docker + [--certificate-expiry=CERTIFICATE_EXPIRY] # value in days for when the server certificates expire, defaults to 825 days + [--rebuild], [--no-rebuild] # generates new certificates from the existing CA for certiciate type VPNs + [--bucket=BUCKET] # s3 bucket, if not set one will be generated for you +``` + +## Certificate Authenticated VPN + +When renewing the server and client certificates for the Client VPN there are 2 options [renew](#renew) or [rebuild](#rebuild). + +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. + +The Update process can take as long as 1-2 hours. + +### renew + +This is the default option and should be used + +```sh +cfn-vpn renew [name] --bucket [s3-bucket] +``` + +### rebuild + +This creates new certificates and should only be used if renew doesn't work. + +```sh +cfn-vpn renew [name] --bucket [s3-bucket] --rebuild +``` + +### Updating Client Config + +Once the VPN has been updated you will need to retrieve the new vpn endpoint such as + +``` +*.cvpn-endpoint-.prod.clientvpn..amazonaws.com +``` + +Replace the endpoint value in each of the clients opvn configs and reimport them into the vpn client. + +``` +remote kdipkcte.cvpn-endpoint-.prod.clientvpn..amazonaws.com 443 +``` + +## VPNs Using Federated Access + +run the renew command with the default options + +```sh +cfn-vpn renew [name] --bucket [s3-bucket] +``` + +This will recreate the vpn with the updated server certificate. + +This process can take 1-2 hours. + +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. \ No newline at end of file diff --git a/docs/certificate-users.md b/docs/certificate-users.md index 92486ae..bc48c60 100644 --- a/docs/certificate-users.md +++ b/docs/certificate-users.md @@ -11,6 +11,13 @@ It will be bundled into a tar and stored encrypted in your provided s3 bucket. cfn-vpn client myvpn --client-cn user1 --bucket mybucket ``` +## Short Term Client + +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. + +``` +cfn-vpn client myvpn --client-cn user1 --bucket mybucket --certificate-expiry 7 +``` ## Revoke a user diff --git a/lib/cfnvpn.rb b/lib/cfnvpn.rb index b439806..411afe9 100644 --- a/lib/cfnvpn.rb +++ b/lib/cfnvpn.rb @@ -10,6 +10,7 @@ require 'cfnvpn/actions/embedded' require 'cfnvpn/actions/subnets' require 'cfnvpn/actions/params' +require 'cfnvpn/actions/renew_certificate' module CfnVpn class Cli < Thor @@ -23,6 +24,9 @@ def __print_version register CfnVpn::Actions::Init, 'init', 'init [name]', 'Create a AWS Client VPN' tasks["init"].options = CfnVpn::Actions::Init.class_options + register CfnVpn::Actions::RenewCertificate, 'renew', 'renew [name]', 'Renews a Server and Client certificates from the existing CA' + tasks["renew"].options = CfnVpn::Actions::RenewCertificate.class_options + register CfnVpn::Actions::Modify, 'modify', 'modify [name]', 'Modify your AWS Client VPN' tasks["modify"].options = CfnVpn::Actions::Modify.class_options diff --git a/lib/cfnvpn/acm.rb b/lib/cfnvpn/acm.rb index 5b054c0..23a0eea 100644 --- a/lib/cfnvpn/acm.rb +++ b/lib/cfnvpn/acm.rb @@ -23,13 +23,15 @@ def import_certificate(cert,key,ca) end def tag_certificate(arn,name,type,cfnvpn_name) + tags = [ + { key: "Name", value: name }, + { key: "cfnvpn:name", value: cfnvpn_name }, + { key: "cfnvpn:certificate:type", value: type } + ] + @client.add_tags_to_certificate({ certificate_arn: arn, - tags: [ - { key: "Name", value: name }, - { key: "cfnvpn:name", value: cfnvpn_name }, - { key: "cfnvpn:certificate:type", value: type } - ] + tags: tags }) end @@ -37,13 +39,20 @@ def load_certificate(cert) File.read("#{@cert_dir}/#{cert}") end - def certificate_exists?(name) - return true - end + def get_certificate_tags(certificate_arn,key=nil) + resp = @client.list_tags_for_certificate({ + certificate_arn: certificate_arn + }) - def get_certificate(name) - return 'arn' - end + if key.nil? + return resp.tags + else + resp.tags.each do |tag| + return tag.value if tag.key == key + end + raise "no tag key #{key} matched the certificate #{certificate_arn}" + end + end end end diff --git a/lib/cfnvpn/actions/client.rb b/lib/cfnvpn/actions/client.rb index e56491a..fdce1ca 100644 --- a/lib/cfnvpn/actions/client.rb +++ b/lib/cfnvpn/actions/client.rb @@ -17,6 +17,7 @@ class Client < Thor::Group class_option :bucket, desc: 's3 bucket', required: true class_option :client_cn, desc: 'client certificate common name', required: true class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker' + class_option :certificate_expiry, type: :string, desc: 'value in days for when the client certificates expire, defaults to 825 days' def self.source_root File.dirname(__FILE__) @@ -37,7 +38,7 @@ def create_certificate s3.get_object("#{@cert_dir}/ca.tar.gz") CfnVpn::Log.logger.info "Generating new client certificate #{@options['client_cn']} using openvpn easy-rsa" cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local']) - CfnVpn::Log.logger.debug cert.generate_client(@options['client_cn']) + CfnVpn::Log.logger.debug cert.generate_client(@options['client_cn'],@options['certificate_expiry']) s3.store_object("#{@cert_dir}/#{@options['client_cn']}.tar.gz") end diff --git a/lib/cfnvpn/actions/init.rb b/lib/cfnvpn/actions/init.rb index ea1917f..1909cfa 100644 --- a/lib/cfnvpn/actions/init.rb +++ b/lib/cfnvpn/actions/init.rb @@ -21,6 +21,7 @@ class Init < Thor::Group class_option :server_cn, required: true, desc: 'server certificate common name' class_option :client_cn, desc: 'client certificate common name' class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker' + class_option :certificate_expiry, type: :string, desc: 'value in days for when the server certificates expire, defaults to 825 days' class_option :bucket, desc: 's3 bucket, if not set one will be generated for you' class_option :subnet_ids, required: true, type: :array, desc: 'subnet id to associate your vpn with' @@ -115,7 +116,7 @@ def generate_server_certificates CfnVpn::Log.logger.info "Generating certificates using openvpn easy-rsa" cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local']) @client_cn = @options['client_cn'] ? @options['client_cn'] : "client-vpn.#{@options['server_cn']}" - cert.generate_ca(@options['server_cn'],@client_cn) + cert.generate_ca(@options['server_cn'],@client_cn,@options['certificate_expiry']) end def upload_certificates diff --git a/lib/cfnvpn/actions/renew_certificate.rb b/lib/cfnvpn/actions/renew_certificate.rb new file mode 100644 index 0000000..2fc7b90 --- /dev/null +++ b/lib/cfnvpn/actions/renew_certificate.rb @@ -0,0 +1,141 @@ +require 'thor' +require 'fileutils' +require 'cfnvpn/deployer' +require 'cfnvpn/certificates' +require 'cfnvpn/compiler' +require 'cfnvpn/log' +require 'cfnvpn/clientvpn' +require 'cfnvpn/globals' +require 'cfnvpn/s3_bucket' +require 'cfnvpn/acm' + +module CfnVpn::Actions + class RenewCertificate < Thor::Group + include Thor::Actions + + argument :name + + class_option :region, aliases: :r, default: ENV['AWS_REGION'], desc: 'AWS Region' + class_option :verbose, desc: 'set log level to debug', type: :boolean + + class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker' + class_option :certificate_expiry, type: :string, desc: 'value in days for when the server certificates expire, defaults to 825 days' + class_option :rebuild, type: :boolean, default: false, desc: 'generates new certificates from the existing CA for certiciate type VPNs' + class_option :bucket, desc: 's3 bucket, if not set one will be generated for you' + + def self.source_root + File.dirname(__FILE__) + end + + def set_loglevel + CfnVpn::Log.logger.level = Logger::DEBUG if @options['verbose'] + end + + def create_build_directory + @build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}" + CfnVpn::Log.logger.debug "creating directory #{@build_dir}" + FileUtils.mkdir_p(@build_dir) + @cert_dir = "#{@build_dir}/certificates" + FileUtils.mkdir_p(@cert_dir) + end + + def stack_exist + @deployer = CfnVpn::Deployer.new(@options['region'],@name) + if !@deployer.does_cf_stack_exist() + 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" + exit 1 + end + end + + def initialize_config + @config = CfnVpn::Config.get_config(@options['region'], @name) + end + + def set_client_cn + @client_cn = nil + if @config[:type] == 'certificate' + acm = CfnVpn::Acm.new(@options['region'], @cert_dir) + @client_cn = acm.get_certificate_tags(@config[:client_cert_arn],'Name') + CfnVpn::Log.logger.info "Client CN #{@client_cn}" + end + end + + def renew_certificates + if @config[:type] == 'certificate' + s3 = CfnVpn::S3.new(@options['region'],@options['bucket'],@name) + s3.get_object("#{@cert_dir}/ca.tar.gz") + + if @options['rebuild'] + CfnVpn::Log.logger.info "rebuilding server and #{@client_cn} certificates" + cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local']) + cert.rebuild(@config[:server_cn],@client_cn,@options['certificate_expiry']) + else + CfnVpn::Log.logger.info "renewing server and #{@client_cn} certificates" + cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local']) + cert.renew(@config[:server_cn],@client_cn,@options['certificate_expiry']) + end + else + CfnVpn::Log.logger.info "recreating server and #{@client_cn} certificates with a new CA" + cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local']) + cert.generate_ca(@options['server_cn'],@options['certificate_expiry']) + end + end + + def upload_certificates + cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local']) + @config[:server_cert_arn] = cert.upload_certificates(@options['region'],'server','server',@config[:server_cn]) + if @config[:type] == 'certificate' + # we only need the server certificate to ACM if it is a SAML federated client vpn + @config[:client_cert_arn] = cert.upload_certificates(@options['region'],@client_cn,'client') + # and only need to upload the certs to s3 if using certificate authenitcation + s3 = CfnVpn::S3.new(@options['region'],@config[:bucket],@name) + s3.store_object("#{@build_dir}/certificates/ca.tar.gz") + end + end + + def deploy_vpn + compiler = CfnVpn::Compiler.new(@name, @config) + template_body = compiler.compile + CfnVpn::Log.logger.info "Creating cloudformation changeset for stack #{@name}-cfnvpn in #{@options['region']}" + change_set, change_set_type = @deployer.create_change_set(template_body: template_body) + @deployer.wait_for_changeset(change_set.id) + changeset_response = @deployer.get_change_set(change_set.id) + + changes = {"Add" => [], "Modify" => [], "Remove" => []} + change_colours = {"Add" => "green", "Modify" => 'yellow', "Remove" => 'red'} + + changeset_response.changes.each do |change| + action = change.resource_change.action + changes[action].push([ + change.resource_change.logical_resource_id, + change.resource_change.resource_type, + change.resource_change.replacement ? change.resource_change.replacement : 'N/A', + change.resource_change.details.collect {|detail| detail.target.name }.join(' , ') + ]) + end + + changes.each do |type, rows| + next if !rows.any? + puts "\n" + table = Terminal::Table.new( + :title => type, + :headings => ['Logical Resource Id', 'Resource Type', 'Replacement', 'Changes'], + :rows => rows) + puts table.to_s.send(change_colours[type]) + end + + CfnVpn::Log.logger.info "Cloudformation changeset changes:" + puts "\n" + continue = yes? "Continue?", :green + if !continue + CfnVpn::Log.logger.info("Cancelled cfn-vpn modifiy #{@name}") + exit 1 + end + + @deployer.execute_change_set(change_set.id) + @deployer.wait_for_execute(change_set_type) + CfnVpn::Log.logger.info "Changeset #{change_set_type} complete" + end + + end +end \ No newline at end of file diff --git a/lib/cfnvpn/certificates.rb b/lib/cfnvpn/certificates.rb index 94cd4a1..fc233fc 100644 --- a/lib/cfnvpn/certificates.rb +++ b/lib/cfnvpn/certificates.rb @@ -1,5 +1,5 @@ require 'fileutils' -require 'mkmf' +require 'time' require 'cfnvpn/acm' require 'cfnvpn/s3' require 'cfnvpn/log' @@ -28,19 +28,25 @@ def initialize(build_dir, cfnvpn_name, easyrsa_local = false) FileUtils.mkdir_p(@pki_dir) end - def generate_ca(server_cn,client_cn) + def generate_ca(server_cn,client_cn,expiry=nil) + opts = "" + unless expiry.nil? + opts += "--days=#{expiry}" + end + if @easyrsa_local ENV["EASYRSA_REQ_CN"] = server_cn ENV["EASYRSA_PKI"] = @pki_dir system("easyrsa init-pki") system("easyrsa build-ca nopass") - system("easyrsa build-server-full server nopass") - system("easyrsa build-client-full #{client_cn} nopass") + system("easyrsa #{opts} build-server-full server nopass") + system("easyrsa #{opts} build-client-full #{client_cn} nopass") 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) system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/") else @docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}" @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}" + @docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\"" @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output" @docker_cmd << @easyrsa_image @docker_cmd << "sh -c 'create-ca'" @@ -48,14 +54,20 @@ def generate_ca(server_cn,client_cn) end end - def generate_client(client_cn) + def generate_client(client_cn,expiry=nil) + opts = "" + unless expiry.nil? + opts += "--days=#{expiry}" + end + if @easyrsa_local ENV["EASYRSA_PKI"] = @pki_dir system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}") - system("easyrsa build-client-full #{client_cn} nopass") + system("easyrsa #{opts} build-client-full #{client_cn} nopass") 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") else @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}" + @docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\"" @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output" @docker_cmd << @easyrsa_image @docker_cmd << "sh -c 'create-client'" @@ -63,6 +75,65 @@ def generate_client(client_cn) end end + def renew(server_cn,client_cn,expiry=nil) + opts = "" + unless expiry.nil? + opts += "--days=#{expiry}" + end + + if @easyrsa_local + ENV["EASYRSA_REQ_CN"] = server_cn + ENV["EASYRSA_PKI"] = @pki_dir + system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}") + system("easyrsa #{opts} renew server nopass") + system("easyrsa #{opts} renew #{client_cn} nopass") + 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) + system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/") + else + @docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}" + @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}" + @docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\"" + @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output" + @docker_cmd << @easyrsa_image + @docker_cmd << "sh -c 'renew'" + CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}` + end + end + + def rebuild(server_cn,client_cn,expiry=nil) + timestamp = Time.now.getutc.to_i + opts = "" + unless expiry.nil? + opts += "--days=#{expiry}" + end + + if @easyrsa_local + ENV["EASYRSA_REQ_CN"] = server_cn + ENV["EASYRSA_PKI"] = @pki_dir + system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}") + + FileUtils.mv("#{@pki_dir}/reqs/server.req", "#{@pki_dir}/reqs/server.req.bak-#{timestamp}") + FileUtils.mv("#{@pki_dir}/issued/server.crt", "#{@pki_dir}/issued/server.req.bak-#{timestamp}") + FileUtils.mv("#{@pki_dir}/private/server.key", "#{@pki_dir}/private/server.req.bak-#{timestamp}") + FileUtils.mv("#{@pki_dir}/reqs/#{client_cn}.req", "#{@pki_dir}/reqs/#{client_cn}.req.bak-#{timestamp}") + FileUtils.mv("#{@pki_dir}/issued/#{client_cn}.crt", "#{@pki_dir}/issued/#{client_cn}.req.bak-#{timestamp}") + FileUtils.mv("#{@pki_dir}/private/#{client_cn}.key", "#{@pki_dir}/private/#{client_cn}.req.bak-#{timestamp}") + + system("easyrsa #{opts} build-server-full server nopass") + system("easyrsa #{opts} build-client-full #{client_cn} nopass") + 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) + system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/") + else + @docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}" + @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}" + @docker_cmd << "-e EASYRSA_OPTS=\"#{opts}\"" + @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output" + @docker_cmd << @easyrsa_image + @docker_cmd << "sh -c 'rebuild'" + CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}` + end + end + def revoke_client(client_cn) if @easyrsa_local ENV["EASYRSA_PKI"] = @pki_dir diff --git a/lib/cfnvpn/version.rb b/lib/cfnvpn/version.rb index 392d1da..90cb5c9 100644 --- a/lib/cfnvpn/version.rb +++ b/lib/cfnvpn/version.rb @@ -1,4 +1,4 @@ module CfnVpn - VERSION = "1.4.5".freeze + VERSION = "1.5.0".freeze CHANGE_SET_VERSION = VERSION.gsub('.', '-').freeze end