Uploaded image for project: 'Service Packs and Hot Fixes'
  1. Service Packs and Hot Fixes
  2. MNT-13989

securing external authentication with non null external.authentication.proxyUserName fails

    Details

      Description

      In this Jira I preferred to present a setup that is modified incrementally towards the target configuration. You may however prefer to jump to step 3)
      to get to the problem configuration

      How to reproduce?
      =================

      1) create a 4.1.9.10 (linux pg tomccat) external auth system with HTTP and empty proxyUserName

      authentication.chain=external1:external
      external.authentication.proxyUserName=
      external.authentication.proxyHeader=X-Alfresco-Remote-User
      

      and confirm you external auth system works:

      curl -v -H "X-Alfresco-Remote-User: admin" http://localhost:8080/alfresco/webdav
      > GET /alfresco/webdav HTTP/1.1
      > User-Agent: curl/7.38.0
      > Host: localhost:8080
      > Accept: */*
      > X-Alfresco-Remote-User: admin
      > 
      < HTTP/1.1 200 OK
      ....
      

      2) modify the system created at step 1) to now enable SSL:

      a) choose a DNS name for your HTTPS server: I chose "server1.foo"
      (add it to your /etc/hosts file)

      b) we create our own CA (Certificate Authority) and sign our server cert with it.
      We need the CA as we will need at step 3)a) below to create a client certificate
      Here is what I did:

      # Create the CA Key and Certificate for signing Client Certs
      openssl genrsa -des3 -out ca.key 4096
      openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj '/CN=Alex CA'
      
      # Create the Server Key, CSR, and Certificate
      openssl genrsa -des3 -out server.key 1024
      openssl req -new -key server.key -out server.csr -subj '/CN=server1.foo'
      
      
      # We're self signing our own server cert here.  This is a no-no in production.
      openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
      
      # generate a keystore format PKCS12 containing key +  certificate
      openssl pkcs12 -export -in server.crt -inkey server.key -out keystore.p12 -name serveralias -CAfile ca.crt 
      
      # package the (server) keystore JKS format
      keytool -importkeystore -deststorepass mypass -destkeypass mypass -destkeystore keystore.jks -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass mypass -alias serveralias
      
      # package the (CA) truststore in JKS
      keytool -import -alias caalias -file ca.crt -keystore ca.jks
      

      c) modify tomcat server.xml to create an HTTPS connector:

         <Connector
      	port="8443"
      	protocol="HTTP/1.1"
      	SSLEnabled="true"
              maxThreads="150"
      	scheme="https"
      	secure="true"
              clientAuth="false"
      	sslProtocol="TLS"
      	keystoreFile="/home/madon/ssl/compute/ca/keystore.jks"
      	keystorePass="mypass"
      	truststoreFile="/home/madon/ssl/compute/ca/ca.jks"
      	truststorePass="mypass"
      	/>
       

      c) confirm external header-based authentication works to HTTPS with external.authentication.proxyUserName still empty:

      curl -v \
      -H "X-Alfresco-Remote-User: admin" \
      --cacert /home/madon/ssl/compute/ca/ca.crt \
      https://server1.foo:8443/alfresco/webdav
      
      > GET /alfresco/webdav HTTP/1.1
      > User-Agent: curl/7.38.0
      > Host: server1.foo:8443
      > Accept: */*
      > X-Alfresco-Remote-User: admin
      > 
      < HTTP/1.1 200 OK
      ...
      

      3) modify again the setup to create a 4.1.9.10 (linux pg tomccat) external auth system with HTTPS and NON empty proxyUserName:

      a) complete your mini PKI infrastructure started at 2)b) creating a client cert with subject alfresco-system

      # Create the Client Key and CSR
      openssl genrsa -des3 -out client.key 1024
      openssl req -new -key client.key -out client.csr -subj '/CN=alfresco-system'
      
      # Sign the client certificate with our CA cert.  Unlike signing our own server cert, this is what we want to do.
      openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt
      
      # optional: put  the client certificate in JKS format
      keytool -import -alias clientalias -file client.crt -keystore client.jks
      

      b) modify your tomcat server.xml to process client X.509 certificate, that is, change the 8443 Connector clientAuth attribute from:

      clientAuth="false"
      

      to

      clientAuth="want"
      

      to end up with a connector definition similar to:

         <Connector
      	port="8443"
      	protocol="HTTP/1.1"
      	SSLEnabled="true"
              maxThreads="150"
      	scheme="https"
      	secure="true"
              clientAuth="want"
      	sslProtocol="TLS"
      	keystoreFile="/home/madon/ssl/compute/ca/keystore.jks"
      	keystorePass="mypass"
      	truststoreFile="/home/madon/ssl/compute/ca/ca.jks"
      	truststorePass="mypass"
      	/>
      

      c) in alfresco-global.properties, change the empty value of external.authentication.proxyUserName to alfresco-system (the subject of the client certificate created at step 3)a)) to end up with a external authentication section like this:

      authentication.chain=external1:external
      external.authentication.proxyUserName=alfresco-system
      external.authentication.proxyHeader=X-Alfresco-Remote-User
      

      d) try to confirm that you can authenticate with client cert using:

      curl -v \
      -H "X-Alfresco-Remote-User: admin" \
      --cacert /home/madon/ssl/compute/ca/ca.crt \
      --cert /home/madon/ssl/compute/ca/client.crt \
      --key /home/madon/ssl/compute/ca/client.key \
      https://server1.foo:8443/alfresco/webdav
      

      Result:
      =======
      Authentication fails:

      > GET /alfresco/webdav HTTP/1.1
      > User-Agent: curl/7.38.0
      > Host: server1.foo:8443
      > Accept: */*
      > X-Alfresco-Remote-User: admin
      > 
      < HTTP/1.1 401 Unauthorized
      

      Expected result:
      ================
      Customer and Support would expect that the server refuses to authentication when there is no client cert but works when there is the client cert.
      Here it always fails.
      But maybe we do not understand the real meaning of this proxyUsername parameter (as its documentation is too brief):
      I thus also raised a DOC jira MNT-13990

      Notes:
      ======
      1) If your curl test fails before step 3) then setting in JAVA_OPTS

      -Djavax.net.debug=ssl,record,handshake,keygen,session,defaultctx,sslctx,sessioncache,keymanager,trustmanager,data,verbose,plaintext,packet
      

      may help.
      2) I reproduced the same result on 5.0.0.6
      3) logging

      log4j.logger.org.alfresco.repo.security.authentication.external=debug
      log4j.logger.org.alfresco.repo.security.authentication=debug
      

      produced nothing in 4.1 and in 5.0.0.6 it output:

      2015-04-29 12:04:47,692  DEBUG [authentication.external.DefaultRemoteUserMapper] [http-bio-8443-exec-4] Getting RemoteUser from http request.
      2015-04-29 12:04:47,692  DEBUG [authentication.external.DefaultRemoteUserMapper] [http-bio-8443-exec-4] The remote user id is: null
      2015-04-29 12:04:47,692  DEBUG [authentication.external.DefaultRemoteUserMapper] [http-bio-8443-exec-4] The header user id is: admin
      2015-04-29 12:04:47,692  DEBUG [authentication.external.DefaultRemoteUserMapper] [http-bio-8443-exec-4] The proxy user name is: alfresco-system
      2015-04-29 12:04:47,692  DEBUG [authentication.external.DefaultRemoteUserMapper] [http-bio-8443-exec-4] Returning null
      

      4) you can confirm that the X.509 client certificate it read by the server creating in your alfresco
      tomcat/webapps/alfresco directory a file test.jsp:

      <%@page import="java.util.*"%>
      <%@page import="java.security.cert.X509Certificate"%>
      <pre>
      <%
       
      for (Enumeration<String> enumeration = request.getAttributeNames(); enumeration.hasMoreElements();) {
      String attributeName = enumeration.nextElement();
      Object attribute = request.getAttribute(attributeName);
      out.println(attributeName + " -> " + attribute.getClass().getName() + ":" + attribute.toString());
      }
       
      %>
      
      
      <%
      X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
          if (certs != null) {
            for (int i = 0; i < certs.length; i++) {
              // out.println("Client Certificate [" + i + "] = " + certs[i].toString());
      	out.println("Client Certificate [" + i + "] = " + certs[i].getSubjectX500Principal().toString());
            }
          } else {
            if ("https".equals(request.getScheme())) {
              out.println("This was an HTTPS request, " + "but no client certificate is available");
            } else {
              out.println("This was not an HTTPS request, " + "so no client certificate is available");
            }
      }
      %>
      </pre>
      

      and then call that JSP script:

      curl -v \
      -H "X-Alfresco-Remote-User: admin" \
      --cacert /home/madon/ssl/compute/ca/ca.crt \
      --cert /home/madon/ssl/compute/ca/client.crt \
      --key /home/madon/ssl/compute/ca/client.key \
      https://server1.foo:8443/alfresco/test.jsp
      
      < HTTP/1.1 200 OK
      * Server Apache-Coyote/1.1 is not blacklisted
      < Server: Apache-Coyote/1.1
      < Set-Cookie: JSESSIONID=E729B543040A9AE8DB38E820E1ADE1AF; Path=/alfresco/; Secure; HttpOnly
      < Content-Type: text/html;charset=ISO-8859-1
      < Content-Length: 950
      < Date: Wed, 29 Apr 2015 10:12:54 GMT
      < 
      
      <pre>
      javax.servlet.request.ssl_session -> java.lang.String:5540aea687f9c46dca5111e287285287ca95db744a3e56985cad1f5449528b6b
      javax.servlet.request.ssl_session_id -> java.lang.String:5540aea687f9c46dca5111e287285287ca95db744a3e56985cad1f5449528b6b
      javax.servlet.request.ssl_session_mgr -> org.apache.tomcat.util.net.jsse.JSSESupport:org.apache.tomcat.util.net.jsse.JSSESupport@11dd760e
      javax.servlet.request.key_size -> java.lang.Integer:128
      javax.servlet.request.X509Certificate -> [Ljava.security.cert.X509Certificate;:[Ljava.security.cert.X509Certificate;@62719a4b
      javax.servlet.request.cipher_suite -> java.lang.String:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
      org.springframework.web.context.request.RequestContextListener.REQUEST_ATTRIBUTES -> org.springframework.web.context.request.ServletRequestAttributes:org.apache.catalina.connector.Request@17f3a2fc
      
      
      
      Client Certificate [0] = CN=alfresco-system
      Client Certificate [1] = CN=Alex CA
      
      </pre>
      

        Attachments

          Issue Links

            Structure

              Activity

                People

                • Assignee:
                  closedbugs Closed Bugs
                  Reporter:
                  amadon Alex Madon [X] (Inactive)
                • Votes:
                  1 Vote for this issue
                  Watchers:
                  6 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:

                    Time Tracking

                    Estimated:
                    Original Estimate - Not Specified
                    Not Specified
                    Remaining:
                    Remaining Estimate - 0 minutes
                    0m
                    Logged:
                    Time Spent - 3 days, 1 hour
                    3d 1h

                      Structure Helper Panel