CMDBuild Forum

Problems using CMDBuild webservice

Has anyone been able to successfully implement a PHP client for the CMDBuild webservice?  I have been trying for a few days to learn with WSO2 WSF/PHP using the example from the webservice documentation but I am not able to get it working at all.

 

My sample script right now is:

<?php

 

$RequestPayloadString = <<<XML

<ns1:getCardList xmlns:ns1="http://soap.services.cmdbuild.org">

  <className>Department</className>

</ns1:getCardList>

XML;

 

$url = "http://SERVER:PORT/cmdbuild/services/soap/Webservices";

$Security_options = array ("useUsernameToken" => TRUE);

$Policy = new WSPolicy(array("security" => $Security_options));

$Security_token = new WSSecurityToken(array ("user" => "admin", "password" => "admin", "passwordType" => "Digest"));

$Client = new WSClient(array ("to" => $url, "policy" => $Policy, "securityToken" => $Security_token));

try {

  $response = $Client->request($RequestPayloadString);

} catch (Exception $e) {

  if ($e instanceof WSFault) {

    printf("Soap Fault: %s\n", $e->Reason);

  } else {

    printf("Message = %s\n",$e->getMessage());

  }

}

 

The code you have posted looks right…
What problems you have
experienced? Can you provide us any detail of what doesn’t work and possibly also a log to undestand what’s wrong?

Best regards.

 

I'm in a similar situation, trying an example like this.    All I get is:

PHP Fatal error:  Uncaught exception 'Exception' with message 'Error , NO Response Received' in /tmp/test.php:26
Stack trace:
#0 /tmp/test.php(26): WSClient->request(Object(WSMessage))
#1 {main}
  thrown in /tmp/test.php on line 26

Trying to hit my server using http://localhost:8080/cmdbuild/services/soap/Webservices.  I'm not sure how to debug this, whether this is an exception from the server or an installation issue.  Nothing in Tomcat logs.  CMDBuild otherwise (from Web UI standpoint) looks ok.  Any advice?

-Alan

 

Previously Tecnoteca wrote:

The code you have posted looks right...
What problems you have
experienced? Can you provide us any detail of what doesn't work and possibly also a log to undestand what's wrong?

Best regards.

 

 

I've become convinced that the problem is interaction between the WSO2 PHP plugin version 2.1.0 and CMDBuild, specifically in terms of the WSsecurity stuff (Rampart).  I believe I have, based on a lot of Google-ing, replaced the policy mechanism with something that at least gets the request to the server, and an attempt by the server to respond.  But I believe the request is not accepted by the client because the server end does not provide the correct security headers for the client.

 

Notably, log messages in the client side that look like this:

[Mon Oct 31 18:17:47 2011] [debug] phase.c(202) Invoke the handler AddressingOutHandler within the phase MessageOut

[Mon Oct 31 18:17:47 2011] [info]  Starting addressing out handler

[Mon Oct 31 18:17:47 2011] [debug] addr_out_handler.c(137) No action present. Stop processing addressing

[Mon Oct 31 18:17:47 2011] [debug] phase.c(202) Invoke the handler RampartOutHandler within the phase Security

[Mon Oct 31 18:17:47 2011] [warning] msg_ctx.c(1384) RampartClientConfiguration not set in message context

[Mon Oct 31 18:17:47 2011] [error] rampart_out_handler.c(130) [rampart]Security header building failed.

[Mon Oct 31 18:17:47 2011] [error] phase.c(224) Handler RampartOutHandler invoke failed within phase Security

 

Is there any way the developers can post a working example for all of out here that really need to prove the API is usable and working?  Anything would be appreciated.

-Alan

 

Attached you can find a sample PHP command line script to query CMDBuild SOAP services. It DOES NOT work with WSO2 WSF/PHP 2.1.0 because there are some issues with the PasswordDigest authentication. The working configuration was:
  • CentOS 5.5 i386
  • WSO2 WSF/PHP 2.0.0
  • PHP Command Line Interface 5.1.6
Please note that you can also use plaintext passwords (hopefully on an encrypted connection) by setting the property force.ws.password.digest=false in the configuration file auth.conf (it is commented out by default).

Paolo

cmdbuild-php-wsclient.zip (5.6 KB)

Thank you for the information, especially the auth.conf pointer.

 

