removes the privileged data source from the application and the ability to have a web UI for a setup

Sat, 31 Mar 2018 18:11:09 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 31 Mar 2018 18:11:09 +0200
changeset 19
1a0ac419f714
parent 18
a94b172c3a93
child 20
bd1a76c91d5b

removes the privileged data source from the application and the ability to have a web UI for a setup

This is a permanent decision: setups should be performed on the server by some admin. There is too much, which could go wrong and we have little chance to catch anything within a web UI.

src/java/de/uapcore/lightpit/Constants.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/DatabaseFacade.java file | annotate | diff | comparison | revisions
web/META-INF/context.xml file | annotate | diff | comparison | revisions
--- a/src/java/de/uapcore/lightpit/Constants.java	Sun Dec 31 17:43:39 2017 +0100
+++ b/src/java/de/uapcore/lightpit/Constants.java	Sat Mar 31 18:11:09 2018 +0200
@@ -59,6 +59,11 @@
     public static final String CTX_ATTR_DB_SCHEMA = "db-schema";
     
     /**
+     * Name for the context parameter optionally specifying a database dialect.
+     */
+    public static final String CTX_ATTR_DB_DIALECT = "db-dialect";
+    
+    /**
      * Key for the request attribute containing the class name of the currently dispatching module.
      */
     public static final String REQ_ATTR_MODULE_CLASSNAME = fqn(AbstractLightPITServlet.class, "moduleClassname");
--- a/src/java/de/uapcore/lightpit/DatabaseFacade.java	Sun Dec 31 17:43:39 2017 +0100
+++ b/src/java/de/uapcore/lightpit/DatabaseFacade.java	Sat Mar 31 18:11:09 2018 +0200
@@ -56,76 +56,52 @@
      */
     private static final int DB_TEST_TIMEOUT = 10;
     
+    public static enum Dialect {
+        Postgres;
+    }
+    
+    /**
+     * The database dialect to use.
+     * 
+     * May be override by context parameter.
+     * 
+     * @see Constants#CTX_ATTR_DB_DIALECT
+     */
+    private Dialect dialect = Dialect.Postgres;
+    
     /**
      * The default schema to test against when validating the connection.
      * 
      * May be overridden by context parameter.
+     * 
+     * @see Constants#CTX_ATTR_DB_SCHEMA
      */
     private static final String DB_DEFAULT_SCHEMA = "lightpit";
     
     /**
-     * The attribute name in the servlet context under which an instance of this class can be found.
+     * The attribute name in the Servlet context under which an instance of this class can be found.
      */
     public static final String SC_ATTR_NAME = DatabaseFacade.class.getName();
     private ServletContext sc;
     
-    private static final String PRIVILEGED_DS_JNDI_NAME = "jdbc/lightpit/dbo";
-    private Optional<DataSource> privilegedDataSource;
+    private static final String DS_JNDI_NAME = "jdbc/lightpit/app";
+    private Optional<DataSource> dataSource;
     
-    private static final String UNPRIVILEGED_DS_JNDI_NAME = "jdbc/lightpit/app";
-    private Optional<DataSource> unprivilegedDataSource;
-    
-
     /**
-     * Returns an optional privileged data source.
-     * 
-     * Privileged data sources should be able to execute any kind of DDL
-     * statements to perform installation or configuration steps.
-     * 
-     * This optional should always be empty in live operation. Modules which
-     * provide installation or configuration steps MUST check the presence of
-     * a privileged data source and SHOULD display an informative message if
-     * it is currently disabled.
-     * 
-     * @return an optional privileged data source
-     */
-    public Optional<DataSource> getPrivilegedDataSource() {
-        return privilegedDataSource;
-    }
-
-    /**
-     * Returns an optional unprivileged data source.
+     * Returns the data source.
      * 
      * The Optional returned should never be empty. However, if something goes
      * wrong during initialization, the data source might be absent.
      * Hence, users of this data source are forced to check the existence.
      * 
-     * @return an optional unprivileged data source
-     */
-    public Optional<DataSource> getUnprivilegedDataSource() {
-        return unprivilegedDataSource;
-    }
-
-    /**
-     * Returns the JNDI resource name of the privileged data source.
-     * 
-     * Modules may use this information to provide useful information to the user.
-     * 
-     * @return the JNDI resource name of the privileged data source
+     * @return a data source
      */
