SOAP web service uri or namespace format - python

So I have seen SOAP client programs with namespace and url for python
and using uri and proxy for perl such as below
python soap client:
#!/usr/bin/python
import sys
from SOAPpy import SOAPProxy
option = sys.argv[1]
serverUrl='http://localhost:9000'
namespace='urn:/Date'
server = SOAPProxy(serverUrl, namespace)
response = server.dateInfo(option)
# read out the response
if (response == None):
print "Call returned error."
sys.exit(1)
print "Currently server date and time is " + response
perl soap client:
#!perl -w
use SOAP::Lite;
$soap_response = SOAP::Lite
-> uri('http://www.soaplite.com/Demo')
-> proxy('http://services.soaplite.com/hibye.cgi')
-> languages();
#res = $soap_response->paramsout;
$res = $soap_response->result;
print "Result is $res, outparams are #res\n";
Now here in first, namespace is urn:/Date
and in second program uri is http://www.soaplite.com/Demo.
I know that uri and namespace are words used to represent the same i.e. namespace used by SOAP to register a service.
My question is that whether the format used to name it
i.e. urn:... or http://... mandatory
or can I simply use something like testwebservice to register web service

The namespace name is an absolute IRI. (An IRI is basically an URI with support for non-ASCII characters.) Any absolute IRI. The scheme (http, urn, etc) doesn't matter. It can't be testwebservice since that's not a valid absolute IRI (or URI).
The namespace name is only used for identification purposes. It isn't used for resource retrieval, so using an HTTP IRI that would return 404 is perfectly fine.

Related

Zeep with namespace(?) variables