What plans are there to update the API to use "contemporary" SOAP libraries?  Unfortunately PHP 5.1 is quite old, and the WSO2 2.0.x version do not build against PHP 5.3.x. 

 

Also, my experiments so far with using Python SUDS against the API, with cleartext authentication, yield parse syntax errors on the responses from your API.

 

Are there near-term plans to address accessibility issues in the SOAP API (making it more usable to popular SOAP client APIs)?  Is there any plan to replace or augment the SOAP API with a REST version, that more clients could really use?

-Alan

 

 

Previously Alan wrote:

What plans are there to update the API to use "contemporary" SOAP libraries?  Unfortunately PHP 5.1 is quite old, and the WSO2 2.0.x version do not build against PHP 5.3.x.

CMDBuild APIs (the WSDL) are dynamically generated by Apache CXF, a mature and maintained services framework. I think that the issues with WSO2 2.1.x rely on the digested autentication mechanisms, so with plain text passwords you should be fine. Since we don't maintain any PHP library, that example was all I could provide. It might work on newer versions of WSO2 with only small changes. Anyway, in my opinion, it is not an API issue if the client library doesn't implement correctly the standards. As far as I remember WSO2 2.1.x crashed badly far before sending the SOAP message.

Also, my experiments so far with using Python SUDS against the API, with cleartext authentication, yield parse syntax errors on the responses from your API.

Can you post an example of those errors? (request, response, client error)

Are there near-term plans to address accessibility issues in the SOAP API (making it more usable to popular SOAP client APIs)?  Is there any plan to replace or augment the SOAP API with a REST version, that more clients could really use?

We are regularly updating the CXF server library but it's impossible, and pointless, to address every client library issue. Feel free to discuss, and perhaps contribute to the project if you spot an issue.

 

In the next year, we are scheduled to work on the web services, possibly issuing a new API. Due to time constraints, it's anyway unlikely that a REST interface will be added any time soon. Of course this is not a technical issue.

Paolo

>>Anyway, in my opinion, it is not an API
issue if the client library doesn’t implement correctly the standards.
As far as I remember >>WSO2 2.1.x crashed badly far before sending the
SOAP message.


If one tweaks the policy file it uses, one can get farther.  But there are deep problems it seems in the WSO2 PHP 2.1 library and I’ve not gotten a successful call yet.  And unless you regress back to PHP 5.1, you have little choice but use 2.1.

Philosophically, there is an API issue if there exist virtually no clients in the real world that can access (use) the API.  I have determined that the problem with python SUDS (0.4 current) is that the CMDBuild API is answering in MTOM (xop+xml) responses, which SUDS does not implement.  I have not yet found a Python or Ruby SOAP client library that implements MTOM response handling, which is a real issue.  This is in addition to not many services implementing WSSE Digest auth compatible with the CMDBuild service (but at least this can be worked around with the plaintext password change, and running SSL).

Is there a way to disable MTOM responses in CMDBuild, or in the CXF options?

One can note that the WSO2 libraries supposedly implement WSSE Digest and MTOM support.  But you should note their code is, perhaps except for the Java and PHP instances, abandoned.  The C, Python, and Ruby bindings have not been updated since 2008-2009, and most will not even build or run with current Ruby and Python versions.  I work in a Python/Ruby shop, and there’s little desire to add Java to the mix.

A Python example with SUDS 0.4, and an example of the issue.  Note the plugin which prints the response body as received, before SAX XML parsing:

from suds.client import Client
from suds.plugin import *
from suds.wsse import *
from suds import WebFault

class MyPlugin(MessagePlugin):
    def received(self, context):
        print “-- the reply, for SAX parsing:”
        print context.reply
        print "-- end of the reply, for SAX parsing:"

url = "http://localhost:8080/cmdbuild/services/soap/Webservices?wsdl"
client = Client(url, plugins=[MyPlugin()])
security = Security()
token = UsernameToken(‘admin’, ‘admin’)
security.tokens.append(token)
client.set_options(wsse=security)
print client.service.getCardList(‘Building’)

root@ops03:~/test# python pytest.py
– the reply, for SAX parsing:

