Server Structure

The InfinityDB Server has a simple structure. Just download from the shop at boilerbay.com the InfinityDB v6 trial distribution zip and the seed database zip, and expand the seed into a home directory. Then, launch using a provided script giving the home directory and a URL for the server to listen on. You can also specify a URL for a RemoteItemSpaceServer to launch to allow access from RemoteClientItemSpace’s.

The server can be run standalone, or an application can run the server as a library without any effect on existing application code. The application can also provide a set of custom Servlets to extend the server’s native web server. The Servlet API is a standard Java environment used in many Java web servers, although InfinityDB does not accept remote Servlet submissions in war files, but instead the Servlet code runs directly in the server JVM. The server’s web-based admin and backend data browser and editor can be made available alongside the application. The data browser and editor is particularly valuable in debugging and managing applications.

Security is not strongly enforced within the JVM, so it is possible for the application to violate the server’s rules with sufficient effort. However, from outside the JVM, security is enforced for socket access, user web access, and file access from other processes.

The Home Directory

The home directory contains multiple database files, web assets, and the security-related files. It has the structure below, and it normally just goes in ~/infinitydb-home. Permissions will vary for the directories based on sensitivity. This structure can be overridden in certain ways.

Directory Contents

DirectoryFileContent
data/defaultmeta-data.infdbContains all system configuration information except web configuration including: database names and their associated file names, user names and password hashes, roles, and permission grants between roles and databases. Databases may also be declared remote or given relative or absolute paths. Meta-data.infdb is a regular InfinityDB Encrypted file that is only modified by the MetaData class within the server.
data/default/filesdemo_readonly.infdb,
demo_writeable.infdb, further infinitydb files
Any InfinityDB database files can be placed here, manually copied in or created by the administration web page. There is no limitation on the contents or structure of the files. A convenient way to backup is to manually copy the default subdirectory into another subdirectory under data. All files here may be listed and accessed by the web-based database browser by permitted or database owner users.
web/defaultweb assetsAll html, js, css, images, and other static web files. Some of these are specific to the server. There is no limit to these, and they show up in the root of the server’s web site. Putting application code in a subdirectory would be good. Access is public, but Servlets may be protected by user credentials. Future versions may make static access protectable also.
web/default/WEB_INFweb.xmlA configuration file in the standard format for Servlets. It determines mainly the Servlet paths within the site’s URLS. The Servlets are provided as code within the Server’s JVM with class names configured here. There are predefined Servlets under the special infinitydb URL path prefix for administration and data browsing.
key-store.keystore.p12The server’s SSL private key file or other backup or alternative private key files in standard pkcs#12 format. If the server is launched in http mode, this is ignored. You can use OpenSSL on these.
key-store-password.keystore.p12.passwordA file containing the private key file password. This directory will have tight permissions.
trust-storecacerts
cacerts.p12
cacerts.pem
Trust stores in Java’s native .jks format, standard pkcs#12 .p12 format, or .pem base64 format, which is unencrypted. This is used when declaring a database remote, i.e. existing on a different server. The trust store in $JAVA_HOME/lib/security/cacerts is used by default, however. This cacerts is a copy from JDK10. Custom stores may be added.
trust-store-passwordcacerts.password
Passwords for trust stores. Permissions can be set tightly here. cacerts.password defaults to ‘changeit’, the common value.
meta-data-password/defaultmeta-data.passwordCurrent password of metadata.infdb. This is the master password, so it will have tight permissions. The subdirectory corresponds to the data/default or other backup so multiple passwords can be kept. This is currently static, but will be dynamic later, such as through the admin web page.
logslog.txtStandard out and standard err from the server process. This will currently accumulate, and should be deleted occasionally manually. Pipe to /dev/null to prevent that for now.
Home directory structure

Launch a Server

To launch a server from inside a JVM first provide a DirectoryConfiguration. All of the parameters but httpServerUrl may be null to get the defaults described above, and system properties can be used. See the launcher script. By default ~/infinitydb-home is used. There are other constructors that allow the various subdirectories and files of home to be placed anywhere you want instead.

    public DirectoryConfiguration(File homeDirectory, File webDirectory,
            URL httpServerUrl, URL remoteItemSpaceUrl) throws IOException

The httpServerUrl might be https://localhost:37411 for example, and remoteItemSpaceUrl might be null or https://localhost:37412 for example. They should be either both http or both https. Now just construct a server:

    public InfinityDBHttpServer(
            DirectoryConfiguration directoryConfiguration,
            boolean isWriteable,
            String servletContextRoot)
            throws Exception

ServletContextRoot is nullable.

Opening a Database

Database files are under data/default/files. Each such file can have any file name, but it is accessed from code running within the server or client using a two-part internal database name like ‘demo/readonly’ containing a single slash. Each part starts with a letter, and then has letters, digits, underscores, dots, and dashes. This naming allows databases to be accessed from REST within URLs for example, like https://infinitydb.com:37411/infinitydb/data/demo/readonly. The port is arbitrary, and either http or https is used depending on how the server was launched.

First, use MetaDataFactory.getMetaData() to get a MetaData:

    public static MetaData getMetaData(
            DirectoryConfiguration directoryConfiguration, boolean isWriteable)
            throws IOException, GeneralSecurityException

The data directory of the DirectoryConfiguration is used to identify a particular instance of MetaData in a static Map, if you want multiple in your JVM. Now open some databases. A database is a local or remote InfinityDB file, so it is treated as a subclass of ItemSpace, which you get from the MetaData:

    ItemSpace getItemSpaceByName(String itemSpaceName, Authority userAuthority,
            ItemSpaceAccessPermissions requestedItemSpaceAccessPermissions)
            throws IOException, RemoteItemSpaceException

