Skip to main content
Participant
April 17, 2012
Answered

WSDL ColdFusion version visible - need it hidden

  • April 17, 2012
  • 1 reply
  • 4225 views

I have a web service and the auto generated WSDL at http://mysite/webservice.cfc?wsdl includes the full ColdFusion version number in comments on the second line of the WSDL.
E.G. <!--WSDL created by ColdFusion version 9,0,1,274733-->

The example on http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-78a6.html shows the comment as:

<!--WSDL created by ColdFusion -->

Is there a production style setting that can be used to hide this version number when auto generating the WSDL?

Alternatively, is the auto generated WSDL stored temporarily on the CF server that can be read and edited onRequestStart and returned instead of the originally auto generated WSDL?

I know i can set the "wsdlFile" property to a specific WSDL file that I can edit to remove the version number in webservice.cfc but I wanted to avoid having to manually maintain the WSDL.

Thanks in advance for any assistane with this.

Tom

This topic has been closed for replies.
Correct answer CFBYSTANDER

If the application.cfc contains onRequest() and it is not deleted during onRequestStart() for WSDL requests then no output is rendered to the screen. This is because onRequest() expects a file to be included and none is. For displaying the generated WSDL I do not wish to include a template so I delete the method for requests for WSDL. If the application.cfc does not contain onRequest then the delete is not needed.

The locks are present because the application scope is not single threaded in onRequestStart().

The code does not do anything when the web service is actually invoked. It is only when the WSDL is requested that the code is processed. Since the documentation and the implementation of the web service are separate I don't think changing the way the WSDL is returned on the fly is a breach of the web service call contract.

The WSDL should change very rarely, I agree. Which is another reason for having the WSDL generated automatically as any manual processing would be needed so rarely that it could be forgotten about even though it could be well documented.

The issue with writing the WSDL to the file is that <cfcomponent> will only auto generate the WSDL if the wsdlFile attribute isn't present.

In order to have the <cfcomponent> auto generate the WSDL i'd need to deploy the <cfcomponent> without the wsdlFile attribute and then request it via cfhttp and then i'd need to write the WSDL, with CF version removed, to the server using cffile and then i'd need to alter the <cfcomponent> containing the remote function so that it contained the wsdlFile attribute. Since the production code is overwritten regularly with the code from our version control system this would mean adding a scheduled job to generate the wsdlFile. Also after any scheduled release the job would need to be run too as the WSDL file would be deleted during the release. Either that or the manual process would be needed across multiple CF servers and instances.

Having the WSDL modified when it is requested means the production code matches what's in version control and means I won't have to manually maintain any files. So, if the CFC changes and the auto generated WSDL changes those changes are available immediately and with no developer/admin effort.

Thank you for taking the time to look at this problem and look at the code I wrote as it has made me think about the details a lot more closely even though our solutions to the problem are ultimately quite different.

Cheers

Tom


There was an issue with the original solution where if you hit the page with enough simultaneous requests you would have application.InterceptWSDL defined even though you weren't the request that was calling CFHTTP. Whilst an unlikely problem it kind of defeats the purpose of not wanting to show the ColdFusion version and patch number in the WSDL for penetration testing purposes. I've bypassed that problem by ditching the application.interceptWSDL and using the userAgent attribute on CFHTTP. I normally avoid the CGI scope since it can vary by web server but in this case it seems the best solution. Here's the new code:

<cffunction name="onRequestStart" returnType="boolean" output="no">

