changeset 1510:b213cf27152b

merge
author robcast
date Mon, 02 May 2016 20:14:10 +0200
parents e7e38e1f68df (diff) b3d81e4581a7 (current diff)
children 7995afe760a8
files
diffstat 8 files changed, 153 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/servlet/src/main/java/digilib/auth/IpAuthnOps.java	Sun May 01 12:03:03 2016 +0200
+++ b/servlet/src/main/java/digilib/auth/IpAuthnOps.java	Mon May 02 20:14:10 2016 +0200
@@ -41,7 +41,7 @@
 import digilib.util.XMLMapLoader;
 
 /**
- * Implements AuthnOps using paths defined in an XML config file.
+ * Implements AuthnOps using IP adresses defined in an XML config file.
  * 
  * The name of the configuration file is read from the digilib config parameter "auth-file".
  * <p/>
@@ -112,7 +112,6 @@
     public List<String> getUserRoles(DigilibRequest dlRequest) throws AuthOpException {
         HttpServletRequest request = ((DigilibServletRequest) dlRequest).getServletRequest();
         String ip = request.getRemoteAddr();
-        logger.debug("Getting roles for ip "+ip);
         List<String> provided = null;
         if (ip.contains(":")) {
             // IPv6
@@ -121,6 +120,7 @@
             // IPv4
             provided = authIP4s.match(ip);
         }        
+        logger.debug("Roles provided by ip "+ip+": "+provided);
         return provided;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/main/java/digilib/auth/IpOpenIdAuthnOps.java	Mon May 02 20:14:10 2016 +0200
@@ -0,0 +1,96 @@
+package digilib.auth;
+
+/*
+ * #%L
+ * Authentication class implementation using IP addresses and Servlet user information
+ * 
+ * Digital Image Library servlet components
+ * 
+ * %%
+ * Copyright (C) 2016 MPIWG Berlin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as 
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Lesser Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Lesser Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>.
+ * #L%
+ * Author: Robert Casties (robcast@berlios.de)
+ */
+
+import java.util.List;
+
+import digilib.conf.DigilibConfiguration;
+import digilib.conf.DigilibRequest;
+
+/**
+ * Implements AuthnOps using IP adresses defined in an XML config file and an OpenId Connect ID token.
+ * 
+ * The name of the configuration file is read from the digilib config parameter "auth-file".
+ * <p/>
+ * The tags "digilib-adresses" and "digilib-oauth" are read from the configuration file:
+ * <pre>  
+ * {@code
+ * <digilib-addresses>
+ *   <address ip="130.92.68" role="eastwood-coll,ptolemaios-geo" />
+ *   <address ip="130.92.151" role="wtwg" />
+ *   <address ip="0:0:0:0:0:0:0:1" role="local" />
+ * </digilib-addresses>
+ * 
+ * <digilib-oauth>
+ *   <openid issuer="https://id.some.where" clientid="myclient" roles="someusers" keytype="jwk">
+ *     {"kty":"RSA","e":"AQAB","kid":"rsa1","n":"qjQ5U3wXzamg9R...idGpIiVilMDVBs"}
+ *   </openid>
+ * </digilib-oauth>
+ * }
+ * </pre>
+ * A computer with an ip address that matches "ip" is automatically granted all roles under "role".
+ * The ip address is matched from the left (in full quads). Roles under "role" must be separated by comma only (no spaces).
+ * 
+ * If roles provided by IP are not sufficient it uses the "id_token" parameter containing a valid token signed with the configured key
+ * including the configured issuer (iss) and clientid (aud) to grant the configured roles.
+ */
+public class IpOpenIdAuthnOps extends IpAuthnOps {
+
+    protected OpenIdAuthnOps openIdAuthnOps;
+    
+    /* (non-Javadoc)
+     * @see digilib.auth.IpAuthnOps#init(digilib.conf.DigilibConfiguration)
+     */
+    @Override
+    public void init(DigilibConfiguration dlConfig) throws AuthOpException {
+        // init IpAuthnOps
+        super.init(dlConfig);
+        // init openIdAuthnOps
+        openIdAuthnOps = new OpenIdAuthnOps();
+        openIdAuthnOps.init(dlConfig);
+    }
+
+    /* (non-Javadoc)
+     * @see digilib.auth.IpAuthnOps#getUserRoles(digilib.conf.DigilibRequest)
+     */
+    @Override
+    public List<String> getUserRoles(DigilibRequest dlRequest) throws AuthOpException {
+        List<String> roles = super.getUserRoles(dlRequest);
+        if (roles == null) {
+            // no IP roles
+            roles = openIdAuthnOps.getUserRoles(dlRequest);
+        } else {
+            List<String> idRoles = openIdAuthnOps.getUserRoles(dlRequest);
+            if (idRoles != null) {
+                // add OpenID roles at the end
+                roles.addAll(idRoles);
+            }
+        }
+        return roles;
+    }
+
+}
--- a/servlet/src/main/java/digilib/auth/IpServletAuthnOps.java	Sun May 01 12:03:03 2016 +0200
+++ b/servlet/src/main/java/digilib/auth/IpServletAuthnOps.java	Mon May 02 20:14:10 2016 +0200
@@ -34,7 +34,7 @@
 import digilib.conf.DigilibServletRequest;
 
 /**
- * Implements AuthnOps using paths defined in an XML config file and Servlet API isUserInRole().
+ * Implements AuthnOps using IP adresses defined in an XML config file and Servlet API isUserInRole().
  * 
  * The name of the configuration file is read from the digilib config parameter "auth-file".
  * <p/>
--- a/servlet/src/main/java/digilib/auth/MetaAccessAuthzOps.java	Sun May 01 12:03:03 2016 +0200
+++ b/servlet/src/main/java/digilib/auth/MetaAccessAuthzOps.java	Mon May 02 20:14:10 2016 +0200
@@ -33,8 +33,6 @@
 import java.util.List;
 import java.util.Map;
 
-import javax.servlet.http.HttpServletRequest;
-
 import digilib.conf.DigilibConfiguration;
 import digilib.conf.DigilibServletConfiguration;
 import digilib.conf.DigilibServletRequest;
@@ -52,22 +50,25 @@
  * 
  * The name of the configuration file is read from the digilib config parameter "auth-file".
  * <p/>
- * Tags "digilib-access" and "digilib-adresses" are read from the configuration file:
+ * The tag "digilib-access" is read from the auth-file configuration file:
  * <pre>
  * {@code
  * <digilib-access>
  *   <access type="group:mpiwg" role="mpiwg-user"/>
+ *   <access type="default" role=""/>
  * </digilib-access>
  * }
  * </pre>
  * A user must supply one of the roles under "role" to access any object with the metadata "access" type of "type".
  * Roles under "role" must be separated by comma only (no spaces).
+ * Access type "default" applies to objects without metadata access tag.
  * 
  */
 public class MetaAccessAuthzOps extends AuthzOpsImpl {
 
-    private File configFile;
-    private Map<String, List<String>> rolesMap;
+    protected File configFile;
+    protected Map<String, List<String>> rolesMap;
+    protected List<String> defaultRoles = null;
 
     /**
      * Initialize authentication operations.
@@ -84,7 +85,7 @@
         logger.debug("IpRoleServletAuthops.init (" + configFile + ")");
         Map<String, String> roleList = null;
         try {
-            // load role mappings
+            // load access role mappings
             XMLMapLoader roleLoader = new XMLMapLoader("digilib-access", "access", "type", "role");
             roleList = roleLoader.loadUri(configFile.toURI());
         } catch (Exception e) {
@@ -98,9 +99,15 @@
         for (String k : roleList.keySet()) {
             String rs = roleList.get(k);
             String[] ra = rs.split(",");
-            rolesMap.put(k, Arrays.asList(ra));
+            if (k.equalsIgnoreCase("default") && !rs.isEmpty()) {
+                // set default roles
+                defaultRoles = Arrays.asList(ra);
+            } else {
+                // add access roles to map
+                rolesMap.put(k, Arrays.asList(ra));
+            }
         }
-        // set authentication
+        // set authentication ops
         this.authnOps = (AuthnOps) dlConfig.getValue(DigilibServletConfiguration.AUTHN_OP_KEY);
     }
 
@@ -120,7 +127,6 @@
      */
     @Override
     public List<String> rolesForPath(DigilibServletRequest dlRequest) throws AuthOpException {
-        HttpServletRequest request = dlRequest.getServletRequest();
         DocuDirent imgs;
         try {
             // try to get image file from JobDescription
@@ -143,19 +149,33 @@
         try {
             imgs.checkMeta();
             MetadataMap meta = imgs.getMeta().getFileMeta();
-            access = meta.get("access");
+            if (meta != null) {
+                access = meta.get("access");
+            }
         } catch (Exception e) {
             logger.error("Error getting access meta for file!");
         }
         if (access == null) {
-            // no access restriction - allow
-            logger.debug("rolesForPath (" + imgs.getName() + ") by [" + request.getRemoteAddr() + "]: (none)");
+            // no access tag - use default
+            logger.debug("Roles required for " + imgs.getName() + ": "+defaultRoles+"(default)");
+            return defaultRoles;
+        } else if (access.equalsIgnoreCase("free")) {
+            // access free
+            logger.debug("Roles required for " + imgs.getName() + ": (free)");
             return null;
         }
         // get required roles
-        List<String> required = rolesMap.get(access);
-        logger.debug("rolesForPath (" + imgs.getName() + ") by [" + request.getRemoteAddr() + "]: "+required);
-        return required;
+        if (rolesMap.containsKey(access)) {
+            List<String> required = rolesMap.get(access);
+            logger.debug("Roles required for " + imgs.getName() + ": "+required);
+            return required;
+        } else {
+            // no mapping to role
+            logger.error("Error: no role for access type '"+access+"'");
+            // use default
+            logger.debug("Roles required for " + imgs.getName() + ": "+defaultRoles+"(substituted default)");
+            return defaultRoles;            
+        }
     }
 
 }
--- a/servlet/src/main/java/digilib/auth/OpenIdAuthnOps.java	Sun May 01 12:03:03 2016 +0200
+++ b/servlet/src/main/java/digilib/auth/OpenIdAuthnOps.java	Mon May 02 20:14:10 2016 +0200
@@ -172,7 +172,7 @@
         }
         
         // set token cookie name