Application code running in the server uses such ItemSpaces in exactly the same way as it does in standalone InfinityDB Embedded or InfinityDB Encrypted applications. There is also no restriction against application code working with InfinityDB database files as usual outside of the server’s knowledge.

All application code can do certain safe things via MetaData like open and list permitted databases. All MetaData operations require a valid Authority, which is just a username and password. Authorities are automatically checked for password validity on use. A special Authority with user name ‘admin’ has total control over the metadata. Some MetaData methods require both a normal user Authority and the admin Authority.

    public Authority(String userName, char[] passWord)

The Authority can be constructed by application code in any way desired, but Servlet application code can use the ServletSupport class to get it from the request (using HTTP Basic Authentication):

    public static synchronized Authority
            getUserAuthority(HttpServletRequest req,
                    HttpServletResponse resp)
                    throws IOException, RemoteItemSpaceException;

Application code can use MetaData to determine if an Authority is valid for a given database explicitly if desired:

boolean checkUserIsAuthorizedForItemSpace(Authority authority,
            String itemSpaceName,
            ItemSpaceAccessPermissions requestedItemSpaceAccessPermissions,
            boolean isPermissionsAnyOf)
            throws RemoteItemSpaceException, IOException;
    

Client Access Through RemoteItemSpace

Java clients can securely access the databases through a ‘RemoteItemSpaceServer’ that is configured at server launch. This server runs on a different port from the web server but in the same JVM. The client uses a corresponding RemoteClientItemSpace to connect between them . The ‘ItemPacket’ protocol uses fast, binary checksummed blocks of data that can transfer Items singly or in bulk. See the example code.

Distributed Databases

The RemoteItemSpaceServer feature is also used for transparently distributed databases. The admin can configure a database as either a local file in the data directory as described above, or locally with an absolute path, or else as a remote database in a different server. Client applications access either the local or remote identically, not knowing where the data actually lives. The admin simply declares a database name as being attached to a URN like file:myfile.infdb for a local file with relative path, or file:/mydirectory/myfile.infdb for a local file with an absolute path, or http://remoteserver:port/mydb/mydb or https:/remoteserver:port/mydb/mydb for remote use. This even works transitively, reflexively and concurrently, with multiple connections automatically created as needed. The back-end web-based database browser and editor can therefore see remote databases. User authentication is performed both locally and again remotely.

Client Access Through REST

REST is a secure request-response protocol based on HTTP that accesses data in the server according to a URL that contains the database name. The request or response can contain JSON or a BLOB with a mimetype. An example URL to get some JSON is https://infinitydb.com:37411/infinitydb/data/demo/readonly/Documentation (user name ‘testUser’ password ‘db’, database ‘demo/readonly’, Item prefix ‘Documentation’). For an example BLOB see https://infinitydb.com:37411/infinitydb/data/demo/readonly/Pictures/%22pic2%22. Also, the database can be navigated bidirectionally by Item. The web server contains a Servlet that implements the protocol. Python or the shell’s curl command can be used, and JavaScript is on the way. The curl command is in unix and in Windows it is available in cygwin.

For Python use access.py in the python directory in the download. Here is some example client code:

from infinitydb.access import *

# port 37411 is usual
infinitydb_url = 'https://infinitydb.com:37411/infinitydb/data'
#infinitydb_url = 'http://localhost:37411/infinitydb/data'

""" Database names (URI components) """

# Databases have one slash separating two names each like
# [A-Za-z][A-Za-z0-9._-]*
# An infinitydb server by default has these available for the testUser
#database_uri = 'demo/writeable'
database_uri = 'demo/readonly'

""" The User Name and Password """

# A public guest user for browsing and experimentation, in the
# 'guest' role. Contact us for your own experimentation login and db.
user = 'testUser'
password = 'db'

""" The connection to the database """

infdb = InfinityDBAccessor(infinitydb_url, db=database_uri, user=user, password=password)
    
""" Get JSON given a prefix Item from the connection """

# To see the documentation as JSON in the demo/readonly database, go to:
# https://infinitydb.com:37411/infinitydb/data/demo/readonly/Documentation
# Here we read that JSON into content, with success being a boolean.
# The JSON is represented by nested dicts and lists.
# We use a path prefix of ['Documentation'] which is an Item with a single string component:
success, content = infdb.get_json(['Documentation'])

Current Limitations

InfinityDB Client/Server version 6.0.0, the current version on 2021-4-5, has these limitations:

  • Server database files cannot be encrypted, even though the version 5 encryption feature is present. The admin console will soon get the ability to store their passwords in the metadata and to change them, and to create new encrypted databases.
  • The meta-data.infdb file is encrypted but its password is static, in meta-data-password/default/meta-data.password. The admin console will soon be able to change it. Therefore, meta-data.infdb is only effectively obfuscated, so keep its permissions tight. Database passwords will get stored in meta-data.infdb literally, i.e. un-hashed. Once the password becomes dynamic, backups created by copying everything under /data/default are effectively secure, given encrypted databases. In the future, backups may be done automatically.
  • Static web assets cannot be protected by user permissions.
  • There is no way yet to quiesce or gracefully shutdown a server, such as for backup. Data is never lost or corrupted in any case. Database files being written to cannot be copied safely at the same time, but this is impossible due to file locking anyway.
  • The seed database (Actually a zip of the initialization home directory) has a static admin password, but it is not possible to deduce it from the seed because it is hashed. We will tell you the password by email – then you change it by hand immediately in the admin console after unzipping.

Please send feedback to support@boilerbay.com.