–uuid:c9f58e57-8c1b-4bbf-8b6d-f8033fbab201
Content-Type: application/xop+xml; charset=UTF-8; type=“text/xml”;
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/”><soap:Body><ns2:getCardListResponse xmlns:ns2=“http://soap.services.cmdbuild.org”><ns2:return><ns2:cards><ns2:attributeList><ns2:name>Description</ns2:name><ns2:value>Data Center</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Id</ns2:name><ns2:value>64</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Notes</ns2:name><ns2:value></ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>IdClass</ns2:name><ns2:value>19425</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Code</ns2:name><ns2:value>DC</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Address</ns2:name><ns2:value>Main street 16</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>BeginDate</ns2:name><ns2:value>24/07/11 18:40:14</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Status</ns2:name><ns2:value>A</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>ZIP</ns2:name><ns2:value>58213</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>City</ns2:name><ns2:value>London</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>User</ns2:name><ns2:value>admin</ns2:value></ns2:attributeList><ns2:attributeList><ns2:code>25</ns2:code><ns2:name>Country</ns2:name><ns2:value>England</ns2:value></ns2:attributeList><ns2:beginDate>2011-07-24T18:40:14.637Z</ns2:beginDate><ns2:className>Building</ns2:className><ns2:id>64</ns2:id><ns2:metadata><ns2:key>runtime.privileges</ns2:key><ns2:value>write</ns2:value></ns2:metadata><ns2:user>admin</ns2:user></ns2:cards><ns2:cards><ns2:attributeList><ns2:name>Description</ns2:name><ns2:value>Office Building A</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Id</ns2:name><ns2:value>73</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Notes</ns2:name><ns2:value></ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>IdClass</ns2:name><ns2:value>19425</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Code</ns2:name><ns2:value>B1</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Address</ns2:name><ns2:value>Liverpool Street 18</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>BeginDate</ns2:name><ns2:value>24/07/11 18:41:12</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Status</ns2:name><ns2:value>A</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>ZIP</ns2:name><ns2:value>12100</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>City</ns2:name><ns2:value>London</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>User</ns2:name><ns2:value>admin</ns2:value></ns2:attributeList><ns2:attributeList><ns2:code>25</ns2:code><ns2:name>Country</ns2:name><ns2:value>England</ns2:value></ns2:attributeList><ns2:beginDate>2011-07-24T18:41:12.996Z</ns2:beginDate><ns2:className>Building</ns2:className><ns2:id>73</ns2:id><ns2:metadata><ns2:key>runtime.privileges</ns2:key><ns2:value>write</ns2:value></ns2:metadata><ns2:user>admin</ns2:user></ns2:cards><ns2:cards><ns2:attributeList><ns2:name>Description</ns2:name><ns2:value>Office Building B</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Id</ns2:name><ns2:value>76</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Notes</ns2:name><ns2:value></ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>IdClass</ns2:name><ns2:value>19425</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Code</ns2:name><ns2:value>B2</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Address</ns2:name><ns2:value>Liverpool Street 22</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>BeginDate</ns2:name><ns2:value>24/07/11 18:41:06</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>Status</ns2:name><ns2:value>A</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>ZIP</ns2:name><ns2:value>12100</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>City</ns2:name><ns2:value>London</ns2:value></ns2:attributeList><ns2:attributeList><ns2:name>User</ns2:name><ns2:value>admin</ns2:value></ns2:attributeList><ns2:attributeList><ns2:code>25</ns2:code><ns2:name>Country</ns2:name><ns2:value>England</ns2:value></ns2:attributeList><ns2:beginDate>2011-07-24T18:41:06.636Z</ns2:beginDate><ns2:className>Building</ns2:className><ns2:id>76</ns2:id><ns2:metadata><ns2:key>runtime.privileges</ns2:key><ns2:value>write</ns2:value></ns2:metadata><ns2:user>admin</ns2:user></ns2:cards><ns2:totalRows>3</ns2:totalRows></ns2:return></ns2:getCardListResponse></soap:Body></soap:Envelope>
–uuid:c9f58e57-8c1b-4bbf-8b6d-f8033fbab201–
– end of the reply, for SAX parsing:
Traceback (most recent call last):
  File “pytest.py”, line 24, in <module>
    print client.service.getCardList(‘Building’)
  File “/usr/lib/pymodules/python2.7/suds/client.py”, line 542, in call
    return client.invoke(args, kwargs)
  File “/usr/lib/pymodules/python2.7/suds/client.py”, line 602, in invoke
    result = self.send(soapenv)
  File “/usr/lib/pymodules/python2.7/suds/client.py”, line 647, in send
    result = self.succeeded(binding, reply.message)
  File “/usr/lib/pymodules/python2.7/suds/client.py”, line 684, in succeeded
    reply, result = binding.get_reply(self.method, reply)
  File “/usr/lib/pymodules/python2.7/suds/bindings/binding.py”, line 145, in get_reply
    replyroot = sax.parse(string=reply)
  File “/usr/lib/pymodules/python2.7/suds/sax/parser.py”, line 136, in parse
    sax.parse(source)
  File “/usr/lib/python2.7/xml/sax/expatreader.py”, line 107, in parse
    xmlreader.IncrementalParser.parse(self, source)
  File “/usr/lib/python2.7/xml/sax/xmlreader.py”, line 123, in parse
    self.feed(buffer)
  File “/usr/lib/python2.7/xml/sax/expatreader.py”, line 211, in feed
    self._err_handler.fatalError(exc)
  File “/usr/lib/python2.7/xml/sax/handler.py”, line 38, in fatalError
    raise exception