I have an XML/WCF API I need to implement something against. The API client library is only provided as c# in Windows and our company does not do either c# or Windows. I am now experimenting with Python and zeep. The api is Symmetry access control system API if anyone is interested.
I can connect to the server and read the wsdl structure. This works:
URL='https://localhost/smsXMLWebService/SMSXMLWebService.svc?singleWsdl'
URL2='https://localhost/smsXMLWebService/smsXMLWebService.svc'
session = Session()
session.verify = False
transport = Transport(session=session)
self.client = zeep.Client(URL, transport=transport)
self.service = self.client.create_service('{http://tempuri.org/}WSHttpBinding_ISMSXMLWebService', URL2)
Now everything from that point forward will require login to the platform. In the example c# code this is done as follows:
G4TAPI = new SMSXMLWebServiceClient();
G4TAPI.ClientCredentials.UserName.UserName = txtUserName.Text
G4TAPI.ClientCredentials.UserName.Password = txtPassword.Text.ToLower();
G4TAPI.G4TLogin();
My self.service has now G4TLogin() call and it seems to attempt to connect when I wireshark the traffic. But how do I set the username and password as they are not given as parameters to G4TLogin() method?
This does not work:
self.service.ClientCredentials.UserName.UserName = "api"
This is very much out of my comfort zone and I may be using incorrect terminology here. Any ideas?
The error message is
AttributeError: Service has no operation 'ClientCredentials'
When using Zeep make sure to study the namespaces in WSDL URL, using
python -mzeep "YourWsdlUrlGoesHere"
Get the parameters and make a Python dictionary from them (in my case facing C#, including username and password in the dictionary) note that one might need to make nested dictionary like in my case.
from requests import Session
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
from zeep import Client
from zeep.transports import Transport
request = { "Credential":{"Username": "yourusername",
"Password": "yourpassword"},
"RN": "150147119"
}
session = Session()
client = Client('http://your url and wsdl../Invoice.svc?Wsdl',transport=Transport(session=session))
r = client.service.NameOfYourService(request)
print(r)
Do not pass user and password in Zeep formal format. Passing the dictionary worked for me.
In my case the WSDL suggested user and password be in credential and a string be passed in RN and finally all be passed in a one variable.

How can I get crypto keys via SL api as in portal?

I'm trying to get the cryptographic keys just like portal, but I can't make my mask work, can someone tell me what's wrong with the following request, btw I am using the following url
https://sldn.softlayer.com/reference/services/softlayer_security_certificate_request/getsslcertificaterequests
and jic python api client is used and also rest requests can work for me to get the socket layers.
mask = "mask[accountId, certificateSigningRequest, certificateAuthorityName, id]
response = client['SoftLayer_Security_Certificate_Request'].getsslcertificaterequests()
I also want to find how to search the virtual ips associated to the certificates but I don't find what api method does what i need.
Your current code will retrieve only one of the certificates and not the stored security certificates, in order to make your mask work you need to add close the string with " double quote, and the method you are calling should be getSslCertificateRequests, see below:
accountId = 202768 #change this value
mask = "mask[accountId, certificateSigningRequest, certificateAuthorityName, id]"
response = client['SoftLayer_Security_Certificate_Request'].getSslCertificateRequests(accountId)
Currently the portal use SoftLayer_Account::getSecurityCertificate to retrieve the stored security certificates including SSL, use the following Python script:
import SoftLayer
from pprint import pprint as pp
USERNAME = 'set-me'
# Endpoint url that contains all the Api Services.
API_KEY = 'set-me'
# Generate one for you or your users, or view yours at
https://control.softlayer.com/account/users
client = SoftLayer.create_client_from_env(username=USERNAME,
api_key=API_KEY)
accountService = client['SoftLayer_Account']
try:
""""
getSecurityCertificates() retrieves stored security certificates (ie. SSL)
"""""
result = accountService.getSecurityCertificates()
pp(result)
except SoftLayer.SoftLayerAPIError as e:
""""
If there was an error returned from the SoftLayer API then bomb out with the
error message.
"""""
print("Unable to retrieve the Account's stored security certificates (i.e. SSL) . %s %s " % (e.faultCode, e.faultString))
To find the virtual ip addresses associated you should use the method getAdcLoadBalancers and send the id value obtained in the previous method, try this Rest request.
https://[username]:[apiKey]#api.softlayer.com/rest/v3.1/SoftLayer_Account/getAdcLoadBalancers?objectFilter={"adcLoadBalancers":{"securityCertificateId":{"operation":[id]}}}
Remember to change the username and apiKey for valid credentials, and the id mentioned above to retrieve the associated load balancer ip addresses.

Execute an OpenWhisk Action from within a Python Action on Bluemix

I've written a Python action on Bluemix OpenWhisk, and I need to call another action (actually a binding to a public package) from within this action. A sequence won't do it, because I need to call it a varying number of times with different parameters depending on the input.
How to invoke openwhisk action within openwhisk platform on bluemix? mentions how to do it from JavaScript, but the OpenWhisk package doesn't seem to be available for Python.
Actions can be invoked using a HTTP request to the platform API. The Python runtime in OpenWhisk includes the requests library for making HTTP calls.
Here's an example of an action that calls another (child) in the same namespace.
import os
import requests
APIHOST = os.environ.get('__OW_API_HOST')
NAMESPACE = os.environ.get('__OW_NAMESPACE')
USER_PASS = os.environ.get('__OW_API_KEY').split(':')
def main(params):
action = 'child'
url = APIHOST + '/api/v1/namespaces/' + NAMESPACE + '/actions/' + action
response = requests.post(url, data=params, params={'blocking': 'true'}, auth=(USER_PASS[0], USER_PASS[1]))
print(response.json())
return {"text": "invoked!"}
Swagger documentation for full API is available here.
There is an open issue to create a Python client library to make this easier.

Is there a way to provide an external WSDL file to a Python Suds client

I am working with a SOAP service where the project provides an external WSDL file. I am using Python + Suds to connect to the service. I run into issues because the (https) service URL looks like:
/sipxconfig/services/UserService?wsdl
But the WSDL ath that URL does not match the external WSDL file that is provided by the project. The SOAP document returned does match the external WSDL file. So my suds client raises a fault.
I have so far managed to work around this by writing a suds plugin to "correct" the SOAP XML returned so that it matches the dynamically created WSDL (at the URL). However, I was hoping there was a way to feed the subs client the external WSDL file and then switch it to using the URL for the service.
I tried something like this:
wsdl_file = os.path.abspath(args.wsdl_file)
client = Client("file://%s" % wsdl_file, transport=t, username=sip_user, password=sip_pwd, doctor=doctor)
client.set_options(location=url)
#Get the results.
user_search = client.factory.create("UserSearch")
user_search.byUserName = args.find_user
user_search.byFuzzyUserNameOrAlias = args.fuzzy
user_search.byGroup = args.group
result = client.service.findUser(user_search)
#^^^
#Error here!
But it ultimately results in a MethodNotFound exception.
I run netstat in another terminal, and I can see that the client is not making a network connection to the external service.
Has anyone else managed to feed Suds WSDL from a file?
Thanks,
Carl
So I determined I was on the correct track, but my SOAP service had multiple ports. I needed to do the following:
wsdl_file = os.path.abspath(args.wsdl_file)
client = Client("file://%s" % wsdl_file, transport=t, username=sip_user, password=sip_pwd, doctor=doctor)
client.set_options(location=url)
#Get the results.
user_search = client.factory.create("UserSearch")
user_search.byUserName = args.find_user
user_search.byFuzzyUserNameOrAlias = args.fuzzy
user_search.byGroup = args.group
result = client.service['UserService'].findUser(user_search)
# ^^^^^^^^^^^^^^^
# This was the missing bit that threw me off!
Thanks,
Carl

namespaces in SOAPpy not working as expected

I'm having an issue correctly interfacing with a SOAP API running on Axis2:
What happens is I should call the login method with two arguments (loginName and password) and it returns an authentication token that I will use for subsequent interaction.
#!/usr/bin/python
from SOAPpy import SOAPProxy
s_user = 'Administrator'
s_pass = 'securityThroughObscurity'
s_host = '192.168.76.130:8998'
namespace = 'http://bcc.inc.com/IncSecurity'
url = 'http://' + s_host + '/axis2/services/IncSecurityService'
DHCPServ = SOAPProxy(url, namespace)
DHCPServ.config.dumpSOAPOut = 1
DHCPServ.config.dumpSOAPIn = 1
DHCPResp = DHCPServ.login(loginName=s_user, password=s_pass)
The Axis2 server on the other side returns an XML error stating Data element of the OM Node is NULL. Looking at the Axis2 logs, I see the error is adb_login.c(383) non nillable or minOuccrs != 0 element loginName missing
I then packet captured the login XML from a known working Java client versus the XML from this client and these are the differences between the two:
SOAPpy:
<ns1:login xmlns:ns1="http://bcc.inc.com/IncSecurity" SOAP-ENC:root="1">
<password xsi:type="xsd:string">securityThroughObscurity</password>
<loginName xsi:type="xsd:string">Administrator</loginName>
</ns1:login>
Java:
<ns2:login xmlns:ns2="http://bcc.inc.com/IncSecurity">
<ns2:loginName>Administrator</ns2:loginName>
<ns2:password>securityThroughObscurity</ns2:password>
</ns2:login>
So this means that for some reason (probably related to my lack of knowledge in Python and SOAPpy) the namespace is not being applied to the variables being used in the login method, so by all accounts they don't actually exist and the error is warranted.
Also, it seems to be flipping the variables around and putting the password before loginName but I don't think that matters much.
What am I doing wrong?
Looks like it's a known bug in SOAPPy, someone has suggested a simple patch: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=523083
Alternately (assuming you have access to the service WSDL), SOAPPy lets you specify a WSDL instead of just a namespace. This looks like it will provide better namespace information to the envelope generation code. http://diveintopython.net/soap_web_services/introspection.html
Finally, if SOAPPy just isn't working for you, try Suds (it's better documented than SOAPPy).
from suds.client import Client
from suds.wsse import *
client = Client(WSDL_LOCATION)
guid = client.service.someFunctionName("a string argument", 42)
Good luck!

Categories

Resources