daemon: allow to filter connections by parent path

Some use cases:

 - Reject connections initiated by certain paths:

   Deny all connections initiated by cron*:
        /usr/sbin/cron
            /usr/bin/curl

     "action": "reject",
     "operator: {
        "type": "list",
        "operand": "list",
        "data": "",
        "list": [
     	   {
                "type": "regexp",
                "operand": "process.parent.path",

                // /usr/bin/crond , /usr/bin/crontab, ...
                "data": "^/usr/(s|)bin/cron"
           }
        ]
     }

 - Reject or Allow connections of binaries launched by another app:

       "action": "allow",
       "operator": {
       	"type": "list",
       	"operand": "list",
       	"data": "",
       	"list": [
       	    {
                "type": "simple",
       	        "operand": "process.parent.path",
       	        "data": "/opt/spotify/bin/spotify"
       	    },
       	    {
       	        "type": "simple",
       	        "operand": "process.path",
       	        "data": "/usr/bin/wget"
       	    }
       	  ]
       }

You can also combine multiple parent paths, to allow a command launched
from a specific chain of processes:

    /usr/lib/systemd/systemd
        /usr/sbin/cron
             /bin/sh
                 /usr/bin/curl

The order is checked from the newest process to the oldest (curl -> sh
-> cron -> systemd)

The operand can be used with any of the existing types (simple, regexp,
etc).

Related: #406
This commit is contained in:
Gustavo Iñiguez Goia 2025-02-13 01:23:31 +01:00
parent deba3e2252
commit 2509d21e30
Failed to generate hash of commit

View file

@ -43,6 +43,7 @@ const (
OpTrue = Operand("true")
OpProcessID = Operand("process.id")
OpProcessPath = Operand("process.path")
OpProcessParentPath = Operand("process.parent.path")
OpProcessCmd = Operand("process.command")
OpProcessEnvPrefix = Operand("process.env.")
OpProcessEnvPrefixLen = 12
@ -389,6 +390,14 @@ func (o *Operator) Match(con *conman.Connection, hasChecksums bool) bool {
return o.listMatch(con, hasChecksums)
} else if o.Operand == OpProcessPath {
return o.cb(con.Process.Path)
} else if o.Operand == OpProcessParentPath {
p := con.Process
for pp := p.Parent; pp != nil; pp = pp.Parent {
if o.cb(pp.Path) {
return true
}
}
return false
} else if o.Operand == OpProcessCmd {
return o.cb(strings.Join(con.Process.Args, " "))
} else if o.Operand == OpDstHost && con.DstHost != "" {