Difference between revisions of "Kerberos"

From OpenKM Documentation
Jump to: navigation, search
(Created page with '{{Advice|This documentation is based on forum post http://forum.openkm.com/viewtopic.php?f=6&t=9371 Alternate auth method for WS.}} Setup we use: * Samba4 AD * OpenKM C…')
 
Line 3: Line 3:
 
Setup we use:
 
Setup we use:
  
  * Samba4 AD
+
* Samba4 AD
  * OpenKM Community 6.2.1. hosted on Ubuntu 12.04 within a OpenVZ container
+
* OpenKM Community 6.2.1. hosted on Ubuntu 12.04 within a OpenVZ container
  * Java version: 1.6.0_27 OpenJDK 64-Bit
+
* Java version: 1.6.0_27 OpenJDK 64-Bit
  
 
{{Note|when I tried to replicate this setup on 6.2.2 I had to upgrade java version but that one had a problem with handling of 'file:<keytab location>' attribute value, so you'd have to make a minor correction in the kerberos extension files (I'll post a link later if I can find it)}}
 
{{Note|when I tried to replicate this setup on 6.2.2 I had to upgrade java version but that one had a problem with handling of 'file:<keytab location>' attribute value, so you'd have to make a minor correction in the kerberos extension files (I'll post a link later if I can find it)}}
Line 11: Line 11:
 
I won't go into details on how to set up Samba4 AD or kerberize a server since there's plenty of documentation vailable, so this config assumes you already have a working AD/Kerberos environment or know how to set up one.
 
I won't go into details on how to set up Samba4 AD or kerberize a server since there's plenty of documentation vailable, so this config assumes you already have a working AD/Kerberos environment or know how to set up one.
  
  * '''Base DN in AD''': DC=fictional,DC=company
+
* '''Base DN in AD''': DC=fictional,DC=company
  * '''Bind user''': ldap-lookup, pass 'secret01'
+
* '''Bind user''': ldap-lookup, pass 'secret01'
  * '''Users are stored in''': OU=Employees,DC=fictional,DC=company
+
* '''Users are stored in''': OU=Employees,DC=fictional,DC=company
  * '''Groups are stored in''': OU=Groups,DC=fictional,DC=company
+
* '''Groups are stored in''': OU=Groups,DC=fictional,DC=company
  * '''AD hostname''': ad
+
* '''AD hostname''': ad
  * '''OpenKM server hostname''': openkm
+
* '''OpenKM server hostname''': openkm
  * '''Keytab is located in''' /etc/krb5.keytab and has a HTTP/openkm.fictional.company service name.