xml.sax._exceptions.SAXParseException: <unknown>:2:0: syntax error

 

Previously Alan wrote:

Is there a way to disable MTOM responses in CMDBuild, or in the CXF options?
The configuration of CXF is in WEB-INF/org/cmdbuild/soapws.xml (will be in WEB-INF/classes/org/cmdbuild/soapws.xml in the next release) and MTOM is enabled by:

   <jaxws:binding>
      <soap:soapBinding mtomEnabled="true" version="1.2" />
   </jaxws:binding>
 
Paolo
 
P.S.
We had to tweak a little the unmaintained ZSI 2.1-a1 Python library to use it with CMDBuild. The patch is attached and also online: https://svn.plone.org/svn/collective/tecnoteca.plonecmdbuild/trunk/tecnoteca/plonecmdbuild/extra/cmdbuild-zsi.patch

cmdbuild-zsi-patch (4.0 KB)
Now,the problem is that it  responses 'The security token could not be authenticated or authorized'', and I do not know how to authorize using security?
 
 
Here is my codes .
 
Code based python (in linux_centos6.3 64):
 
#! /usr/bin/python
# -*- coding:utf-8 -*-
import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
 
from suds.client import Client
from suds.plugin import *
from suds.wsse import *
from suds import WebFault
 
 
url = "http://http://10.200.190.2:8080/services/soap/Webservices?wsdl"
client = Client(url)
security = Security()
token = UsernameToken('xuezhe.zhang', 'mypwd')
security.tokens.append(token)
client.set_options(wsse=security)
print client.service.getCardList('Building')
 
 
The responses:
 
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedAuthentication</faultcode><faultstring>The security token could not be authenticated or authorized</faultstring></soap:Fault></soap:Body></soap:Envelope>
Traceback (most recent call last):
  File "cmdb_webservice2.py", line 20, in <module>
    print client.service.getCardList('Building')
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 542, in __call__
    return client.invoke(args, kwargs)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 602, in invoke
    result = self.send(soapenv)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 649, in send
    result = self.failed(binding, e)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 702, in failed
    r, p = binding.get_fault(reply)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/bindings/binding.py", line 265, in get_fault
    raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'The security token could not be authenticated or authorized'
 
I fixed same problem by patching suds lib. 
 
