benkonrath / transip-api

Python implementation for the TransIP API
https://transip-api.readthedocs.io/en/latest/
MIT License
23 stars 23 forks source link

api calls involving lists. #52

Open mathijswesterhof opened 4 years ago

mathijswesterhof commented 4 years ago

I am currently experiencing issues with requests involving lists. Requests made to the transip api with string parameters like get_whois or get_info are working as intended but when i get a batch function i get the following error. File "/usr/local/lib/python3.7/dist-packages/transip/service/domain.py", line 25, in batch_check_availability return self._simple_request('batchCheckAvailability', domain_names) File "/usr/local/lib/python3.7/dist-packages/transip/client.py", line 202, in _simple_request return getattr(self.soap_client.service, method)(*args) File "/usr/local/lib/python3.7/dist-packages/suds/client.py", line 521, in __call__ return client.invoke(args, kwargs) File "/usr/local/lib/python3.7/dist-packages/suds/client.py", line 581, in invoke result = self.send(soapenv) File "/usr/local/lib/python3.7/dist-packages/suds/client.py", line 619, in send description=tostr(e), original_soapenv=original_soapenv) File "/usr/local/lib/python3.7/dist-packages/suds/client.py", line 670, in process_reply raise WebFault(fault, replyroot) suds.WebFault: Server raised fault: 'Exception received from JSON Server: Invalid API signature, signature does not match the request. (timestamp: 0.87884700 1572513446)' I have verified that my key and username are working and that the ip is whitelisted. I have created the input of the batch_check_availability like l = list('example.com','example.org','example.net') i also checked with a command in front of the credential mapper to check if it was a timeout. that is not the case in both direct and secondary aproach the batch assignment would fail. i hope you can help solve the issue for completeness i've uploaded the complete trace of the error transip_batch_error_log.txt

mathijswesterhof commented 4 years ago

I have contacted the Transip team about this issue. The issue lies within the signing of the message, the array of data send to create the call is used to sign the whole call. the soap part of that call seems to be correct. the sign however is not. cookie = self.build_cookie(mode=kwargs.get('mode', MODE_RO), method=method, parameters=args) will i investigate this further

if possible it would be great to post example usage of the api not using the cli but by calling it directly.

mathijswesterhof commented 4 years ago

the moment a list gets passed into a batch function it disapears when arrived at the cookie creator. i can subscribe this with an example. assume we have: li = list('addr.com', 'example.com') and we use it on the batch function client.batch_check_availability(li) which can be substituted with client._simple_request('batchCheckAvailability', li) _simple_request accepts (method, *args, **kwargs) and uses those to produce a cookie with cookie = self.build_cookie(mode=kwargs.get('mode', MODE_RO), method=method, parameters=args) here our list transforms into a tuple like this: (['addr.com', 'example.com'],) when the cookie is build it tries to sign it with the parameters like this message_to_sign = self._build_signature_message( service_name=self.service_name, method_name=method, timestamp=timestamp, nonce=nonce, additional=parameters ) the signature builder then uses that additional parameter to add it into the sign but that is where it goes wrong. for index, value in enumerate(additional): ... if isinstance(value, list): ... ... for entryindex, entryvalue in enumerate(value): ... ... ... if isinstance(entryvalue, SudsObject): ... ... ... ... for objectkey, objectvalue in entryvalue: ... ... ... ... ... objectvalue = convert_value(objectvalue) ... ... ... ... ... sign[str(index) + '[' + str(entryindex) + '][' + objectkey + ']'] = objectvalue ... elif isinstance(value, SudsObject): ... ... for entryindex, entryvalue in value: ... ... ... key = str(index) + '[' + str(entryindex) + ']' ... ... ... sign[key] = convert_value(entryvalue) ... else: ... ... sign[index] = convert_value(value) accepts the additional parameter and slices it into index and value where value is the normal list. the list passes the instance check on lists. then gets thrown away because it has no SudsObjects.

conclusion:

Question: What do we need to fill the Suds object with to get it accepted as valid cookie hash?

benkonrath commented 4 years ago

Could you try again with the latest release (2.1.0)? There's a fix for calls with list results and I'm curious if this also fixes your problem. Thanks.

websitefavourite commented 3 years ago

I'm also experiencing this issue

domains = ['test1.nl', 'test2.nl'] print(domain_service.batch_check_availability(domains))

results in: suds.WebFault: Server raised fault: 'Exception received from JSON Server: Invalid API signature, signature does not match the request. (timestamp: 0.97579900 1602590987)'

other non list calls are working fine