+
* '''Keytab is located in''' /etc/krb5.keytab and has a HTTP/openkm.fictional.company service name.
  
 
Before starting the install,create ROLE_USER and ROLE_ADMIN roles in your AD (if that isn't possible you can also use custom roles in your OpenKM config).
 
Before starting the install,create ROLE_USER and ROLE_ADMIN roles in your AD (if that isn't possible you can also use custom roles in your OpenKM config).
Line 23: Line 23:
 
Configure your OpenKM Admin/Config tab like this:
 
Configure your OpenKM Admin/Config tab like this:
  
CODE: SELECT ALL
+
{|
principal.adapter       com.openkm.principal.LdapPrincipalAdapter      
+
! Property
principal.database.filter.inactive.users   Boolean         
+
! Value
principal.ldap.mail.attribute       mail      
+
|-
principal.ldap.mail.search.base       ou=Employees,dc=fictional,dc=company      
+
|principal.adapter
principal.ldap.mail.search.filter       (&(objectClass=person)(userPrincipalName={0}))      
+
|com.openkm.principal.LdapPrincipalAdapter
principal.ldap.referral       follow      
+
|-
principal.ldap.role.attribute       cn      
+
|principal.database.filter.inactive.users
principal.ldap.role.search.base   List    ou=Groups,dc=fictional,dc=company      
+
|true
principal.ldap.role.search.filter       objectClass=group      
+
|-
principal.ldap.roles.by.user.attribute       memberOf      
+
|principal.ldap.mail.attribute
principal.ldap.roles.by.user.search.base       ou=Employees,dc=fictional,dc=company      
+
|mail
principal.ldap.roles.by.user.search.filter       (&(objectClass=person)(userPrincipalName={0}))      
+
|-
principal.ldap.security.credentials       secret01      
+
|principal.ldap.mail.search.base
principal.ldap.security.principal       cn=ldap-lookup,cn=Users,dc=fictional,dc=company      
+
|ou=Employees,dc=fictional,dc=company
principal.ldap.server       ldap://ad.fictional.company:389      
+
|-
principal.ldap.user.attribute       userPrincipalName      
+
|principal.ldap.mail.search.filter
principal.ldap.user.search.base   List    ou=Employees,dc=fictional,dc=company      
+
|(&(objectClass=person)(userPrincipalName={0}))
principal.ldap.user.search.filter       objectClass=person      
+
|-
 +
|principal.ldap.referral
 +
|follow
 +
|-
 +
|principal.ldap.role.attribute
 +
|cn
 +
|-
 +
|principal.ldap.role.search.base
 +
|ou=Groups,dc=fictional,dc=company
 +
|-
 +
|principal.ldap.role.search.filter
 +
|objectClass=group
 +
|-
 +
|principal.ldap.roles.by.user.attribute
 +
|memberOf
 +
|-
 +
|principal.ldap.roles.by.user.search.base
 +
|ou=Employees,dc=fictional,dc=company
 +
|-
 +
|principal.ldap.roles.by.user.search.filter
 +
|(&(objectClass=person)(userPrincipalName={0}))
 +
|-
 +
|principal.ldap.security.credentials
 +
|secret01
 +
|-
 +
|principal.ldap.security.principal
 +
|cn=ldap-lookup,cn=Users,dc=fictional,dc=company
 +
|-
 +
|principal.ldap.server
 +
|ldap://ad.fictional.company:389
 +
|-
 +
|principal.ldap.user.attribute
 +
|userPrincipalName
 +
|-
 +
|principal.ldap.user.search.base
 +
|ou=Employees,dc=fictional,dc=company
 +
|-
 +
|principal.ldap.user.search.filter
 +
|objectClass=person
 +
|-
 +
|prop
 +
|val
 +
|-
 +
|prop
 +
|val
 +
|-
 +
|prop
 +
|val
 +
|-
 +
|prop
 +
|val
 +
|-
 +
|prop
 +
|val
 +
|}
 +
 
 +
 
 +
             
 
principal.ldap.username.attribute      cn       
 
principal.ldap.username.attribute      cn       
 
principal.ldap.username.search.base      ou=Employees,dc=fictional,dc=company       
 
principal.ldap.username.search.base      ou=Employees,dc=fictional,dc=company       

Revision as of 10:43, 1 April 2013


Nota idea.png This documentation is based on forum post [Alternate auth method for WS].

Setup we use:

  • Samba4 AD
  • OpenKM Community 6.2.1. hosted on Ubuntu 12.04 within a OpenVZ container
  • Java version: 1.6.0_27 OpenJDK 64-Bit

Nota clasica.png when I tried to replicate this setup on 6.2.2 I had to upgrade java version but that one had a problem with handling of 'file:<keytab location>' attribute value, so you'd have to make a minor correction in the kerberos extension files (I'll post a link later if I can find it)

I won't go into details on how to set up Samba4 AD or kerberize a server since there's plenty of documentation vailable, so this config assumes you already have a working AD/Kerberos environment or know how to set up one.

  • Base DN in AD: DC=fictional,DC=company
  • Bind user: ldap-lookup, pass 'secret01'
  • Users are stored in: OU=Employees,DC=fictional,DC=company
  • Groups are stored in: OU=Groups,DC=fictional,DC=company
  • AD hostname: ad
  • OpenKM server hostname: openkm
  • Keytab is located in /etc/krb5.keytab and has a HTTP/openkm.fictional.company service name.

Before starting the install,create ROLE_USER and ROLE_ADMIN roles in your AD (if that isn't possible you can also use custom roles in your OpenKM config).

Configure your OpenKM Admin/Config tab like this:

Property Value
principal.adapter com.openkm.principal.LdapPrincipalAdapter
principal.database.filter.inactive.users true
principal.ldap.mail.attribute mail
principal.ldap.mail.search.base ou=Employees,dc=fictional,dc=company
principal.ldap.mail.search.filter (&(objectClass=person)(userPrincipalName={0}))
principal.ldap.referral follow
principal.ldap.role.attribute cn
principal.ldap.role.search.base ou=Groups,dc=fictional,dc=company
principal.ldap.role.search.filter objectClass=group
principal.ldap.roles.by.user.attribute memberOf
principal.ldap.roles.by.user.search.base ou=Employees,dc=fictional,dc=company
principal.ldap.roles.by.user.search.filter (&(objectClass=person)(userPrincipalName={0}))
principal.ldap.security.credentials secret01
principal.ldap.security.principal cn=ldap-lookup,cn=Users,dc=fictional,dc=company
principal.ldap.server ldap://ad.fictional.company:389
principal.ldap.user.attribute userPrincipalName
principal.ldap.user.search.base ou=Employees,dc=fictional,dc=company
principal.ldap.user.search.filter objectClass=person
prop val
prop val
prop val
prop val
prop val


principal.ldap.username.attribute cn principal.ldap.username.search.base ou=Employees,dc=fictional,dc=company principal.ldap.username.search.filter (&(objectClass=person)(userPrincipalName={0})) principal.ldap.users.by.role.attribute userPrincipalName principal.ldap.users.by.role.search.base ou=Employees,dc=fictional,dc=company principal.ldap.users.by.role.search.filter (&(objectClass=person)(memberOf=cn={0},ou=Groups,dc=fictional,dc=company))


At this point you can also decide to use custom default roles, however, this requires setting read permissions on every repository node - this can be done through the interface for every node except Trash folder, for which you will have to manually add an entry into the database.

1) Download and install OpenKM using your prefered method 2) Download the Spring Security Kerberos Extension .jar file and put it into your OpenKM lib folder ( for example, /opt/tomcat/webapps/OpenKM/WEB-INF/lib) http://netload.in/dateiZrhLN1m90h/sprin ... OT.jar.htm Alternatively you can download and compile the file yourself from https://github.com/SpringSource/spring- ... -kerberos/ (note that this is a newer version which I have not yet tested) 3) Create the keytab for your OpenKM server and make sure it will be readable by tomcat 4) Open OpenKM.xml and comment out the authentication manager, since you will be doing all the changes directly in applicationContext.xml 5) Change the applicationContext.xml