-        tokenCookieName = dlConfig.getAsString("auth-token-cookie");
+        tokenCookieName = dlConfig.getAsString("authn-token-cookie");
     }
 
     /* (non-Javadoc)
@@ -226,9 +226,9 @@
             secondPassJwtConsumer.processContext(jwtContext);
             JwtClaims claims = jwtContext.getJwtClaims();
             String sub = claims.getSubject();
-            logger.debug("id_token authenticated user '"+sub+"'");
             // get roles
             List<String> provided = idpRoles.get(issuer);
+            logger.debug("Roles provided by id_token (sub='"+sub+"'): "+provided);
             return provided;
             
         } catch (InvalidJwtException | MalformedClaimException e) {
--- a/servlet/src/main/java/digilib/auth/PathAuthzOps.java	Sun May 01 12:03:03 2016 +0200
+++ b/servlet/src/main/java/digilib/auth/PathAuthzOps.java	Mon May 02 20:14:10 2016 +0200
@@ -103,9 +103,9 @@
      */
     public List<String> rolesForPath(DigilibServletRequest dlRequest) throws digilib.auth.AuthOpException {
         String filepath = dlRequest.getFilePath();
-        logger.debug("rolesForPath: " + filepath);
         // which roles are required?
         List<String> required = authPaths.match(filepath);
+        logger.debug("Roles required for "+filepath+": "+required);
         return required;
     }
 
