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": [
"sQBc60569Z4mcf0Idf6OIu+u+Ht+vjz9rqQDx7/mdHUKoMWcFpvfcHRA3Ta5yB1HlHsIRkRajLtdLFmRgpwtiQ==",
"zAVlcn/qje8jAjL6HWyMZrKiKuYgLIWfVn4uHZA2KaPLbQWCII9wymJe+WPmAph2Qbau5pYDPXAzjVfYo2pU6Q=="
]
}
},
"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.
sensor.api.host
(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
.
sensor.install.verifiers.group
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"}
{"type":"Window","time":1594209078132495,"sensor":"f5d4650e-5c73-4384-bfeb-90153fe65e0c","group":"68886d61-572b-41a5-8edd-93a564fb5ba3"}
{"type":"WindowLocation","time":1594209078152194,"sensor":"f5d4650e-5c73-4384-bfeb-90153fe65e0c","group":"68886d61-572b-41a5-8edd-93a564fb5ba3","protocol":"https","hostname":"www.youtube.com","port":0,"path":"/","search":"","hash":"","windowReference":1594209078132495}
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"},
{"type":"Window","time":1594209078132495,"sensor":"f5d4650e-5c73-4384-bfeb-90153fe65e0c","group":"68886d61-572b-41a5-8edd-93a564fb5ba3"},
{"type":"WindowLocation","time":1594209078152194,"sensor":"f5d4650e-5c73-4384-bfeb-90153fe65e0c","group":"68886d61-572b-41a5-8edd-93a564fb5ba3","protocol":"https","hostname":"www.youtube.com","port":0,"path":"/","search":"","hash":"","windowReference":1594209078132495},
]
This specific formatting is used to facilitate both line by line parsing of events or parsing the entire file as a JSON array.