-    public String getPrivilegedDataSourceJNDIName() {
-        return PRIVILEGED_DS_JNDI_NAME;
+    public Optional<DataSource> getDataSource() {
+        return dataSource;
     }
-
-    /**
-     * Returns the JNDI resource name of the unprivileged data source.
-     * 
-     * Modules may use this information to provide useful information to the user.
-     * 
-     * @return the JNDI resource name of the unprivileged data source
-     */
-    public String getUnprivilegedDataSourceJNDIName() {
-        return UNPRIVILEGED_DS_JNDI_NAME;
+    
+    public Dialect getSQLDialect() {
+        return dialect;
     }
     
     private static void checkConnection(DataSource ds, String testSchema, String errMsg) {
@@ -146,28 +122,13 @@
         }
     }
     
-    private static Optional<DataSource> retrievePrivilegedDataSource(Context ctx) {
+    private static Optional<DataSource> retrieveDataSource(Context ctx) {
         DataSource ret = null;
         try {
-            ret = (DataSource)ctx.lookup(PRIVILEGED_DS_JNDI_NAME);
-            LOG.info("Privileged data source {} retrieved from context.", PRIVILEGED_DS_JNDI_NAME);
-            LOG.warn("Your application may be vulnerable due to privileged database access. Make sure that privileged data sources are only available during installation or configuration.");
+            ret = (DataSource)ctx.lookup(DS_JNDI_NAME);
+            LOG.info("Data source retrieved.");
         } catch (NamingException ex) {
-            LOG.info("Privileged data source not available. This is perfectly OK. Activate only, if you need to do installation or configuration.");
-            /* in case the absence of the DataSource is not intended, log something more useful on debug level */
-            LOG.debug("Reason for the missing data source: ", ex);
-        }
-        return Optional.ofNullable(ret);
-    }
-    
-    private static Optional<DataSource> retrieveUnprivilegedDataSource(Context ctx) {
-        DataSource ret = null;
-        try {
-            ret = (DataSource)ctx.lookup(UNPRIVILEGED_DS_JNDI_NAME);
-            LOG.info("Unprivileged data source retrieved.");
-        } catch (NamingException ex) {
-            LOG.error("Unprivileged data source {} not available.", UNPRIVILEGED_DS_JNDI_NAME);
-            /* for the unprivileged DataSource log the exception on error level (ordinary admins could find this useful) */
+            LOG.error("Data source {} not available.", DS_JNDI_NAME);
             LOG.error("Reason for the missing data source: ", ex);
         }
         return Optional.ofNullable(ret);
@@ -177,7 +138,7 @@
     public void contextInitialized(ServletContextEvent sce) {
         sc = sce.getServletContext();
         
-        privilegedDataSource = unprivilegedDataSource = null;
+        dataSource = null;
         
         final String contextName = Optional
                 .ofNullable(sc.getInitParameter(Constants.CTX_ATTR_JNDI_CONTEXT))
@@ -185,17 +146,23 @@
         final String dbSchema = Optional
                 .ofNullable(sc.getInitParameter(Constants.CTX_ATTR_DB_SCHEMA))
                 .orElse(DB_DEFAULT_SCHEMA);
+        final String dbDialect = sc.getInitParameter(Constants.CTX_ATTR_DB_DIALECT);
+        if (dbDialect != null) {
+            try {
+                dialect = Dialect.valueOf(dbDialect);
+            } catch (IllegalArgumentException ex) {
+                LOG.error(String.format("Unknown or unsupported database dialect %s. Defaulting to %s.", dbDialect, dialect));
+            }
+        }
 
         try {
             LOG.debug("Trying to access JNDI context {}...", contextName);
             Context initialCtx = new InitialContext();
             Context ctx = (Context) initialCtx.lookup(contextName);
             
-            privilegedDataSource = retrievePrivilegedDataSource(ctx);
-            unprivilegedDataSource = retrieveUnprivilegedDataSource(ctx);
+            dataSource = retrieveDataSource(ctx);
             
-            privilegedDataSource.ifPresent((ds) -> checkConnection(ds, dbSchema, "Checking privileged connection failed"));
-            unprivilegedDataSource.ifPresent((ds) -> checkConnection(ds, dbSchema, "Checking unprivileged connection failed"));
+            dataSource.ifPresent((ds) -> checkConnection(ds, dbSchema, "Checking database connection failed"));
         } catch (NamingException | ClassCastException ex) {
             LOG.error("Cannot access JNDI resources.", ex);
         }
@@ -206,6 +173,6 @@
 
     @Override
     public void contextDestroyed(ServletContextEvent sce) {
-        privilegedDataSource = unprivilegedDataSource = null;
+        dataSource = null;
     }    
 }
--- a/web/META-INF/context.xml	Sun Dec 31 17:43:39 2017 +0100
+++ b/web/META-INF/context.xml	Sat Mar 31 18:11:09 2018 +0200
@@ -2,10 +2,5 @@
 <Context path="/lightpit">
     <ResourceLink name="jdbc/lightpit/app"
                   global="jdbc/lightpit/app"
-                    type="javax.sql.DataSource" />
-    
-    <!-- Remove this link after installation and configuration -->
-    <ResourceLink name="jdbc/lightpit/dbo"
-                  global="jdbc/lightpit/dbo"
-                    type="javax.sql.DataSource" />
+                  type="javax.sql.DataSource" />
 </Context>

mercurial