Repository: ansible-collections/community.vmware

Issue:
ssl.wrap_socket() was removed in Python 3.12
##### SUMMARY
`ssl.wrap_socket()` was [removed in Python 3.12](https://docs.python.org/3.12/whatsnew/3.12.html#ssl). We use it here:

https://github.com/ansible-collections/community.vmware/blob/fa98edf8514d6c479ccfc3b15d30c6e7542006ec/plugins/module_utils/vmware.py#L1194

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
module_utils/vmware.py

##### ADDITIONAL INFORMATION
ansible-collections/community.general#7542


Discussion:
In vmware_deploy_ovf I use much less code, but possible without error handling...

```
def _get_thumbprint(self, hostname):
        pem = ssl.get_server_certificate((hostname, 443))
        sha1 = hashlib.sha1(
            ssl.PEM_cert_to_DER_cert(pem)).hexdigest().upper()
        colon_notion = ':'.join(sha1[i:i + 2] for i in range(0, len(sha1), 2))

        return None if sha1 is None else colon_notion
```
@ihumster Maybe we can consolidate this somehow.

BTW, I'm not 100% sure but using thumbprints (instead of full full SSL certificate validation) might be something that won't be possible in the future: [vSphere security hardening impact on Client plugins](https://blogs.vmware.com/code/2023/11/15/vsphere-security-strong-mode-and-its-impact-on-vsphere-client-plugins/):

> The strong mode also supports full SSL certificates as trust exchange mechanism, which may impact some vSphere APIs using certificate thumbprints as arguments, or as part of the API response. Such APIs may not be supported when the strong mode is switched on. 
Hi

is there a workaround, or an ETA for a patch ? I had to downgrade from Python 3.12 to 3.11 in order to user the `vmware_host` module, which is not a big deal but Renovate keeps telling me that an update is available :)

Thanks in advance !

Resolving patch:
diff --git a/plugins/module_utils/vmware.py b/plugins/module_utils/vmware.py
--- a/plugins/module_utils/vmware.py
+++ b/plugins/module_utils/vmware.py
@@ -1174,9 +1174,9 @@ def vcenter_version_at_least(self, version=None):
         self.module.fail_json(msg='The passed vCenter version: %s is None.' % version)
 
     def get_cert_fingerprint(self, fqdn, port, proxy_host=None, proxy_port=None):
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        sock.settimeout(1)
         if proxy_host:
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            sock.settimeout(1)
             sock.connect((
                 proxy_host,
                 proxy_port))
@@ -1191,17 +1191,16 @@ def get_cert_fingerprint(self, fqdn, port, proxy_host=None, proxy_port=None):
             der_cert_bin = ctx.wrap_socket(sock, server_hostname=fqdn).getpeercert(True)
             sock.close()
         else:
-            wrapped_socket = ssl.wrap_socket(sock)
             try:
-                wrapped_socket.connect((fqdn, port))
-            except socket.error as socket_error:
-                self.module.fail_json(msg="Cannot connect to host : %s" % socket_error)
-            else:
-                der_cert_bin = wrapped_socket.getpeercert(True)
-                wrapped_socket.close()
-
-        string = str(hashlib.sha1(der_cert_bin).hexdigest())
-        return ':'.join(a + b for a, b in zip(string[::2], string[1::2]))
+                pem = ssl.get_server_certificate((fqdn, port))
+            except Exception:
+                self.module.fail_json(msg=f"Cannot connect to host: {fqdn}")
+            der_cert_bin = ssl.PEM_cert_to_DER_cert(pem)
+        if der_cert_bin:
+            string = str(hashlib.sha1(der_cert_bin).hexdigest())
+            return ':'.join(a + b for a, b in zip(string[::2], string[1::2]))
+        else:
+            self.module.fail_json(msg=f"Unable to obtain certificate fingerprint for host: {fqdn}")
 
     def get_managed_objects_properties(self, vim_type, properties=None):
         """


Test patch: