The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Coldfusion and WHM API

Discussion in 'cPanel Developers' started by paulmccarthy, Oct 26, 2010.

  1. paulmccarthy

    paulmccarthy Member

    Joined:
    Oct 26, 2010
    Messages:
    5
    Likes Received:
    0
    Trophy Points:
    1
    Good evening,

    I have a quick question - I just got off the phone to Hostgator and they told me that I couldn't use the WHM API because I was creating the request in Coldfusion and not PHP.

    To me this doesn't make much sense - I thought the whole point of an API is to allow interactivity between different languages and platforms etc?

    I have to admit, I'm fairly new to this - but the guy at the other end of the phone was less than convincing so I was hoping that someone may be able to shed some light on this for me!?

    Here's the setup:-

    I have a membership site on a Microsoft box - this is where the requests will be sent from. On a separate server, I have a Hostgator reseller account with WHM installed (version 11.26.20).

    The idea is that members of my membership site can automatically create a hosting account that comes free with the membership.

    My current coldfusion script spits out this error:-

    "Other Error: COM.Allaire.ColdFusion.HTTPFailure

    * Message: Connection Failure: Status code unavailable"

    Which concerns me!

    So, Coldfusion + WHM - is it possible?

    Thanks in advance!!!!
    Paul
     
  2. MattDees

    MattDees cPanel Product Owner
    Staff Member

    Joined:
    Apr 29, 2005
    Messages:
    417
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Our APIs work over basic HTTP POST/GET transactions, so any language capable of doing HTTP requests can work with our APIs.

    That being said, some languages can be more difficult than others due to variances in how HTTP is handled between different clients.

    I have never had to work with our APIs from coldfusion so I am not aware what you may have to encounter, but if you have any problems please open a thread.
     
  3. purdue512

    purdue512 Registered

    Joined:
    Oct 27, 2010
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    1
    I don't see why this would be a problem. The idea that the API call would HAVE to be PHP defeats much of the reasons APIs were invented.

    We use ColdFusion extensively and have never hit an API we couldn't work with. We probably have over 20 APIs under our belt. That being said, there is rarely ColdFusion support or examples.

    Can you post a little more detail about what you are trying / getting back. Perhaps I can help.
     
  4. paulmccarthy

    paulmccarthy Member

    Joined:
    Oct 26, 2010
    Messages:
    5
    Likes Received:
    0
    Trophy Points:
    1
    Hi Purdue,

    That's exactly what I thought APIs were used for - I tried explaining this several times to the Hostgator rep but I got the same answer - it can't be done!

    So I went and tried anyway :)

    I really appreciate you offering to help out - thank you!

    Here's my code:-

    Code:
    <cfset #whmusername# = "whmuser">
    <cfset #whmhash# = "hash code here">
    
    <cfset #query# = "https://hostip:2087/json-api/createacct?username=rogers2&plan=whmuser_Member&ip=n&password=testpass&contactemail=tom@lootnier.com&domain=testdomain2.com">
    
    <cfset #whmhash# = REReplace(#whmhash#,"(\r|\n)","","all") >
    
    <cfhttp url=#query# throwonerror="false" username=#whmusername# password=#whmhash# >
    
    <cfif #cfhttp.StatusCode# neq "200 OK">
    <cfset #error#="cfhttp threw error "&#cfhttp.StatusCode#&#cfhttp.errorDetail#&" for "&#query# >
    <cfthrow detail= #error# />
    <cfelse>
    <cfoutput>
    #cfhttp.filecontent#
    </cfoutput>
    And here's what I get in return:-

    Other Error: Application

    cfhttp threw error Connection Failure. Status code unavailable.I/O Exception: peer not authenticated for https://hostip:2087/json-api/create...ail=paul@krystal.co.uk&domain=testdomain2.com


    Any ideas you have would be great!

    I have a feeling that this might have something to do with the SSL certificate not being listed as being signed by a trusted source and that I might have to import the PEM file into the JRE library. That's what I'm working on doing next - it's a bit of a stab in the dark though!

    Thanks in advance Purdue!
    Paul
     
  5. sirdopes

    sirdopes Well-Known Member
    PartnerNOC

    Joined:
    Sep 25, 2007
    Messages:
    141
    Likes Received:
    0
    Trophy Points:
    16
    The ssl that is installed for cpanel is from a trusted source but is set to the hostname of the server. You can use the hostname so you don't get an error about the ssl. I've never used coldfusion before but I just installed it and am seeing if I can get it working. Have you tried it on port 2086 without the ssl instead?
     
  6. paulmccarthy

    paulmccarthy Member

    Joined:
    Oct 26, 2010
    Messages:
    5
    Likes Received:
    0
    Trophy Points:
    1
    Hi Sirdopes,

    Thanks for your reply -

    Right, I've had some success here!

    So, I've connected to the API and carried out some instructions (account creation etc) successfully! However, here's the thing, I can only connect using port 2086 over standard HTTP and when I send my unencrypted password directly! Not ideal :D

    So here's a couple of things:-

    1) When I take the code for my successful 2086 connection (with hardcoded password) and change to https and 2087 then I get the "Peer not authenticated" - as I mentioned above.

    I have a feeling that this has something to do with the SSL certificate not being listed in the keystore...

    2) When I take the code for my successful 2086 connection and use my remote access key (hash)...I get a "403 Forbidden" message.


    If I could get one of the above sorted then I lessen my chances of a hacking! 2 of the above would mean I'd have the added benefit of sleeping at night :)

    Ideally the SSL needs to be sorted, which is why I'm messing about with this:- Using Keytool to Import SSL Certificates into Sun JDK - TalkingTree.com

    Cheers Sirdopes - I appreciate you looking into this :)
    Best Regards,
    Paul
     
  7. paulmccarthy

    paulmccarthy Member

    Joined:
    Oct 26, 2010
    Messages:
    5
    Likes Received:
    0
    Trophy Points:
    1
    I've tried setting that to the hostname - unfortunately I don't think that's the issue.

    Have a look at the post in the link above and have a look at the keystore issue that other Coldfusion developers have been getting...I think that's my problem
     
  8. paulmccarthy

    paulmccarthy Member

    Joined:
    Oct 26, 2010
    Messages:
    5
    Likes Received:
    0
    Trophy Points:
    1
    Update:-

    I have connected to the WHM API with the hash key now.

    Here is the complete script:-

    Code:
    <cfset #whmusername# = "Insert WHM User Name Here">
    <cfset #whmhash# = "Insert Remote Access Key Here">
    
    <cfset #query# = "hostname:2086/json-api/listaccts">
    
    <cfset #whmhash# = REReplace(#whmhash#,"(\r|\n)","","all") >
    
    <cfhttp url=#query# throwonerror="false" method="get">
    <cfhttpparam type="header" name="Authorization" value="WHM #whmUser#:#whmhash#"> 
    </cfhttp>
    
    <cfdump var="#CFHTTP#">
    
    <cfif #cfhttp.StatusCode# neq "200 OK">
    <cfset #error#="cfhttp threw error "&#cfhttp.StatusCode#&#cfhttp.errorDetail#&" for "&#query# >
    <cfthrow detail= #error# /><br><br>
    
    <cfelse>
    <cfoutput>
    #cfhttp.filecontent#
    </cfoutput>
    </cfif>

    This was the key element that I was missing:-

    Code:
    <cfhttpparam type="header" name="Authorization" value="WHM #whmUser#:#whmhash#"> 
    Now I just need to figure out the SSL issue!
     
  9. openmind

    openmind Member

    Joined:
    Oct 30, 2007
    Messages:
    24
    Likes Received:
    0
    Trophy Points:
    1
    You gotta love Hostgator for talking balls as normal ;)

    I've been playing with this this morning and I've got the basis of a custom tag going now for interfacing with WHM via ColdFusion MX. The custom tag is as follows:

    Code:
    <!---
    Custom tag for interfacing with WHM
    ---->
    <cfprocessingdirective suppresswhitespace="yes">
    	<!---required attributes for all calls--->
    	<cfparam name="reqatt" default="whmhost,whmuser,whmhash,RequestType,function,result">
    	<!---timeout for the request in seconds--->
    	<cfparam name="whmtimeout" default="20">
    	<!---Response Handler--->
    	<cfset Response=structnew()>
    	<cftry>
    		<!---trim all attributes--->
    		<cfloop collection="#attributes#" item="Key">
    			<cfset attributes[Key]=Trim(attributes[Key])>
    		</cfloop>
    		<!---check for the required attributes--->
    		<cfloop list="#reqatt#" index="varname">
    			<cfset varval="attributes." & varname>
    			<cfif NOT IsDefined(varval)>
    				<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' is missing.">
    			</cfif>
    			<cfif Evaluate(varval) EQ "">
    				<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' must not be empty.">
    			</cfif>
    		</cfloop>
    		<!---ensure the RequestType is either xml-api or json-api--->
    		<cfif attributes.RequestType NEQ "xml-api" AND attributes.RequestType NEQ "json-api">
    			<cfthrow type="cf_whm.InvalidAttribute" message="The RequestType attribute must be set to either xml-api or json-api">
    		</cfif>
    		<!---trim all breaks from the hash--->
    		<cfset whmhash=REReplace(attributes.whmhash,"(\r|\n)","","all") >
    		<!---set the base query url--->
    		<cfset whmurl=attributes.whmhost & "/" & attributes.RequestType & "/" & attributes.function>
    		<!---handler for additional options--->
    		<cfparam name="whmquery" default="">
    		<!---WHM Functions--->
    		<cfswitch expression="#attributes.function#">
    			<!---DNS Functions (http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/XmlApi#DNS%20functions)--->
    			<!---
    				Name: adddns
    				Function: This function creates a DNS zone.
    			--->
    			<cfcase value="adddns">
    				<cfparam name="add_reqatt" default="domain,ip">
    				<cfloop list="#add_reqatt#" index="varname">
    					<cfset varval="attributes." & varname>
    					<cfif NOT IsDefined(varval)>
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' is missing.">
    					</cfif>
    					<cfif Evaluate(varval) EQ "">
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' must not be empty.">
    					</cfif>
    				</cfloop>
    				<cfset whmquery="domain=" & attributes.domain & "&ip=" & attributes.ip>
    				<!---optional parameters--->
    				<cfif IsDefined("attributes.dnstemplate")>
    					<cfswitch expression="#attributes.dnstemplate#">
    						<cfcase value="standard">
    							<cfset whmquery=whmquery & "&template=standard">
    						</cfcase>
    						<cfcase value="simple">
    							<cfset whmquery=whmquery & "&template=simple">
    						</cfcase>
    						<cfcase value="standardvirtualftp">
    							<cfset whmquery=whmquery & "&template=standard">
    						</cfcase>
    						<cfdefaultcase>
    							<cfthrow type="cf_whm.InvalidAttribute" message="If defining the dnstemplate attribute it must be set to standard, simple or standardvirtualftp">
    						</cfdefaultcase>
    					</cfswitch>
    				</cfif>
    			</cfcase>
    			<!---/adddns--->
    			<!---
    				Name: killdns
    				Function: This API function lets you delete a DNS zone.
    			--->
    			<cfcase value="killdns">
    				<cfparam name="add_reqatt" default="domain">
    				<cfloop list="#add_reqatt#" index="varname">
    					<cfset varval="attributes." & varname>
    					<cfif NOT IsDefined(varval)>
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' is missing.">
    					</cfif>
    					<cfif Evaluate(varval) EQ "">
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' must not be empty.">
    					</cfif>
    				</cfloop>
    				<cfset whmquery="domain=" & attributes.domain>
    			</cfcase>
    			<!---/killdns--->
    			<!---
    				Name: getzonerecord
    				Function: This function will return zone records for a domain.
    			--->
    			<cfcase value="getzonerecord">
    				<!---check for the additional required attributes--->
    				<cfparam name="add_reqatt" default="domain,line">
    				<cfloop list="#add_reqatt#" index="varname">
    					<cfset varval="attributes." & varname>
    					<cfif NOT IsDefined(varval)>
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' is missing.">
    					</cfif>
    					<cfif Evaluate(varval) EQ "">
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' must not be empty.">
    					</cfif>
    				</cfloop>
    				<cfset whmquery="domain=" & attributes.domain & "&line=" & attributes.line>
    			</cfcase>
    			<!---/getzonerecord--->
    			<!---
    				Name: listzones
    				Function: This function will generate a list of all domains and corresponding DNS zones associated with your server.
    			--->
    			<cfcase value="listzones">
    				<!---No additional parameters required--->
    			</cfcase>
    			<!---/listzones--->
    			<!---
    				Name: dumpzone
    				Function: This function displays the DNS zone configuration for a specific domain. 
    			--->
    			<cfcase value="dumpzone">
    				<!---check for the additional required attributes--->
    				<cfparam name="add_reqatt" default="domain">
    				<cfloop list="#add_reqatt#" index="varname">
    					<cfset varval="attributes." & varname>
    					<cfif NOT IsDefined(varval)>
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' is missing.">
    					</cfif>
    					<cfif Evaluate(varval) EQ "">
    						<cfthrow type="cf_whm.InvalidAttribute" message="Required Attribute '#VarName#' must not be empty.">
    					</cfif>
    				</cfloop>
    				<cfset whmquery="domain=" & attributes.domain>
    			</cfcase>
    			<!---/dumpzone--->
    			<!---/DNS Functions--->
    			<cfdefaultcase>
    				<!---Invalid function requested--->
    				<cfthrow type="cf_whm.TagError" message="The function '#attributes.function#' is not recognised.">
    			</cfdefaultcase>
    		</cfswitch>
    		<!---/WHM Functions--->
    		<!---send the command to the server--->
    		<cfhttp url="#whmurl#?#whmquery#" method="get" timeout="#whmtimeout#" resolveurl="yes">
    			<cfhttpparam type="header" name="Authorization" value="WHM #attributes.whmuser#:#whmhash#">
    		</cfhttp>
    		<cfif cfhttp.StatusCode NEQ "200 OK">
    			<cfthrow type="cf_whm.TagError" message="cfhttp threw error: StatusCode: #cfhttp.StatusCode# Error Detail: #cfhttp.errorDetail#">
    		</cfif>
    		<cfscript>
    			Response = StructNew();
    			Response.Status = "COMPLETED";
    			Response.StatusDetail = cfhttp.filecontent;
    		</cfscript>
    		<!---Error Handlers--->
    		<cfcatch type="cf_whm.WHMError">
    			<cfscript>
    				Response = StructNew();
    				Response.Status = "WHMERROR";
    				Response.StatusDetail = CFCATCH.Message;
    			</cfscript>
    		</cfcatch>
    		<cfcatch type="cf_whm.TagError">
    			<cfscript>
    				Response = StructNew();
    				Response.Status = "TAGERROR";
    				Response.StatusDetail = CFCATCH.Message;
    			</cfscript>
    		</cfcatch>
    		<cfcatch type="cf_whm.InvalidAttribute">
    			<cfscript>
    				Response = StructNew();
    				Response.Status = "CFERROR";
    				Response.StatusDetail = CFCATCH.Message;
    			</cfscript>
    		</cfcatch>
    		<cfcatch type="any">
    			<cfscript>
    				Response = StructNew();
    				Response.Status = "TAGERROR";
    				Response.StatusDetail = CFCATCH.Message;
    			</cfscript>
    		</cfcatch>
    	</cftry>
    	<cfset SetVariable("caller.#attributes.result#", Response )>
    </cfprocessingdirective>
    
    To call the tag you can use cfmodule or just save the above as whm.cfm in your custom tags directory. So for example to delete a dns zone you would do:

    Code:
    <cfmodule template="whm.cfm"
    	whmhost="123.123.123.123:2086"
    	whmuser="whm-user"
    	whmhash="your-hash-key"
    	RequestType="xml-api"
    	function="killdns"
    	domain="domainname.co.uk"
    	result="whmresponse">
    
    <cfdump var="#whmresponse#">
    <cfif IsXML(whmresponse.statusdetail)>
    	<cfdump var="#xmlparse(whmresponse.statusdetail)#">	
    </cfif>
    Hope this helps, it only does some basic dns functions so far; I might whack it on RiaForge at a later stage...
     
Loading...

Share This Page