From 9917fbc180ac32c567e3edc6b51670f485bb1213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 12 Mar 2019 17:18:38 +0100 Subject: [PATCH 1/2] Adjust clients $compression type to match servers Allow new compress option --- manifests/client.pp | 2 +- spec/defines/openvpn_client_spec.rb | 4 ++-- spec/defines/openvpn_server_spec.rb | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manifests/client.pp b/manifests/client.pp index e1ce5cc0..668ee774 100644 --- a/manifests/client.pp +++ b/manifests/client.pp @@ -45,7 +45,7 @@ # define openvpn::client ( String $server, - Enum['comp-lzo', ''] $compression = 'comp-lzo', + String $compression = 'comp-lzo', Enum['tap', 'tun'] $dev = 'tun', Integer $mute = 20, Boolean $mute_replay_warnings = true, diff --git a/spec/defines/openvpn_client_spec.rb b/spec/defines/openvpn_client_spec.rb index beeeffc4..3808bda2 100644 --- a/spec/defines/openvpn_client_spec.rb +++ b/spec/defines/openvpn_client_spec.rb @@ -99,7 +99,7 @@ let(:params) do { 'server' => 'test_server', - 'compression' => 'comp-lzo', + 'compression' => 'compress lz4', 'dev' => 'tap', 'mute' => 10, 'mute_replay_warnings' => false, @@ -135,7 +135,7 @@ it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^proto\s+udp$}) } it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^remote\s+somewhere\s+123$}) } it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^remote\s+galaxy\s+123$}) } - it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^comp-lzo$}) } + it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^compress lz4$}) } it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^resolv-retry\s+2m$}) } it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^verb\s+1$}) } it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^mute\s+10$}) } diff --git a/spec/defines/openvpn_server_spec.rb b/spec/defines/openvpn_server_spec.rb index d35248b8..b6f21b1b 100644 --- a/spec/defines/openvpn_server_spec.rb +++ b/spec/defines/openvpn_server_spec.rb @@ -241,7 +241,7 @@ 'city' => 'Some City', 'organization' => 'example.org', 'email' => 'testemail@example.org', - 'compression' => 'fake_compression', + 'compression' => 'compress lz4', 'port' => '123', 'proto' => 'udp', 'group' => 'someone', @@ -293,7 +293,7 @@ it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^proto\s+udp$}) } it { is_expected.not_to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^proto\s+tls-server$}) } it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^port\s+123$}) } - it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^fake_compression$}) } + it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^compress lz4$}) } it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^group\s+someone$}) } it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^user\s+someone$}) } it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^log\-append\s+/var/log/openvpn/test_server\.log$}) } @@ -377,7 +377,7 @@ 'city' => 'Some City', 'organization' => 'example.org', 'email' => 'testemail@example.org', - 'compression' => 'fake_compression', + 'compression' => 'compress lz4', 'port' => '123', 'proto' => 'udp', 'group' => 'someone', @@ -683,7 +683,7 @@ 'city' => 'Some City', 'organization' => 'example.org', 'email' => 'testemail@example.org', - 'compression' => 'fake_compression', + 'compression' => 'compress lz4', 'port' => '123', 'proto' => 'udp', 'group' => 'someone', From 288a498c54c3c7e272288bdb863df727978ec433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Fri, 15 Mar 2019 14:55:44 +0100 Subject: [PATCH 2/2] Add tls_crypt --- manifests/ca.pp | 8 ++++++- manifests/client.pp | 24 +++++++++++++++++++- manifests/server.pp | 34 +++++++++++++++++------------ spec/defines/openvpn_client_spec.rb | 6 +++++ spec/defines/openvpn_server_spec.rb | 21 +++++++++++++++++- templates/client_external_auth.erb | 3 +++ templates/server.erb | 3 +++ 7 files changed, 82 insertions(+), 17 deletions(-) diff --git a/manifests/ca.pp b/manifests/ca.pp index a8797215..6d123b73 100644 --- a/manifests/ca.pp +++ b/manifests/ca.pp @@ -14,6 +14,7 @@ # @param key_ou Value for organizationalUnitName_default variable in openssl.cnf and KEY_OU in vars # @param key_cn Value for commonName_default variable in openssl.cnf and KEY_CN in vars # @param tls_auth Determins if a tls key is generated +# @param tls_static_key Determins if a tls key is generated # @example # openvpn::ca { # 'my_user': @@ -37,8 +38,13 @@ String $key_name = '', String $key_ou = '', Boolean $tls_auth = false, + Boolean $tls_static_key = false, ) { + if $tls_auth { + warning('Parameter $tls_auth is deprecated. Use $tls_static_key instead.') + } + include openvpn $group_to_set = $group ? { undef => $openvpn::group, @@ -217,7 +223,7 @@ require => Exec["create crl.pem on ${name}"], } - if $tls_auth { + if $tls_static_key { exec { "generate tls key for ${name}": command => 'openvpn --genkey --secret keys/ta.key', cwd => "${etc_directory}/openvpn/${name}/easy-rsa", diff --git a/manifests/client.pp b/manifests/client.pp index e1ce5cc0..0efafce5 100644 --- a/manifests/client.pp +++ b/manifests/client.pp @@ -20,6 +20,7 @@ # @param pam DEPRECATED: Boolean, Enable/Disable. # @param authuserpass Set if username and password required # @param tls_auth Activates tls-auth to Add an additional layer of HMAC authentication on top of the TLS control channel to protect against DoS attacks. This has to be set to the same value as on the Server +# @param tls_crypt Encrypt and authenticate all control channel packets with the key from keyfile. (See --tls-auth for more background.) # @param x509_name Common name of openvpn server to make an x509-name verification # @param setenv Set a custom environmental variable name=value to pass to script. # @param setenv_safe Set a custom environmental variable OPENVPN_name=value to pass to script. This directive is designed to be pushed by the server to clients, and the prepending of "OPENVPN_" to the environmental variable is a safety precaution to prevent a LD_PRELOAD style attack from a malicious or compromised server. @@ -67,6 +68,7 @@ String $up = '', String $down = '', Boolean $tls_auth = false, + Boolean $tls_crypt = false, Optional[String] $x509_name = undef, Optional[Integer] $sndbuf = undef, Optional[Integer] $rcvbuf = undef, @@ -89,6 +91,7 @@ $extca_enabled = pick(getparam(Openvpn::Server[$server], 'extca_enabled'), $server_extca_enabled) if $extca_enabled { fail('cannot currently create client configs when corresponding openvpn::server is extca_enabled') } + if $tls_auth and $tls_crypt { fail('tls_auth and tls_crypt are mutually exclusive') } $ca_name = pick($shared_ca, $server) Openvpn::Ca[$ca_name] @@ -164,7 +167,7 @@ require => Exec["generate certificate for ${name} in context of ${ca_name}"], } - if $tls_auth { + if $tls_auth or $tls_crypt { file { "${etc_directory}/openvpn/${server}/download-configs/${name}/keys/${name}/ta.key": ensure => link, target => "${etc_directory}/openvpn/${server}/easy-rsa/keys/ta.key", @@ -319,4 +322,23 @@ order => '13', } } + elsif $tls_crypt { + concat::fragment { "/etc/openvpn/${server}/download-configs/${name}.ovpn/tls_crypt_open_tag": + target => "${etc_directory}/openvpn/${server}/download-configs/${name}.ovpn", + content => "\n", + order => '11', + } + + concat::fragment { "${etc_directory}/openvpn/${server}/download-configs/${name}.ovpn/tls_crypt": + target => "${etc_directory}/openvpn/${server}/download-configs/${name}.ovpn", + source => "${etc_directory}/openvpn/${server}/download-configs/${name}/keys/${name}/ta.key", + order => '12', + } + + concat::fragment { "${etc_directory}/openvpn/${server}/download-configs/${name}.ovpn/tls_crypt_close_tag": + target => "${etc_directory}/openvpn/${server}/download-configs/${name}.ovpn", + content => "\n", + order => '13', + } + } } diff --git a/manifests/server.pp b/manifests/server.pp index 5a1d68de..61c17e62 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -68,6 +68,7 @@ # @param key_ou Value for organizationalUnitName_default variable in openssl.cnf and KEY_OU in vars # @param key_cn Value for commonName_default variable in openssl.cnf and KEY_CN in vars # @param tls_auth Activates tls-auth to Add an additional layer of HMAC authentication on top of the TLS control channel to protect against DoS attacks. +# @param tls_crypt Encrypt and authenticate all control channel packets with the key from keyfile. (See --tls-auth for more background.) # @param tls_server If proto not tcp it lets you choose if the parameter tls-server is set or not. # @param tls_client Allows you to set this server up as a tls-client connection. # @param server_poll_timeout Value for timeout before trying the next server. @@ -187,6 +188,7 @@ Boolean $persist_key = false, Boolean $persist_tun = false, Boolean $tls_auth = false, + Boolean $tls_crypt = false, Boolean $tls_server = false, Boolean $tls_client = false, Optional[Integer] $server_poll_timeout = undef, @@ -221,6 +223,10 @@ fail("Using systemd and namespecific rclink's (BSD-style) is not allowed") } + if $tls_auth and $tls_crypt { + fail('tls_auth and tls_crypt are mutually exclusive') + } + if $openvpn::manage_service { if $facts['service_provider'] == 'systemd' { $lnotify = Service["openvpn@${name}"] @@ -307,20 +313,20 @@ $ca_common_name = $common_name ::openvpn::ca { $name: - country => $country, - province => $province, - city => $city, - organization => $organization, - email => $email, - common_name => $common_name, - group => $group, - ssl_key_size => $ssl_key_size, - ca_expire => $ca_expire, - key_expire => $key_expire, - key_cn => $key_cn, - key_name => $key_name, - key_ou => $key_ou, - tls_auth => $tls_auth, + country => $country, + province => $province, + city => $city, + organization => $organization, + email => $email, + common_name => $common_name, + group => $group, + ssl_key_size => $ssl_key_size, + ca_expire => $ca_expire, + key_expire => $key_expire, + key_cn => $key_cn, + key_name => $key_name, + key_ou => $key_ou, + tls_static_key => $tls_auth or $tls_crypt, } ## Renewal of crl.pem diff --git a/spec/defines/openvpn_client_spec.rb b/spec/defines/openvpn_client_spec.rb index beeeffc4..2434de68 100644 --- a/spec/defines/openvpn_client_spec.rb +++ b/spec/defines/openvpn_client_spec.rb @@ -153,6 +153,12 @@ it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^remote-cert-tls\s+server$}) } end + context 'test tls_crypt' do + let(:params) { { 'server' => 'test_server', 'tls_crypt' => true } } + + it { is_expected.to contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(%r{^tls-crypt keys/test_client/ta\.key$}) } + end + context 'omitting the cipher key' do let(:params) { { 'server' => 'test_server' } } diff --git a/spec/defines/openvpn_server_spec.rb b/spec/defines/openvpn_server_spec.rb index d35248b8..a8c70cfb 100644 --- a/spec/defines/openvpn_server_spec.rb +++ b/spec/defines/openvpn_server_spec.rb @@ -356,10 +356,29 @@ key_cn: 'yolo', key_name: 'burp', key_ou: 'NSA', - tls_auth: true) + tls_static_key: true) } end + context 'creating a server setting all parameters including tls_crypt' do + let(:params) do + { + 'country' => 'CO', + 'province' => 'ST', + 'city' => 'Some City', + 'organization' => 'example.org', + 'email' => 'testemail@example.org', + 'proto' => 'tcp6', + 'tls_crypt' => true + } + end + + it { is_expected.to contain_file('/etc/openvpn/test_server.conf').with_content(%r{^tls-crypt\s+/etc/openvpn/test_server/keys/ta.key$}) } + + # OpenVPN easy-rsa CA + it { is_expected.to contain_openvpn__ca('test_server').with(tls_static_key: true) } + end + # tests dedicated to easyrsa version 2 context 'with easyrsa 2.0' do let(:facts) do diff --git a/templates/client_external_auth.erb b/templates/client_external_auth.erb index 147da431..e429e423 100644 --- a/templates/client_external_auth.erb +++ b/templates/client_external_auth.erb @@ -7,3 +7,6 @@ key keys/<%= @name %>/<%= @name %>.key tls-client tls-auth keys/<%= @name %>/ta.key 1 <% end -%> +<% if @tls_crypt -%> +tls-crypt keys/<%= @name %>/ta.key +<% end -%> diff --git a/templates/server.erb b/templates/server.erb index b375e7ef..3db2d724 100644 --- a/templates/server.erb +++ b/templates/server.erb @@ -182,6 +182,9 @@ key-direction 0 key-direction 1 <% end -%> <% end -%> +<% if @tls_crypt -%> +tls-crypt <%= @etc_directory -%>/openvpn/<%= @name %>/keys/ta.key +<% end -%> <% if @fragment != false -%> fragment <%= @fragment %> <% end -%>