Add new api option force_no_cert (#124)

* Add new option force_no_cert

Connect to a router without a certificate by using ADH ciphers.
This can be useful when setting up a device.

* Changelog

* Update plugins/doc_fragments/api.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update changelogs/fragments/124-api.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
PhiBo 2022-11-12 09:47:52 +01:00 committed by GitHub
parent 78d8cfb1ad
commit 9567bbf292
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 2 deletions

View file

@ -113,6 +113,7 @@ Example playbook:
password: "{{ password }}" password: "{{ password }}"
username: "{{ username }}" username: "{{ username }}"
tls: true tls: true
force_no_cert: false
validate_certs: true validate_certs: true
validate_cert_hostname: true validate_cert_hostname: true
ca_path: /path/to/ca-certificate.pem ca_path: /path/to/ca-certificate.pem

View file

@ -0,0 +1,3 @@
minor_changes:
- api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers
(https://github.com/ansible-collections/community.routeros/pull/124).

View file

@ -107,6 +107,7 @@ Setting up encryption
It is recommended to always use ``tls: true`` when connecting with the API, even if you are only connecting to the device through a trusted network. The following options control how TLS/SSL is used: It is recommended to always use ``tls: true`` when connecting with the API, even if you are only connecting to the device through a trusted network. The following options control how TLS/SSL is used:
:force_no_cert: Setting to ``true`` connects to the device without a certificate. **This is discouraged to use in production and is susceptible to Man-in-the-Middle attacks**, but might be useful when setting the device up. The default value is ``false``.
:validate_certs: Setting to ``false`` disables any certificate validation. **This is discouraged to use in production**, but is needed when setting the device up. The default value is ``true``. :validate_certs: Setting to ``false`` disables any certificate validation. **This is discouraged to use in production**, but is needed when setting the device up. The default value is ``true``.
:validate_cert_hostname: Setting to ``false`` (default) disables hostname verification during certificate validation. This is needed if the hostnames specified in the certificate do not match the hostname used for connecting (usually the device's IP). It is recommended to set up the certificate correctly and set this to ``true``; the default ``false`` is chosen for backwards compatibility to an older version of the module. :validate_cert_hostname: Setting to ``false`` (default) disables hostname verification during certificate validation. This is needed if the hostnames specified in the certificate do not match the hostname used for connecting (usually the device's IP). It is recommended to set up the certificate correctly and set this to ``true``; the default ``false`` is chosen for backwards compatibility to an older version of the module.
:ca_path: If you are not using a commerically trusted CA certificate to sign your device's certificate, or have not included your CA certificate in Python's truststore, you need to point this option to the CA certificate. :ca_path: If you are not using a commerically trusted CA certificate to sign your device's certificate, or have not included your CA certificate in Python's truststore, you need to point this option to the CA certificate.

View file

@ -46,6 +46,17 @@ options:
- RouterOS api port. If I(tls) is set, port will apply to TLS/SSL connection. - RouterOS api port. If I(tls) is set, port will apply to TLS/SSL connection.
- Defaults are C(8728) for the HTTP API, and C(8729) for the HTTPS API. - Defaults are C(8728) for the HTTP API, and C(8729) for the HTTPS API.
type: int type: int
force_no_cert:
description:
- Set to C(true) to connect without a certificate when I(tls=true).
- See also I(validate_certs).
- B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible
to Man-in-the-Middle attacks, because the keys used in the exchange are not authenticated.
Instead of simply connecting without a certificate to "make things work" have a look at
I(validate_certs) and I(ca_path).
type: bool
default: false
version_added: 2.4.0
validate_certs: validate_certs:
description: description:
- Set to C(false) to skip validation of TLS certificates. - Set to C(false) to skip validation of TLS certificates.

View file

@ -41,6 +41,7 @@ def api_argument_spec():
hostname=dict(type='str', required=True), hostname=dict(type='str', required=True),
port=dict(type='int'), port=dict(type='int'),
tls=dict(type='bool', default=False, aliases=['ssl']), tls=dict(type='bool', default=False, aliases=['ssl']),
force_no_cert=dict(type='bool', default=False),
validate_certs=dict(type='bool', default=True), validate_certs=dict(type='bool', default=True),
validate_cert_hostname=dict(type='bool', default=False), validate_cert_hostname=dict(type='bool', default=False),
ca_path=dict(type='path'), ca_path=dict(type='path'),
@ -49,7 +50,7 @@ def api_argument_spec():
) )
def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path, encoding, timeout): def _ros_api_connect(module, username, password, host, port, use_tls, force_no_cert, validate_certs, validate_cert_hostname, ca_path, encoding, timeout):
'''Connect to RouterOS API.''' '''Connect to RouterOS API.'''
if not port: if not port:
if use_tls: if use_tls:
@ -68,7 +69,10 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c
if use_tls: if use_tls:
ctx = ssl.create_default_context(cafile=ca_path) ctx = ssl.create_default_context(cafile=ca_path)
wrap_context = ctx.wrap_socket wrap_context = ctx.wrap_socket
if not validate_certs: if force_no_cert:
ctx.check_hostname = False
ctx.set_ciphers("ADH:@SECLEVEL=0")
elif not validate_certs:
ctx.check_hostname = False ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE ctx.verify_mode = ssl.CERT_NONE
elif not validate_cert_hostname: elif not validate_cert_hostname:
@ -101,6 +105,7 @@ def create_api(module):
module.params['hostname'], module.params['hostname'],
module.params['port'], module.params['port'],
module.params['tls'], module.params['tls'],
module.params['force_no_cert'],
module.params['validate_certs'], module.params['validate_certs'],
module.params['validate_cert_hostname'], module.params['validate_cert_hostname'],
module.params['ca_path'], module.params['ca_path'],