| Issue 137: | Eclipse Plugin Enhancement: Allow username/password to be passed as part of webservice call. | |
| 1 person starred this issue and may be notified of changes. | Back to list |
It would be nice to be able to pass the username/password as part of the RemoteFacade webservice call from Eclipse. This would allow users who can't put the RemoteFacade behind basic auth to secure the webservice. See: http://groups.google.com/group/mxunit/browse_thread/thread/e384cb7779678e9b
Aug 7, 2008
Project Member
#1
marc.es...@gmail.com
Aug 7, 2008
Hey Marc, the more I think about this the more I realize this is an organizational issue I need to deal with on my end. For the record there is a way to do it with the existing stuff built in, just use basic auth over SSL. (I haven't tried it, but if basic auth works in the plugin I'm assuming basic auth over SSL will work as well.) The problem is, my server admins are reluctant to enable basic auth as they see it as a potential security issue, which it could be if not used over SSL. (Usernames and passwords are sent in clear text.) But again, this is my issue, not yours. As for the security issues of having a publicly accessible remotefacade.cfc, there are a few. First malicious users could gain insight into the design of your application. This obviously depends on your tests, and how useful that information may be is questionable, but there is the potential to expose a vulnerability via your tests. (Now I would argue if you are worried about security at all you shouldn't be developing on a publicly accessible development server, but...) Second, many of my unit tests run against the database, and a few are pretty resource intensive. I would think you could create a DOS attack or just generally mess with someone by pounding on the remotefacade.cfc. The best approach I think would be to have NTLM support, but I realize there are challenges there.
Aug 7, 2008
nathan,
ahhhh, i didn't understand that this was publicly accessible. I thought it was a
dev server inside your own environment. I understand that many government shops, and
military in particular, still require shared dev servers with ntlm auth even though
they're not publicly accessible.
As for the ntlm authentication, I'm going to assume you're using ntlmv2, and
unfortunately it looks like the only package out there that supports ntlmv2 is an
extremely expensive (5k or so if i remember correctly) package. the stuff in
httpclient, which i'm using in the plugin, only supports ntlmv1, which apparently
noone uses anyway. also from what i remember, the folks at apache working on axis and
httpclient have no intentions at all of providing ntlmv2 support.
a few things to consider if you want to try it out: every time you hit "run" on the
plugin view, here's what happens:
1) plugin calls startTestRun() from the remote facade, which returns a "test run key"
2) plugin passes that test run key back to the framework for every test it calls
3) plugin calls endTestRun() when all tests are complete.
possibly you could hook into this. maybe you change startTestRun() to return a custom
kind of key... instead of just a UUID, maybe it's a UUID + some special key. then,
in your executeTestCase(), you can look for that special token to be passed in the
testrunkey. if the token isn't present, then throw an error.
this way, even someone who knows that executeTestCase is a method in the framework
wouldn't be able to run it b/c they'd have ot know your special token.
the bad thing here is that that still leaves getComponentMethods() exposed because
that doesn't use any test run key. still... they'd have to be pretty good at guessing
the full path to your objects for this to be useful, and even then what they'd see is
a list of test names returned.
If none of this is sufficient, then we can talk more about passing the login
credentials in every webservice request. i'm not opposed to that since it does make
sense to me. largely the decisions to be made are around the obfuscation of the
credentials... is md5 checksum enough, for example? either case, it couldn't be clear
text, obviously. so it'd have to be encrypted in such a way that on the CF side,
you'd need to be able to encrypt a known set of credentials and compare them with the
encrypted credentials passed over the wire and confirm they match. i.e. not cfif
arguments.password eq "nathanIsCool" but instead cfif arguments.password eq
hash("nathanIsCool")
here though, you'd probably have problems with this in a team environment b/c you'd
need to compare the credentials against a list of people's stuff... unless you just
had a group username/password to use which would make sense in your case.
Let me know if you want to pursue this further!
Owner:
marc.esher
Aug 7, 2008
I don't think it is necessary to pursue this further. Thanks for entertaining the idea though.
Aug 7, 2008
sure thing Nathan. If you change your mind, don't hesitate to post back here!
Aug 7, 2008
Marc, I thought about this a little more and basic auth sends the username/password over the wire for every request, so I just needed to trigger basic auth via ColdFusion. Placing the attached Application.cfc in the same folder as my "empty" remotefacade.cfc triggers basic authentication. This should work, however loading the test methods seems to fail with the following error: "Exception message trying to connect to url https://seven-dev.wharton.upenn.edu/stat/tests/remotefacade.cfc?wsdl is: org.xml.sax.SAXParseException: Premature end of file." I can get a list of tests, just not a list of methods. Any ideas?
Aug 8, 2008
off the top of my head, no. a few questions though: 1) is your server a unix server by any chance? possibly you're hitting this bug if it is: https://code.google.com/p/mxunit/issues/detail?id=138 2) if you hit the remotefacade.cfc?wsdl&method=ping in your browser, does it prompt you for username and password? and if you type them in, do you get a response? 3) in eclipse, if you go to window -- show view -- PDE Runtime -- Error Log, do you see any entries in the error log that have any more detail? thanks nathan.
Aug 8, 2008
1) I'm on windows.
2) Yes I can access the remotefacade.cfc via my browser. I get a username/password
prompt and after logging in I see the correct headers being sent.
3) Looking at this log I can see no webservice calls are working. I have errors
similar to:
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: org.xml.sax.SAXParseException: Premature end of file.
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:org.xml.sax.SAXParseException: Premature end
of file.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:345)
at
org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
at org.apache.axis.Message.getSOAPEnvelope(Message.java:424)
at org.apache.axis.server.AxisServer.initSOAPConstants(AxisServer.java:345)
at org.apache.axis.server.AxisServer.invoke(AxisServer.java:279)
at org.apache.axis.transport.http.AxisServlet.doPost(AxisServlet.java:699)
at coldfusion.xml.rpc.CFCServlet.doAxisPost(CFCServlet.java:163)
at coldfusion.filter.AxisFilter.invoke(AxisFilter.java:43)
at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:219)
at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:51)
at coldfusion.filter.PathFilter.invoke(PathFilter.java:86)
at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:69)
at
coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
at coldfusion.xml.rpc.CFCServlet.invoke(CFCServlet.java:106)
at coldfusion.xml.rpc.CFCServlet.doPost(CFCServlet.java:182)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:78)
at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:259)
at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:541)
at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:204)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
{http://xml.apache.org/axis/}hostname:xxxxxxxxxxxxxxxxxxxxxxx
I'm actually testing with the getServerType method and one thing I have noticed,
accessing the remotefacade via my browser uses a HTTP GET request. The eclipse
plugin uses a HTTP/XML POST and ColdFusion seems to choke on this. The error message
above (Premature end of file) is actually being return by ColdFusion.
Aug 8, 2008
hey nathan, in the mxunit/samples directory there's a file named "RemoteFacadeTester.cfm". Can you open that up, plop your URL into there, add your username/password to the cfinvoke tag, and see what you get?
Aug 8, 2008
I get the same error:
Cannot perform web service invocation executeTestCase.
The fault returned when invoking the web service operation is:
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: org.xml.sax.SAXParseException: Premature end of file.
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:org.xml.sax.SAXParseException: Premature end
of file.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at javax.xml.parsers.SAXParser.parse(SAXParser.j... ''
The error occurred in C:\inetpub\wwwroot\mxunit\samples\RemoteFacadeTester.cfm: line 34
32 : <!--- now run that same component using the remote facade --->
33 : <h1>running test through remote facade</h1>
34 : <cfinvoke webservice="#remoteURL#" method="executeTestCase"
componentName="#mycomponent#" methodNames="#myfunction#" TestRunKey=""
returnvariable="remoteRunResults" username="username" password="password">
35 :
36 : <cfdump var="#remoteRunResults#" label="remoteRunResults" expand="false">
Aug 8, 2008
whew. i was hoping you'd say that! Because that means it's not a plugin problem per se. now, as to figure out how to figure it out... do you have any tcp monitoring tools? I think the thing is we need to see the stuff going back and forth over the wire. can you do that?
Aug 8, 2008
It is definitely not a plugin problem. I've already looked at the HTTP traffic using
Wireshark and it looks fine. The problem seems to be with ColdFusion. If I call the
GetHttpRequestData() function in either Application.cfm or Application.cfc's
onRequestStart method ColdFusion chokes on the HTTP/XML POST. If I take the call to
GetHttpRequestData() it works fine.
This works:
<cffunction name="onRequestStart" returnType="boolean" output="true">
<cfargument type="String" name="targetPage" required=true/>
<cfset var requestData = "" />
<cfreturn true />
</cffunction>
This fails:
<cffunction name="onRequestStart" returnType="boolean" output="true">
<cfargument type="String" name="targetPage" required=true/>
<cfset var requestData = GetHttpRequestData() />
<cfreturn true />
</cffunction>
Aug 8, 2008
I don't have time to investigate further at the moment, but I'll be looking into this some more over the weekend.
Aug 8, 2008
fascinating. tell me: is there anything you'd like me to do to help you figure this out?
Aug 8, 2008
sounds good.
Aug 8, 2008
If you know how to get the request header data without using GetHttpRequestData() that would help. If you don't know how to do that off the top of your head I can look it up. I'll definitely let you know what I find out.
Aug 8, 2008
i believe you can use getSoapRequestHeader() for this.
Aug 8, 2008
OK, so it seams calling GetHttpRequestData() causes soap requests to bomb out. The attached Application.cfc sucessfully implements basic authentication for the remotefacade.cfc by reading the Authorization HTTP header via GetPageContext(). This sample has the username and password hardcoded as "username" and "password" but you could easily modify it to look up credentials wherever you may have them stored. Note, for basic authentication to be secure you must use it over SSL. Thanks for your help with this Marc.
Aug 8, 2008
nice! So you're all set then?
Aug 8, 2008
Yep.
Mar 28, 2009
(No comment was entered for this change.)
Status:
Fixed
|