You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by David Mansfield <cx...@dm.cobite.com> on 2015/05/03 16:20:41 UTC

Re: canonicalized host name for kerberos (SPNEGO)

FYI: this much I have confirmed.  Using the following class as 
replacement to the default KerberosAuthOutInterceptor does the trick.

A small bit of refactoring and I should have this down in the Abstract 
base class.

package com.cobite.cxf.interceptor;

import java.net.InetAddress;
import java.net.URI;
import java.util.logging.Level;

public class KerberosAuthOutInterceptor extends org.apache.cxf.jaxrs.security.KerberosAuthOutInterceptor {
     private String realm;

     private String getCanonicalHostName(String hostName) {
	String canonicalHostName = hostName;
	try {
	    InetAddress in = InetAddress.getByName(hostName);
	    canonicalHostName = in.getCanonicalHostName();
	    LOG.fine("resolved hostName="+hostName+" to canonicalHostName="+canonicalHostName);
	} catch (Exception e) {
	    LOG.warning("unable to resolve canonical hostname: "+hostName+": "+e.getMessage());
	}
	return canonicalHostName;
     }
     
     @Override
     protected String getCompleteServicePrincipalName(URI currentURI) {
         String name = "HTTP/" + getCanonicalHostName(currentURI.getHost());
         if (realm != null) {
             name += "@" + realm;
         }
         if (LOG.isLoggable(Level.FINE)) {
             LOG.fine("Service Principal Name is " + name);
         }
         return name;
     }

     public void setRealm(String realm) {
         this.realm = realm;
     }
}


-- 
Thanks,
David Mansfield
Cobite, INC.
On 04/29/2015 04:43 AM, Colm O hEigeartaigh wrote:
> Either a github pull request, or else you can create a JIRA and attach the
> diff there if you prefer. Yes your changes sound fine, so long as the
> current behaviour can be enabled via a switch
> (useCanonicalHostname=true/false sounds fine).
>
> Colm.
>
> On Tue, Apr 28, 2015 at 7:48 PM, David Mansfield <cx...@dm.cobite.com> wrote:
>
>> Yes.  Does the below summary sound ok?  Not sure how can I get the socket
>> reference in the auth supplier, but I haven't really looked too hard.
>>
>> Once I have it ready, I can do a pull request in github or a patch here or
>> whatever.  What's your preference?
>>
>> The document http://cxf.apache.org/coding-guidelines.html doesn't seem
>> too stringent, I'll be careful I promise!
>>
>> Thanks,
>> David
>>
>> On 04/28/2015 06:54 AM, Colm O hEigeartaigh wrote:
>>
>>> Would you be willing to submit a patch for this?
>>>
>>> Colm.
>>>
>>> On Mon, Apr 27, 2015 at 5:44 PM, David Mansfield <cx...@dm.cobite.com>
>>> wrote:
>>>
>>>   Hi All,
>>>> Most (*) SPNEGO client implementations will canonicalize a host name when
>>>> using it to create a service principal.
>>>>
>>>> CXF seems to be an exception.  If a CNAME is used, say:
>>>> mywebservice.example.com is a CNAME for
>>>> sysadmins-like-really-long-hostnames.example.com, most setups will
>>>> expect
>>>> a request for HTTP/
>>>> sysadmins-like-really-long-hostnames.example.com@EXAMPLE.COM. In this
>>>> case, CXF will not be able to authenticate.
>>>>
>>>> I note, is IS possible to specify the servicePrincipalName directly, but
>>>> that breaks the transparency of using a CNAME in the first place, as the
>>>> configuration will need to reference the specific back-end providing the
>>>> service.
>>>>
>>>> Providing hostname canonicalization will fix the need to "know" about the
>>>> details behind the scenes.
>>>>
>>>> As this behavior would be a defaults-changing one, maybe we could add
>>>> useCanonicalHostname=true/false (default false I guess).
>>>>
>>>> Implementation-wise, I think you need to get the socket, and then:
>>>>
>>>>     socket.getInetAddress().getCanonicalHostName()
>>>>
>>>> This would replace:
>>>>    uri.getHost()
>>>>
>>>> that is currently used in
>>>> org.apache.cxf.transport.http.auth.AbstractSpnegoAuthSupplier
>>>>
>>>>
>>>> (*) Most that I have personally used :-)
>>>>
>>>> --
>>>> Thanks,
>>>> David Mansfield
>>>> Cobite, INC.
>>>>
>>>>
>>>
>


Re: [PATCH] canonicalized host name for kerberos (SPNEGO)

Posted by Colm O hEigeartaigh <co...@apache.org>.
Hi David,

Can you create a JIRA + attach the patch there please? Or else a github
pull request.

Colm.

On Mon, May 4, 2015 at 10:37 PM, David Mansfield <cx...@dm.cobite.com> wrote:

> Hi All,
>
> The attached patch (against 3.0.4 git) implements an additional property,
> useCanonicalHostname, which is supported by the AbstractSpnegoAuthSupplier,
> and therefore available to SpnegoAuthSupplier and
> KerberosAuthOutInterceptor.
>
> The default behavior is not modified.  If useCanonicalHostname is set,
> then the service principal will be created using the canonical name of the
> remote host.
>
> For example, if there is a CNAME DNS record for host.example.com which
> refers to an A record host-a-b-c.example.com, the default behavior would
> be to generate a service principal HTTP/host.example.com. When
> useCanonicalHostname is set to true, the service principal would be HTTP/
> host-a-b-c.example.com. Most browsers and many other HTTP user agents
> perform this kind of canonicalization.
>
> This can be configured in XML as follows:
>
>      <bean id="myAuthSupplier"
> class="org.apache.cxf.transport.http.auth.SpnegoAuthSupplier">
>          <property name="useCanonicalHostname" value="true" />
>      </bean>
>           <http-conf:conduit name="...">
>          <http-conf:authorization>
>              <sec:AuthorizationType>Negotiate</sec:AuthorizationType>
>              <sec:Authorization>CXFClient</sec:Authorization>
>          </http-conf:authorization>
>                   <http-conf:authSupplier bean="myAuthSupplier" />
>      </http-conf:conduit>
>
>
> Or similarly for KerberosAuthOutInterceptor.
>
> --
> Thanks,
> David Mansfield
> Cobite, INC.
>
> On 05/03/2015 10:20 AM, David Mansfield wrote:
>
>> FYI: this much I have confirmed.  Using the following class as
>> replacement to the default KerberosAuthOutInterceptor does the trick.
>>
>> A small bit of refactoring and I should have this down in the Abstract
>> base class.
>>
>> package com.cobite.cxf.interceptor;
>>
>> import java.net.InetAddress;
>> import java.net.URI;
>> import java.util.logging.Level;
>>
>> public class KerberosAuthOutInterceptor extends
>> org.apache.cxf.jaxrs.security.KerberosAuthOutInterceptor {
>>     private String realm;
>>
>>     private String getCanonicalHostName(String hostName) {
>>     String canonicalHostName = hostName;
>>     try {
>>         InetAddress in = InetAddress.getByName(hostName);
>>         canonicalHostName = in.getCanonicalHostName();
>>         LOG.fine("resolved hostName="+hostName+" to
>> canonicalHostName="+canonicalHostName);
>>     } catch (Exception e) {
>>         LOG.warning("unable to resolve canonical hostname:
>> "+hostName+": "+e.getMessage());
>>     }
>>     return canonicalHostName;
>>     }
>>         @Override
>>     protected String getCompleteServicePrincipalName(URI currentURI) {
>>         String name = "HTTP/" +
>> getCanonicalHostName(currentURI.getHost());
>>         if (realm != null) {
>>             name += "@" + realm;
>>         }
>>         if (LOG.isLoggable(Level.FINE)) {
>>             LOG.fine("Service Principal Name is " + name);
>>         }
>>         return name;
>>     }
>>
>>     public void setRealm(String realm) {
>>         this.realm = realm;
>>     }
>> }
>>
>>
>>
>
>


-- 
Colm O hEigeartaigh

Talend Community Coder
http://coders.talend.com

[PATCH] canonicalized host name for kerberos (SPNEGO)

Posted by David Mansfield <cx...@dm.cobite.com>.
Hi All,

The attached patch (against 3.0.4 git) implements an additional 
property, useCanonicalHostname, which is supported by the 
AbstractSpnegoAuthSupplier, and therefore available to 
SpnegoAuthSupplier and KerberosAuthOutInterceptor.

The default behavior is not modified.  If useCanonicalHostname is set, 
then the service principal will be created using the canonical name of 
the remote host.

For example, if there is a CNAME DNS record for host.example.com which 
refers to an A record host-a-b-c.example.com, the default behavior would 
be to generate a service principal HTTP/host.example.com. When 
useCanonicalHostname is set to true, the service principal would be 
HTTP/host-a-b-c.example.com. Most browsers and many other HTTP user 
agents perform this kind of canonicalization.

This can be configured in XML as follows:

      <bean id="myAuthSupplier" 
class="org.apache.cxf.transport.http.auth.SpnegoAuthSupplier">
          <property name="useCanonicalHostname" value="true" />
      </bean>
           <http-conf:conduit name="...">
          <http-conf:authorization>
              <sec:AuthorizationType>Negotiate</sec:AuthorizationType>
              <sec:Authorization>CXFClient</sec:Authorization>
          </http-conf:authorization>
                   <http-conf:authSupplier bean="myAuthSupplier" />
      </http-conf:conduit>


Or similarly for KerberosAuthOutInterceptor.

-- 
Thanks,
David Mansfield
Cobite, INC.

On 05/03/2015 10:20 AM, David Mansfield wrote:
> FYI: this much I have confirmed.  Using the following class as
> replacement to the default KerberosAuthOutInterceptor does the trick.
>
> A small bit of refactoring and I should have this down in the Abstract
> base class.
>
> package com.cobite.cxf.interceptor;
>
> import java.net.InetAddress;
> import java.net.URI;
> import java.util.logging.Level;
>
> public class KerberosAuthOutInterceptor extends
> org.apache.cxf.jaxrs.security.KerberosAuthOutInterceptor {
>     private String realm;
>
>     private String getCanonicalHostName(String hostName) {
>     String canonicalHostName = hostName;
>     try {
>         InetAddress in = InetAddress.getByName(hostName);
>         canonicalHostName = in.getCanonicalHostName();
>         LOG.fine("resolved hostName="+hostName+" to
> canonicalHostName="+canonicalHostName);
>     } catch (Exception e) {
>         LOG.warning("unable to resolve canonical hostname:
> "+hostName+": "+e.getMessage());
>     }
>     return canonicalHostName;
>     }
>         @Override
>     protected String getCompleteServicePrincipalName(URI currentURI) {
>         String name = "HTTP/" +
> getCanonicalHostName(currentURI.getHost());
>         if (realm != null) {
>             name += "@" + realm;
>         }
>         if (LOG.isLoggable(Level.FINE)) {
>             LOG.fine("Service Principal Name is " + name);
>         }
>         return name;
>     }
>
>     public void setRealm(String realm) {
>         this.realm = realm;
>     }
> }
>
>



[PATCH] canonicalized host name for kerberos (SPNEGO)

Posted by David Mansfield <da...@cobite.com>.
Hi All,

The attached patch (against 3.0.4 git) implements an additional 
property, useCanonicalHostname, which is supported by the 
AbstractSpnegoAuthSupplier, and therefore available to 
SpnegoAuthSupplier and KerberosAuthOutInterceptor.

The default behavior is not modified.  If useCanonicalHostname is set, 
then the service principal will be created using the canonical name of 
the remote host.

For example, if there is a CNAME DNS record for host.example.com which 
refers to an A record host-a-b-c.example.com, the default behavior would 
be to generate a service principal HTTP/host.example.com. When 
useCanonicalHostname is set to true, the service principal would be 
HTTP/host-a-b-c.example.com. Most browsers and many other HTTP user 
agents perform this kind of canonicalization.

This can be configured in XML as follows:

     <bean id="myAuthSupplier" class="org.apache.cxf.transport.http.auth.SpnegoAuthSupplier">
         <property name="useCanonicalHostname" value="true" />
     </bean>
     
     <http-conf:conduit name="...">
         <http-conf:authorization>
             <sec:AuthorizationType>Negotiate</sec:AuthorizationType>
             <sec:Authorization>CXFClient</sec:Authorization>
         </http-conf:authorization>
         
         <http-conf:authSupplier bean="myAuthSupplier" />
     </http-conf:conduit>


Or similarly for KerberosAuthOutInterceptor.

-- 
Thanks,
David Mansfield
Cobite, INC.

On 05/03/2015 10:20 AM, David Mansfield wrote:
> FYI: this much I have confirmed.  Using the following class as 
> replacement to the default KerberosAuthOutInterceptor does the trick.
>
> A small bit of refactoring and I should have this down in the Abstract 
> base class.
>
> package com.cobite.cxf.interceptor;
>
> import java.net.InetAddress;
> import java.net.URI;
> import java.util.logging.Level;
>
> public class KerberosAuthOutInterceptor extends 
> org.apache.cxf.jaxrs.security.KerberosAuthOutInterceptor {
>     private String realm;
>
>     private String getCanonicalHostName(String hostName) {
>     String canonicalHostName = hostName;
>     try {
>         InetAddress in = InetAddress.getByName(hostName);
>         canonicalHostName = in.getCanonicalHostName();
>         LOG.fine("resolved hostName="+hostName+" to 
> canonicalHostName="+canonicalHostName);
>     } catch (Exception e) {
>         LOG.warning("unable to resolve canonical hostname: 
> "+hostName+": "+e.getMessage());
>     }
>     return canonicalHostName;
>     }
>         @Override
>     protected String getCompleteServicePrincipalName(URI currentURI) {
>         String name = "HTTP/" + 
> getCanonicalHostName(currentURI.getHost());
>         if (realm != null) {
>             name += "@" + realm;
>         }
>         if (LOG.isLoggable(Level.FINE)) {
>             LOG.fine("Service Principal Name is " + name);
>         }
>         return name;
>     }
>
>     public void setRealm(String realm) {
>         this.realm = realm;
>     }
> }
>
>