Patch for suds-0.4:
145,146c145
<         reply_body = reply[reply.find('<soap'):reply.find('</soap:Envelope>')+len('</soap:Envelope>')]
<         replyroot = sax.parse(string=reply_body)
---
>         replyroot = sax.parse(string=reply)
diff -r venv_sentry/lib/python2.7/site-packages/suds/wsse.py v_wg_fabric/lib/python2.7/site-packages/suds/wsse.py
174d173
<         p.set("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText")
179d177
diff -r venv_sentry/lib/python2.7/site-packages/suds/wsse.py v_wg_fabric/lib/python2.7/site-packages/suds/wsse.py
179d178
<             n.set("EncodingType", 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary') 
 
 
And below fully work test example python client for cmdbuild:  
 
from suds.client import Client
from suds.wsse import Security, UsernameToken
 
c = Client("http://cmdbuild.iv:8080/fabdev/services/soap/Private?wsdl")
 
s = Security()
t = UsernameToken(USR, PSW)
s.tokens.append(t)
c.set_options(wsse=s)
 
print c.service.getCardList("B")
print c.service.getCardList("B", {'name':'Code'})
print c.service.getCard("B", 40039, {'name':'Code', 'value':'expBb'})
print c.service.createCard(new_b)
print c.service.createCard(new_a)
 
print c.service.deleteCard("B", 40031)
print c.service.getCardHistory("B", 40031)
 
print c.service.updateCard("B", 40039, [{'name':'Notes', 'value':'1'}])
print c.service.updateCard({'id':40039, 'className':"B",  'attributeList':{'name':'Description', 'value':'Updated description1'}})
print c.service.updateCard("A", 40041, [{'name':'Notes', 'value':'1'}])
 
Previously yanqu wrote:
Now,the problem is that it  responses 'The security token could not be authenticated or authorized'', and I do not know how to authorize using security?
 
 
Here is my codes .
 
Code based python (in linux_centos6.3 64):
 
#! /usr/bin/python
# -*- coding:utf-8 -*-
import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
 
from suds.client import Client
from suds.plugin import *
from suds.wsse import *
from suds import WebFault
 
 
url = "http://http://10.200.190.2:8080/services/soap/Webservices?wsdl"
client = Client(url)
security = Security()
token = UsernameToken('xuezhe.zhang', 'mypwd')
security.tokens.append(token)
client.set_options(wsse=security)
print client.service.getCardList('Building')
 
 
The responses:
 
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedAuthentication</faultcode><faultstring>The security token could not be authenticated or authorized</faultstring></soap:Fault></soap:Body></soap:Envelope>
Traceback (most recent call last):
  File "cmdb_webservice2.py", line 20, in <module>
    print client.service.getCardList('Building')
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 542, in __call__
    return client.invoke(args, kwargs)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 602, in invoke
    result = self.send(soapenv)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 649, in send
    result = self.failed(binding, e)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 702, in failed
    r, p = binding.get_fault(reply)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/bindings/binding.py", line 265, in get_fault
    raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'The security token could not be authenticated or authorized'
 

 

What I found is that you have to use digest passwords. Take a look at the code at https://gist.github.com/copitux/5029872, I ended up using a slightly modified version of that and then you just call UsernameDigestToken(user, password)

instead of UsernameToken().

 

One other gocha -- I had to call c.set_options(retxml=True) to keep from getting a suds/sax error (xml.sax._exceptions.SAXParseException: <unknown>:1:0: syntax error

). For some reason adding that option gets rid of the error.

 

Here is the code I ended up using (hopefully not too badly formatted... and with the real user credentials removed). Note: it doesn't actually do anything yet other than dump the XML for my buildings.

 

#!/usr/bin/python

import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)

from suds.client import Client
from suds.wsse import Security, UsernameToken
from base64 import b64encode
try:
    from hashlib import sha1,md5
except:
    from sha import new as sha1
    from md5 import md5

# From https://gist.github.com/copitux/5029872
# Need to send a digest password to CMDBuild, plain text won't work
class UsernameDigestToken(UsernameToken):
    """
    Represents a basic I{UsernameToken} WS-Security token with password digest
    @ivar username: A username.
    @type username: str
    @ivar password: A password.
    @type password: str
    @ivar nonce: A set of bytes to prevent reply attacks.
    @type nonce: str
    @ivar created: The token created.
    @type created: L{datetime}
   
    @doc: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
    """
   
    def __init__(self, username=None, password=None):
        UsernameToken.__init__(self, username, password)
        self.setcreated()
        self.setnonce()
 
    def setnonce(self, text=None):
        """
        Set I{nonce} which is arbitraty set of bytes to prevent
        reply attacks.
        @param text: The nonce text value.
        Generated when I{None}.
        @type text: str
       
        @override: Nonce save binary string to build digest password
        """
        if text is None:
            s = []
            s.append(self.username)
            s.append(self.password)
            s.append(self.sysdate())
            m = md5()
            m.update(':'.join(s))
            self.raw_nonce = m.digest()
            self.nonce = b64encode(self.raw_nonce)
        else:
            self.nonce = text
           
    def xml(self):
        usernametoken = UsernameToken.xml(self)
        password = usernametoken.getChild('Password')
        nonce = usernametoken.getChild('Nonce')
        created = usernametoken.getChild('Created')
        password.set('Type', 'http://docs.oasis-open.org/wss/2004/01/'
                     'oasis-200401-wss-username-token-profile-1.0'
                     '#PasswordDigest')
        s = sha1()
        s.update(self.raw_nonce)
        s.update(created.getText())
        s.update(password.getText())
        password.setText(b64encode(s.digest()))
        nonce.set('EncodingType', 'http://docs.oasis-open.org/wss/2004'
                  '/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary')
        return usernametoken

