4 Managing Policies
For more information about policy rules and how they work, see About Policy Rules.
Listing Policy Rules
To list policy rules that are in use by fapolicyd, run:
sudo fapolicyd-cli -l
Output from this command might be similar to the following:
-> %languages=application/x-bytecode.ocaml,application/x-bytecode.python,application/java-archive,text/x-java,application/x-java-applet,application/javascript,text/javascript,text/x-awk,text/x-gawk,text/x-lisp,application/x-elc,text/x-lua,text/x-m4,text/x-nftables,text/x-perl,text/x-php,text/x-python,text/x-R,text/x-ruby,text/x-script.guile,text/x-tcl,text/x-luatex,text/x-systemtap
1. allow perm=any uid=0 : dir=/var/tmp/
2. allow perm=any uid=0 trust=1 : all
3. allow perm=open exe=/usr/bin/rpm : all
4. allow perm=open exe=/usr/bin/python3.9 comm=dnf : all
5. deny_audit perm=any pattern=ld_so : all
6. deny_audit perm=any all : ftype=application/x-bad-elf
7. allow perm=open all : ftype=application/x-sharedlib trust=1
8. deny_audit perm=open all : ftype=application/x-sharedlib
9. allow perm=execute all : trust=1
10. allow perm=open all : ftype=%languages trust=1
11. deny_audit perm=any all : ftype=%languages
12. allow perm=any all : ftype=text/x-shellscript
13. deny_audit perm=execute all : all
14. allow perm=open all : all
Note that the rules are numbered. When fapolicyd runs in debug mode, the output displays the rule number that's enforced for an event. You can use this information to decide whether you need to insert a new policy rule to change the existing policy and to decide where that rule might need to be in the policy hierarchy. See Debugging and Permissive Mode for information on debugging.
You can compare this list to the compiled rules to check whether you need to reload the rules into fapolicyd.
sudo cat /etc/fapolicyd/compiled.rules
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
, ordeny_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
, orany
. If no permission is specified, the default value isopen
. - 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 beall
,auid
,uid
,gid
,sessionid
,pid
,ppid
,trust
,comm
,exe
,dir
,device
,pattern
. See thefapolicyd.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
,sha256hash
. See thefapolicyd.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 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 allow a group of trusted users to run files matching the defined languages in their home directories
- 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. - 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 thelanguages
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 thelanguages
macro. Thedeny_log
rule causes the event to be added to both the audit log and to the system log.
- Grant all users in the group
- Compile and load the new
rules.
sudo fagenrules --load
See Checking and Loading Policy Rules for more information.
- Verify that the rule is in effect.
-
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")
-
Set the file mode to executable:
chmod +x $HOME/test_fapolicyd.py
-
Run the file:
The following output is displayed:$HOME/test_fapolicyd.py
Test succeeded
-
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:
Output similar to the following is displayed:sudo ausearch --start today -m fanotify
... time->Fri Jan 5 12:05:39 2024 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 allow users to run a trusted application
Note that creating rules to allow particular applications to 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.
- 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 in the case that the trusted bash shell tries to run the untrusted application at the path
/opt/external/app.bin
, where that file is of MIME typeapplication/x-executable
, the action is allowed. Note that the decision is set toallow_log
so that the action is logged for when we verify that the rule is working. After you have verified the rule, you can change the decision toallow
.Tip:
To check the mime type of a file when writing rules, run the following command: fapolicyd-cli --ftype /path-to-fileNote 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 modified:
- 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=340e...74f3cdd3babb
Set the value of
sha256hash
to the value that you obtained from running the previous command.
- Obtain the SHA-256 hash for the
file.
- Compile and load the new rules.
sudo fagenrules --load
See Checking and Loading Policy Rules for more information.
- 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 toallow_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:
Jan 05 14:22:36 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
Checking and Loading Policy Rules
If rules have been added or changed, you must check for consistency with the compiled rule set that fapolicyd uses and load them into fapolicyd.
- Check for inconsistencies between the rules in
/etc/fapolicyd/rules.d
and the compiled rules in/etc/fapolicyd/compiled.rules
.sudo fagenrules --check
If the rules in
/etc/fapolicyd/rules.d
have been updated and need to be recompiled and loaded, the output appears as follows:/sbin/fagenrules: Rules have changed and should be updated
- To compile the rules in
/etc/fapolicyd/rules.d
and load them into fapolicyd, run:sudo fagenrules --load
You don't need to restart fapolicyd for the changes to take effect.
- List the rules to review that the changes have loaded correctly into
fapolicyd.
sudo fapolicyd-cli -l
Changing Default Policy Logging
Default policy rules shipped with fapolicyd are configured to only log to the audit log for denials. This configuration is appropriate for production systems but the information stored in these logs might be limited for debugging purposes. If you need to track which rules are being used to make the final decision on an event, you can either run fapolicyd in debugging mode, or you could change rules to output information to the system log. For more information on running fapolicyd in debugging mode, see Debugging and Permissive Mode.
Policy rule decisions identify whether to log information and how that information must be
logged. By default, for denial decisions, the rules that are included in the
fapolicyd package use the deny_audit
decision type. You can
change all deny_audit
decision type to
deny_log
to log information to both the audit log
and to the system log.
To enhance logging:
- Update all rules in
/etc/fapolicyd/rules.d
to replacedeny_audit
withdeny_log
.sudo bash -c 'for i in /etc/fapolicyd/rules.d/*; do sed -i "s/deny_audit/deny_log/g" $i; done'
You can also enable logging for any allow rules, but doing so can result in verbose output and can have significant performance impact.
- Check that the rules are
updated.
sudo fagenrules --check
- Load the new rules.
sudo fagenrules --load
- Review the rules to ensure that the change has loaded correctly into
fapolicyd.
sudo fapolicyd-cli -l | grep 'deny_log'
When an event is denied by fapolicyd and the decision is set to
deny_log
, an entry appears in the system log, similar to the
following:
fapolicyd[1478]: rule=13 dec=deny_log perm=execute auid=1000 pid=5361 exe=/usr/bin/bash :
path=/home/user/demo.bin ftype=application/x-executable trust=0
Note that the output includes the rule number for the rule that fapolicyd used to make the final decision to deny the event.
To view system log entries for fapolicyd, run:
sudo journalctl -S today -u fapolicyd