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
     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>

mercurial