diff --git a/changelogs/fragments/7392-lxd-inventory-server-cert.yml b/changelogs/fragments/7392-lxd-inventory-server-cert.yml new file mode 100644 index 0000000000..bc7e922aaf --- /dev/null +++ b/changelogs/fragments/7392-lxd-inventory-server-cert.yml @@ -0,0 +1,3 @@ +minor_changes: + - lxd inventory plugin - add ``server_cert`` option for trust anchor to use for TLS verification of server certificates (https://github.com/ansible-collections/community.general/pull/7392). + - lxd inventory plugin - add ``server_check_hostname`` option to disable hostname verification of server certificates (https://github.com/ansible-collections/community.general/pull/7392). diff --git a/plugins/inventory/lxd.py b/plugins/inventory/lxd.py index 5133236180..ccc5128c05 100644 --- a/plugins/inventory/lxd.py +++ b/plugins/inventory/lxd.py @@ -41,6 +41,20 @@ DOCUMENTATION = r''' aliases: [ cert_file ] default: $HOME/.config/lxc/client.crt type: path + server_cert: + description: + - The server certificate file path. + type: path + version_added: 8.0.0 + server_check_hostname: + description: + - This option controls if the server's hostname is checked as part of the HTTPS connection verification. + This can be useful to disable, if for example, the server certificate provided (see O(server_cert) option) + does not cover a name matching the one used to communicate with the server. Such mismatch is common as LXD + generates self-signed server certificates by default. + type: bool + default: true + version_added: 8.0.0 trust_password: description: - The client trusted password. @@ -286,7 +300,7 @@ class InventoryModule(BaseInventoryPlugin): urls = (url for url in url_list if self.validate_url(url)) for url in urls: try: - socket_connection = LXDClient(url, self.client_key, self.client_cert, self.debug) + socket_connection = LXDClient(url, self.client_key, self.client_cert, self.debug, self.server_cert, self.server_check_hostname) return socket_connection except LXDClientException as err: error_storage[url] = err @@ -1078,6 +1092,8 @@ class InventoryModule(BaseInventoryPlugin): try: self.client_key = self.get_option('client_key') self.client_cert = self.get_option('client_cert') + self.server_cert = self.get_option('server_cert') + self.server_check_hostname = self.get_option('server_check_hostname') self.project = self.get_option('project') self.debug = self.DEBUG self.data = {} # store for inventory-data diff --git a/plugins/module_utils/lxd.py b/plugins/module_utils/lxd.py index 7f5362532a..68a1c690fe 100644 --- a/plugins/module_utils/lxd.py +++ b/plugins/module_utils/lxd.py @@ -41,7 +41,7 @@ class LXDClientException(Exception): class LXDClient(object): - def __init__(self, url, key_file=None, cert_file=None, debug=False): + def __init__(self, url, key_file=None, cert_file=None, debug=False, server_cert_file=None, server_check_hostname=True): """LXD Client. :param url: The URL of the LXD server. (e.g. unix:/var/lib/lxd/unix.socket or https://127.0.0.1) @@ -52,6 +52,10 @@ class LXDClient(object): :type cert_file: ``str`` :param debug: The debug flag. The request and response are stored in logs when debug is true. :type debug: ``bool`` + :param server_cert_file: The path of the server certificate file. + :type server_cert_file: ``str`` + :param server_check_hostname: Whether to check the server's hostname as part of TLS verification. + :type debug: ``bool`` """ self.url = url self.debug = debug @@ -61,6 +65,10 @@ class LXDClient(object): self.key_file = key_file parts = generic_urlparse(urlparse(self.url)) ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) + if server_cert_file: + # Check that the received cert is signed by the provided server_cert_file + ctx.load_verify_locations(cafile=server_cert_file) + ctx.check_hostname = server_check_hostname ctx.load_cert_chain(cert_file, keyfile=key_file) self.connection = HTTPSConnection(parts.get('netloc'), context=ctx) elif url.startswith('unix:'):