Page tree
Skip to end of metadata
Go to start of metadata

WIP

This page is a work in progress


Overview

Centralized configuration via mod-configuration is problematic from a security perspective. It provides a convenient mechanism for storing configuration, but the permission granularity is too coarse. Granting a user the ability to access an entry for one app means that they will also have access to ALL configuration entries.

One idea was proposed that all modules have a system interface which can be implement (or not), which presents a common interface for accessing configuration specific to various modules.  This means the clients (the UI for instance) are presented a common interface for getting configuration instead of each module doing it their own way.

The "Configuration" System Interface

Modules can choose to implement this multiple interface "configuration"

  • GET /configurations/entries
  • GET /configurations/entries/<id>
  • POST /configurations/entries
  • PUT /configurations/entries/<id>
  • DELETE /configurations/entries/<id>

Each of which would be protected by discrete permissions, e.g. mod-foo might have:

  • foo.configurations.collection.get,
  • foo.configurations.item.get (put/post/delete)

Storage Layer

TBD... Just because the configuration APIs are distributed doesn't mean the configuration information must be.  In the case of storage modules, they may choose to just store their configuration in postgres as doing so would probably require little effort.  For business logic modules, or modules which have specific needs (e.g. the configuration is sensitive and should be encrypted, etc.) could choose to use a central configuration module for storage.

Here's where it might make sense to pull in additional technologies that are better suited to these requirements.  See the Technologies section below.  Having a module that presents a common interface in front of these technologies which is used internally (i.e. intended to be called only by other modules, not directly by clients) is an option that provides flexibility and opens the door to many potential benefits.

mod-configuration-storage

  • Implements the configuration interface, or something that looks very similar.
  • Uses a java interface to allow developers to add support for various underlying storage technologies - Maybe the default is just postgresql?
  • Could enable multiple storage technologies, and the ability for the client to specify which storage they want to use...
    • This should be implemented via something like attributes so that the client doesn't need to know which storage technologies are available... just that there's one that has the attributes it cares about.
      • For instance - store this thing somewhere that's "secure".  The module then looks for a configured storage that has the "secure" attribute, and stores it there. 
      • We'd have to allow for the administrator/operator to specify an order of precedence to help the module choose the right one in some cases.

Configuration

  • Via json and/or properties config file(s)...
  • System property:  -DstorageConfigs=vault-config.properties,postgres-config.json

    • postgres-config.json:

      {
        "host":"localhost",
        "port":5432,
        "username":"folio",
        "password":"letmein",
        "database":"folio"
      }
    • vault-config.properties: 

      # Used by the factory class to match impl w/ config
      type=vault
      
      # the address of your vault
      # Default: http://127.0.0.1:8200
      address={VAULT_ADDR}
      
      # whether or not to use SSL [true|false]
      # Default: false
      enableSSL=true
      #
      # NOTE: JKS-based config trumps PEM-based config. If you provide both JKS and PEM configs,
      # then the JKS config will be used.
      # You cannot "mix-and-match", providing a JKS-based truststore and PEM-based client auth data.
      #
      # the path to an X.509 certificate in unencrypted PEM format, using UTF-8 encoding
      ssl.pem.path={PEM_PATH}
      #
      # the path to a JKS truststore file containing Vault server certs that can be trusted
      #ssl.truststore.jks.path={TRUSTSTORE_PATH}
      #
      # the path to a JKS keystore file containing a client cert and private key
      #ssl.keystore.jks.path={KEYSTORE_PATH}
      #
      # the password used to access the JKS keystore (optional)
      #ssl.keystore.password={KEYWORD_PASSWORD}
      

Technologies

This list isn't intended to be comprehensive, just to give an idea of the types of things I'm referring to.

Other Considerations

  • Migration of config data would need to be done on a per-module basis.  We could effectively deprecate mod-configuration and then at some later date retire/end-of-life it entirely.

JIRA

  • No labels

6 Comments

  1. Just to clarify. This configuration can be used by the backend module itself both in the context of tenants and let's say globally. If a tenant Id is provided, this is a configuration for this particular tenant, if not it means it is a global configuration. The case for this is a module startup and initialization.

  2. Also, it makes sense to provide out of the box connectors/adapters for the most useful/popular providers like Vault, PostgreSQL, Zookeeper

  3. Given that the intent behind distribution of the configuration is to partition it into more granular sets than can be accessed independently. I'm not sure I understand the re-consolidation of this information in storage.

    Would a client that has permissions to access the configuration storage API have the ability to access any configuration?

    1. I think the idea is that only modules would be able to call the configuration storage API.  It's not meant to be called directly by a user.  I think right now the only way to do this is by convention - there's no formal mechanism to enforce this.  However, some teams have already gone down this road - see the acquisitions storage modules (e.g. mod-orders-storage, mod-finance-storage, etc.)

      1. I think the idea is that only modules would be able to call the configuration storage API.

        Does that mean the modules would be allowed to read / write each others configuration?

        I think right now the only way to do this is by convention - there's no formal mechanism to enforce this.

        Is a convention sufficient to allay the concerns of the security auditors who raised the prominence of this topic?

        However, some teams have already gone down this road - see the acquisitions storage modules (e.g. mod-orders-storage, mod-finance-storage, etc.)

        I thought they have done that specifically to their context, that isn't shared. My questions were intended to be around the part of the proposal that defined a shared configuration storage module.

  4. I'd suggest to take a look at API provided by Vert.x Config: https://vertx.io/docs/vertx-config/java/

    This might be a solution to one of our goals: having a general API to work with configuration and different configuration storages/providers

    This API can be potentially used by BE modules as a standard to work with configuration. If a module does need to expose some configuration to a user then it uses this API to implement The "Configuration" System Interface, otherwise the module just use it internally