Sat, 31 Mar 2018 18:11:09 +0200
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.
1.1 --- a/src/java/de/uapcore/lightpit/Constants.java Sun Dec 31 17:43:39 2017 +0100 1.2 +++ b/src/java/de/uapcore/lightpit/Constants.java Sat Mar 31 18:11:09 2018 +0200 1.3 @@ -59,6 +59,11 @@ 1.4 public static final String CTX_ATTR_DB_SCHEMA = "db-schema"; 1.5 1.6 /** 1.7 + * Name for the context parameter optionally specifying a database dialect. 1.8 + */ 1.9 + public static final String CTX_ATTR_DB_DIALECT = "db-dialect"; 1.10 + 1.11 + /** 1.12 * Key for the request attribute containing the class name of the currently dispatching module. 1.13 */ 1.14 public static final String REQ_ATTR_MODULE_CLASSNAME = fqn(AbstractLightPITServlet.class, "moduleClassname");
2.1 --- a/src/java/de/uapcore/lightpit/DatabaseFacade.java Sun Dec 31 17:43:39 2017 +0100 2.2 +++ b/src/java/de/uapcore/lightpit/DatabaseFacade.java Sat Mar 31 18:11:09 2018 +0200 2.3 @@ -56,76 +56,52 @@ 2.4 */ 2.5 private static final int DB_TEST_TIMEOUT = 10; 2.6 2.7 + public static enum Dialect { 2.8 + Postgres; 2.9 + } 2.10 + 2.11 + /** 2.12 + * The database dialect to use. 2.13 + * 2.14 + * May be override by context parameter. 2.15 + * 2.16 + * @see Constants#CTX_ATTR_DB_DIALECT 2.17 + */ 2.18 + private Dialect dialect = Dialect.Postgres; 2.19 + 2.20 /** 2.21 * The default schema to test against when validating the connection. 2.22 * 2.23 * May be overridden by context parameter. 2.24 + * 2.25 + * @see Constants#CTX_ATTR_DB_SCHEMA 2.26 */ 2.27 private static final String DB_DEFAULT_SCHEMA = "lightpit"; 2.28 2.29 /** 2.30 - * The attribute name in the servlet context under which an instance of this class can be found. 2.31 + * The attribute name in the Servlet context under which an instance of this class can be found. 2.32 */ 2.33 public static final String SC_ATTR_NAME = DatabaseFacade.class.getName(); 2.34 private ServletContext sc; 2.35 2.36 - private static final String PRIVILEGED_DS_JNDI_NAME = "jdbc/lightpit/dbo"; 2.37 - private Optional<DataSource> privilegedDataSource; 2.38 + private static final String DS_JNDI_NAME = "jdbc/lightpit/app"; 2.39 + private Optional<DataSource> dataSource; 2.40 2.41 - private static final String UNPRIVILEGED_DS_JNDI_NAME = "jdbc/lightpit/app"; 2.42 - private Optional<DataSource> unprivilegedDataSource; 2.43 - 2.44 - 2.45 /** 2.46 - * Returns an optional privileged data source. 2.47 - * 2.48 - * Privileged data sources should be able to execute any kind of DDL 2.49 - * statements to perform installation or configuration steps. 2.50 - * 2.51 - * This optional should always be empty in live operation. Modules which 2.52 - * provide installation or configuration steps MUST check the presence of 2.53 - * a privileged data source and SHOULD display an informative message if 2.54 - * it is currently disabled. 2.55 - * 2.56 - * @return an optional privileged data source 2.57 - */ 2.58 - public Optional<DataSource> getPrivilegedDataSource() { 2.59 - return privilegedDataSource; 2.60 - } 2.61 - 2.62 - /** 2.63 - * Returns an optional unprivileged data source. 2.64 + * Returns the data source. 2.65 * 2.66 * The Optional returned should never be empty. However, if something goes 2.67 * wrong during initialization, the data source might be absent. 2.68 * Hence, users of this data source are forced to check the existence. 2.69 * 2.70 - * @return an optional unprivileged data source 2.71 + * @return a data source 2.72 */ 2.73 - public Optional<DataSource> getUnprivilegedDataSource() { 2.74 - return unprivilegedDataSource; 2.75 + public Optional<DataSource> getDataSource() { 2.76 + return dataSource; 2.77 } 2.78 - 2.79 - /** 2.80 - * Returns the JNDI resource name of the privileged data source. 2.81 - * 2.82 - * Modules may use this information to provide useful information to the user. 2.83 - * 2.84 - * @return the JNDI resource name of the privileged data source 2.85 - */ 2.86 - public String getPrivilegedDataSourceJNDIName() { 2.87 - return PRIVILEGED_DS_JNDI_NAME; 2.88 - } 2.89 - 2.90 - /** 2.91 - * Returns the JNDI resource name of the unprivileged data source. 2.92 - * 2.93 - * Modules may use this information to provide useful information to the user. 2.94 - * 2.95 - * @return the JNDI resource name of the unprivileged data source 2.96 - */ 2.97 - public String getUnprivilegedDataSourceJNDIName() { 2.98 - return UNPRIVILEGED_DS_JNDI_NAME; 2.99 + 2.100 + public Dialect getSQLDialect() { 2.101 + return dialect; 2.102 } 2.103 2.104 private static void checkConnection(DataSource ds, String testSchema, String errMsg) { 2.105 @@ -146,28 +122,13 @@ 2.106 } 2.107 } 2.108 2.109 - private static Optional<DataSource> retrievePrivilegedDataSource(Context ctx) { 2.110 + private static Optional<DataSource> retrieveDataSource(Context ctx) { 2.111 DataSource ret = null; 2.112 try { 2.113 - ret = (DataSource)ctx.lookup(PRIVILEGED_DS_JNDI_NAME); 2.114 - LOG.info("Privileged data source {} retrieved from context.", PRIVILEGED_DS_JNDI_NAME); 2.115 - 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."); 2.116 + ret = (DataSource)ctx.lookup(DS_JNDI_NAME); 2.117 + LOG.info("Data source retrieved."); 2.118 } catch (NamingException ex) { 2.119 - LOG.info("Privileged data source not available. This is perfectly OK. Activate only, if you need to do installation or configuration."); 2.120 - /* in case the absence of the DataSource is not intended, log something more useful on debug level */ 2.121 - LOG.debug("Reason for the missing data source: ", ex); 2.122 - } 2.123 - return Optional.ofNullable(ret); 2.124 - } 2.125 - 2.126 - private static Optional<DataSource> retrieveUnprivilegedDataSource(Context ctx) { 2.127 - DataSource ret = null; 2.128 - try { 2.129 - ret = (DataSource)ctx.lookup(UNPRIVILEGED_DS_JNDI_NAME); 2.130 - LOG.info("Unprivileged data source retrieved."); 2.131 - } catch (NamingException ex) { 2.132 - LOG.error("Unprivileged data source {} not available.", UNPRIVILEGED_DS_JNDI_NAME); 2.133 - /* for the unprivileged DataSource log the exception on error level (ordinary admins could find this useful) */ 2.134 + LOG.error("Data source {} not available.", DS_JNDI_NAME); 2.135 LOG.error("Reason for the missing data source: ", ex); 2.136 } 2.137 return Optional.ofNullable(ret); 2.138 @@ -177,7 +138,7 @@ 2.139 public void contextInitialized(ServletContextEvent sce) { 2.140 sc = sce.getServletContext(); 2.141 2.142 - privilegedDataSource = unprivilegedDataSource = null; 2.143 + dataSource = null; 2.144 2.145 final String contextName = Optional 2.146 .ofNullable(sc.getInitParameter(Constants.CTX_ATTR_JNDI_CONTEXT)) 2.147 @@ -185,17 +146,23 @@ 2.148 final String dbSchema = Optional 2.149 .ofNullable(sc.getInitParameter(Constants.CTX_ATTR_DB_SCHEMA)) 2.150 .orElse(DB_DEFAULT_SCHEMA); 2.151 + final String dbDialect = sc.getInitParameter(Constants.CTX_ATTR_DB_DIALECT); 2.152 + if (dbDialect != null) { 2.153 + try { 2.154 + dialect = Dialect.valueOf(dbDialect); 2.155 + } catch (IllegalArgumentException ex) { 2.156 + LOG.error(String.format("Unknown or unsupported database dialect %s. Defaulting to %s.", dbDialect, dialect)); 2.157 + } 2.158 + } 2.159 2.160 try { 2.161 LOG.debug("Trying to access JNDI context {}...", contextName); 2.162 Context initialCtx = new InitialContext(); 2.163 Context ctx = (Context) initialCtx.lookup(contextName); 2.164 2.165 - privilegedDataSource = retrievePrivilegedDataSource(ctx); 2.166 - unprivilegedDataSource = retrieveUnprivilegedDataSource(ctx); 2.167 + dataSource = retrieveDataSource(ctx); 2.168 2.169 - privilegedDataSource.ifPresent((ds) -> checkConnection(ds, dbSchema, "Checking privileged connection failed")); 2.170 - unprivilegedDataSource.ifPresent((ds) -> checkConnection(ds, dbSchema, "Checking unprivileged connection failed")); 2.171 + dataSource.ifPresent((ds) -> checkConnection(ds, dbSchema, "Checking database connection failed")); 2.172 } catch (NamingException | ClassCastException ex) { 2.173 LOG.error("Cannot access JNDI resources.", ex); 2.174 } 2.175 @@ -206,6 +173,6 @@ 2.176 2.177 @Override 2.178 public void contextDestroyed(ServletContextEvent sce) { 2.179 - privilegedDataSource = unprivilegedDataSource = null; 2.180 + dataSource = null; 2.181 } 2.182 }
3.1 --- a/web/META-INF/context.xml Sun Dec 31 17:43:39 2017 +0100 3.2 +++ b/web/META-INF/context.xml Sat Mar 31 18:11:09 2018 +0200 3.3 @@ -2,10 +2,5 @@ 3.4 <Context path="/lightpit"> 3.5 <ResourceLink name="jdbc/lightpit/app" 3.6 global="jdbc/lightpit/app" 3.7 - type="javax.sql.DataSource" /> 3.8 - 3.9 - <!-- Remove this link after installation and configuration --> 3.10 - <ResourceLink name="jdbc/lightpit/dbo" 3.11 - global="jdbc/lightpit/dbo" 3.12 - type="javax.sql.DataSource" /> 3.13 + type="javax.sql.DataSource" /> 3.14 </Context>