diff --git a/auth/Makefile b/auth/Makefile deleted file mode 100644 index 36c0b4b3ada259db9223bb0beab4ac31cc12d664..0000000000000000000000000000000000000000 --- a/auth/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -################################################################################ -LIB_DIR = target/lib -TARGET = $(LIB_DIR)/vlkb-auth.jar -CLASS_DIR = target/classes -VERSION ?= $(shell git describe) -################################################################################ -EXT_LIB_DIR = ../java-libs/lib -################################################################################ -JC = javac -JFLAGS = -g -CLASSPATH = $(CLASS_DIR):$(EXT_LIB_DIR)/* -################################################################################ -SRC_DIR = src/main/java:src/test/java -SOURCES = $(wildcard src/*Filter.java) src/main/java/AuthPolicy.java src/test/java/Main.java -################################################################################ - -all : build - -build : jar - -.PHONY: classes makedirs clean test - -makedirs: - mkdir -p $(CLASS_DIR) $(LIB_DIR) - -classes: makedirs - $(JC) $(JFLAGS) -cp $(CLASSPATH) -sourcepath $(SRC_DIR) -d $(CLASS_DIR) $(SOURCES) - -jar: classes - jar -cf $(TARGET) -C $(CLASS_DIR) . - -clean : - rm -fr $(CLASS_DIR) $(LIB_DIR) - rmdir target - -run-test: - java -cp $(CLASSPATH) Main ../test/token.base64 - -test: - @echo "SOURCES : "$(SOURCES) - diff --git a/auth/permissions-table.sql b/auth/permissions-table.sql deleted file mode 100644 index 8ac6fd17eee6e20105ba8a3097509e5716aac1a2..0000000000000000000000000000000000000000 --- a/auth/permissions-table.sql +++ /dev/null @@ -1,6 +0,0 @@ - - -create table permissions ( obs_publisher_did varchar primary key, groups TEXT[] NULL ); - -INSERT INTO permissions (obs_publisher_did, groups) VALUES ('ivo://auth.example.org/datasets/fits?cubes/part-Eridanus_full_image_V3.fits#0','{AllPrivate}'); - diff --git a/auth/resources/Backup/auth.properties-AuthLibExample b/auth/resources/Backup/auth.properties-AuthLibExample deleted file mode 100644 index d032f0cb0c9f8f50485e411524038de94b0982be..0000000000000000000000000000000000000000 --- a/auth/resources/Backup/auth.properties-AuthLibExample +++ /dev/null @@ -1,14 +0,0 @@ -client_id=test -client_secret=test-secret -rap_uri=http://localhost/rap-ia2 -store_state_on_login_endpoint=true -scope=openid read:userspace write:userspace read:fileserver write:fileserver read:gms read:rap - -gms_uri=http://localhost:8082/gms -groups_autoload=false - -# default values -access_token_endpoint=/auth/oauth2/token -user_authorization_endpoint=/auth/oauth2/authorize -check_token_endpoint=/auth/oauth2/token -jwks_endpoint=/auth/oidc/jwks diff --git a/auth/resources/Backup/shiro.ini b/auth/resources/Backup/shiro.ini deleted file mode 100644 index 4324a25031ec4eab8cdd1b1aa288afd17f3300eb..0000000000000000000000000000000000000000 --- a/auth/resources/Backup/shiro.ini +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2013 Les Hazlewood and contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# INI configuration is very powerful and flexible, while still remaining succinct. -# Please http://shiro.apache.org/configuration.html and -# http://shiro.apache.org/web.html for more. - -[main] -shiro.loginUrl = /login.jsp -cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager -securityManager.cacheManager = $cacheManager -#securityManager.realm = $stormpathRealm - -[users] -# syntax: user = password , roles -vialactea = ia2vlkb, ROLE_ADMIN - -[roles] -ROLE_ADMIN = * - -[urls] -#/login.jsp = authc -/logout = logout -/** = authcBasic -#/ivoa/resources/basic/** = authcBasic -#/ivoa/resources/full/** = authc - diff --git a/auth/resources/auth.properties b/auth/resources/auth.properties deleted file mode 100644 index c9c8aee27f0017b03a10a17896236eae4a93a018..0000000000000000000000000000000000000000 --- a/auth/resources/auth.properties +++ /dev/null @@ -1,10 +0,0 @@ -rap_uri=https://sso.ia2.inaf.it/rap-ia2 -gms_uri=https://sso.ia2.inaf.it/gms -client_id=vospace_ui_demo -client_secret=VOSpaceDemo123 - -groups_autoload=true -store_state_on_login_endpoint=true -scope=openid email profile read:rap - -allow_anonymous_access=true diff --git a/auth/resources/iamtoken.properties b/auth/resources/iamtoken.properties deleted file mode 100644 index d275d68bee277ed3450eee1349d4a3a2c48210dc..0000000000000000000000000000000000000000 --- a/auth/resources/iamtoken.properties +++ /dev/null @@ -1,13 +0,0 @@ - -# certificates endpoint -#jwks_url= -introspect= -client_name= -client_password= - -# account created for the service -resource_id= - -# username for non-authenticated requests -non_authn_username=anonymous - diff --git a/auth/resources/neatoken.properties b/auth/resources/neatoken.properties deleted file mode 100644 index 839e15d714346acd080d3bc7474dc164e97a4af8..0000000000000000000000000000000000000000 --- a/auth/resources/neatoken.properties +++ /dev/null @@ -1,10 +0,0 @@ - -# certificates endpoint -jwks_url= - -# account created for the service -resource_id= - -# username for non-authenticated requests -non_authn_username=anonymous - diff --git a/auth/src/main/java/AuthPolicy.java b/auth/src/main/java/AuthPolicy.java deleted file mode 100644 index 8c3d60f3b88d9899726e44c213a751d6cbb3a203..0000000000000000000000000000000000000000 --- a/auth/src/main/java/AuthPolicy.java +++ /dev/null @@ -1,338 +0,0 @@ - -// external inputs: -// User data (name and list of groups) -// List of PublisherDid's as param to some app-function (multi-cutout, merge) -// Database connection (from Settings) - -// For Non-authenticated requests two behaviours possible: -// A, setups with configured security: return only PUBLIC data -// B, setups wihtout need of security: access all data -// Currently B supported: Vlkb security filters will always set UsePrincipal. -// Security filters could reserve 'anonymous' user for non-authenticated requests, if needed. -// So missing UserPrincipal is interpreted as setup without security filters - full access allowed. - - -import java.util.logging.Logger; - -import java.io.PrintWriter; -import java.security.Principal; - -import java.util.List; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.HashSet; -import java.util.Arrays; -import java.util.ListIterator; - - - -public class AuthPolicy -{ - private static final Logger LOGGER = Logger.getLogger(AuthPolicy.class.getName()); - - enum Access { PUBLIC_ONLY, PUBLIC_AND_AUTHORIZED_PRIVATE }; - private Access access; - - private String userName; - private String[] userGroups; - private boolean userGroupsValid; - - private String dbConnUrl; - private String dbUserName; - private String dbPassword; - - - public AuthPolicy(String userName, String[] userGroups) - { - this.userName = userName; - this.userGroups = userGroups; - this.userGroupsValid = true; - - access = Access.PUBLIC_AND_AUTHORIZED_PRIVATE; - - LOGGER.info("User [Groups]: " + userName + " [ " + String.join(" ", userGroups) + " ]" ); - } - - - - - public AuthPolicy(Principal principal) - { - if(principal == null) - { - access = Access.PUBLIC_ONLY; - userName = null; - userGroups = null; - userGroupsValid = false; - LOGGER.info("Non authenticated request (UserPrincipal null in HttpServletRequest)"); - } - else - { - if(principal instanceof VlkbUser) - { - VlkbUser vlkbUser = (VlkbUser) principal; - - userName = vlkbUser.getName(); - userGroups = vlkbUser.getGroupsAsArray(); - userGroupsValid = true; - - access = Access.PUBLIC_AND_AUTHORIZED_PRIVATE; - - LOGGER.info("User [Groups]: " + userName + " [ " + String.join(" ", userGroups) + " ]" ); - } - else - { - userName = principal.getName(); - LOGGER.info("DBG principal not instance of VlkbUser, but has user-name: " + userName); - userGroups = new String[]{""};//{"VLKB.groupA", "AllPrivate"}; // was for shiro - userGroupsValid = true; - access = Access.PUBLIC_AND_AUTHORIZED_PRIVATE; - //throw new IllegalArgumentException("UserPrincipal is not of expected type"); - } - } - } - - - - public String getUserName() - { - return userName; - } - - public boolean getUserGroupsValid() - { - return userGroupsValid; - } - - - public String[] getUserGroups() - { - return userGroups; - } - - public String getUserGroupsSqlFormat() - { - if( (userGroups != null) && (userGroups.length > 0) ) - { - return "\"" + String.join("\",\"" , userGroups) + "\""; - } - else - { - return null; - } - } - - public String getUserGroupsAsString(String separator) - { - if( (userGroups != null) && (userGroups.length > 0) ) - { - return String.join(separator, userGroups); - } - else - { - return null; - } - } - - - - - public String getAccessPolicy() - { - return access.name(); // returns enum as string - } - - - - public void toXML(PrintWriter writer) - { - writer.println("<AccessPolicy>" + this.getAccessPolicy() + "</AccessPolicy>"); - String ug = getUserGroupsAsString(" "); - if(userName != null) writer.println("<UserName>" + userName + "</UserName>"); - if(ug != null) writer.println("<GroupNames>" + ug + "</GroupNames>"); - } - - - - public String[] filterAuthorized(String[] pubdidArr, String dbConnUrl, String dbUserName, String dbPassword) - { - this.dbConnUrl = dbConnUrl; - this.dbUserName = dbUserName; - this.dbPassword = dbPassword; - - LOGGER.info("with String[] trace"); - return filterAuthorized(new ArrayList<String>(Arrays.asList(pubdidArr)), dbConnUrl); - } - - private String[] filterAuthorized(ArrayList<String> pubdidList, String dbConnUrl) - { - //LOGGER.info("with List <String> trace"); - switch(access) - { - case PUBLIC_ONLY : - filterNotPublic(pubdidList, dbConnUrl); - break; - - case PUBLIC_AND_AUTHORIZED_PRIVATE : - filterNotAuthorized(pubdidList, dbConnUrl); - break; - - default : - assert false : "Unrecoginzed access : " + access; - } - return pubdidList.toArray(new String[0]); - } - - - private void filterNotPublic(ArrayList<String> pubdids, String dbConnUrl) - { - LOGGER.info("trace"); - assert pubdids != null; - //LOGGER.info("PublisherDID list original : " + String.join(" ", pubdids)); - - List<AuthPolicyDb.PubdidGroups> privateUniqPubdids = db_queryPrivateUniqPubdidGroups(dbConnUrl, pubdids); - List<String> notAuthorizedUniqPubdids = pubdidsNotPublic(privateUniqPubdids, userGroups); - - LOGGER.info("AuthZ removes: " + String.join(" ", notAuthorizedUniqPubdids)); - - removeNotAuthorized(pubdids, notAuthorizedUniqPubdids); - - //LOGGER.info("PublisherDID list filtered : " + (pubdids.isEmpty() ? "" : String.join(" ", pubdids))); - } - - - private List<String> pubdidsNotPublic(List<AuthPolicyDb.PubdidGroups> pubdidList, String[] userGroups) - { - LOGGER.info("trace"); - //LOGGER.info("userGroups: " + String.join(" ",userGroups)); - - List<String> pubdidsNotAuthorizedList = new LinkedList<String>(); - ListIterator<AuthPolicyDb.PubdidGroups> it = pubdidList.listIterator(); - - while (it.hasNext()) - { - AuthPolicyDb.PubdidGroups pubdidGroups = it.next(); - - //LOGGER.info(pubdidGroups.pubdid + " : " + String.join(" ",pubdidGroups.groups)); - - if( true )// isIntersectionEmpty(pubdidGroups.groups, userGroups) ) - { - pubdidsNotAuthorizedList.add(pubdidGroups.pubdid); - } - } - - return pubdidsNotAuthorizedList; - } - - - - private void filterNotAuthorized(ArrayList<String> pubdids, String dbConnUrl) - { - LOGGER.info("trace"); - assert pubdids != null; - //LOGGER.info("PublisherDID list original : " + String.join(" ", pubdids)); - - List<AuthPolicyDb.PubdidGroups> privateUniqPubdids = db_queryPrivateUniqPubdidGroups(dbConnUrl, pubdids); - List<String> notAuthorizedUniqPubdids = pubdidsNotAuthorized(privateUniqPubdids, userGroups); - - LOGGER.info("AuthZ removes: " + String.join(" ", notAuthorizedUniqPubdids)); - - removeNotAuthorized(pubdids, notAuthorizedUniqPubdids); - - //LOGGER.info("PublisherDID list filtered : " + (pubdids.isEmpty() ? "" : String.join(" ", pubdids))); - } - - - - private void removeNotAuthorized(ArrayList<String> pubdids, List<String> notAuthorizedUniqPubdids) - { - ListIterator<String> itr = pubdids.listIterator(); - while (itr.hasNext()) - { - String pubdid = itr.next(); - - for(String notAuthPubdid : notAuthorizedUniqPubdids) - { - if (pubdid.equals(notAuthPubdid)) itr.remove(); - } - } - - return; - } - - - - private List<AuthPolicyDb.PubdidGroups> db_queryPrivateUniqPubdidGroups(String dbConnUrl, List<String> pubdids) - { - AuthPolicyDb adb; - synchronized(AuthPolicyDb.class) - { - AuthPolicyDb.dbConnUrl = this.dbConnUrl; - AuthPolicyDb.dbUserName = this.dbUserName; - AuthPolicyDb.dbPassword = this.dbPassword; - - adb = new AuthPolicyDb(); - } - - Set<String> uniqPubdids = new HashSet<String>(pubdids); - - if(uniqPubdids.isEmpty()) - { - List<AuthPolicyDb.PubdidGroups> privatePubdidGroups = Collections.emptyList(); - return privatePubdidGroups; - } - else - { - // FIXME handle DB-exceptions - List<AuthPolicyDb.PubdidGroups> privatePubdidGroups = adb.queryGroupsPrivateOnly(uniqPubdids); - return privatePubdidGroups; - } - } - - - - private List<String> pubdidsNotAuthorized(List<AuthPolicyDb.PubdidGroups> pubdidList, String[] userGroups) - { - LOGGER.info("trace"); - //LOGGER.info("userGroups: " + String.join(" ",userGroups)); - - List<String> pubdidsNotAuthorizedList = new LinkedList<String>(); - ListIterator<AuthPolicyDb.PubdidGroups> it = pubdidList.listIterator(); - - while (it.hasNext()) - { - AuthPolicyDb.PubdidGroups pubdidGroups = it.next(); - - //LOGGER.info(pubdidGroups.pubdid + " : " + String.join(" ",pubdidGroups.groups)); - - if( isIntersectionEmpty(pubdidGroups.groups, userGroups) ) - { - pubdidsNotAuthorizedList.add(pubdidGroups.pubdid); - } - } - - return pubdidsNotAuthorizedList; - } - - - - private boolean isIntersectionEmpty(String[] stringsA, String[] stringsB) - { - for(String strA : stringsA) - for(String strB : stringsB) - { - if(strA.equals(strB)) - { - return false; - } - } - return true; - } - - - -} - diff --git a/auth/src/main/java/AuthPolicyDb.java b/auth/src/main/java/AuthPolicyDb.java deleted file mode 100644 index 9f737ece7415810ae6d92fecca867f70d7385675..0000000000000000000000000000000000000000 --- a/auth/src/main/java/AuthPolicyDb.java +++ /dev/null @@ -1,256 +0,0 @@ - -import java.util.logging.Logger; - -// mySQL access -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.Driver; -import java.sql.ResultSet; -import java.sql.Statement; -import java.sql.SQLException; -import java.sql.Array; -// import javax.sql.*; needed if using DataSource instead of DriverManager for DB-connections - -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; - -import java.util.Enumeration; -import java.util.List; -import java.util.LinkedList; -import java.util.Set; -import java.util.HashSet; -import java.util.ArrayList; - -import java.lang.ClassNotFoundException; - - - -public class AuthPolicyDb -{ - private static final Logger LOGGER = Logger.getLogger(AuthPolicyDb.class.getName()); - - private static final String DB_DRIVER = "org.postgresql.Driver"; - //private static final Settings settings = Settings.getInstance(); - //static public Settings.DBConn dbconn = settings.dbConn; - static public String dbConnUrl; - static public String dbUserName; - static public String dbPassword; - - private Connection conn; - private Statement st; - private ResultSet res; - - AuthPolicyDb(){ - conn = null; - st = null; - res = null; - } - - - - public class PubdidGroups - { - String pubdid; - String[] groups; - PubdidGroups(String pubdid, String[] groups) - { - this.pubdid = pubdid; - this.groups = groups; - } - } - - -/* - private String convertToVlkbPubdid(String obscorePubdid) - { - final String PUBDID_PREFIX = dbconn.obscorePublisher; - - if(obscorePubdid.startsWith(PUBDID_PREFIX)) - return obscorePubdid.substring( PUBDID_PREFIX.length() ); - else - return obscorePubdid; - } - - private Set<String> convertToObscorePubdids(Set<String> vlkbPubdids) - { - final String PUBDID_PREFIX = dbconn.obscorePublisher; - - Set<String> obscorePubdids = new HashSet<String>(); - - for(String pubdid : vlkbPubdids) - { - String obscorePubdid = "\'" + PUBDID_PREFIX + pubdid + "\'"; - obscorePubdids.add(obscorePubdid); - } - - return obscorePubdids; - } -*/ - - public List<PubdidGroups> queryGroupsPrivateOnly(Set<String> uniqPubdids) - { - //Set<String> uniqObscorePubdids = convertToObscorePubdids(uniqPubdids); - Set<String> uniqObscorePubdids = uniqPubdids; - String commaSepObscorePubdids = String.join("\',\'", uniqObscorePubdids); - - assert (commaSepObscorePubdids != null) && (!commaSepObscorePubdids.isEmpty()); - - String TheQuery = "SELECT obs_publisher_did,groups FROM obscore " - + "WHERE (policy = 'PRIV') AND (obs_publisher_did IN (\'"+commaSepObscorePubdids+"\'));"; - - // FIXME use separate table holding _only_ private data-id's - //String TheQuery = "SELECT obs_publisher_did,groups FROM permissions " - // + "WHERE (obs_publisher_did IN (\'"+commaSepObscorePubdids+"\'));"; - - //LOGGER.info(TheQuery); - - List<PubdidGroups> pubdidGroups = new LinkedList<PubdidGroups>(); - try - { - res = doQuery(TheQuery); - - while (res.next()) - { - //String pubdid = convertToVlkbPubdid(res.getString("obs_publisher_did")); - String pubdid = res.getString("obs_publisher_did"); - Array groupsArr = res.getArray("groups"); - - String[] groups = null; - if(groupsArr == null) - groups = null; - else - groups = (String[]) groupsArr.getArray(); - - PubdidGroups pg = new PubdidGroups(pubdid, groups); - pubdidGroups.add(pg); - } - } - catch (SQLException se) - { - logSqlExInfo(se); - se.printStackTrace(); - } - catch (ClassNotFoundException e) - { - LOGGER.info("DB driver "+ DB_DRIVER +" not found: " + e.getMessage()); - e.printStackTrace(); - } - finally - { - closeAll(); - } - - return pubdidGroups; - } - - - private void closeAll() - { - if(res != null ) try { res.close(); } catch(Exception e) {LOGGER.info("DB ResultSet::close() failed");} - if(st != null ) try { st.close(); } catch(Exception e) {LOGGER.info("DB Statement::close() failed");} - if(conn != null ) try { conn.close();} catch(Exception e) {LOGGER.info("DB Connection::close() failed");} - } - - private void logSqlExInfo(SQLException se){ - - /* dbconn.print_class_vars(); */ - - System.err.println("SQLState : " + se.getSQLState()); - System.err.println("ErrorCode: " + se.getErrorCode()); - System.err.println("Message : " + se.getMessage()); - Throwable t = se.getCause(); - while(t != null) { - System.err.println("Cause: " + t); - t = t.getCause(); - } - } - - - - private ResultSet doQuery(String TheQuery) - throws SQLException, ClassNotFoundException - { - - /* https://docs.oracle.com/javase/tutorial/jdbc/basics/connecting.html : - Any JDBC 4.0 drivers that are found in your class path are automatically loaded. - (However, you must manually load any drivers prior to JDBC 4.0 with the method - Class.forName.) - */ - // try { -// Class.forName(DB_DRIVER); - /* OR - DriverManager.registerDriver(new org.postgresql.Driver()); - */ - - /*LOGGER.info(getClasspathString());*/ - LOGGER.info(getRegisteredDriverList()); - - // FIXME seems DriverManager expects jdbc:postgresql driver scheme, it does not support postgresql:// scheme - // additionally: - // jdbc:postgresql:// scheme does not support username:password in the URL. - // So: - // receive postgresql:// scheme with user:password and convert to jdbc:postgresql:// - // by extracting userName and password from the URL-string and prepending 'jdbc:' - // - - /* LOGGER.info("DBMS URL: " + dbConnUrl); - URI dbConnUri = new URI(dbConnUrl); - - String userInfoString = dbConnUri.getUserInfo(); - - if(userInfoString == null) throw new AssertionError("DBMS URL must contain user:password but it is: " + dbConnUrl); - - String[] userInfo = userInfoString.split(":"); - - if(userInfo.length < 2) throw new AssertionError("DBMS URL must contain user:password but it is: " + dbConnUrl); - - String userName = userInfo[0]; - String password = userInfo[1]; - - String dbConnJdbcUrl = "jdbc:" + dbConnUrl.replace(userInfoString + "@", ""); - */ LOGGER.info("DBMS URL: " + dbConnUrl); - LOGGER.info("DBMS userName: " + dbUserName); - LOGGER.info("DBMS password: " + dbPassword); - - conn = DriverManager.getConnection(dbConnUrl, dbUserName, dbPassword); - - st = conn.createStatement(); - - // } catch (Exception e){ e.printStackTrace();} - - return st.executeQuery(TheQuery); - } - - - private String getClasspathString() { - StringBuffer classpath = new StringBuffer("getClasspathString:\r\n"); - ClassLoader applicationClassLoader = this.getClass().getClassLoader(); - if (applicationClassLoader == null) { - applicationClassLoader = ClassLoader.getSystemClassLoader(); - } - URL[] urls = ((URLClassLoader)applicationClassLoader).getURLs(); - for(int i=0; i < urls.length; i++) { - classpath.append(urls[i].getFile()).append("\r\n"); - } - - return classpath.toString(); - } - - - private String getRegisteredDriverList() - { - StringBuffer drvList = new StringBuffer("getRegisteredDriverList:\r\n"); - for (Enumeration e = DriverManager.getDrivers(); - e.hasMoreElements(); ) - { - Driver d = (Driver) e.nextElement(); - String driverClass = d.getClass().getName(); - drvList.append(driverClass).append("\r\n"); - } - return drvList.toString(); - } - - -} diff --git a/auth/src/main/java/IA2TokenConvFilter.java b/auth/src/main/java/IA2TokenConvFilter.java deleted file mode 100644 index a64c181ed275cda3bfd0af2e7b84a2b37dc0f709..0000000000000000000000000000000000000000 --- a/auth/src/main/java/IA2TokenConvFilter.java +++ /dev/null @@ -1,130 +0,0 @@ - -import it.inaf.ia2.aa.data.User; - -import java.io.IOException; -import java.util.*; // ArrayList<String> - -import java.util.logging.Logger; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - - -import javax.servlet.http.HttpServletRequestWrapper; -import java.security.Principal; - - -public class IA2TokenConvFilter implements Filter -{ - private static final Logger LOGGER = Logger.getLogger("IA2TokenConvFilter"); - - @Override - public void init(FilterConfig fc) throws ServletException - { - LOGGER.info("trace"); - } - - @Override - public void destroy() - { - LOGGER.info("trace"); - } - - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException - { - LOGGER.info("trace"); - - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) res; - - String authHeader = request.getHeader("Authorization"); - if (authHeader != null) - { - LOGGER.info("Authorization header: " + authHeader.substring(0, 7+60) + " ..."); - if (authHeader.startsWith("Bearer ")) - { - - - Principal principal = request.getUserPrincipal(); - if(principal == null) - { - LOGGER.warning("User principal is null"); - response.sendError(500, "Internal error - User principal is not correct"); - return; - } - - VlkbUser user = new VlkbUser(); - - if(principal instanceof it.inaf.ia2.aa.data.User) - { - it.inaf.ia2.aa.data.User alUser = (it.inaf.ia2.aa.data.User) principal; - - String userId = alUser.getName();//UserId - String userLabel = alUser.getUserLabel(); - List<String> groups = alUser.getGroups(); - - // FIXME check is any NULL ? - - user.setUserId(userId); - user.setUserLabel(userLabel); - user.setGroups(groups); - } - else - { - LOGGER.warning("User principal is incorrect type"); - response.sendError(500, "Internal error - User principal is not correct type"); - return; - } - - HttpServletRequestWrapper requestWithPrincipal - = new RequestWithPrincipal(request, user); - - chain.doFilter(requestWithPrincipal, response); - return; - } - else - { - LOGGER.warning("Detected Authorization header without Bearer token."); - } - } - else - { - LOGGER.warning("Request has no Authorization header."); - if(request.getUserPrincipal() != null) - { - LOGGER.warning("User principal is set however no Authorization header present"); - // response.sendError(500, "Internal error - It is not expected that Principal set in request but there is no Auhtprozation in HTTP-Header"); // FIXME use other err code not 500 here - // return; - } - } - chain.doFilter(request, response); -// response.sendError(401, "Unauthorized"); - } - - - - private static class RequestWithPrincipal extends HttpServletRequestWrapper - { - private final VlkbUser user; - - public RequestWithPrincipal(HttpServletRequest request, VlkbUser user) - { - super(request); - this.user = user; - } - - @Override - public Principal getUserPrincipal() { - return user; - } - } - -} - diff --git a/auth/src/main/java/IamSigningKeyResolver.java b/auth/src/main/java/IamSigningKeyResolver.java deleted file mode 100644 index ff89893067b2748ea91f6cda0d638eb0b3ea9126..0000000000000000000000000000000000000000 --- a/auth/src/main/java/IamSigningKeyResolver.java +++ /dev/null @@ -1,153 +0,0 @@ - -// 1. HTTPS -import java.net.URL; -import java.io.*; -import javax.net.ssl.HttpsURLConnection; - -// 2. json deser -//import org.codehaus.jackson.map.ObjectMapper; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonAutoDetect; - - -// 3, extract PublicKey -import java.util.Base64; -import java.io.ByteArrayInputStream; -import java.security.GeneralSecurityException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -// 4, validate token -import java.security.spec.InvalidKeySpecException; -import java.security.NoSuchAlgorithmException; -import java.security.Key; -import java.security.PublicKey; -import java.security.interfaces.RSAPublicKey; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.JwsHeader; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.jackson.io.JacksonDeserializer; -import io.jsonwebtoken.SigningKeyResolverAdapter; -import io.jsonwebtoken.security.Jwk; -import io.jsonwebtoken.security.Jwks; -// only dbg: when keys taken from file, not URL -import java.nio.file.Files; -import java.nio.file.Paths; - -import java.util.logging.Logger; - -public class IamSigningKeyResolver extends SigningKeyResolverAdapter -{ - private static final Logger LOGGER = Logger.getLogger(IamSigningKeyResolver.class.getName()); - private String keysURL; - - - public IamSigningKeyResolver(String keysUrl) {this.keysURL = keysUrl;} - - @Override - public Key resolveSigningKey(JwsHeader jwsHeader, Claims claims) - { - LOGGER.info( "IamSigningKeyResolver::resolveSigningKey" ); - - //inspect the header or claims, lookup and return the signing key - - String keyId = jwsHeader.getKeyId(); //or any other field that you need to inspect - - Key key = null; - try - { - key = lookupVerificationKey(keyId); //implement me - } - catch(Exception e) - { - e.printStackTrace(); - } - - return key; - } - - - - private Key lookupVerificationKey(String keyId) - throws Exception, GeneralSecurityException - { - LOGGER.info( "IamSigningKeyResolver::lookupVerificationKey" ); - - String jsonKeys = doHttps(); - - PublicKey pubKey = (PublicKey)getKeyFromKeys(jsonKeys, keyId); - - return pubKey; - } - - - private String doHttps() throws Exception - { - LOGGER.info("doHttps : " + keysURL); - - URL myUrl = new URL(keysURL); - HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection(); - InputStream is = conn.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - - String inputLine; - String jsonKeys = ""; - while ((inputLine = br.readLine()) != null) { - jsonKeys = jsonKeys + inputLine; - } - - br.close(); - - return jsonKeys; - } - - - private Key getKeyFromKeys(String jsonKeys, String keyId) - throws JsonProcessingException, GeneralSecurityException, IOException - { - LOGGER.info( "IamSigningKeyResolver::getKeyFromKeys"); - - Key key = null; - - ObjectMapper mapper = new ObjectMapper(); - - JsonNode keysNode = mapper.readTree(jsonKeys).get("keys"); - if(keysNode.isArray()) - { - for (JsonNode node : keysNode) - { - String nodeContent = mapper.writeValueAsString(node); - - LOGGER.info("key: " + nodeContent); - - Jwk<?> jwk = Jwks.parser().build().parse(nodeContent); - - String jwkkid = jwk.getId(); - - LOGGER.info("kid-token : " + keyId + "kid-store : " + jwkkid + " key-type: " + jwk.getType()); - - if(keyId.equals(jwkkid)) - { - key = jwk.toKey(); - } - } - } - - return key; - } - -} - diff --git a/auth/src/main/java/IamTokenFilter.java b/auth/src/main/java/IamTokenFilter.java deleted file mode 100644 index f434f824fb0f3e03e69398bd23795d69f148d5eb..0000000000000000000000000000000000000000 --- a/auth/src/main/java/IamTokenFilter.java +++ /dev/null @@ -1,431 +0,0 @@ - -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.InvalidClaimException; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.jackson.io.JacksonDeserializer; - -import java.security.spec.InvalidKeySpecException; -import java.security.NoSuchAlgorithmException; - -import javax.servlet.http.HttpServletRequestWrapper; -import java.security.Principal; - -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.IOException; -import java.util.List; // ArrayList<String> -import java.util.Map; -import java.util.HashMap; -import java.util.*; - -import java.util.logging.Logger; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.ServletOutputStream; - -public class IamTokenFilter implements Filter -{ - private static final Logger LOGGER = Logger.getLogger("IamTokenFilter"); - private static final IamTokenSettings settings = IamTokenSettings.getInstance(); - - final String RESPONSE_ENCODING = "utf-8"; - - final String keysUrl = settings.security.jwksEndpoint; - final String INTROSPECT_URL = settings.getIntrospectUrl(); - final String CLIENT_PASS = settings.getClientName() + ":" + settings.getClientPassword(); - - - @Override - public void init(FilterConfig fc) throws ServletException {} - - @Override - public void destroy() {} - - - @Override - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) - throws IOException, ServletException - { - String authHeader = ((HttpServletRequest)req).getHeader("Authorization"); - - ServletOutputStream respOutputStream = resp.getOutputStream(); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(respOutputStream, RESPONSE_ENCODING)); - - if(authHeader==null) - { - final String AUTH_ERR = "Request without Authorization header. Only authenticated requests allowed."; - LOGGER.info(AUTH_ERR); - sendAuthenticationError((HttpServletResponse)resp, writer, AUTH_ERR); - } - else - { - authHeader = authHeader.trim(); - - if (authHeader.startsWith("Bearer ") && (authHeader.length() > "Bearer ".length())) - { - LOGGER.info("Request with Authorization header and has Bearer entry"); - String token = authHeader.substring("Bearer ".length()).trim(); - - doFilterBearer(req, token, resp, chain); - } - else - { - final String AUTH_ERR = "Authorization header with Bearer-token expected, but it starts with : " - + authHeader.substring(0, "Bearer ".length()) + "..."; - LOGGER.info(AUTH_ERR); - sendUsageError((HttpServletResponse)resp, writer, AUTH_ERR); - } - } - } - - - - - private void doFilterBearer(ServletRequest req, String token, ServletResponse resp, FilterChain chain) - throws IOException, ServletException - { - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse)resp; - - ServletOutputStream respOutputStream = response.getOutputStream(); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(respOutputStream, RESPONSE_ENCODING)); - - try - { - IntrospectResponse insResp = new IntrospectResponse(CLIENT_PASS, INTROSPECT_URL, token); - - if(insResp.isTokenActive()) - { - String idString = request.getParameter("ID"); - Ivoid ivoid = new Ivoid(idString); - - String ivoidPath = ivoid.getLocalPart(); - String tokenPath = insResp.getPathFromStorageReadScope(); - - LOGGER.info("Path from IVOID: " + ivoidPath); - LOGGER.info("Path from token: " + tokenPath); - - if(tokenPath.endsWith(ivoidPath)) - { - LOGGER.info("Access authorized."); - chain.doFilter(request, response); - } - else - { - final String AUTH_ERR = "Bearer token does not authorize access to : " + ivoidPath; - LOGGER.info(AUTH_ERR); - sendAuthorizationError(response, writer, AUTH_ERR); - } - } - else - { - final String AUTH_ERR = "Bearer-token is inactive."; - LOGGER.info(AUTH_ERR); - sendAuthorizationError(response, writer, AUTH_ERR); - } - - } - catch(IndexOutOfBoundsException ex) - { - LOGGER.info("IndexOutOfBoundsException: " + ex.getMessage()); - sendUsageError(response, writer, ex.getMessage()); - } - catch(IllegalArgumentException ex) - { - LOGGER.info("IllegalArgumentException: " + ex.getMessage()); - sendUsageError(response, writer, ex.getMessage()); - } - catch(Exception ex) - { - LOGGER.info("Exception: " + ex.getMessage()); - ex.printStackTrace(); - sendError(response, writer, ex.toString()); - } - finally - { - writer.close(); - respOutputStream.close(); - } - } - - - - // 5. SODA sunc Responses [Table 6] - // Success: 200 (Ok) or 204 (NO Content) and set HTTP-Headers: Content-Type & Content_encoding (if applicable) - //Error Code Description - //=================================================================================== - //Error General error (not covered below) - //AuthenticationError Not authenticated - //AuthorizationError Not authorized to access the resource - //ServiceUnavailable Transient error (could succeed with retry) - //UsageError Permanent error (retry pointless) - //MultiValuedParamNotSupported request included multiple values for a parameter - // but the service only supports a single value - - - protected void sendError(HttpServletResponse response, PrintWriter printWriter, String message) - { - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - response.setContentType("text/plain"); - printWriter.println("Error : " + message); - } - - - protected void sendAuthenticationError(HttpServletResponse response, PrintWriter printWriter, String message) - { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - response.setContentType("text/plain"); - printWriter.println("AuthenticationError : " + message); - } - - - protected void sendAuthorizationError(HttpServletResponse response, PrintWriter printWriter, String message) - { - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - response.setContentType("text/plain"); - printWriter.println("AuthorizationError : " + message); - } - - - protected void sendServiceUnavailable(HttpServletResponse response, PrintWriter printWriter, String message) - { - response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - response.setContentType("text/plain"); - printWriter.println("ServiceUnavailable : " + message); - } - - - protected void sendUsageError(HttpServletResponse response, PrintWriter printWriter, String message) - { - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - response.setContentType("text/plain"); - printWriter.println("UsageError : " + message); - } - - - protected void sendMultiValuedParamNotSupported(HttpServletResponse response, PrintWriter printWriter, String message) - { - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - response.setContentType("text/plain"); - printWriter.println("MultiValuedParamNotSupported : " + message); - } - - - - - - - // Implementation with JWKs endpoint (explicit signiture verification): - - //final String resourceId = settings.security.resourceId; //"vlkb" - //final String realmName = "neanias-production"; - //final String keysUrl = "https://sso.neanias.eu/auth/realms/" + realmName + "/protocol/openid-connect/certs"; - - /*/@Override - public void OLD_doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException - { - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) res; - - String qString = request.getQueryString(); - if(qString == null) - LOGGER.info(request.getRequestURL().toString()); - else - LOGGER.info(request.getRequestURL() + " " + qString); - - String authHeader = request.getHeader("Authorization"); - if (authHeader == null) - { - boolean non_authenticated_request = (settings.security.non_authn_username != null); - - if(non_authenticated_request) - { - chain.doFilter(request, response); - } - else - { - LOGGER.info("Request without Authorization header, no Principal added"); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, - "No Authorization in HTTP-header. Only authorized requests allowed."); - } - return; - } - else - { - - if (authHeader.startsWith("Bearer ") && (authHeader.length() > "Bearer ".length())) - { - LOGGER.info("Request with Authorization header and has Bearer entry"); - - String jws = authHeader.substring("Bearer ".length()); - - try - { - VlkbUser user = getUserFromAccessToken(jws); - - HttpServletRequestWrapper requestWithPrincipal - = new RequestWithPrincipal(request, user); - - chain.doFilter(requestWithPrincipal, response); - return; - - } - catch (JwtException | InvalidTokenException ex) - { - LOGGER.warning("Token invalid: " + ex.toString()); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Token invalid"); - return; - } - catch (Exception ex) - { - LOGGER.severe(ex.toString()); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Error during authorization"); - return; - } - - } - else - { - LOGGER.warning("Request with Authorization header but without Bearer token"); - - response.sendError(HttpServletResponse.SC_BAD_REQUEST, - "Only Bearer authorization supported or token missing"); - return; - } - - } - } -*/ - - - /*/ validate and parse the token - - private List<String> parseScopes(Claims claims) - { - String scopeStr = (String)claims.get("scope"); - List<String> scopes = new ArrayList<String>(Arrays.asList(scopeStr.split(" "))); - - if (scopes.stream().anyMatch(s -> s.startsWith("storage.read:"))) - { - return scopes; - } - else - { - final String AUTH_ERR = "Invalid token: missing storage.read scope: " + scopeStr; - LOGGER.warning(AUTH_ERR); - throw new InvalidTokenException(AUTH_ERR); - } - } - - - - VlkbUser getUserFromAccessToken(String jwsString) - //throws JwtException, InvalidTokenException <-- FIXME - { - long clockSkew = 3 * 60; //3 minutes FIXME get from Config file - - Jws<Claims> jws = Jwts - .parser() - //.setAllowedClockSkewSeconds(clockSkew) // FIXME needed ? - .setSigningKeyResolver(new IamSigningKeyResolver(keysUrl)) - .build() - .parseClaimsJws(jwsString); - - Claims claims = jws.getBody(); - - LOGGER.info("scope: " + (String)claims.get("scope")); - - List<String> scopes = parseScopes(claims); - - String storageReadScope = ""; - - for(int i=0;i<scopes.size();i++) - { - if(scopes.get(i).startsWith("storage.read:")) - { - storageReadScope = scopes.get(i); - } - } - - LOGGER.info("storage.read: " + storageReadScope); - - String path = storageReadScope.substring(storageReadScope.lastIndexOf(":") + 1); - - LOGGER.info("path: " + path); - - // set User/Principal - - VlkbUser user = new VlkbUser(); - user.setAccessToken(jwsString); - user.setExpirationTime(0);//FIXME - user.setUserId((String) claims.get("sub")); - user.setUserLabel((String) claims.get("name")); - user.setGroups(scopes); // FIXME temp store scopes where roles were in neanias - - return user; - } - - - - - - private static class RequestWithPrincipal extends HttpServletRequestWrapper - { - private final VlkbUser user; - - public RequestWithPrincipal(HttpServletRequest request, VlkbUser user) - { - super(request); - this.user = user; - } - - @Override - public Principal getUserPrincipal() { - return user; - } - } -*/ - - - - - /* - private boolean isMapStringObject(Object obj) - { - if(obj instanceof Map) - { - Map map = (Map)obj; - - Set<?> s = map.keySet(); - Iterator<?> it = s.iterator(); - while(it.hasNext()) - { - Object el = it.next(); - if(! (el instanceof String)) - { - return false; - } - } - - return true; - } - else - return false; - } - */ - - -} - diff --git a/auth/src/main/java/IamTokenSettings.java b/auth/src/main/java/IamTokenSettings.java deleted file mode 100644 index a5ec5a2d3f2f5c8084851bdc90153f92eda83aef..0000000000000000000000000000000000000000 --- a/auth/src/main/java/IamTokenSettings.java +++ /dev/null @@ -1,106 +0,0 @@ - -import java.util.logging.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import java.io.PrintWriter; - -/* for Csv-loadSubsurveys * / -import com.opencsv.*; -import com.opencsv.exceptions.*; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.util.Map; -import java.util.List; -import java.util.ArrayList; -*/ - - - -class IamTokenSettings -{ - private static final Logger LOGGER = Logger.getLogger("IamTokenSettings"); - - static final String VLKB_PROPERTIES = "iamtoken.properties"; - - public static class Security - { - String jwksEndpoint; - String introspectEndpoint; - String clientName; - String clientPassword; - String resourceId; - - String non_authn_username = null; - } - - public Security security; - - - // will not start without config-file - // no reasonable code-defaults can be invented - public static IamTokenSettings getInstance() - { - try - { - InputStream ins = - IamTokenSettings.class.getClassLoader().getResourceAsStream(VLKB_PROPERTIES); - - if (ins != null) - { - Properties properties = new Properties(); - properties.load(ins); - - Security security = loadSecurity(properties); - - return new IamTokenSettings(security); - } - else - { - throw new IllegalStateException(VLKB_PROPERTIES + " not found in classpath"); - } - - } - catch(IOException ex) - { - throw new IllegalStateException("Error while loading " + VLKB_PROPERTIES + " file", ex); - } - } - - public String getIntrospectUrl() { return this.security.introspectEndpoint; } - public String getClientName() { return this.security.clientName; } - public String getClientPassword() { return this.security.clientPassword; } - -/* FIXME all fail if reurned string is null */ - - - private IamTokenSettings(Security security) - { - this.security = security; - } - - - private static Security loadSecurity(Properties properties) - { - Security security = new IamTokenSettings.Security(); - security.jwksEndpoint = getPropertyStriped(properties, "jwks_url"); - security.introspectEndpoint = getPropertyStriped(properties, "introspect"); - security.clientName = getPropertyStriped(properties, "client_name"); - security.clientPassword = getPropertyStriped(properties, "client_password"); - security.resourceId = getPropertyStriped(properties, "resource_id"); - security.non_authn_username = getPropertyStriped(properties, "non_authenticated_username"); - return security; - } - - - private static String getPropertyStriped(Properties properties, String setting) - { - String st = properties.getProperty(setting); - if(st != null) return st.strip(); - else return st; - } - - -} - diff --git a/auth/src/main/java/IntrospectResponse.java b/auth/src/main/java/IntrospectResponse.java deleted file mode 100644 index 4ac4b8b0e519cf051c34e6f47683a944bcfd1174..0000000000000000000000000000000000000000 --- a/auth/src/main/java/IntrospectResponse.java +++ /dev/null @@ -1,111 +0,0 @@ - -import java.util.logging.Logger; - -// 1. Https -import java.net.URL; -import java.io.*; -import javax.net.ssl.HttpsURLConnection; - -// 2. json deser -//import org.codehaus.jackson.map.ObjectMapper; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonAutoDetect; - -class IntrospectResponse -{ - private static final Logger LOGGER = Logger.getLogger("IntrospectResponse"); - - public boolean active; - public String scope; - - public IntrospectResponse(String uPass, String url, String token) throws Exception - { - final String POST_PARAM = "token=" + token; - String resp = doHttps(uPass, url, POST_PARAM); - decodeIRespJson(resp); - } - - public boolean isTokenActive() { return active; } - - public String getPathFromStorageReadScope() - { - if(scope == null) - { - throw new IllegalStateException("Introspect Response has scope = null. Probably token not active."); - } - else - { - String[] scopes = scope.split(" "); - for(String scope : scopes) - { - if(scope.startsWith("storage.read:")) - { - return scope.substring("storage.read:".length()); - } - } - throw new IllegalStateException( - "Introspect Response with 'storage.read' scope expected, but received scope: " + scope); - } - } - - - - private String doHttps(String uPass, String url, String postParams) throws Exception - { - LOGGER.info("doHttps : " + url); - - URL myUrl = new URL(url); - HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection(); - conn.setRequestMethod("POST"); - - String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(uPass.getBytes()); - - conn.setRequestProperty ("Authorization", basicAuth); - - - conn.setDoOutput(true); - OutputStream os = conn.getOutputStream(); - os.write(postParams.getBytes()); - os.flush(); - os.close(); - - InputStream is = conn.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - - String inputLine; - String jsonKeys = ""; - while ((inputLine = br.readLine()) != null) { - jsonKeys = jsonKeys + inputLine; - } - - br.close(); - - return jsonKeys; - } - /* - @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY); - static class IResp - { - boolean active; - String[] scope; - } - */ - private void decodeIRespJson(String json) throws IOException - { - ObjectMapper mapper = new ObjectMapper(); - active = mapper.readTree(json).get("active").asBoolean(); - if(active) - { - scope = mapper.readTree(json).get("scope").asText(); - } - } - -} diff --git a/auth/src/main/java/InvalidTokenException.java b/auth/src/main/java/InvalidTokenException.java deleted file mode 100644 index c248c9ffed6eea80fb76469218f5cbce55edb057..0000000000000000000000000000000000000000 --- a/auth/src/main/java/InvalidTokenException.java +++ /dev/null @@ -1,10 +0,0 @@ - - -public class InvalidTokenException extends RuntimeException -{ - public InvalidTokenException(String message) - { - super(message); - } -} - diff --git a/auth/src/main/java/Ivoid.java b/auth/src/main/java/Ivoid.java deleted file mode 100644 index 5b36ade61214ebecd4295e60411d715b91257109..0000000000000000000000000000000000000000 --- a/auth/src/main/java/Ivoid.java +++ /dev/null @@ -1,30 +0,0 @@ - - -class Ivoid -{ - private String localPart; - - public Ivoid(String ivoid) - { - if(ivoid.startsWith("ivo://")) - { - int lastQ = ivoid.lastIndexOf("?"); - if( lastQ < 0 ) - { - throw new IllegalArgumentException("IVOID must contain '?' but none found in: " + ivoid); - } - else - { - localPart = ivoid.substring(lastQ + 1);// +1: skip '?' - // throws IndexOutOfBoundsException - // if lastQ = str.length -> returns "" (empty string) - } - } - else - { - throw new IllegalArgumentException("IVOID must start with 'ivo://' but it is: " + ivoid); - } - } - - public String getLocalPart(){ return localPart; } -} diff --git a/auth/src/main/java/NeaSigningKeyResolver.java b/auth/src/main/java/NeaSigningKeyResolver.java deleted file mode 100644 index 72af2343a183b24d4c8e9977fd0823ad4fb05200..0000000000000000000000000000000000000000 --- a/auth/src/main/java/NeaSigningKeyResolver.java +++ /dev/null @@ -1,191 +0,0 @@ - -// 1. HTTPS -import java.net.URL; -import java.io.*; -import javax.net.ssl.HttpsURLConnection; - -// 2. json deser -//import org.codehaus.jackson.map.ObjectMapper; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonAutoDetect; - - -// 3, extract PublicKey -import java.util.Base64; -import java.io.ByteArrayInputStream; -import java.security.GeneralSecurityException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -// 4, validate token -import java.security.spec.InvalidKeySpecException; -import java.security.NoSuchAlgorithmException; -import java.security.Key; -import java.security.PublicKey; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.JwsHeader; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.jackson.io.JacksonDeserializer; -import io.jsonwebtoken.SigningKeyResolverAdapter; - -// only dbg: when keys taken from file, not URL -import java.nio.file.Files; -import java.nio.file.Paths; - -import java.util.logging.Logger; - -public class NeaSigningKeyResolver extends SigningKeyResolverAdapter -{ - private static final Logger LOGGER = Logger.getLogger(NeaSigningKeyResolver.class.getName()); - - // FIXME to config file - //final String pubkeyURL = "https://sso.neanias.eu/auth/realms/neanias-development"; - //final String keysURL = pubkeyURL + "/protocol/openid-connect/certs"; - // OR: - // final String realmName = "skao-devel"; --> url= .../realms/ + realm + /protocol/openid-connect/... - String pubkeyURL = "https://sso.neanias.eu/auth/realms/neanias-production"; - String keysURL = pubkeyURL + "/protocol/openid-connect/certs"; - // from ESc email: https://sso.neanias.eu/auth/realms/neanias-production/protocol/openid-connect/auth - - NeaSigningKeyResolver(String keysUrl) {this.keysURL = keysUrl;} - - private String doHttps() throws Exception - { - LOGGER.info("doHttps : " + keysURL); - - URL myUrl = new URL(keysURL); - HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection(); - InputStream is = conn.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - - String inputLine; - String jsonKeys = ""; - while ((inputLine = br.readLine()) != null) { - jsonKeys = jsonKeys + inputLine; - } - - br.close(); - - return jsonKeys; - } - - - - - // deserialize keys - - @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) - static class NeaKey - { - String kid; - String kty; - String alg; - String use; - String n; - String e; - String[] x5c; - String x5t; - @JsonProperty("x5t#S256") String x5t_S256; - } - - - private String getCertFromKeys(String jsonKeys, String keyId) - throws JsonProcessingException, GeneralSecurityException, IOException - { - LOGGER.info( "NeaSigningKeyResolver::getCertFromKeys"); - - ObjectMapper mapper = new ObjectMapper(); - - String cert = null; - - JsonNode keysNode = mapper.readTree(jsonKeys).get("keys"); - if(keysNode.isArray()) - { - for (JsonNode node : keysNode) - { - String nodeContent = mapper.writeValueAsString(node); - NeaKey key = mapper.readValue(nodeContent,NeaKey.class); - - LOGGER.info("keyId : " + keyId - +"\nKey::kid : " + key.kid); - - if(keyId.equals(key.kid)) - { - cert = key.x5c[0]; - } - } - } - - return cert; - } - - - - - private PublicKey getPublicKeyFromPemCert(String certBase64) - throws GeneralSecurityException - { - LOGGER.info( "NeaSigningKeyResolver::getPublicKeyFromPemCert"); - - CertificateFactory fac = CertificateFactory.getInstance("X509"); - ByteArrayInputStream in = new ByteArrayInputStream(Base64.getDecoder().decode(certBase64)); - X509Certificate cert = (X509Certificate)fac.generateCertificate(in); - return cert.getPublicKey(); - } - - - - - private Key lookupVerificationKey(String keyId) - throws Exception, GeneralSecurityException - { - LOGGER.info( "NeaSigningKeyResolver::lookupVerificationKey" ); - - String jsonKeys = doHttps(); - - String cert = getCertFromKeys(jsonKeys, keyId); - - PublicKey pubKey = (PublicKey)getPublicKeyFromPemCert(cert); - - return pubKey; - } - - - - - @Override - public Key resolveSigningKey(JwsHeader jwsHeader, Claims claims) - { - LOGGER.info( "NeaSigningKeyResolver::resolveSigningKey" ); - - //inspect the header or claims, lookup and return the signing key - - String keyId = jwsHeader.getKeyId(); //or any other field that you need to inspect - - Key key = null; - try - { - key = lookupVerificationKey(keyId); //implement me - } - catch(Exception e) - { - e.printStackTrace(); - } - - return key; - } -} - diff --git a/auth/src/main/java/NeaTokenFilter.java b/auth/src/main/java/NeaTokenFilter.java deleted file mode 100644 index f24dc4c3ab688d2c096083e403991d97af58a3af..0000000000000000000000000000000000000000 --- a/auth/src/main/java/NeaTokenFilter.java +++ /dev/null @@ -1,241 +0,0 @@ - -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.InvalidClaimException; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.jackson.io.JacksonDeserializer; - -import java.security.spec.InvalidKeySpecException; -import java.security.NoSuchAlgorithmException; - -import javax.servlet.http.HttpServletRequestWrapper; -import java.security.Principal; - -import java.io.IOException; -import java.util.List; // ArrayList<String> -import java.util.Map; -import java.util.HashMap; -import java.util.*; - -import java.util.logging.Logger; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -//import NeaSigningKeyResolver; - -public class NeaTokenFilter implements Filter -{ - private static final Logger LOGGER = Logger.getLogger("NeaTokenFilter"); - private static final NeaTokenSettings settings = NeaTokenSettings.getInstance(); - - final String resourceId = settings.security.resourceId; //"vlkb" - //final String realmName = "neanias-production"; - //final String keysUrl = "https://sso.neanias.eu/auth/realms/" + realmName + "/protocol/openid-connect/certs"; - final String keysUrl = settings.security.jwksEndpoint; - - @Override - public void init(FilterConfig fc) throws ServletException {} - - @Override - public void destroy() {} - - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException -{ - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) res; - - String qString = request.getQueryString(); - if(qString == null) - LOGGER.info(request.getRequestURL().toString()); - else - LOGGER.info(request.getRequestURL() + " " + qString); - - String authHeader = request.getHeader("Authorization"); - if (authHeader == null) - { - boolean non_authenticated_request = (settings.security.non_authn_username != null); - - if(non_authenticated_request) - { - chain.doFilter(request, response); - } - else - { - LOGGER.info("Request without Authorization header, no Principal added"); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, - "No Authorization in HTTP-header. Only authorized requests allowed."); - } - return; - } - else - { - - if (authHeader.startsWith("Bearer ") && (authHeader.length() > "Bearer ".length())) - { - LOGGER.info("Request with Authorization header and has Bearer entry"); - - String jws = authHeader.substring("Bearer ".length()); - - try - { - VlkbUser user = getUserFromAccessToken(jws); - - HttpServletRequestWrapper requestWithPrincipal - = new RequestWithPrincipal(request, user); - - chain.doFilter(requestWithPrincipal, response); - return; - - } - catch (JwtException | InvalidTokenException ex) - { - LOGGER.warning("Token invalid: " + ex.toString()); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Token invalid"); - return; - } - catch (Exception ex) - { - LOGGER.severe(ex.toString()); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Error during authorization"); - return; - } - - } - else - { - LOGGER.warning("Request with Authorization header but without Bearer token"); - - response.sendError(HttpServletResponse.SC_BAD_REQUEST, - "Only Bearer authorization supported or token missing"); - return; - } - - } -} - - -private boolean isMapStringObject(Object obj) -{ - if(obj instanceof Map) - { - Map map = (Map)obj; - - Set<?> s = map.keySet(); - Iterator<?> it = s.iterator(); - while(it.hasNext()) - { - Object el = it.next(); - if(! (el instanceof String)) - { - return false; - } - } - - return true; - } - else - return false; -} - -// validate and parse the token - -private List<String> validateAndParseRoles(Claims claims) -{ - Map mapobj = null; - - Object obj = claims.get("resource_access"); - if(isMapStringObject(obj)) - //if(obj instanceof Map<?,?>) - mapobj = (Map)obj;//claims.get("resource_access"); - - ////////////////////////////////////////////////////////////////////// - - Map<String,Object> resourceAccess = (Map<String, Object>)claims.get("resource_access"); - - if(resourceAccess != null) - { - - Map<String, Object> resource = (Map<String, Object>)resourceAccess.get(resourceId); - if (resource != null) - { - List<String> roles = (List<String>)resource.get("roles"); - return roles; - } - else - { - LOGGER.warning("Token invalid: 'resource_access' must have value: " + resourceId); - throw new InvalidTokenException( - "missing 'resource_access' must have value: " + resourceId); - } - } - else - { - LOGGER.warning("Token invalid: missing 'resource_access' claim"); - throw new InvalidTokenException("missing 'resource_access' claim"); - } -} - - - -VlkbUser getUserFromAccessToken(String jwsString) - //throws JwtException, InvalidTokenException <-- FIXME -{ - long clockSkew = 3 * 60; //3 minutes FIXME get from Config file - - Jws<Claims> jws = Jwts - .parser() - .setAllowedClockSkewSeconds(clockSkew) // FIXME needed ? - .setSigningKeyResolver(new NeaSigningKeyResolver(keysUrl)) - .build() - .parseClaimsJws(jwsString); - - Claims claims = jws.getBody(); - - List<String> roles = validateAndParseRoles(claims); - - // set User/Principal - - VlkbUser user = new VlkbUser(); - user.setAccessToken(jwsString); - user.setExpirationTime(0);//FIXME - user.setUserId((String) claims.get("sub")); - user.setUserLabel((String) claims.get("name")); - user.setGroups(roles); - - return user; -} - - - - - -private static class RequestWithPrincipal extends HttpServletRequestWrapper -{ - private final VlkbUser user; - - public RequestWithPrincipal(HttpServletRequest request, VlkbUser user) - { - super(request); - this.user = user; - } - - @Override - public Principal getUserPrincipal() { - return user; - } -} - -} - diff --git a/auth/src/main/java/NeaTokenSettings.java b/auth/src/main/java/NeaTokenSettings.java deleted file mode 100644 index ce71c442a1d34e917e403ccab445f983f884a5b0..0000000000000000000000000000000000000000 --- a/auth/src/main/java/NeaTokenSettings.java +++ /dev/null @@ -1,98 +0,0 @@ - -import java.util.logging.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import java.io.PrintWriter; - -/* for Csv-loadSubsurveys * / -import com.opencsv.*; -import com.opencsv.exceptions.*; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.util.Map; -import java.util.List; -import java.util.ArrayList; -*/ - - - -class NeaTokenSettings -{ - private static final Logger LOGGER = Logger.getLogger("NeaTokenSettings"); - - static final String VLKB_PROPERTIES = "neatoken.properties"; - - public static class Security - { - String jwksEndpoint; - String resourceId; - - String non_authn_username = null; - } - - public Security security; - - - // will not start without config-file - // no reasonable code-defaults can be invented - public static NeaTokenSettings getInstance() - { - try - { - InputStream ins = - NeaTokenSettings.class.getClassLoader().getResourceAsStream(VLKB_PROPERTIES); - - if (ins != null) - { - Properties properties = new Properties(); - properties.load(ins); - - Security security = loadSecurity(properties); - - return new NeaTokenSettings(security); - } - else - { - throw new IllegalStateException(VLKB_PROPERTIES + " not found in classpath"); - } - - } - catch(IOException ex) - { - throw new IllegalStateException("Error while loading " + VLKB_PROPERTIES + " file", ex); - } - } - - - -/* FIXME all fail if reurned string is null */ - - - private NeaTokenSettings(Security security) - { - this.security = security; - } - - - private static Security loadSecurity(Properties properties) - { - Security security = new NeaTokenSettings.Security(); - security.jwksEndpoint = getPropertyStriped(properties, "jwks_url"); - security.resourceId = getPropertyStriped(properties, "resource_id"); - security.non_authn_username = getPropertyStriped(properties, "non_authenticated_username"); - return security; - } - - - private static String getPropertyStriped(Properties properties, String setting) - { - String st = properties.getProperty(setting); - if(st != null) return st.strip(); - else return st; - } - - -} - diff --git a/auth/src/main/java/VlkbUser.java b/auth/src/main/java/VlkbUser.java deleted file mode 100644 index 6691c03693d6aa541c2ff6e9ea89287d3dfba768..0000000000000000000000000000000000000000 --- a/auth/src/main/java/VlkbUser.java +++ /dev/null @@ -1,96 +0,0 @@ - -import java.security.Principal; -import java.util.List; - -public class VlkbUser implements Principal { - - private String userId; - private String userLabel; - private String accessToken; - private String idToken; - private String refreshToken; - private long expirationTime; - private List<String> groups; - - @Override - public String getName() { - return userId; - } - - public VlkbUser setUserId(String userId) { - this.userId = userId; - return this; - } - - public String getUserLabel() { - return userLabel; - } - - public VlkbUser setUserLabel(String userLabel) { - this.userLabel = userLabel; - return this; - } - - public String getAccessToken() { - return accessToken; - } - - public VlkbUser setAccessToken(String accessToken) { - this.accessToken = accessToken; - return this; - } - - public VlkbUser setRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - return this; - } - - public String getRefreshToken() { - return refreshToken; - } - - public String getIdToken() { - return idToken; - } - - public VlkbUser setIdToken(String idToken) { - this.idToken = idToken; - return this; - } - - public long getExpirationTime() { - return expirationTime; - } - - public VlkbUser setExpirationTime(long expirationTime) { - this.expirationTime = expirationTime; - return this; - } - - public boolean isTokenExpired() { - return getExpiresIn() < 0; - } - - public long getExpiresIn() { - return expirationTime - System.currentTimeMillis() / 1000; - } - - public VlkbUser setExpiresIn(int expiresIn) { - this.expirationTime = System.currentTimeMillis() / 1000 + expiresIn; - return this; - } - - public List<String> getGroups() { - return groups; - } - - public String[] getGroupsAsArray() { - return groups.toArray(new String[0]); - } - - - public void setGroups(List<String> groups) { - this.groups = groups; - } -} - diff --git a/auth/src/test/java/Main.java b/auth/src/test/java/Main.java deleted file mode 100644 index a97f4542c66c8f969c3bd487fcb2d19b22d41c07..0000000000000000000000000000000000000000 --- a/auth/src/test/java/Main.java +++ /dev/null @@ -1,43 +0,0 @@ -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - - -class Main -{ - public static void main(String[] args) - { - System.out.println("calling Introspect"); - - final String tokenFilename = args[0]==null ? "token.base64" : args[0]; - - final String USER = "02cc260f-9837-4907-b2cb-a1a2d764fb15"; - final String PWD = "AJMi3qrB6AHRp_6y55tEwU-IpJ8uZ6X4QXeQ3W4la6dc-BlkzAY1OQpAE9hb1W7-VfYl4208FUtjE2Cl3hUYLkQ"; - final String IEP = "https://iam-escape.cloud.cnaf.infn.it/introspect"; - - try - { - final String TOKEN = new String(Files.readAllBytes(Paths.get(tokenFilename))); - - IntrospectResponse ir = new IntrospectResponse(USER+":"+PWD, IEP, TOKEN); - - System.out.println("active: " + ir.active ); - System.out.println("scope : " + ir.scope ); - if(ir.active) - System.out.println("IR: " + ir.getPathFromStorageReadScope()); - } - catch(IOException e) - { - System.out.println( "EXCPT: " + e.getMessage() ); - e.printStackTrace(); - } - catch(Exception e) - { - System.out.println( "EXCPT: " + e.getMessage() ); - e.printStackTrace(); - } - - - - } -} diff --git a/data-discovery/Makefile.m2-libs b/data-discovery/Makefile.m2-libs deleted file mode 100644 index e04bcfcf851de3ab9cfc84805e65769ce6733c3d..0000000000000000000000000000000000000000 --- a/data-discovery/Makefile.m2-libs +++ /dev/null @@ -1,93 +0,0 @@ -################################################################################ -# args -WEBAPP_WAR ?= vlkb-datasetssearch.war -AUTH ?= -VERSION ?= $(shell git describe) -################################################################################ -# target -################################################################################ -# insternal -JSRC = java/vlkb -ROOT = webapp -AUTH = ../../../auth -#META_DIR = webapp/META-INF -#CLASS_DIR = webapp/WEB-INF/classes -MVN_REPO = ~/.m2/repository -################################################################################ - -all: build - -libs-m2: - mkdir -p $(JSRC)/lib - cp $(MVN_REPO)/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar $(JSRC)/lib - cp $(MVN_REPO)/com/opencsv/opencsv/5.7.1/opencsv-5.7.1.jar $(JSRC)/lib - cp $(MVN_REPO)/it/inaf/ia2/auth-lib/2.0.0-SNAPSHOT/auth-lib-2.0.0-SNAPSHOT.jar $(JSRC)/lib - cp $(MVN_REPO)/it/inaf/ia2/rap-client/1.0-SNAPSHOT/rap-client-1.0-SNAPSHOT.jar $(JSRC)/lib - cp $(MVN_REPO)/org/postgresql/postgresql/42.6.0/postgresql-42.6.0.jar $(JSRC)/lib - cp $(MVN_REPO)/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar $(JSRC)/lib - cp $(MVN_REPO)/org/slf4j/slf4j-simple/1.7.36/slf4j-simple-1.7.36.jar $(JSRC)/lib - cp $(MVN_REPO)/ch/qos/logback/logback-core/1.4.7/logback-core-1.4.7.jar $(JSRC)/lib - cp $(MVN_REPO)/ch/qos/logback/logback-classic/1.4.7/logback-classic-1.4.7.jar $(JSRC)/lib - cp $(MVN_REPO)/com/fasterxml/jackson/core/jackson-databind/2.15.1/jackson-databind-2.15.1.jar $(JSRC)/lib - cp $(MVN_REPO)/com/fasterxml/jackson/core/jackson-annotations/2.15.1/jackson-annotations-2.15.1.jar $(JSRC)/lib - cp $(MVN_REPO)/com/fasterxml/jackson/core/jackson-core/2.15.1/jackson-core-2.15.1.jar $(JSRC)/lib - - -libs: - mkdir -p $(JSRC)/lib - cp ../../../java-libs/lib/*.jar $(JSRC)/lib - cp $(AUTH)/lib/*.jar $(JSRC)/lib - -build-auth: - make -C $(AUTH) build - -clean-auth: - make -C $(AUTH) clean - - -clean-libs: clean-auth - -rm -fr $(JSRC)/lib - - -.PHONY: build -build: build-auth libs - make -C $(JSRC) VERSION=$(VERSION) - -rm -fr $(ROOT)/WEB-INF/classes - -rm -fr $(ROOT)/WEB-INF/lib - cp -r $(JSRC)/classes $(ROOT)/WEB-INF/ - cp -r $(JSRC)/lib $(ROOT)/WEB-INF/ - -clean: clean-libs - make -C $(JSRC) clean - rm -fr $(ROOT)/WEB-INF/classes - rm -fr $(ROOT)/WEB-INF/lib - - - - -.PHONY: war -war: - cat resources/web.xml-begining resources/web.xml-format-filter resources/web.xml-$(AUTH)-filter resources/web.xml-authorization-filter resources/web.xml-servlets resources/web.xml-ending > $(ROOT)/WEB-INF/web.xml - #cat resources/web.xml-begining resources/web.xml-servlets resources/web.xml-ending > $(ROOT)/WEB-INF/web.xml - @jar -cf $(WEBAPP_WAR) -C $(ROOT) index.html \ - $(ROOT)/*.xsl \ - $(ROOT)/*.js \ - $(ROOT)/WEB-INF/*.xml \ - $(ROOT)/WEB-INF/classes/* \ - $(ROOT)/WEB-INF/lib/*.jar - @ls -l $(WEBAPP_WAR) - - -.PHONY: uninstall -uninstall : - rm -f $(ROOT)/WEB-INF/*.xml* $(WEBAPP_WAR) - - -.PHONY: test -test: - @echo "WEBAPP_WAR : "$(WEBAPP_WAR) - @echo "ROOT : "$(ROOT) - -.PHONY: testwar -testwar: - jar -tf $(WEBAPP_WAR) diff --git a/data-discovery/config/auth.properties b/data-discovery/config/auth.properties deleted file mode 100644 index c9c8aee27f0017b03a10a17896236eae4a93a018..0000000000000000000000000000000000000000 --- a/data-discovery/config/auth.properties +++ /dev/null @@ -1,10 +0,0 @@ -rap_uri=https://sso.ia2.inaf.it/rap-ia2 -gms_uri=https://sso.ia2.inaf.it/gms -client_id=vospace_ui_demo -client_secret=VOSpaceDemo123 - -groups_autoload=true -store_state_on_login_endpoint=true -scope=openid email profile read:rap - -allow_anonymous_access=true diff --git a/data-discovery/config/iamtoken.properties b/data-discovery/config/iamtoken.properties deleted file mode 100644 index e0935bb1f2d6f832b04b22c9dac817eac6741e5d..0000000000000000000000000000000000000000 --- a/data-discovery/config/iamtoken.properties +++ /dev/null @@ -1,10 +0,0 @@ - -#jwks_url=https://iam-escape.cloud.cnaf.infn.it/jwk -introspect=https://iam-escape.cloud.cnaf.infn.it/introspect -client_name=02cc260f-9837-4907-b2cb-a1a2d764fb15 -client_password=AJMi3qrB6AHRp_6y55tEwU-IpJ8uZ6X4QXeQ3W4la6dc-BlkzAY1OQpAE9hb1W7-VfYl4208FUtjE2Cl3hUYLkQ - -resource_id=vlkb - -non_authn_username=anonymous - diff --git a/data-discovery/config/neatoken.properties b/data-discovery/config/neatoken.properties deleted file mode 100644 index 21793e2600441bc6122e1ce54387ad8525bbd297..0000000000000000000000000000000000000000 --- a/data-discovery/config/neatoken.properties +++ /dev/null @@ -1,7 +0,0 @@ - -jwks_url=https://sso.neanias.eu/auth/realms/neanias-production/protocol/openid-connect/certs - -resource_id=vlkb - -non_authn_username=anonymous - diff --git a/data-discovery/config/shiro.ini b/data-discovery/config/shiro.ini deleted file mode 100644 index 4324a25031ec4eab8cdd1b1aa288afd17f3300eb..0000000000000000000000000000000000000000 --- a/data-discovery/config/shiro.ini +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2013 Les Hazlewood and contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# INI configuration is very powerful and flexible, while still remaining succinct. -# Please http://shiro.apache.org/configuration.html and -# http://shiro.apache.org/web.html for more. - -[main] -shiro.loginUrl = /login.jsp -cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager -securityManager.cacheManager = $cacheManager -#securityManager.realm = $stormpathRealm - -[users] -# syntax: user = password , roles -vialactea = ia2vlkb, ROLE_ADMIN - -[roles] -ROLE_ADMIN = * - -[urls] -#/login.jsp = authc -/logout = logout -/** = authcBasic -#/ivoa/resources/basic/** = authcBasic -#/ivoa/resources/full/** = authc - diff --git a/data-discovery/mvn-build.sh b/data-discovery/mvn-build.sh index 3aefd995baff849e90f45657a2f7e57e1114380a..66c5f7ca30d884aaa332f38fb8d2bca9a6eb0efa 100755 --- a/data-discovery/mvn-build.sh +++ b/data-discovery/mvn-build.sh @@ -6,6 +6,5 @@ echo "class Version { static String asString = \"${VERSION}\";}" > src/main/java mvn package #JAVA_HOME=/usr/lib/jvm/java-17-openjdk-17.0.9.0.9-3.fc38.x86_64 mvn package - # java show class version: # find . -name "*.class" -exec file -b {} \; | awk -F',' '{print $NF}' | sort -u diff --git a/data-discovery/mvn-install-local-deps.sh b/data-discovery/mvn-install-local-deps.sh deleted file mode 100755 index 41ee4fde7b3311b96aa4eddc580e378540b1e2cf..0000000000000000000000000000000000000000 --- a/data-discovery/mvn-install-local-deps.sh +++ /dev/null @@ -1,20 +0,0 @@ - -mvn install:install-file \ - -Dfile=src/main/java/vlkb/auth/ext/auth-lib-2.0.0-SNAPSHOT.jar \ - -DgroupId=it.inaf.ia2.aa.data \ - -DartifactId=auth-lib \ - -Dversion=2.0.0-SNAPSHOT \ - -Dpackaging=jar \ - -DgeneratePom=true - - - -mvn install:install-file \ - -Dfile=src/main/java/vlkb/auth/ext/rap-client-1.0-SNAPSHOT.jar \ - -DgroupId=it.inaf.ia2.rap.data \ - -DartifactId=rap-client \ - -Dversion=1.0-SNAPSHOT \ - -Dpackaging=jar \ - -DgeneratePom=true - - diff --git a/data-discovery/mvn-install-own-deps.sh b/data-discovery/mvn-install-own-deps.sh deleted file mode 100755 index 1ed3d8b97d2156780a8d190c1780760504c34e11..0000000000000000000000000000000000000000 --- a/data-discovery/mvn-install-own-deps.sh +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -mvn install:install-file \ - -Dfile=../java-libs/lib/auth-lib-2.0.0-SNAPSHOT.jar \ - -DgroupId=it.inaf.ia2 \ - -DartifactId=auth-lib \ - -Dversion=2.0.0-SNAPSHOT \ - -Dpackaging=jar \ - -DgeneratePom=true - -mvn install:install-file \ - -Dfile=../java-libs/lib/rap-client-1.0-SNAPSHOT.jar \ - -DgroupId=it.inaf.ia2 \ - -DartifactId=rap-client \ - -Dversion=1.0-SNAPSHOT \ - -Dpackaging=jar \ - -DgeneratePom=true - - diff --git a/data-discovery/notes-separate-search-from-dacc.tex b/data-discovery/notes-separate-search-from-dacc.tex deleted file mode 100644 index 554ead5e25045e03fdf8a429a95595f39e506d54..0000000000000000000000000000000000000000 --- a/data-discovery/notes-separate-search-from-dacc.tex +++ /dev/null @@ -1,67 +0,0 @@ - - -commons: - -Settings --> duplicate accepatble --> common-beans lib ? - -Subsurvey --> out of the scope of the search-problem/design concern (belongs to presentation-problem): solve by filter run after search, on search results: array of ID's (sewarch problem: based Coord's identify data by ID's (IN: Coords OUT: array os ID's; Subsurvey are needed for presentation of the isearch-result) - - -AuthPolicy - the same as Subsurveys: not in search-problem area ; belongs to seacurity-problem (solve by separate filter run after the search and filtering output ID's) - - -Coord : duplicate acceptable [ truly common -> (vo-beans? small lib of commons?)] - -Inputs : (aggregate of all of the above) ??? - -SubsurveyId : search inut param and result presentation-problem area - dacc vlkb-specific: header update feature-related (not part of the strict dacc-problem area) - - - - - -search-servlet --> auth-filter(output-ID array) --> presentation-xml-filter - -dacc-servlet --> auth-filter(input-ID array) --> update fits-header - --------------------------------------------- -'Pure' search and 'pure' dacc design: - -definitions: -pure-search operates on ObsCore. Input: coords Output: list of publisher-did's -pure-dacc operates on disk-files: Input: ID + coords Output: cut data in a file - -commons: - -Settings -> duplicate ok - -Subsurvey metadata -> not needed neither pure-search nor pure-dacc - -AuthPolicy -> not needed - -Coord: true common (use vo-beans lib approach?) - -SubsurveyId -> search-only (input-para-param) - - -------------------------------------------------- -TODO. - -SubsurveyMetadata - table holding in memory subsurveys metadata from csv file read at app init. - - provides: extraCards for vlkb-soda to update headers --> needs subsurveyId !! - metadata set for search result-xml -(put into all Servlet code : Serlvets must not contain any Survey[] array: loadCsv inside SubsurveyMetadata class; not Servlets) -remains common but later easier to move to Filter - -Currently VlkbSql needed in dacc due to resolveByMapping() call using DB to resolve legacy pubdid (generated -from dir and filename of the fitsfile replacing / and spaces with _ and - respectibely - this process being non-reversible) - -RESULT: Subsurvey + SubsurveyId = SubsurveyMetadata and should be active only in vlkb-compatibility mode - -Additionally: -* search results (for vlkb) must be array if pairs: (publisherDid, [subsurveyId]) ?? check SIAv2 : sia should identify rows in ObsCore ?? -* input to dacc (for vlkb-soda) must resolve to hdu or the pair: fitspathanme+hdunnum + [subsurveyID] - if no header-updates, then no subsurveyId needed - - - diff --git a/data-discovery/pom.xml b/data-discovery/pom.xml index f4708cc4830da8909ddea712079fdef6443a1af3..3f192d2c67ea2199e3cb65236135745332ca1961 100644 --- a/data-discovery/pom.xml +++ b/data-discovery/pom.xml @@ -19,22 +19,6 @@ <dependencies> - <!-- local --> - <dependency> - <groupId>it.inaf.ia2</groupId> - <artifactId>auth-lib</artifactId> - <version>2.0.0-SNAPSHOT</version> - <scope>provided</scope> - </dependency> - - <!-- local --> - <dependency> - <groupId>it.inaf.ia2</groupId> - <artifactId>rap-client</artifactId> - <version>1.0-SNAPSHOT</version> - <scope>provided</scope> - </dependency> - <!-- local --> <dependency> <groupId>vo</groupId> @@ -112,6 +96,8 @@ <scope>provided</scope> </dependency> + <!-- vlkb-volib dependencies --> + <!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple --> <dependency> <groupId>com.googlecode.json-simple</groupId> @@ -119,20 +105,6 @@ <version>1.1</version> </dependency> - <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api --> - <dependency> - <groupId>io.jsonwebtoken</groupId> - <artifactId>jjwt-api</artifactId> - <version>0.11.5</version> - </dependency> - - <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson --> - <dependency> - <groupId>io.jsonwebtoken</groupId> - <artifactId>jjwt-jackson</artifactId> - <version>0.11.5</version> - </dependency> - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> diff --git a/data-discovery/src/main/resources/authpolicy.properties b/data-discovery/src/main/resources/authpolicy.properties deleted file mode 100644 index d1d5756218a28b49df6e1f92a8828c9f62c24cac..0000000000000000000000000000000000000000 --- a/data-discovery/src/main/resources/authpolicy.properties +++ /dev/null @@ -1,7 +0,0 @@ -# database for table with permissions -db_uri= -db_schema= -db_user_name= -db_password= - - diff --git a/data-discovery/src/main/webapp/WEB-INF/web-search-garrtoken.xml b/data-discovery/src/main/webapp/WEB-INF/web-search-garrtoken.xml deleted file mode 100644 index b814b2a15fea714d2b1f96a45af394904ddc9258..0000000000000000000000000000000000000000 --- a/data-discovery/src/main/webapp/WEB-INF/web-search-garrtoken.xml +++ /dev/null @@ -1,76 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. ---> - -<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> - <display-name>Via Lactea. Query FITS datacubes.</display-name> - <distributable/> - - - <filter> - <filter-name>FormatResponseFilter</filter-name> - <filter-class>FormatResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>FormatResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - - <filter> - <filter-name>TokenFilter</filter-name> - <filter-class>NeaTokenFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>TokenFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - <filter> - <filter-name>AuthorizationResponseFilter</filter-name> - <filter-class>AuthorizationResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>AuthorizationResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - -<servlet> - <servlet-name>vlkb_search</servlet-name> - <servlet-class>SearchServlet</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_search</servlet-name> - <url-pattern></url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_availability</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_availability</servlet-name> - <url-pattern>/availability</url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <url-pattern>/capabilities</url-pattern> -</servlet-mapping> - - -</web-app> - - diff --git a/data-discovery/src/main/webapp/WEB-INF/web-search-ia2token.xml b/data-discovery/src/main/webapp/WEB-INF/web-search-ia2token.xml deleted file mode 100644 index 54dd67150f867fae0c6a069aa495c96c84f72dd8..0000000000000000000000000000000000000000 --- a/data-discovery/src/main/webapp/WEB-INF/web-search-ia2token.xml +++ /dev/null @@ -1,87 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. ---> - -<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> - <display-name>Via Lactea. Query FITS datacubes.</display-name> - <distributable/> - - - <filter> - <filter-name>FormatResponseFilter</filter-name> - <filter-class>FormatResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>FormatResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - - <filter> - <filter-name>TokenFilter</filter-name> - <filter-class>it.inaf.ia2.aa.TokenFilter</filter-class> - </filter> - - <filter-mapping> - <filter-name>TokenFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - <filter> - <filter-name>UserTypeConverter</filter-name> - <filter-class>IA2TokenConvFilter</filter-class> - </filter> - - <filter-mapping> - <filter-name>UserTypeConverter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - <filter> - <filter-name>AuthorizationResponseFilter</filter-name> - <filter-class>AuthorizationResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>AuthorizationResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - -<servlet> - <servlet-name>vlkb_search</servlet-name> - <servlet-class>SearchServlet</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_search</servlet-name> - <url-pattern></url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_availability</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_availability</servlet-name> - <url-pattern>/availability</url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <url-pattern>/capabilities</url-pattern> -</servlet-mapping> - - -</web-app> - - diff --git a/data-discovery/src/main/webapp/WEB-INF/web-search-iamtoken.xml b/data-discovery/src/main/webapp/WEB-INF/web-search-iamtoken.xml deleted file mode 100644 index 8cde90b5b438e1dfe1d7884f32b5814be86d7645..0000000000000000000000000000000000000000 --- a/data-discovery/src/main/webapp/WEB-INF/web-search-iamtoken.xml +++ /dev/null @@ -1,76 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. ---> - -<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> - <display-name>Via Lactea. Query FITS datacubes.</display-name> - <distributable/> - - - <filter> - <filter-name>FormatResponseFilter</filter-name> - <filter-class>FormatResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>FormatResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - - <filter> - <filter-name>TokenFilter</filter-name> - <filter-class>IamTokenFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>TokenFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - <filter> - <filter-name>AuthorizationResponseFilter</filter-name> - <filter-class>AuthorizationResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>AuthorizationResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - -<servlet> - <servlet-name>vlkb_search</servlet-name> - <servlet-class>SearchServlet</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_search</servlet-name> - <url-pattern></url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_availability</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_availability</servlet-name> - <url-pattern>/availability</url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <url-pattern>/capabilities</url-pattern> -</servlet-mapping> - - -</web-app> - - diff --git a/data-discovery/src/main/webapp/WEB-INF/web.xml b/data-discovery/src/main/webapp/WEB-INF/web.xml index bdd5291f861b2559bc588a23b7250aae7a3ce2ad..fa3a7e50a377521afaf053d921f4584e306528db 100644 --- a/data-discovery/src/main/webapp/WEB-INF/web.xml +++ b/data-discovery/src/main/webapp/WEB-INF/web.xml @@ -6,6 +6,7 @@ --> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> + <display-name>Via Lactea. Query FITS datacubes.</display-name> <distributable/> @@ -20,82 +21,34 @@ </filter-mapping> -<!-- uncomment IA2 or GARR authorization filter to enable security - - <filter> - <filter-name>TokenFilter</filter-name> - <filter-class>it.inaf.ia2.aa.TokenFilter</filter-class> - </filter> - - <filter-mapping> - <filter-name>TokenFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - <filter> - <filter-name>UserTypeConverter</filter-name> - <filter-class>IA2TokenConvFilter</filter-class> - </filter> - - <filter-mapping> - <filter-name>UserTypeConverter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - - - <filter> - <filter-name>TokenFilter</filter-name> - <filter-class>NeaAuthFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>TokenFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> ---> - -<!-- additionally uncomment this to enable groups-based authorization check - <filter> - <filter-name>AuthorizationResponseFilter</filter-name> - <filter-class>AuthorizationResponseFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>AuthorizationResponseFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> ---> - - - -<servlet> - <servlet-name>vlkb_search</servlet-name> - <servlet-class>SearchServlet</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_search</servlet-name> - <url-pattern></url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_availability</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_availability</servlet-name> - <url-pattern>/availability</url-pattern> -</servlet-mapping> - - -<servlet> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <servlet-class>VlkbServletFile</servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>vlkb_vosi_capabilities</servlet-name> - <url-pattern>/capabilities</url-pattern> -</servlet-mapping> - + <servlet> + <servlet-name>vlkb_search</servlet-name> + <servlet-class>SearchServlet</servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>vlkb_search</servlet-name> + <url-pattern></url-pattern> + </servlet-mapping> + + + <servlet> + <servlet-name>vlkb_vosi_availability</servlet-name> + <servlet-class>VlkbServletFile</servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>vlkb_vosi_availability</servlet-name> + <url-pattern>/availability</url-pattern> + </servlet-mapping> + + + <servlet> + <servlet-name>vlkb_vosi_capabilities</servlet-name> + <servlet-class>VlkbServletFile</servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>vlkb_vosi_capabilities</servlet-name> + <url-pattern>/capabilities</url-pattern> + </servlet-mapping> </web-app>