Multi Tenancy and Configuration

For some more background see also this summary of discussions in the Sling Mailing List.

PRIO 1 Configuration levels

The term "tenant" is not enough to describe the configuration separation requirements. Instead of a flat list of tenants, we need to distinguish different levels of "configurability".

We differentiate the following levels:

  1. Global (whole system)
    1. Global all instances
    2. Global instance type-specific
    3. Global application-specific
  2. Region(s)
  3. Site
  4. Language

The "Global" level needs more explanation:

  • "Global all instances": is a configuration that is the same for all instances, all applications, all regions, sites and languages.
  • "Global instance-specific": like "global all instances", but the configuration may differ depending on the instance type, e.g. master vs. slave in a cluster
  • "Global application-specific":
    • Multiple applications are deployed on the same instance with different sets of templates and components
    • Each site uses only the templates and components of one application, but all are hosted on the same instance
    • Multiple sites exists in different regions, every using the templates and components of one of the applications
    • Some shared functionality is configured differently depending on the application/template set used for a site
    • Example: The rewriter logic should behave differently depending on the application/template set
    • How to detect the application for a given resource context? It is not possible to differentiate between the applications just based a content root path like /content/app1, /content/app2. The safest way is to check the application of the associated resource. Or a regexp matching of the resource path based on certain conventions which path parts are mandatory for the different applications - e.g. /content/.*/app1/.*

The other levels "Region(s)", "Site" and "Language" can be mapped directly to the content hierarchy. "Region(s)" may be one or more levels.

PRIO 1 Configuration inheritance

Some parameters are only used on global level, no inheritance concept is used here. Each parameter has a default value set by the application which defines the parameter.

Other parameters are used on Site/Language level. For those a configuration parameter inheritance is required which allows to define and override the default configuration values for parameters on the levels higher than Site/Language.

E.g. a configuration parameter which controls which activates a feature in a site is set to "on" on global level, but is overridden on some sites where it is set to "off".

A "force mode" should be available which allows setting the parameter value on a higher level without the possibility to overwrite it on the Site/Language level.

The inheritance is either based on the configuration level hierarchy/content path hierarchy, or by explicitly selecting an "inheritance parent" for each configuration location.

PRIO 1 Placeholder support

Often same values like URLs or paths have to be defined in multiple parameter values. It is helpful to have placeholder concept in configuration parameters which allows to define them centrally, but reference locally.

If a placeholder value is changed, all references configuration values have to be changed as well.

Additionally this is helpful to separate environment-dependent settings from other settings. E.g. all parameters that are different between stages like T&I, QS and Production could be extracted as parameters, allowing to deploy the same configuration package to all stages and only changing the placeholders per environment maintained in a separate package.

If has to be decided whether placeholders are supported only on global level, or a hierarchy, access control and inheritance concept is defined for them as well.

PRIO 1 Configuration change propagation

Every change that is done to the configuration should be propagated at once to the configuration consumers.

In case of OSGi services the OSGi configuration management should be used, which already defines the proper handling of configuration changes by either restarting the service or applying the configuration at runtime if the OSGi service supports it.

For all other areas it should be sufficient when the changed configuration parameters are active for the next request that is issued after the configuration change was done.

It should be possible to not only propagate each configuration change of each parameter or placeholder individually, but in bulk changes as well.

PRIO 2 Configuration access control

On global level, the configuration can be changed either by system administrators, or is part of the application deployment (e.g. when configuring built-in default features in an application-specific way).

For all other levels access control should be controlled by ACLs based on the configuration level hierarchy.

Sometimes it is required to further differentiate on a level e.g. in technical-related and business-related parameters, and to use different ACLs for both parts because different teams are responsible for them. But perhaps this can be solved using the configuration level hierarchy as well.

PRIO 2 Configuration provider

Different configuration provider should be allowed that can override each other.

The default configuration provider stores the configuration in the content repository. Thus it is of course possible to package this configuration and replicate it between instances.

Optionally further providers can be configured with either higher or lower priority than the default provider:

  • System environment parameter - e.g. to override certain parameters in a QS environment
  • HTTP Header - only if activated on a machine, e.g. to apply a specific configuration in an automated selenium acceptance test
  • External configuration management system

The configuration providers have not only take the configuration key/value pairs into account, but the configuration level hierarchy as well where they should be applied.

PRIO 1 Configuration parameter metadata

Each parameter has a unique name, using a namespace concept to ensure that application parameter names provided by different applications cannot clash.

Parameter value data types:

  • String
  • Content path (can be stored as string, but perhaps a browse widget in configuration editors would be useful)
  • Integer
  • Float
  • Boolean
  • Array of strings
  • List of key/value pairs
  • Matrix of key/named values pairs.
  • Complex structure e.g. JSON or XML, optionally with schema validation
  • Reference to security-relevant parameter value

Metadata for each configuration parameter:

  • Unique name and namespace
  • Description (Rich Text)
  • Data type
  • Configuration parameter level
  • Mandatory
  • Parameter group(s) - for grouped display in configuration editors
  • Default value
  • Allow override
  • Output channel=Frontend - parameters marked with this are made available via a REST interface for the javascript frontend of the application

Optional additional metadata that may be helpful to be displayed in a configuration editor:

  • Example value
  • Link to external documentation
  • Supported since application version X or up to version Y
  • Deprecated

PRIO 2 Configuration Editor

  • Ideally the same configuration editor can be used on all configuration levels
  • The configuration editor has to respect the ACLs for each configuration level
  • The list of configuration parameters can be filtered by application and parameter group
  • For each configuration parameter
    • Parameter name and the relevant metadata and documentation is displayed
    • The current configured value
    • It is visible if a parameter value is inherited from a higher level, or using its default value
    • The configured value is validated against its data type and perhaps schema
  • Allow copy+paste of bunches of parameter configurations between instances of the configuration editor
  • The configuration editor should provide a feature to see the "effective configuration", the configuration that is active including all default values and inherited values and resolved placholders. Much like the "effective POM" in Maven.

PRIO 2 Audit Logging and Diff Support

Changes to confguration parameters or placeholders should be versionable using the Repository Versioning mechanisms (either automatically or on activation or if a new version is requested by the user).

It has to be possible to do a Diff between configurations at different timepoints. This diff should not only possible for the local configuration element, but for the "effective configuration" as well (see Configuration editor).

In an audit log all change operations done to the configuration should be traced - comparable to the CQ audit log features for content pages.

PRIO 2 Security-relevant configuration data

  • Security-relevant configuration data like passwords should be configured only on global level or separately and referenced from the configuration editor.
  • Security-relevant configuration data should be stored encrypted in a safe way