For my current project, I have to document and define how to call web services on a Windows based SAS analytics server and so I’ve been working on installing a SAS virtual machine server which I can use in my development lab. I battled this installation for several days until I finally figured it out. Well, that’s not really true. I didn’ figure it out on my own, it took a ticket to SAS support to figure out how to install that monolithic beast of 13GB of installation files and laybrinths of documentation from http://support.sas.com.
So now I was at the point where I needed to create a web service on my SAS server. Creating a web service on SAS means that you take a SAS stored proc, not to be confused with an RDBMS stored proc, and use the SAS Enterprise Console to deploy it as a web service. When the Enterprise Console deploys a web service, it will call some services within a web service file named WebServiceMaker.asmx which got installed with SAS. I was excited that I had got to this point because after all, the SAS vendor themselves helped me to install everything I needed. I figured all I needed to do was deploy the SP as a web servce but when I went to deploy, I got this error: Microsoft.Web.Services3.Security.SecurityFault: The security token could not be authenticated or authorized —> System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
Well, so much for my faith in things automatically working if I get them installed with the support of the vendor.
I took a look at the WebServiceMaker.asmx and found it contained these 3 services:
The SAS Enterprise Console indicated it was calling ListWebServices as the first step in deployment so I set about creating a quick .Net console application which called the same service to see what would happen. I knew that WebServiceMaker.asmx was secured with WSE 3.0 and that I wouldn’t be able to call it without passing sometype of credentials but I called it without creds anyway to see what would happen. Of course I got an exception but after researching the error and refreshing my knowledge of WSE, I realized that I needed to pass a UsernameToken in the WS-Security header. I then setup my console app to provide the UsernameToken with some credentials which I assumed would work. These credentials were the sasadm account and password., but I got the same error. Just to make sure I was covering all of the angles, I placed a completely random id and password in the token and called the service again and got the same error.
I then fired up the Fiddler HTTP debugger on my SAS server to get a look at the SOAP request coming out of the Enterprise Console. But I couldn’t get Fiddler to show me the HTTP packets going to and from localhost, even with the tips I found for solving this type of problem during a Google search. So I then installed Microsoft’s netmon tool and was able to get a packet trace of these communications. I had to save the netmon packet trace and open it up with Notepad in order to locate and extract the SOAP request, which Fiddler would have made a piece of cake, but I was able to get it and create an XML file with the SOAP request.
Next I fired up Fiddler on my development workstation and pulled the SOAP request which my console app was sending to the ListWebServices web service. I compared the two requests and found that the two were not syntactically the same but I *think* they were more or less functionaly the same. Here is a list of the diffferences in the two requests:
- .Net used a prefix of soap and the SAS EC (Enterprise Console) used a prefix of soapenv. I was sure this was the problem but according to this article: http://www.experts-exchange.com/Programming/Languages/Java/Q_22096454.html it is probably not.
- The SAS EC placed a funky looking id in the element. I had connected to the SAS EC as the sasadm user so I expected to see the text ‘sasaadm’ here but instead it placed this text: element: sasadm@!*(generatedpassworddomain)*! into the element. My .Net console app was placing the text sasadm into this element.
- The password being passed from the .Net application was cleartext. So the Type attribute of the element was ‘PasswordText’ . The SAS EC used the same Type attribute but the password was definitely not cleartext, it appeared to be some hexadecimal value. This document: http://www.oasis-open.org/committees/wss/documents/WSS-Username-02-0223-merged.pdf indicates a Type attribute of ‘PasswordText’ may not be an actual password but rather a password equivilant. The .Net application was sending a and a element within the element.
My next blog post will discuss my research of these differences. At this point, I don’t know that this will actually solve anything since, like I said, I believe the two requests are functionally the same and they both produce the same error from calling the web service.