Open Toemsel opened 1 year ago
I did hack something together to get the job done. However, I don't want to create a PR for that, since it is.... too hacky for the public. But if someone else has a similar requirement:
appSrv = HubConnectionBuilder()\
.with_url(AppSrvUrl + ':' + str(AppSrvPort) + '/' + AppSrvHub,
options={"verify_ssl": False,
"ssl": {
"serverCert": pathlib.Path("C:/cert/localhost.crt"),
"cert": pathlib.Path("C:/cert/localhost.crt"),
"key": pathlib.Path("C:/cert/localhost.key"),
"secret": ""
},
"headers": {
"Certificate": clientCertHeader
}})\
.configure_logging(logging.DEBUG)\
def start(self):
if not self.skip_negotiation:
self.negotiate()
if self.state == ConnectionState.connected:
self.logger.warning("Already connected unable to start")
return False
self.state = ConnectionState.connecting
self.logger.debug("start url:" + self.url)
self._ws = websocket.WebSocketApp(
self.url,
header=self.headers,
on_message=self.on_message,
on_error=self.on_socket_error,
on_close=self.on_close,
on_open=self.on_open,
)
# sslOptions={"cert_reqs": ssl.CERT_NONE if self.verify_ssl else {}}
sslOptions= { }
# https://docs.python.org/3/library/ssl.html#ssl.VerifyMode
if self._ssl is not None:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_cert_chain(certfile=self._ssl["cert"], keyfile=self._ssl["key"])
context.load_verify_locations(self._ssl["cert"])
sslOptions = {
"cert_reqs": ssl.CERT_REQUIRED,
"ca_certs": self._ssl["serverCert"],
"ssl_version": ssl.PROTOCOL_TLSv1_2,
"certfile": self._ssl["cert"],
"keyfile": self._ssl["key"],
"password": self._ssl["secret"],
"ssl_context": context
}
print(sslOptions)
self._thread = threading.Thread(
target=lambda: self._ws.run_forever(
sslopt=sslOptions
))
self._thread.daemon = True
self._thread.start()
return True
def negotiate(self):
negotiate_url = Helpers.get_negotiate_url(self.url)
self.logger.debug("Negotiate url:{0}".format(negotiate_url))
response = requests.post(
# negotiate_url, headers=self.headers, verify=self.verify_ssl)
negotiate_url, headers=self.headers, verify=self._ssl["serverCert"])
self.logger.debug(
"Response status code{0}".format(response.status_code))
if response.status_code != 200:
raise HubError(response.status_code)\
if response.status_code != 401 else UnAuthorizedHubError()
data = response.json()
if "connectionId" in data.keys():
self.url = Helpers.encode_connection_id(
self.url, data["connectionId"])
# Azure
if 'url' in data.keys() and 'accessToken' in data.keys():
Helpers.get_logger().debug(
"Azure url, reformat headers, token and url {0}".format(data))
self.url = data["url"]\
if data["url"].startswith("ws") else\
Helpers.http_to_websocket(data["url"])
self.token = data["accessToken"]
self.headers = {"Authorization": "Bearer " + self.token}
ofc you have to add the ssl
parameter here and there. But that got our job done.
In addition, if you use an ASP.NET backend, you might use the following config:
services.AddCertificateForwarding(c => c.CertificateHeader = "Certificate");
...
app.UseCertificateForwarding();
In that case, you don't need to extend the library. Instead, you can make use of the optional header:
clientCertFileHandler = open('C:/cert/localhost.crt')
clientCert = clientCertFileHandler.read()
clientCertAscii = clientCert.encode('ascii')
clientCertBase64 = base64.b64encode(clientCertAscii)
clientCertHeader = clientCertBase64.decode()
clientCertFileHandler.close()
print(clientCertHeader)
appSrv = HubConnectionBuilder()\
.with_url(AppSrvUrl + ':' + str(AppSrvPort) + '/' + AppSrvHub,
options={"verify_ssl": False,
"headers": {
"Certificate": clientCertHeader
}})\
.configure_logging(logging.DEBUG)\
Is your feature request related to a problem? Please describe. Due to cert authentication, we require to attach a custom certificate for the client.
Describe the solution you'd like An option to provide a custom certificate. E.g.:
Describe alternatives you've considered I took a look at the implementation details of this project. I did encounter
request
does not implement client certs. StackOverflow exampleAdditional context Add any other context or screenshots about the feature request here.