diff --git a/changelogs/fragments/238_pfsense_openvpn_server.yml b/changelogs/fragments/238_pfsense_openvpn_server.yml
new file mode 100644
index 00000000..0f4d227c
--- /dev/null
+++ b/changelogs/fragments/238_pfsense_openvpn_server.yml
@@ -0,0 +1,5 @@
+bugfixes:
+ - pfsense_openvpn_server - Normalize `tls` text to CRLF line endings to match web interface (https://github.com/pfsensible/core/issues/163).
+minor_changes:
+ - pfsense_openvpn_server - Drop `ncp_enable` parameter no longer used (https://github.com/pfsensible/core/pull/238).
+ - pfsense_openvpn_server - No longer remove `strictusercn` option if not specified to match web interface (https://github.com/pfsensible/core/pull/238).
diff --git a/plugins/module_utils/openvpn_server.py b/plugins/module_utils/openvpn_server.py
index 0bdefad9..424ef5a9 100644
--- a/plugins/module_utils/openvpn_server.py
+++ b/plugins/module_utils/openvpn_server.py
@@ -34,9 +34,6 @@
shared_key=dict(required=False, type='str', no_log=True),
dh_length=dict(default=2048, required=False, type='int'),
ecdh_curve=dict(default='none', required=False, choices=['none', 'prime256v1', 'secp384r1', 'secp521r1']),
- ncp_enable=dict(default=True, required=False, type='bool'),
- # ncp_ciphers=dict(default=list('AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305'), required=False,
- # choices=['AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305'], type='list', elements='str'),
data_ciphers=dict(default=['AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305'], required=False,
choices=['AES-256-CBC', 'AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305'], type='list', elements='str'),
data_ciphers_fallback=dict(default='AES-256-CBC', required=False, choices=['AES-256-CBC', 'AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305']),
@@ -95,6 +92,10 @@
openvpn_delete('server',$ovpn);
"""
+# Define the line endings in bytes for binary mode
+UNIX_LINE_ENDING = b'\n'
+WINDOWS_LINE_ENDING = b'\r\n'
+
class PFSenseOpenVPNServerModule(PFSenseModuleBase):
""" module managing pfSense OpenVPN configuration """
@@ -145,7 +146,6 @@ def _params_to_obj(self):
obj['verbosity_level'] = str(self.params['verbosity_level'])
obj['data_ciphers_fallback'] = self.params['data_ciphers_fallback']
obj['data_ciphers'] = ",".join(self.params['data_ciphers'])
- self._get_ansible_param_bool(obj, 'ncp_enable', force=True, value='enabled', value_false='disabled')
self._get_ansible_param_bool(obj, 'gwredir', force=True, value='yes')
self._get_ansible_param_bool(obj, 'gwredir6', force=True, value='yes')
self._get_ansible_param_bool(obj, 'compression_push', force=True, value='yes', value_false='')
@@ -249,7 +249,9 @@ def _validate_params(self):
# generate during _find_target (after _params_to_obj) - for just generate if not exists
pass
elif re.search('^-----BEGIN OpenVPN Static key V1-----.*-----END OpenVPN Static key V1-----$', key, flags=re.MULTILINE | re.DOTALL):
- params[param] = base64.b64encode(key.encode()).decode()
+ key = key.encode().replace(WINDOWS_LINE_ENDING, UNIX_LINE_ENDING) # Normalize existing CRLF to LF
+ key = key.replace(UNIX_LINE_ENDING, WINDOWS_LINE_ENDING) # Convert all LF to CRLF
+ params[param] = base64.b64encode(key).decode()
else:
key_decoded = base64.b64decode(key.encode()).decode()
if not re.search('^-----BEGIN OpenVPN Static key V1-----.*-----END OpenVPN Static key V1-----$',
@@ -310,7 +312,7 @@ def _find_last_openvpn_idx(self):
def _get_params_to_remove(self):
""" returns the list of params to remove if they are not set """
params_to_remove = []
- for param in ['disable', 'strictusercn', 'push_register_dns', 'remote_cert_tls']:
+ for param in ['disable', 'push_register_dns', 'remote_cert_tls']:
if not self.params[param]:
params_to_remove.append(param)
diff --git a/plugins/modules/pfsense_openvpn_server.py b/plugins/modules/pfsense_openvpn_server.py
index badcff8f..92081136 100644
--- a/plugins/modules/pfsense_openvpn_server.py
+++ b/plugins/modules/pfsense_openvpn_server.py
@@ -122,10 +122,6 @@
choices: ['AES-256-CBC', 'AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305']
type: list
elements: str
- ncp_enable:
- description: Enable data encryption negotiation.
- default: true
- type: bool
digest:
description:
- 'Auth digest algorithm. The list of valid digest algorithms is determined from the output of C(openvpn --show-digests), but curently includes:'
diff --git a/tests/unit/plugins/modules/fixtures/pfsense_openvpn_config.xml b/tests/unit/plugins/modules/fixtures/pfsense_openvpn_config.xml
index c574e51a..6aef0ddb 100644
--- a/tests/unit/plugins/modules/fixtures/pfsense_openvpn_config.xml
+++ b/tests/unit/plugins/modules/fixtures/pfsense_openvpn_config.xml
@@ -349,7 +349,6 @@
both
3
AES-256-GCM,AES-128-GCM,AES-256-CBC
- enabled
keepalive
10
60
@@ -413,7 +412,6 @@
both
1
AES-256-GCM,AES-128-GCM,CHACHA20-POLY1305
- enabled
keepalive
10
60
diff --git a/tests/unit/plugins/modules/test_pfsense_openvpn_server.py b/tests/unit/plugins/modules/test_pfsense_openvpn_server.py
index c43e2dbb..9747de77 100644
--- a/tests/unit/plugins/modules/test_pfsense_openvpn_server.py
+++ b/tests/unit/plugins/modules/test_pfsense_openvpn_server.py
@@ -145,7 +145,6 @@ def check_target_elt(self, obj, target_elt):
self.check_param_equal(obj, target_elt, 'ecdh_curve', default='none')
self.check_param_equal(obj, target_elt, 'data_ciphers_fallback', default='AES-256-CBC')
self.check_param_equal(obj, target_elt, 'data_ciphers', default='AES-256-GCM,AES-128-GCM,CHACHA20-POLY1305')
- self.check_param_bool(obj, target_elt, 'ncp_enable', default=True, value_true='enabled')
self.check_param_equal(obj, target_elt, 'digest', default='SHA256')
self.check_param_equal(obj, target_elt, 'ecdh_curve', default='none')
self.check_param_equal(obj, target_elt, 'allow_compression', default='no')