JSONnet FAQ
JSONnet already has a good tutorial to start with.
Here's a FAQ for reaction:
How do I write defaults at one place and reuse them elsewhere?
Answer
You first define your defaults set:
local filter_default = {
retry: 3,
retryperiod: '3h',
actions: banFor('24h'),
};
The you can use it in your filters:
{
streams: {
ssh: {
filters: {
failedlogin: filter_default + {
regex: ['...'],
},
},
},
},
}
You can override those defaults:
{
streams: {
ssh: {
filters: {
failedlogin: filter_default + {
regex: ['...'],
retry: 1,
},
},
},
},
}
And the +
is optional.
{
streams: {
ssh: {
filters: {
failedlogin: filter_default {
regex: ['...'],
},
},
},
},
}
How do I add multiple actions defined by JSONnet functions on the same filter?
Answer
Let's take this example: we have two functions defining actions:
The first is made to ban the IP using linux's iptables firewall:
local banFor(time) = {
ban: {
cmd: ['ip46tables', '-w', '-A', 'reaction', '-s', '<ip>', '-j', 'DROP'],
},
unban: {
after: time,
cmd: ['ip46tables', '-w', '-D', 'reaction', '-s', '<ip>', '-j', 'DROP'],
},
};
The second sends a mail:
local sendmail(text) = {
mail: {
cmd: ['sh', '-c', '/root/scripts/mailreaction.sh', text],
},
};
Both create a set of actions. We want to merge the two sets.
To merge two sets with JSONnet, it's as easy as set1 + set2
.
Let's see what it ressembles with a real example.
local banFor(time) = {
ban: {
cmd: ['ip46tables', '-w', '-A', 'reaction', '-s', '<ip>', '-j', 'DROP'],
},
unban: {
after: time,
cmd: ['ip46tables', '-w', '-D', 'reaction', '-s', '<ip>', '-j', 'DROP'],
},
};
local sendmail(text) = {
mail: {
cmd: ['sh', '-c', '/root/scripts/mailreaction.sh', text],
},
};
{
streams: {
ssh: {
filters: {
failedlogin: {
regex: [
// skipping
],
retry: 3,
retryperiod: '3h',
actions: banFor('720h') + sendmail('banned <ip> from service ssh'),
},
},
},
},
}
This will generate this configuration:
{
"streams": {
"ssh": {
"filters": {
"failedlogin": {
"regex": [ ],
"retry": 3,
"retryperiod": "3h",
"actions": {
"ban": {
"cmd": [ "ip46tables", "-w", "-A", "reaction", "-s", "<ip>", "-j", "DROP" ]
},
"unban": {
"after": "720h",
"cmd": [ "ip46tables", "-w", "-D", "reaction", "-s", "<ip>", "-j", "DROP" ]
},
"mail": {
"cmd": [ "sh", "-c", "/root/scripts/mailreaction.sh", "banned <ip> from service ssh" ]
}
}
}
}
}
}
}
How do I separate my configuration in multiple files?
Answer
Firstly, you don't need to do this 😉
But if you want to, you can use the import
JSONnet keyword to import files, relative to the file calling them. (Remember, the JSONnet tutorial is a good place to understand its basics).
Here's an example of how you could do this:
reaction.jsonnet
{
streams: {
ssh: import 'ssh.jsonnet',
},
}
ssh.jsonnet
local lib = import 'lib.jsonnet';
{
filters: {
failedlogin: lib.filter_default + {
regex: ['...'],
retry: 3,
retryperiod: '2h',
actions: lib.banFor('720h'),
},
},
}
lib.jsonnet
(definitions you can reuse in all other files)
local banFor(time) = {
ban: {
cmd: ['ip46tables', '-w', '-A', 'reaction', '-s', '<ip>', '-j', 'DROP'],
},
unban: {
after: time,
cmd: ['ip46tables', '-w', '-D', 'reaction', '-s', '<ip>', '-j', 'DROP'],
},
};
local filter_default = {
retry: 3,
retryperiod: '3h',
actions: banFor('24h'),
};
{
banFor: banFor,
filter_default: filter_default,
}