CODE: SELECT ALL <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns:beans="http://www.springframework.org/schema/beans"

            xmlns:security="http://www.springframework.org/schema/security"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:task="http://www.springframework.org/schema/task"
            xmlns:jee="http://www.springframework.org/schema/jee"
            xmlns:jaxws="http://cxf.apache.org/jaxws"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
                                http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                                http://www.springframework.org/schema/security
                                http://www.springframework.org/schema/security/spring-security-3.1.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context-3.1.xsd
                                http://www.springframework.org/schema/task
                                http://www.springframework.org/schema/task/spring-task-3.1.xsd
                                http://www.springframework.org/schema/jee
                                http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
                                http://cxf.apache.org/jaxws
                                http://cxf.apache.org/schemas/jaxws.xsd">
   
   <context:component-scan base-package="com.openkm"/>
   
   
   <beans:import resource="classpath:META-INF/cxf/cxf.xml" />
   <beans:import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
   
   
   <beans:bean id="WSS4JInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
       <beans:constructor-arg>
           <beans:map>
               <beans:entry key="action" value="UsernameToken" />
               <beans:entry key="passwordType" value="PasswordText" />
               <beans:entry key="passwordCallbackClass" value="com.openkm.spring.ClientPasswordCallback" />
           </beans:map>
       </beans:constructor-arg>
   </beans:bean>
   
   <jaxws:endpoint id="authService" implementor="com.openkm.ws.endpoint.AuthService" address="/OKMAuth"/>
   <jaxws:endpoint id="bookmarkService" implementor="com.openkm.ws.endpoint.BookmarkService" address="/OKMBookmark"/>
   <jaxws:endpoint id="documentService" implementor="com.openkm.ws.endpoint.DocumentService" address="/OKMDocument"/>
   <jaxws:endpoint id="folderService" implementor="com.openkm.ws.endpoint.FolderService" address="/OKMFolder"/>
   <jaxws:endpoint id="mailService" implementor="com.openkm.ws.endpoint.MailService" address="/OKMMail"/>
   <jaxws:endpoint id="noteService" implementor="com.openkm.ws.endpoint.NoteService" address="/OKMNote"/>
   <jaxws:endpoint id="notificationService" implementor="com.openkm.ws.endpoint.NotificationService" address="/OKMNotification"/>
   <jaxws:endpoint id="propertyGroupService" implementor="com.openkm.ws.endpoint.PropertyGroupService" address="/OKMPropertyGroup"/>
   <jaxws:endpoint id="propertyService" implementor="com.openkm.ws.endpoint.PropertyService" address="/OKMProperty"/>
   <jaxws:endpoint id="repositoryService" implementor="com.openkm.ws.endpoint.RepositoryService" address="/OKMRepository"/>
   <jaxws:endpoint id="searchService" implementor="com.openkm.ws.endpoint.SearchService" address="/OKMSearch"/>
   <jaxws:endpoint id="dashboardService" implementor="com.openkm.ws.endpoint.DashboardService" address="/OKMDashboard"/>
   <jaxws:endpoint id="workflowService" implementor="com.openkm.ws.endpoint.WorkflowService" address="/OKMWorkflow"/>
   <jaxws:endpoint id="testService" implementor="com.openkm.ws.endpoint.TestService" address="/OKMTest">
   </jaxws:endpoint>
   
   <security:global-method-security secured-annotations="enabled"/>
   
   
   <security:http pattern="/services/**" create-session="stateless">
       <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
       <security:http-basic />
   </security:http>
   
   <security:http pattern="/Status" create-session="stateless">
       <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
       <security:http-basic />
   </security:http>
   
   <security:http pattern="/Download" create-session="stateless">
       <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
       <security:http-basic />
   </security:http>
   
   <security:http pattern="/workflow-register" create-session="stateless">
       <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
       <security:http-basic />
   </security:http>
   
   <security:http pattern="/webdav/**" create-session="stateless">
       <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
       <security:http-basic />
   </security:http>
   
   <security:http pattern="/feed/**" create-session="stateless">
       <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
       <security:http-basic />
   </security:http>
   
  <security:http entry-point-ref="spnegoEntryPoint">
       <security:intercept-url pattern="/frontend/**" access="IS_AUTHENTICATED_FULLY" />
       <security:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
       <security:intercept-url pattern="/admin/**" access="IS_AUTHENTICATED_FULLY" />
       <security:intercept-url pattern="/RepositoryStartup" access="IS_AUTHENTICATED_FULLY" />
       <security:intercept-url pattern="/Test" access="IS_AUTHENTICATED_FULLY" />
       <security:intercept-url pattern="/extension/**" access="IS_AUTHENTICATED_FULLY" />


     <security:custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
     <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=1"/>
  </security:http>
  <beans:bean id="spnegoEntryPoint" class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />
  <beans:bean id="spnegoAuthenticationProcessingFilter" class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
     <beans:property name="authenticationManager" ref="authenticationManager" />
  </beans:bean>
  <security:authentication-manager alias="authenticationManager">
     <security:authentication-provider ref="kerberosServiceAuthenticationProvider" /> 
     <security:authentication-provider ref="kerberosAuthenticationProvider"/> 
  </security:authentication-manager>
  <beans:bean id="kerberosAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosAuthenticationProvider">
     <beans:property name="kerberosClient">
        <beans:bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosClient">
           <beans:property name="debug" value="true"/>
        </beans:bean>
     </beans:property>
     <beans:property name="userDetailsService" ref="ldapUserService"/>
  </beans:bean>
  
  <beans:bean id="kerberosServiceAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
     <beans:property name="ticketValidator">
        <beans:bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
           <beans:property name="servicePrincipal" value="HTTP/openkm.fictional.company" />
           <beans:property name="keyTabLocation" value="file:/etc/krb5.keytab" />
           <beans:property name="debug" value="true" />
        </beans:bean>
     </beans:property>
     <beans:property name="userDetailsService" ref="ldapUserService" />
  </beans:bean>
  
  <beans:bean class="org.springframework.security.extensions.kerberos.GlobalSunJaasKerberosConfig">
     <beans:property name="debug" value="true" />
  </beans:bean>


<beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">

 <beans:constructor-arg value="ldap://ad.fictional.company:389/ "/>
 <beans:property name="userDn" value="CN=ldap-lookup,cn=Users,dc=fictional,dc=company"/>
 <beans:property name="password" value="secret01"/>
 <beans:property name="baseEnvironmentProperties">
     <beans:map>
       <beans:entry>
         <beans:key>
           <beans:value>java.naming.referral</beans:value>
         </beans:key>
         <beans:value>follow</beans:value>
       </beans:entry>
     </beans:map>
   </beans:property>
 </beans:bean>

<beans:bean id="ldapUserService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">

 <beans:constructor-arg index="0">
   <beans:bean class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
     <beans:constructor-arg value="ou=Employees,DC=,fictional,DC=company"/>
   <beans:constructor-arg value="userPrincipalName={0}"/>
     <beans:constructor-arg ref="contextSource"/>
     <beans:property name="searchSubtree" value="true" />
   </beans:bean>
 </beans:constructor-arg>
 <beans:constructor-arg index="1">
   <beans:bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
     <beans:constructor-arg ref="contextSource"/>
     <beans:constructor-arg value="ou=Groups,dc=fictional,dc=company"/>
     <beans:property name="groupRoleAttribute" value="cn"/>
     <beans:property name="searchSubtree" value="true" />
     <beans:property name="convertToUpperCase" value="false"/>
     <beans:property name="rolePrefix" value=""/>
  </beans:bean>
 </beans:constructor-arg>

</beans:bean>

</beans:beans>


Make sure to restart Tomcat.

Open up a browser that supports SPNEGO (Firefox) and add the url of your openkm server to trusted urls (open about:config, search for 'network.n' and add 'openkm.fictional.company' in this case to the list of trusted urls)

If you have a valid kerberos ticket you can then log in to your OpenKM via http://openkm.fictional.company:8080/OpenKM OR log in manually via http://openkm.fictional.company:8080/OpenKM/login.jsp where you type in your AD username/pass. I still have to figure out how to make the server redirect me to login page if the spnego fails, but it's not critical at this point.