Closed bbartling closed 6 months ago
@stan-janssen any chance for a tip? Thanks!!
I stumbled on this issue because I'm trying to do something similar. I came to the conclusion that it should be possible to run the OpenADR server without HTTPS, but that the current implementation does not actually verify any messages if you run the server over HTTP.
If you run the server without any credentials (OpenADRClient(ven_name=..., vtn_url=...)
and OpenADRServer(vtn_id='myvtn', ven_lookup=ven_lookup
). With the logging level set to debug (openleadr.enable_default_logging(level=logging.DEBUG
), you can see a message like the following:
<?xml version="1.0" encoding="utf-8"?>
<oadr:oadrPayload
xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07">
<oadr:oadrSignedObject
xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07" oadr:Id="oadrSignedObject">
<oadr:oadrCreatePartyRegistration ei:schemaVersion="2.0b"
xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
<requestID
xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">7bec6c43-9525-4c5a-a5a0-ad4e541084e0
</requestID>
<oadr:oadrProfileName>2.0b</oadr:oadrProfileName>
<oadr:oadrTransportName>simpleHttp</oadr:oadrTransportName>
<oadr:oadrTransportAddress>None</oadr:oadrTransportAddress>
<oadr:oadrReportOnly>false</oadr:oadrReportOnly>
<oadr:oadrXmlSignature>false</oadr:oadrXmlSignature>
<oadr:oadrVenName>ven_name</oadr:oadrVenName>
<oadr:oadrHttpPullModel>true</oadr:oadrHttpPullModel>
</oadr:oadrCreatePartyRegistration>
</oadr:oadrSignedObject>
</oadr:oadrPayload>
If you create the client and an HTTP server like in the python script below, the public keys are included in the XML request body (shown below, abbreviated), which can be validated, but aren't. I can put any certificate file in the client without the client complaining at all.
server = OpenADRServer(
vtn_id='myvtn',
ven_lookup=ven_lookup,
cert=server_certfile,
key=server_keyfile,
# server does not have an argument that allows it to validate incoming messages, only incoming HTTP traffic
)
client = OpenADRClient(
ven_name='ven_name',
vtn_url='http://localhost:8080',
cert=client_certfile,
key=client_keyfile,
ca_file=server_ca_file, # this does not seem to be used
)
<?xml version="1.0" encoding="utf-8"?>
<oadr:oadrPayload
xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07">
<ds:SignedInfo>
...
</ds:SignedInfo>
<ds:SignatureValue>XzKr...4Q==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MII...xdM=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object Id="prop">
<ds:SignatureProperties>
<ds:SignatureProperty Id="myid" Target="#mytarget">
<dsp:ReplayProtect
xmlns:dsp="http://openadr.org/oadr-2.0b/2012/07/xmldsig-properties">
<dsp:timestamp>2024-01-16T10:39:40.617950Z</dsp:timestamp>
<dsp:nonce>42d126a4a90e4a5cba6867f3bbbf2a0b</dsp:nonce>
</dsp:ReplayProtect>
</ds:SignatureProperty>
</ds:SignatureProperties>
</ds:Object>
</ds:Signature>
<oadr:oadrSignedObject
xmlns:oadr="http://openadr.org/oadr-2.0b/2012/07" oadr:Id="oadrSignedObject">
<oadr:oadrCreatePartyRegistration ei:schemaVersion="2.0b"
xmlns:ei="http://docs.oasis-open.org/ns/energyinterop/201110">
<requestID xmlns="http://docs.oasis-open.org/ns/energyinterop/201110/payloads">2dac3875-5567-435c-b206-7b7dcdd0e3d4 </requestID>
<oadr:oadrProfileName>2.0b</oadr:oadrProfileName>
<oadr:oadrTransportName>simpleHttp</oadr:oadrTransportName>
<oadr:oadrTransportAddress>None</oadr:oadrTransportAddress>
<oadr:oadrReportOnly>false</oadr:oadrReportOnly>
<oadr:oadrXmlSignature>false</oadr:oadrXmlSignature>
<oadr:oadrVenName>ven_name</oadr:oadrVenName>
<oadr:oadrHttpPullModel>true</oadr:oadrHttpPullModel>
</oadr:oadrCreatePartyRegistration>
</oadr:oadrSignedObject>
</oadr:oadrPayload>
@laurens-teirlynck thanks for the tips... does that seem like a viable option if TLS is handled by "Let Encrypt" or something similar and then still do message signing in the way that you showed me? And the message signing is bi-directional right? Server verifies client and client verifies server...
I dug a bit deeper into the code. Signature validation happens https://github.com/OpenLEADR/openleadr-python/blob/main/openleadr/messaging.py#L101-L113. This function is called by the client and server, so it's indeed bi-directional.
However, the server calls this inside the authenticate_message function, but only if request.secure
is True, which only happens if the server is running over HTTPS.
The client does seem to validate the message over HTTP: https://github.com/OpenLEADR/openleadr-python/blob/main/openleadr/client.py#L908
The messages are signed correctly, but the validation doesn't seem correct. The verify function invocation seems to just check that the XML message was signed by a valid certificate, not necessarily a certificate you trust. You would need to pass in a ca-cert.pem
to the verify function (I think).
Hello,
I am encountering an issue with message signing in OpenLEADR and seek guidance on its implementation over HTTP.
I followed the instructions in the OpenLEADR documentation for message signing and successfully generated key.pem and cert.pem files. However, I ran into problems when testing with the one-minute
client.py
andserver.py
examples onlocalhost
.The primary issue seems to be the absence of a ca.crt file, which the system appears to expect but is not generated by the provided bash script in the documentation. The error log indicates an attempt to load a CA certificate for SSL/TLS verification
(ssl_context.load_verify_locations(self.ca_file))
, suggesting that the system is set up for SSL and x509 message signing.I am currently trying to understand if OpenLEADR supports message signing over plain HTTP, or if it requires the TLS features inherently for secure communication. If I had a production VTN server with a dashboard running Let's Encrypt for TLS, but I am interested in knowing if message signing with just
key.pem
andcert.pem
is viable for VEN-VTN communication via OpenLEADR with TLS being handled by Let's Encrypt.For context, here's how I configured the
client.py
andserver.py
(both on localhost):client.py:
server.py
Upon running these, the client-side encounters the mentioned issue.
Any insights or tips on whether OpenLEADR message signing can operate over HTTP without a CA certificate, or if HTTPS is mandatory, would be greatly appreciated.
Thank you! @dyreby