Creating Policy Rules

You might need to create custom policy rules if the default policy is too restrictive and is preventing applications from running. You can also create custom policy rules to further restrict access to applications and files. Rules can be added to the /etc/fapolicyd/rules.d directory following the conventions described in About Policy Rules and in the fapolicyd.rules(5) manual page.

Rules have the following general format:

decision perm subject : object
decision

Whether to allow or deny an event and whether to log that action. Values can be allow, deny, allow_audit, deny_audit, allow_syslog, deny_syslog, allow_log, or deny_log.

perm

The type of permission applied to the file, such as whether to trigger when the object is opened, run, or for any activity on the object. Values can be open, execute, or any. If no permission is specified, the default value is open.

subject

The actor performing the action on the object that the permission and decision applies to. This value can be set to all for every actor, but can also be limited to a particular UID or GID or another executable file. Values can be all, auid, uid, gid, sessionid, pid,ppid, trust, comm, exe, dir, device, or pattern. See the fapolicyd.rules(5) manual page for more detail.

object

The files or applications that the decision applies to. This value can be specified in various ways, such as by providing the path to a particular file, the MIME type of the file or for file matches in the trust database. Values can be all, path, dir, device, ftype, trust, or sha256hash. See the fapolicyd.rules(5) manual page for more detail.

You can specify several subject and object directives for a single rule. For example, you can match the file path, MIME type, and file size as the object for a rule.

Rules can also be created to generate macros, or sets, that consist of a key and a set of values in the form of integers or strings in a comma-separated list. Set rules are prefixed with the percentage (%) symbol, and the set can be referenced when creating a rule by specifying the key prefixed with the percentage (%) symbol. The format of a set rule is as follows:

%key=value1,value2

You can see an example of a set rule in /etc/fapolicyd/rules.d/10-languages.rules.

The following example rules can be used to help guide you when creating custom rules for an environment.

Example 4-1 Create a rule to let a group of trusted users to run files matching the defined languages in their home directories

  1. Create a system group and add trusted users to that group, or select an existing group of trusted users. In this example, we use the adm group for system administrators.

  2. Create a policy rule file at /etc/fapolicyd/rules.d/50-adm-home-trust.rules and add the following content:

    allow perm=any gid=adm : ftype=%languages dir=/home
    deny_log perm=any all : ftype=%languages dir=/home
    Two rules are defined:
    • Grant all users in the group adm all permissions on any files, in the /home directory, of the type described in the languages set in /etc/fapolicyd/rules.d/10-languages.rules.

    • Deny all users any permissions on any files, in the /home directory, of the type described in the languages macro. The deny_log rule causes the event to be added to both the audit log and to the system log.

  3. Compile and load the new rules.

    sudo fagenrules --load

    See Checking and Loading Policy Rules for more information.

  4. Verify that the rule is in effect.

    1. As a user in the adm group, create a test executable file in $HOME/test_fapolicyd.py with the following content:

      #/usr/bin/python3
      print("Test succeeded")
    2. Set the file mode to executable:

      chmod +x $HOME/test_fapolicyd.py
    3. Run the file:

      $HOME/test_fapolicyd.py

      The following output is displayed:

      Test succeeded
    4. As a user that isn't in the adm group, repeat the same steps. When you run the test script, the following output is displayed:

      bash: ./test_fapolicyd.py: Operation not permitted

      If you have auditing configured, you can check for entries in the audit log as follows:

      sudo ausearch --start today -m fanotify

      Output similar to the following is displayed:

      ...
      time->date time
      type=PROCTITLE msg=audit(1704456339.181:406): proctitle="bash"
      type=PATH msg=audit(1704456339.181:406): item=0 name="./test_fapolicyd.py" inode=68153551 
        dev=fc:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_home_t:s0 
        nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1704456339.181:406): cwd="/home/guest"
      type=SYSCALL msg=audit(1704456339.181:406): arch=c000003e syscall=257 success=no exit=-1 
        a0=ffffff9c a1=555d4b74e050 a2=0 a3=0 items=1 ppid=46725 pid=46765 auid=1000 uid=1001 
        gid=1001 euid=1001 suid=1001 fsuid=1001 egid=1001 sgid=1001 fsgid=1001 tty=pts0 ses=3 
        comm="bash" exe="/usr/bin/bash" 
        subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
      type=FANOTIFY msg=audit(1704456339.181:406): resp=2

Example 4-2 Create a rule to let users to run a trusted application

Note that creating rules to let particular applications run is less efficient than adding the application to the trust database. See Adding Files to the Trust File Database for more information. Only add rules for specific files if you need to provide more explicit controls over file accesses. In this example, a rule is created controlling the ability to run a particular binary application that can only be run by using the trusted bash shell binary.

  1. Create a policy rule file at /etc/fapolicyd/rules.d/80-trustapp.rules and add the following content:

    allow_log perm=execute exe=/usr/bin/bash trust=1 : path=/opt/external/app.bin ftype=application/x-executable trust=0

    The rule states that if the trusted bash shell tries to run the untrusted application at the path /opt/external/app.bin, where that file is of MIME type application/x-executable, the action is allowed. Note that the decision is set to allow_log so that the action is logged to help verify that the rule is working. After you have verified the rule, you can change the decision to allow.

    Tip:

    To check the mime type of a file when writing rules, run the following command:

    fapolicyd-cli --ftype /path-to-file

    Note that by specifying the MIME type for the file and the way in which the file can be loaded, the rule is reasonably restrictive. You can optionally create a more restrictive rule based on the SHA-256 hash of the file, which would prevent the rule from applying if the file is changed:

    • Obtain the SHA-256 hash for the file.

      sha256sum /opt/external/app.bin|awk '{print $1}'
    • Use the SHA-256 hash to rewrite the rule as follows:

      allow perm=execute exe=/usr/bin/bash trust=1 : sha256hash=hash

      Set the value of sha256hash to the value that you obtained from running the previous command.

  2. Compile and load the new rule.

    sudo fagenrules --load

    See Checking and Loading Policy Rules for more information.

  3. Verify that the rule is in effect.

    When you try to run /opt/external/app.bin as a standard user from the Bash shell, it runs correctly. Because the decision in the rule is allow_log, you can view the fapolicyd log to see the rule in action. For example, run:

    sudo journalctl -S today -u fapolicyd|tail

    The output displays that the rule is being enforced, for example:

    datetime ro-ansible-ol8 fapolicyd[45792]: rule=13 dec=allow_log 
      perm=execute auid=1000 pid=50439 exe=/usr/bin/bash : path=/opt/app.bin 
      ftype=application/x-executable trust=0