Gateway Configuration

The Weaklayer Gateway Reference Implementation uses the Viper project for configuration parsing. This allows it to accept configuration in several formats. Please see the gateway cli page for instructions on providing the config. This page will use a JSON configuration file.

Here is an example Weaklayer Gateway configuration file.

    "sensor": {
        "api": {
            "host": "localhost",
            "port": 8080,
            "https": {
                "certificate": "./example_cert.pem",
                "key": "./example_key_encrypted.pem",
                "password": "examplekeypassword"
        "token": {
            "duration": 2419200000000,
            "secrets": {
                "current": "jZAcBYO3EussMYp/GtfAx+luMZd17BQX3lgLxCGTLBY47pR2glLuC4XdUlIe70O19Uu4Yy5zqzH7aIbVQbl7cw==",
                "past": [
        "install": {
            "verifiers": [
                    "group": "68886d61-572b-41a5-8edd-93a564fb5ba3",
                    "salt": "oWrccA==",
                    "hash": "bAW4dciXby0vAAhqHDebxsLioy6H3eYzGqvL8CMRhh0=",
                    "checksum": "fhpiskuymKjvsyRKJ/U9ohdKRDpgft4x/Exn/zHM1zs="
    "outputs": [
            "type": "stdout"
            "type": "filesystem",
            "directory": "./events",
            "age": 30000000,
            "size": 100000000

Note: You must supply a configuration file, but some configuration options can also be supplied with environment variables. The environment variable name is the config value name prefixed with WEAKLAYER and using _ as a seperator. For example, if you wanted to provide sensor.api.https.password through an environment variable instead of in the configuration file, you would set the WEAKLAYER_SENSOR_API_HTTPS_PASSWORD environment variable.

Sensor Options

The top-level sensor key (mandatory) contains gateway configuration options that deal with sensor interaction.

Sensor API Endpoint

sensor.api (mandatory) contains options for specifying where the gateway will bind to listen for sensor communications. (mandatory) is the host that the gateway will bind to.
sensor.api.port (mandatory) is the port that the gateway will bind to.
sensor.api.https (optional) contains options for using HTTPS to communicate with sensors instead of HTTP. The gateway will use HTTPS if these options are specified. You should omit this section if you want to use HTTP.

sensor.api.https.certificate (optional) is the relative or absolute path to a PEM-encoded certificate.
sensor.api.https.key (optional) is the relative or absolute path to a PEM-encoded private key. sensor.api.https.password (optional) a password to decrypt the above private key.

While the sensor.api.https.* options are optional, you must specify both certificate and key or neither. Additionally, only provide password if the private key is encrypted.

Sensor Token

The top-level token key (mandatory) contains gateway configuration options that deal with issuing and verifying sensor tokens. The gateway gives sensors a token (JSON Web Tokens) when they perform a successful installation. This token contains the unique identity for that sensor and is signed by the gateway. The sensor attaches this token to every subsequent request to prove its identity. Additionally, sensors present this token (and an install key) to renew their token and keep the same identity.

token.duration (mandatory) specifies how long in microseconds issued tokens are valid for. Sensors can only keep their identity if they renew their token with a token that is currently valid. This means you should pick a big enough duration so a token can last through expected endpoint shutdowns. For example, users may close their browsers when they go home for the weekend. Therefore the duration should probably be at least 259200000000 (3 days in microseconds). However you shouldn't pick too large a value as natural token expiry is an important security feature.

token.secrets contains the secret values that the gateway uses to sign and verify issued tokens. The gateway uses HMAC-SHA256 to sign the tokens so the same secret is used to sign and verify. All secrets in token.secrets.* must be 512-bit secrets. Please use the gateway CLI to generate these secrets

token.secrets.current (mandatory) is the secret that is used to sign new tokens. It is also the first secret tried when verifying tokens.
token.secrets.past (optional) is an array of secrets that are used for verifying tokens but are not used for signing new tokens. This is useful for token secret rotation where you still want to accept tokens signed with an old secret.

Sensor Install

sensor.install (mandatory) contains options for the sensor installation operation. sensor.install.verifiers (mandatory) is an array of verifiers for install keys that the gateway will accept from sensors. This is an array to enable using multiple groups and to allow for multiple verifiers to be used per group. The latter is particularly useful in an install key / verifier rotation scenario. Please see the gateway CLI documentation for instructions on how to create install key / verifier pairs.

An install verifier has four mandatory fields: group, salt, hash and checksum. is the group UUID that sensors will attempt install operations against.
sensor.install.verifiers.salt is a 32-bit salt value used for hashed password storage.
sensor.install.verifiers.hash is a 10000 iteration PBKDF2-SHA256 hash of the install key secret value and the above salt value. The gateway will try to recalculate this hash with the secret that the sensor provides. Installation then succeeds if the hashes match.
sensor.install.verifiers.checksum is a SHA-256 of the above fields. This is used on application startup to ensure the above fields were entered correctly.

Note: The use of a salted 10000 iteration PBKDF2-SHA256 hash is overkill in this scenario. If generated with the gateway CLI, the install key secret value is 512 bits of cryptographically random data. You are solving a much harder problem than password cracking if this is your search space. However, this setup costs little in terms of computation resources, and it is easier to just follow the NIST guidelines on password storage.

Output Options

The top-level outputs key (mandatory) is an array of output objects. This is where the Weaklayer Gateway sends events. The gateway broadcasts all data to all outputs in this array. Currently, there are two types out outputs: stdout and filesystem. Objects in the outputs array must have the type field set to one of the above output types. Other fields are required depending on the type.

Stdout Output

The stdout output contains no other configuration fields. Just use an object with the type field set to stdout like this.

    "type": "stdout"

The gateway will print every event to stdout, one event per line, if you place this object in the outputs array. If will look something like this from the command line (stderr is being routed to a file).

$ weaklayer-gateway server --config example_config.json 2>stderr.log
{"type":"Install","time":1594209020167364,"sensor":"f5d4650e-5c73-4384-bfeb-90153fe65e0c","group":"68886d61-572b-41a5-8edd-93a564fb5ba3","label":"Mitch's Laptop"}

Filesystem Output

The filesystem output makes the gateway write all events to files. There are several configuration options for the filesystem output.
type field must be set to filesystem.
directory is the path to the top level directory where the gateway will write events to files.
age is the maximum age of a file being written to in microseconds. Files being written to will be closed after this amount of time passes.
size is the maximum size of a file being written to in bytes. Files being written to that pass this size will be closed.

The filesystem output requires rwx permissions on the given directory. The gateway will attempt to create this directory with rwxr-x--- permissions if it doesn't exist. Inside this directory, the filesystem output will create an a directory for each sensor group that it encounters. The names of these folders will be equal to the group UUID.

Inside each of these group directories, the gateway will create and write to new files one at a time with rw-r----- permissions. A file being written to will have a name like .{write time start in epoch microseconds}.json (e.g. .1597795248965234.json). Note that the name starts with a dot.

When a file is finished being written because of time passed, file size reached or gateway shutdown it is renamed. Finished files have a name matching the pattern {write time start in epoch microseconds}-{write time end in epoch microseconds}.json (e.g. 1597795248965234-1597795821564823.json).

Every properly closed file is a valid JSON file with a specific format. The first line of the file is an open square bracket ([) to open a JSON array. The last line of the file is a close square bracket (]) to close a JSON array. Each line between the open and close bracket is a complete event followed by a comma (,).

They look like this.

{"type":"Install","time":1594209020167364,"sensor":"f5d4650e-5c73-4384-bfeb-90153fe65e0c","group":"68886d61-572b-41a5-8edd-93a564fb5ba3","label":"Mitch's Laptop"},

This specific formatting is used to facilitate both line by line parsing of events or parsing the entire file as a JSON array.