c = Client("http://localhost:8080/cmdbuild/services/soap/Webservices?wsdl")
 
# Authenticate to CMDBuild SOAP service
s = Security()
t = UsernameDigestToken('admin', 'admin')

s.tokens.append(t)
c.set_options(wsse=s)
c.set_options(retxml=True)
 
# Query the list of buildings
print c.service.getCardList("Building")

 

 

 

Previously yanqu wrote:
Now,the problem is that it  responses 'The security token could not be authenticated or authorized'', and I do not know how to authorize using security?
 
 
Here is my codes .
 
Code based python (in linux_centos6.3 64):
 
#! /usr/bin/python
# -*- coding:utf-8 -*-
import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
 
from suds.client import Client
from suds.plugin import *
from suds.wsse import *
from suds import WebFault
 
 
url = "http://http://10.200.190.2:8080/services/soap/Webservices?wsdl"
client = Client(url)
security = Security()
token = UsernameToken('xuezhe.zhang', 'mypwd')
security.tokens.append(token)
client.set_options(wsse=security)
print client.service.getCardList('Building')
 
 
The responses:
 
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedAuthentication</faultcode><faultstring>The security token could not be authenticated or authorized</faultstring></soap:Fault></soap:Body></soap:Envelope>
Traceback (most recent call last):
  File "cmdb_webservice2.py", line 20, in <module>
    print client.service.getCardList('Building')
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 542, in __call__
    return client.invoke(args, kwargs)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 602, in invoke
    result = self.send(soapenv)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 649, in send
    result = self.failed(binding, e)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 702, in failed
    r, p = binding.get_fault(reply)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/bindings/binding.py", line 265, in get_fault
    raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'The security token could not be authenticated or authorized'
 

 

To follow-up to my own post, the call to c.set_options(retxml=True) is only partially a solution. While it lets the suds call complete, it doesn't parse the response so you have to do it yourself. The better fix is to replace the parser, as the problem is that the response from CMDBuild has headers and separators in it, for example:

DEBUG:suds.client:headers = {'SOAPAction': '""', 'Content-Type': 'text/xml; charset=utf-8'}
DEBUG:suds.client:http succeeded:
--uuid:11a08f19-4b78-4e38-a6cf-49b9779eb91b
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>...</soap:Body></soap:Envelope>
--uuid:11a08f19-4b78-4e38-a6cf-49b9779eb91b--

If you use a parser plugin to strip out just the XML, the sax parser will work fine.

 

Previously Daniel wrote:
What I found is that you have to use digest passwords. Take a look at the code at https://gist.github.com/copitux/5029872, I ended up using a slightly modified version of that and then you just call UsernameDigestToken(user, password)

instead of UsernameToken().

 

One other gocha -- I had to call c.set_options(retxml=True) to keep from getting a suds/sax error (xml.sax._exceptions.SAXParseException: <unknown>:1:0: syntax error

). For some reason adding that option gets rid of the error.

 

Here is the code I ended up using (hopefully not too badly formatted... and with the real user credentials removed). Note: it doesn't actually do anything yet other than dump the XML for my buildings.

 

#!/usr/bin/python

import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)

from suds.client import Client
from suds.wsse import Security, UsernameToken
from base64 import b64encode
try:
    from hashlib import sha1,md5
except:
    from sha import new as sha1
    from md5 import md5

