Skip to content

Commit

Permalink
Add new api option force_no_cert (#124)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
phibos and felixfontein authored Nov 12, 2022
1 parent 78d8cfb commit 9567bbf
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Example playbook:
password: "{{ password }}"
username: "{{ username }}"
tls: true
force_no_cert: false
validate_certs: true
validate_cert_hostname: true
ca_path: /path/to/ca-certificate.pem
Expand Down
3 changes: 3 additions & 0 deletions changelogs/fragments/124-api.yml
Original file line number Diff line number Diff line change
@@ -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).
1 change: 1 addition & 0 deletions docs/docsite/rst/api-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

: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_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.
Expand Down
11 changes: 11 additions & 0 deletions plugins/doc_fragments/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ class ModuleDocFragment(object):
- 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.
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:
description:
- Set to C(false) to skip validation of TLS certificates.
Expand Down
9 changes: 7 additions & 2 deletions plugins/module_utils/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def api_argument_spec():
hostname=dict(type='str', required=True),
port=dict(type='int'),
tls=dict(type='bool', default=False, aliases=['ssl']),
force_no_cert=dict(type='bool', default=False),
validate_certs=dict(type='bool', default=True),
validate_cert_hostname=dict(type='bool', default=False),
ca_path=dict(type='path'),
Expand All @@ -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.'''
if not port:
if use_tls:
Expand All @@ -68,7 +69,10 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c
if use_tls:
ctx = ssl.create_default_context(cafile=ca_path)
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.verify_mode = ssl.CERT_NONE
elif not validate_cert_hostname:
Expand Down Expand Up @@ -101,6 +105,7 @@ def create_api(module):
module.params['hostname'],
module.params['port'],
module.params['tls'],
module.params['force_no_cert'],
module.params['validate_certs'],
module.params['validate_cert_hostname'],
module.params['ca_path'],
Expand Down

0 comments on commit 9567bbf

Please sign in to comment.