--- a/servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java	Sun May 01 12:03:03 2016 +0200
+++ b/servlet/src/main/java/digilib/conf/DigilibServletConfiguration.java	Mon May 02 20:14:10 2016 +0200
@@ -170,7 +170,7 @@
         // DocuDirectory implementation
         newParameter("docudirectory-class", "digilib.io.BaseDirDocuDirectory", null, 'f');
         // name of cookie with authentication token
-        newParameter("auth-token-cookie", "id_token", null, 'f');
+        newParameter("authn-token-cookie", "id_token", null, 'f');
     }
 
     /**
--- a/webapp/src/main/webapp/WEB-INF/digilib-auth.xml.template	Sun May 01 12:03:03 2016 +0200
+++ b/webapp/src/main/webapp/WEB-INF/digilib-auth.xml.template	Mon May 02 20:14:10 2016 +0200
@@ -4,6 +4,7 @@
 
   <digilib-paths>
     <!-- 
+      (authzops-class = "digilib.auth.PathAuthzOps")
       A user must supply one of the roles under "role"
       to access the directory "name".
       Roles under "role" must be separated by comma only (no spaces).  
@@ -12,8 +13,21 @@
     <path name="ptolemaios_geo" role="ptolemaios-geo" />
   </digilib-paths>
 
+  <digilib-access>
+    <!-- 
+      (authzops-class = "digilib.auth.MetaAccessAuthzOps")
+      A user must supply one of the roles under "role" to access any object 
+      with the metadata "access" type of "type".
+      Roles under "role" must be separated by comma only (no spaces).
+      Access type "default" applies to objects without metadata access tag.
+    -->
+    <access type="group:mpiwg" role="mpiwg-user"/>
+    <access type="default" role=""/>
+  </digilib-access>
+
   <digilib-addresses>
     <!-- 
+      (authnops-class = "digilib.auth.IpAuthnOps")
       A computer with an ip address that matches "ip"
       is automatically granted all roles under "role".
       The ip address is matched from the left (in full quads).
@@ -26,6 +40,7 @@
 
   <digilib-oauth>
     <!-- 
+      (authnops-class = "digilib.auth.OpenIdAuthnOps")
       A request with an "id_token" parameter containing a valid token 
       signed with the configured key including the configured issuer (iss)
       and clientid (aud) is granted the configured roles.