# From https://gist.github.com/copitux/5029872
# Need to send a digest password to CMDBuild, plain text won't work
class UsernameDigestToken(UsernameToken):
    """
    Represents a basic I{UsernameToken} WS-Security token with password digest
    @ivar username: A username.
    @type username: str
    @ivar password: A password.
    @type password: str
    @ivar nonce: A set of bytes to prevent reply attacks.
    @type nonce: str
    @ivar created: The token created.
    @type created: L{datetime}
   
    @doc: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
    """
   
    def __init__(self, username=None, password=None):
        UsernameToken.__init__(self, username, password)
        self.setcreated()
        self.setnonce()
 
    def setnonce(self, text=None):
        """
        Set I{nonce} which is arbitraty set of bytes to prevent
        reply attacks.
        @param text: The nonce text value.
        Generated when I{None}.
        @type text: str
       
        @override: Nonce save binary string to build digest password
        """
        if text is None:
            s = []
            s.append(self.username)
            s.append(self.password)
            s.append(self.sysdate())
            m = md5()
            m.update(':'.join(s))
            self.raw_nonce = m.digest()
            self.nonce = b64encode(self.raw_nonce)
        else:
            self.nonce = text
           
    def xml(self):
        usernametoken = UsernameToken.xml(self)
        password = usernametoken.getChild('Password')
        nonce = usernametoken.getChild('Nonce')
        created = usernametoken.getChild('Created')
        password.set('Type', 'http://docs.oasis-open.org/wss/2004/01/'
                     'oasis-200401-wss-username-token-profile-1.0'
                     '#PasswordDigest')
        s = sha1()
        s.update(self.raw_nonce)
        s.update(created.getText())
        s.update(password.getText())
        password.setText(b64encode(s.digest()))
        nonce.set('EncodingType', 'http://docs.oasis-open.org/wss/2004'
                  '/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary')
        return usernametoken

c = Client("http://localhost:8080/cmdbuild/services/soap/Webservices?wsdl")
 
# Authenticate to CMDBuild SOAP service
s = Security()
t = UsernameDigestToken('admin', 'admin')

s.tokens.append(t)
c.set_options(wsse=s)
c.set_options(retxml=True)
 
# Query the list of buildings
print c.service.getCardList("Building")

 

 

 

Previously yanqu wrote:
Now,the problem is that it  responses 'The security token could not be authenticated or authorized'', and I do not know how to authorize using security?
 
 
Here is my codes .
 
Code based python (in linux_centos6.3 64):
 
#! /usr/bin/python
# -*- coding:utf-8 -*-
import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
 
from suds.client import Client
from suds.plugin import *
from suds.wsse import *
from suds import WebFault
 
 
url = "http://http://10.200.190.2:8080/services/soap/Webservices?wsdl"
client = Client(url)
security = Security()
token = UsernameToken('xuezhe.zhang', 'mypwd')
security.tokens.append(token)
client.set_options(wsse=security)
print client.service.getCardList('Building')
 
 
The responses:
 
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedAuthentication</faultcode><faultstring>The security token could not be authenticated or authorized</faultstring></soap:Fault></soap:Body></soap:Envelope>
Traceback (most recent call last):
  File "cmdb_webservice2.py", line 20, in <module>
    print client.service.getCardList('Building')
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 542, in __call__
    return client.invoke(args, kwargs)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 602, in invoke
    result = self.send(soapenv)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 649, in send
    result = self.failed(binding, e)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 702, in failed
    r, p = binding.get_fault(reply)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/bindings/binding.py", line 265, in get_fault
    raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'The security token could not be authenticated or authorized'
 

 

 

I am interested in this solution. Can you give an example?

Thanks

 

 

Previously Daniel wrote:

To follow-up to my own post, the call to c.set_options(retxml=True) is only partially a solution. While it lets the suds call complete, it doesn't parse the response so you have to do it yourself. The better fix is to replace the parser, as the problem is that the response from CMDBuild has headers and separators in it, for example:

DEBUG:suds.client:headers = {'SOAPAction': '""', 'Content-Type': 'text/xml; charset=utf-8'}
DEBUG:suds.client:http succeeded:
--uuid:11a08f19-4b78-4e38-a6cf-49b9779eb91b
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>...</soap:Body></soap:Envelope>
--uuid:11a08f19-4b78-4e38-a6cf-49b9779eb91b--

If you use a parser plugin to strip out just the XML, the sax parser will work fine.

 

Previously Daniel wrote:
What I found is that you have to use digest passwords. Take a look at the code at https://gist.github.com/copitux/5029872, I ended up using a slightly modified version of that and then you just call UsernameDigestToken(user, password)

instead of UsernameToken().

 

