Hi.
I’m having some issues with logging in to a Milestone server with python using the SOAP API.
In our dev environment, everything seems to work fine. Eg:
D:\>type mtest.py
import requests
import uuid
from configparser import ConfigParser
from requests.auth import HTTPBasicAuth
from zeep import Client
from zeep.transports import Transport
if __name__ == “__main__”:
cp = ConfigParser()
cp.read(‘milestone.conf’)
username = cp[‘Milestone’][‘USERNAME’]
password = cp[‘Milestone’][‘PASSWORD’]
hostname = cp[‘Milestone’][‘HOSTNAME’]
session = requests.Session()
session.auth = HTTPBasicAuth(username, password)
client = Client(f’http://{hostname}/ManagementServer/ServerCommandService.svc?singleWsdl’,
transport=Transport(session=session))
print(‘[+] Connected to Server’)
guid = uuid.uuid4()
login_info = client.service.Login(guid, ‘’)
token = login_info[‘Token’]
print(f’[+] Token = {token.replace(hostname, “XXXXXX.XXX.XXX”)}')
exit(0)
D:\>python mtest.py
[+] Connected to Server
[+] Token = TOKEN#a2eaee5d-38d9-4a00-a18d-9727d91728b0#XXXXXX.XXX.XXX//ServerConnector#
D:\>
However, when we run the same code in production:
ks0mh:/tmp> cat mtest.py
import requests
import uuid
from configparser import ConfigParser
from requests.auth import HTTPBasicAuth
from zeep import Client
from zeep.transports import Transport
if __name__ == “__main__”:
cp = ConfigParser()
cp.read(‘milestone.conf’)
username = cp[‘Milestone’][‘USERNAME’]
password = cp[‘Milestone’][‘PASSWORD’]
hostname = cp[‘Milestone’][‘HOSTNAME’]
session = requests.Session()
session.auth = HTTPBasicAuth(username, password)
client = Client(f’http://{hostname}/ManagementServer/ServerCommandService.svc?singleWsdl’,
transport=Transport(session=session))
print(‘[+] Connected to Server’)
guid = uuid.uuid4()
login_info = client.service.Login(guid, ‘’)
token = login_info[‘Token’]
print(f’[+] Token = {token.replace(hostname, “XXXXXX.XXX.XXX”)}')
exit(0)
ks0mh:/tmp> python3 mtest.py
[+] Connected to Server
Traceback (most recent call last):
File “mtest.py”, line 23, in
login_info = client.service.Login(guid, ‘’)
File “/home/ks0mh/.local/lib/python3.6/site-packages/zeep/proxy.py”, line 51, in __call__
kwargs,
File “/home/ks0mh/.local/lib/python3.6/site-packages/zeep/wsdl/bindings/soap.py”, line 135, in send
return self.process_reply(client, operation_obj, response)
File “/home/ks0mh/.local/lib/python3.6/site-packages/zeep/wsdl/bindings/soap.py”, line 229, in process_reply
return self.process_error(doc, operation)
File “/home/ks0mh/.local/lib/python3.6/site-packages/zeep/wsdl/bindings/soap.py”, line 333, in process_error
detail=fault_node.find(“detail”, namespaces=fault_node.nsmap),
zeep.exceptions.Fault: Value cannot be null.
Parameter name: parameters
ks0mh:/tmp>
The only differences I am aware of are the following:
- The dev environment script is being run in Windows, while the production one is being run in Linux. I don’t believe this should have any impact on the outcome.
- The Windows version of python is 3.11.1, while the Linux version is 3.6.15; this could potentially be an issue, however at this point I believe it’s more likely to be something else
- The dev environment version of Milestone is 23.1.56.1, while the one running in production is 22.3.207.3
We have tried using a different SOAP client library, with the same results.
We have tried Ntlm authentication instead of Basic, and the outcome was the same.
Do you have any idea what could be causing this discrepancy in results? Any suggestion on what else to try would be welcome. We have tried everything we could think of, both reasonable and ridiculous ideas, short of upgrading the Linux version of python, because of internal policy.
Thanks!