<cfargument name="targetPage" type="string" required="true">

  <cfif listLast(arguments.targetPage,".") EQ "cfc" AND structkeyexists(url, "wsdl")>>

    <cfif cgi.User_Agent NEQ "UniqueWSDLIdentiferAgent">

      <!--- this will stop the cfhttp request calling itself since cgi.User_Agent will be changed for this request only --->

      <cfhttp useragent="UniqueWSDLIdentiferAgent" url="http://mysite#arguments.thePage#?wsdl" method="get" charset="utf-8" timeout="20" result="GeneratedWSDL" />

    </cfif>

    <cfif structKeyExists(variables, "GeneratedWSDL") and len(GeneratedWSDL.fileContent)>

      <cfprocessingdirective suppresswhitespace="Yes">

      <cfcontent type="text/xml; charset=utf-8">

      <cfoutput>

      #REReplaceNoCase(GeneratedWSDL.filecontent, "<!--WSDL created by ColdFusion [A-Z0-9 ,-->]*\r\n", "", "ALL")#

      </cfoutput>

      </cfprocessingdirective>

      <!--- without aborting here the auto generated WSDL is displayed --->

      <Cfabort>

    </cfif>

    <!--- if we don't delete onRequest then it will fire and no output will be rendered to the screen as no file will be included by onRequest(). This is because OnRequest() is being fired for the cfhttp request and this then stops further processing. --->

    <cfset structDelete(this, "onRequest")>

    <cfset structDelete(variables, "onRequest")>

  </cfif>

  <cfreturn true>

</cffunction>

Hope that helps anyone doing this in the future.

Cheers

Tom

1 reply

BKBK
Community Expert
Community Expert
April 19, 2012

CFBYSTANDER wrote:

I have a web service and the auto generated WSDL at http://mysite/webservice.cfc?wsdl includes the full ColdFusion version number in comments on the second line of the WSDL.
E.G. <!--WSDL created by ColdFusion version 9,0,1,274733-->

The example on http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859 461172e0811cbec22c24-78a6.html shows the comment as:

<!--WSDL created by ColdFusion -->

This is to be expected. It is traditional for text or code generators to include their signature. ColdFusion does it subtly, using a comment. Some generators actually include a 'live' header, comprising many lines!

Is there a production style setting that can be used to hide this version number when auto generating the WSDL?

Alternatively, is the auto generated WSDL stored temporarily on the CF server that can be read and edited onRequestStart and returned instead of the originally auto generated WSDL?

I haven't looked into the inner workings ColdFusion's WSDL generation, but experience tells me it is unlikely that ColdFusion maintains a temporary store for WSDLs. I expect a WSDL to be generated either on the fly or from cache.

That is also what you would hope for. You would want the WSDL to reflect changes you make in your CFC. Also, if you made no changes, you would want ColdFusion to use the cached version, instead of going to all the trouble of generating the WSDL again. 

I know i can set the "wsdlFile" property to a specific WSDL file that I can edit to remove the version number in webservice.cfc

That seems like a good workaround to me.

Added update:

I wanted to avoid having to manually maintain the WSDL.

Remember that the WSDL is available through, for example:

<cfhttp method="get" url="http://mysite/webservice.cfc?wsdl">

Participant
April 19, 2012

Thanks BKBK,

My original problem with using the result from cfhttp was that it would timeout as OnRequestStart would enter a continuous loop as each cfhttp call would call the cfhttp code again. I tried other URL variables but that causes CF to open the CFC explorer which ruled that out. After a bit more sleep i have now solved the problem.
What i've done is set an application variable on the first request and then call <cfhttp method="get" url="http://mysite/webservice.cfc?wsdl"> but then i check if that application variable is set and if it is i know that the request is from the 2nd request and that result.filecontent can then be used and the <!--WSDL created by ColdFusion version x.x.--> can be replaced and the application variable is deleted and then using cfcontent i can display the auto generated WSDL minus the CF version. It's a small processing overhead but resolves the issue that would have been highlighted during penetration testing.

I'll post the code once i've tidied (removed cflog etc) it up a bit in case it is useful for other CF developers. Also, other people looking at your code and providing feedback is always beneficial.

Cheers

Tom

BKBK
Community Expert
Community Expert
April 19, 2012

That is one fact you can count on: your solution will certainly help others.