One other gocha -- I had to call c.set_options(retxml=True) to keep from getting a suds/sax error (xml.sax._exceptions.SAXParseException: <unknown>:1:0: syntax error

). For some reason adding that option gets rid of the error.

 

Here is the code I ended up using (hopefully not too badly formatted... and with the real user credentials removed). Note: it doesn't actually do anything yet other than dump the XML for my buildings.

 

#!/usr/bin/python

import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)

from suds.client import Client
from suds.wsse import Security, UsernameToken
from base64 import b64encode
try:
    from hashlib import sha1,md5
except:
    from sha import new as sha1
    from md5 import md5

# From https://gist.github.com/copitux/5029872
# Need to send a digest password to CMDBuild, plain text won't work
class UsernameDigestToken(UsernameToken):
    """
    Represents a basic I{UsernameToken} WS-Security token with password digest
    @ivar username: A username.
    @type username: str
    @ivar password: A password.
    @type password: str
    @ivar nonce: A set of bytes to prevent reply attacks.
    @type nonce: str
    @ivar created: The token created.
    @type created: L{datetime}
   
    @doc: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
    """
   
    def __init__(self, username=None, password=None):
        UsernameToken.__init__(self, username, password)
        self.setcreated()
        self.setnonce()
 
    def setnonce(self, text=None):
        """
        Set I{nonce} which is arbitraty set of bytes to prevent
        reply attacks.
        @param text: The nonce text value.
        Generated when I{None}.
        @type text: str
       
        @override: Nonce save binary string to build digest password
        """
        if text is None:
            s = []
            s.append(self.username)
            s.append(self.password)
            s.append(self.sysdate())
            m = md5()
            m.update(':'.join(s))
            self.raw_nonce = m.digest()
            self.nonce = b64encode(self.raw_nonce)
        else:
            self.nonce = text
           
    def xml(self):
        usernametoken = UsernameToken.xml(self)
        password = usernametoken.getChild('Password')
        nonce = usernametoken.getChild('Nonce')
        created = usernametoken.getChild('Created')
        password.set('Type', 'http://docs.oasis-open.org/wss/2004/01/'
                     'oasis-200401-wss-username-token-profile-1.0'
                     '#PasswordDigest')
        s = sha1()
        s.update(self.raw_nonce)
        s.update(created.getText())
        s.update(password.getText())
        password.setText(b64encode(s.digest()))
        nonce.set('EncodingType', 'http://docs.oasis-open.org/wss/2004'
                  '/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary')
        return usernametoken

c = Client("http://localhost:8080/cmdbuild/services/soap/Webservices?wsdl")
 
# Authenticate to CMDBuild SOAP service
s = Security()
t = UsernameDigestToken('admin', 'admin')

s.tokens.append(t)
c.set_options(wsse=s)
c.set_options(retxml=True)
 
# Query the list of buildings
print c.service.getCardList("Building")

 

 

 

Previously yanqu wrote:
Now,the problem is that it  responses 'The security token could not be authenticated or authorized'', and I do not know how to authorize using security?
 
 
Here is my codes .
 
Code based python (in linux_centos6.3 64):
 
#! /usr/bin/python
# -*- coding:utf-8 -*-
import logging
import datetime
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
 
from suds.client import Client
from suds.plugin import *
from suds.wsse import *
from suds import WebFault
 
 
url = "http://http://10.200.190.2:8080/services/soap/Webservices?wsdl"
client = Client(url)
security = Security()
token = UsernameToken('xuezhe.zhang', 'mypwd')
security.tokens.append(token)
client.set_options(wsse=security)
print client.service.getCardList('Building')
 
 
The responses:
 
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedAuthentication</faultcode><faultstring>The security token could not be authenticated or authorized</faultstring></soap:Fault></soap:Body></soap:Envelope>
Traceback (most recent call last):
  File "cmdb_webservice2.py", line 20, in <module>
    print client.service.getCardList('Building')
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 542, in __call__
    return client.invoke(args, kwargs)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 602, in invoke
    result = self.send(soapenv)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 649, in send
    result = self.failed(binding, e)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/client.py", line 702, in failed
    r, p = binding.get_fault(reply)
  File "/usr/lib/python2.6/site-packages/suds-0.4-py2.6.egg/suds/bindings/binding.py", line 265, in get_fault
    raise WebFault(p, faultroot)
suds.WebFault: Server raised fault: 'The security token could not be authenticated or authorized'