systemd units
parent
86f27e8aa3
commit
018441b27d
2
TODO.md
2
TODO.md
|
@ -1,7 +1,5 @@
|
|||
# TODO
|
||||
|
||||
* Maybe switch from storing the daily journal in a file, to storing it in a database.
|
||||
* Write the systemd service that starts pyruse on boot.
|
||||
* Write the systemd service+timer that restores bans after a reboot.
|
||||
* Maybe switch from Step.run() recursion to Step.run()-in-a-loop to avoid too-deep call stacks.
|
||||
* Eventually make the code more elegant, as I learn more about Python…
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/python
|
||||
from pyruse import main
|
||||
main.boot(sys.argv[1])
|
|
@ -0,0 +1,3 @@
|
|||
[Unit]
|
||||
Requires=nftables.service
|
||||
After=nftables.service
|
|
@ -0,0 +1,16 @@
|
|||
[Unit]
|
||||
Description=Initialization of pyruse module %I
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/pyruse-boot "%I"
|
||||
CapabilityBoundingSet=CAP_SYS_CHROOT
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=yes
|
||||
PrivateTmp=yes
|
||||
ProtectHome=yes
|
||||
ProtectSystem=full
|
||||
ReadWriteDirectories=/var/lib/pyruse
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,16 @@
|
|||
[Unit]
|
||||
Description=Route systemd-journal logs to filters and actions (ban, report…)
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/pyruse
|
||||
CapabilityBoundingSet=CAP_SYS_CHROOT
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=yes
|
||||
PrivateTmp=yes
|
||||
ProtectHome=yes
|
||||
ProtectSystem=full
|
||||
ReadWriteDirectories=/var/lib/pyruse
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -40,6 +40,36 @@ class Action(base.Action):
|
|||
except IOError:
|
||||
pass # new file
|
||||
|
||||
if previousTS:
|
||||
cmd = list(Action._nft)
|
||||
cmd.append("delete element %s {%s}" % (nftSet, ip))
|
||||
subprocess.run(cmd)
|
||||
|
||||
until = self._doBan(now, ip, nftSet)
|
||||
|
||||
newBan["timestamp"] = until.timestamp()
|
||||
bans.append(newBan)
|
||||
with open(Action._storage, "w") as dataFile:
|
||||
json.dump(bans, dataFile)
|
||||
|
||||
def boot(self):
|
||||
now = datetime.datetime.utcnow()
|
||||
bans = []
|
||||
try:
|
||||
with open(Action._storage) as dataFile:
|
||||
for ban in json.load(dataFile):
|
||||
if ban["timestamp"] <= now.timestamp():
|
||||
continue
|
||||
else:
|
||||
bans.append(ban)
|
||||
self._doBan(now, ip, nftSet)
|
||||
except IOError:
|
||||
pass # no file
|
||||
|
||||
with open(Action._storage, "w") as dataFile:
|
||||
json.dump(bans, dataFile)
|
||||
|
||||
def _doBan(self, now, ip, nftSet):
|
||||
if self.banSeconds:
|
||||
until = now + datetime.timedelta(seconds = self.banSeconds)
|
||||
timeout = " timeout %ss" % str(self.banSeconds)
|
||||
|
@ -47,15 +77,8 @@ class Action(base.Action):
|
|||
until = now + datetime.timedelta(days = 365)
|
||||
timeout = ""
|
||||
|
||||
if previousTS:
|
||||
cmd = list(Action._nft)
|
||||
cmd.append("delete element %s {%s}" % (nftSet, ip))
|
||||
subprocess.run(cmd)
|
||||
cmd = list(Action._nft)
|
||||
cmd.append("add element %s {%s%s}" % (nftSet, ip, timeout))
|
||||
subprocess.run(cmd)
|
||||
|
||||
newBan["timestamp"] = until.timestamp()
|
||||
bans.append(newBan)
|
||||
with open(Action._storage, "w") as dataFile:
|
||||
json.dump(bans, dataFile)
|
||||
return until
|
||||
|
|
|
@ -26,7 +26,15 @@ def _doForEachJournalEntry(fct):
|
|||
if event == journal.APPEND:
|
||||
for entry in j:
|
||||
fct(j)
|
||||
|
||||
|
||||
def boot(modName):
|
||||
if "action_" in modName:
|
||||
module.get({"action": modName}).module.boot()
|
||||
elif "filter_" in modName:
|
||||
module.get({"filter": modName}).module.boot()
|
||||
else:
|
||||
raise ValueError("Neither “action_” nor “filter_” found in the module name; the `boot` feature cannot work for %s\n" % modName)
|
||||
|
||||
def main():
|
||||
_setPyrusePaths()
|
||||
conf = config.Config(PYRUSE_PATHS)
|
||||
|
|
Loading…
Reference in New Issue