udica-0.2.8-4

- confined: make "-l" non optional
- confined: allow asynchronous I/O operations

Resolves: RHEL-29760
This commit is contained in:
Vit Mojzis 2024-02-12 20:04:04 +01:00
parent ddb7e251dc
commit 99051fe5b3
5 changed files with 182 additions and 16 deletions

View File

@ -1,4 +1,4 @@
From 21aa1fb602540d26e3ccad46ab59922da1810dd8 Mon Sep 17 00:00:00 2001 From 3cda61f9a576315e9889821faf495663ad8257ef Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com> From: Vit Mojzis <vmojzis@redhat.com>
Date: Wed, 29 Nov 2023 10:38:48 +0100 Date: Wed, 29 Nov 2023 10:38:48 +0100
Subject: [PATCH] Add option to generate custom policy for a confined user Subject: [PATCH] Add option to generate custom policy for a confined user
@ -13,14 +13,76 @@ https://github.com/Koncpa/confined-users-policy
Signed-off-by: Vit Mojzis <vmojzis@redhat.com> Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
--- ---
README.md | 50 +
setup.py | 1 + setup.py | 1 +
udica/__main__.py | 332 +- udica/__main__.py | 342 +-
udica/confined_user.py | 134 + udica/confined_user.py | 134 +
udica/macros/confined_user_macros.cil | 4367 +++++++++++++++++++++++++ udica/macros/confined_user_macros.cil | 4367 +++++++++++++++++++++++++
4 files changed, 4719 insertions(+), 115 deletions(-) 5 files changed, 4779 insertions(+), 115 deletions(-)
create mode 100644 udica/confined_user.py create mode 100644 udica/confined_user.py
create mode 100644 udica/macros/confined_user_macros.cil create mode 100644 udica/macros/confined_user_macros.cil
diff --git a/README.md b/README.md
index b37b885..37f68b1 100644
--- a/README.md
+++ b/README.md
@@ -170,6 +170,56 @@ SELinux now allows binding to tcp/udp port *21*, but not to *80*:
Ncat: SHA-1 fingerprint: 6EEC 102E 6666 5F96 CC4F E5FA A1BE 4A5E 6C76 B6DC
Ncat: bind to :::80: Permission denied. QUITTING.
+## Creating SELinux policy for confined user
+
+Each Linux user on an SELinux-enabled system is mapped to an SELinux user. By default administrators can choose between the following SELinux users when confining a user account: root, staff_u, sysadm_u, user_u, xguest_u, guest_u (and unconfined_u which does not limit the user's actions).
+
+To give administrators more options in confining users, *udica* now provides a way to generate a custom SELinux user (and corresponding roles and types) based on the specified parameters. The new user policy is assembled using a set of predefined policy macros based on use-cases (managing network, administrative tasks, etc.).
+
+To generate a confined user, use the "confined_user" keyword followed by a list of options:
+
+| Option | Use case |
+| ------------- | ------------- |
+| -a, --admin_commands | Use administrative commands (vipw, passwd, ...) |
+| -g, --graphical_login | Use graphical login environment |
+| -m, --mozilla_usage | Use mozilla firefox |
+| -n, --networking | Manage basic networking (ip, ifconfig, traceroute, tcpdump, ...) |
+| -d, --security_advanced | Manage SELinux settings (semanage, semodule, sepolicy, ...) |
+| -i, --security_basic | Use read-only security-related tools (seinfo, getsebool, sesearch, ...) |
+| -s, --sudo | Run commands as root using sudo |
+| -l, --user_login | Basic rules common to all users (tty, pty, ...) |
+| -c, --ssh_connect | Connect over SSH |
+| -b, --basic_commands | Use basic commands (date, ls, ps, man, systemctl -user, journalctl -user, passwd, ...) |
+
+The new user also needs to be assigned an MLS/MCS level and range. These are set to `s0` and `s0:c0.c1023` respectively by default to work well in *targeted* policy mode.
+For more details see [Red Hat Multi-Level Security documentation](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/using_selinux/index#using-multi-level-security-mls_using-selinux).
+
+```
+$ udica confined_user -abcdgilmns --level s0 --range "s0:c0" custom_user
+
+Created custom_user.cil
+Run the following commands to apply the new policy:
+Install the new policy module
+# semodule -i custom_user.cil /usr/share/udica/macros/confined_user_macros.cil
+Create a default context file for the new user
+# sed -e s|user|custom_user|g /etc/selinux/targeted/contexts/users/user_u > /etc/selinux/targeted/contexts/users/custom_user_u
+Map the new selinux user to an existing user account
+# semanage login -a -s custom_user_u custom_user
+Fix labels in the user's home directory
+# restorecon -RvF /home/custom_user
+```
+
+As prompted by *udica*, the new user policy needs to be installed into the system along with the *confined_user_macros* file and a *default context* file needs to be created before the policy is ready to be used.
+
+Last step is either assignment to an existing linux user (using `semanage login`), or specifying the new SELinux user when creating a new linux user account (no need to run `restorecon` for a new user home directory).
+```
+useradd -Z custom_user_u
+```
+
+The created policy defines a new SELinux user `<user_name>_u`, a corresponding role `<user_name>_r` and a list of types (varies based on selected options) `<user_name>_t, <user_name>_sudo_t, <user_name>_ssh_agent_t, ...`
+
+See [Red Hat Confined User documentation](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/using_selinux/managing-confined-and-unconfined-users_using-selinux#doc-wrapper) for more details about confined users, their assignment, available roles and access they allow.
+
## SELinux labels vs. objects they represent
Policies generated by *udica* work with **SELinux labels** as opposed to filesystem paths, port numbers etc. This means that allowing access to given path (e.g. path to a directory mounted to your container), port number, or any other resource may also allow access to other resources you didn't specify, since the same SELinux label can be assigned to multiple resources.
diff --git a/setup.py b/setup.py diff --git a/setup.py b/setup.py
index deb6457..d3f20f4 100644 index deb6457..d3f20f4 100644
--- a/setup.py --- a/setup.py
@ -34,7 +96,7 @@ index deb6457..d3f20f4 100644
# scripts=["bin/udica"], # scripts=["bin/udica"],
entry_points={"console_scripts": ["udica=udica.__main__:main"]}, entry_points={"console_scripts": ["udica=udica.__main__:main"]},
diff --git a/udica/__main__.py b/udica/__main__.py diff --git a/udica/__main__.py b/udica/__main__.py
index 43d2e43..2bbd401 100644 index 43d2e43..1ba8515 100644
--- a/udica/__main__.py --- a/udica/__main__.py
+++ b/udica/__main__.py +++ b/udica/__main__.py
@@ -13,8 +13,9 @@ @@ -13,8 +13,9 @@
@ -48,7 +110,7 @@ index 43d2e43..2bbd401 100644
# import udica # import udica
from udica.parse import parse_avc_file from udica.parse import parse_avc_file
@@ -25,116 +26,214 @@ from udica.policy import create_policy, load_policy, generate_playbook @@ -25,116 +26,224 @@ from udica.policy import create_policy, load_policy, generate_playbook
def get_args(): def get_args():
@ -248,9 +310,19 @@ index 43d2e43..2bbd401 100644
+ dest="basic_commands", + dest="basic_commands",
+ help="Use basic commands (date, ls, ps, man, systemctl -user, journalctl -user, passwd, ...)", + help="Use basic commands (date, ls, ps, man, systemctl -user, journalctl -user, passwd, ...)",
+ ) + )
+ parser.add_argument("--level", nargs="?", default="s0", dest="level")
+ parser.add_argument( + parser.add_argument(
+ "--range", nargs="?", default="s0-s0:c0.c1023", dest="range" + "--level",
+ nargs="?",
+ default="s0",
+ dest="level",
+ help='MLS/MCS level, defaults to "s0"',
+ )
+ parser.add_argument(
+ "--range",
+ nargs="?",
+ default="s0-s0:c0.c1023",
+ dest="range",
+ help='MLS/MCS range, defaults to "s0-s0:c0.c1023"',
+ ) + )
+ parser.add_argument("uname") + parser.add_argument("uname")
+ else: + else:
@ -373,7 +445,7 @@ index 43d2e43..2bbd401 100644
args = parser.parse_args() args = parser.parse_args()
return vars(args) return vars(args)
@@ -142,6 +241,13 @@ def get_args(): @@ -142,6 +251,13 @@ def get_args():
def main(): def main():
opts = get_args() opts = get_args()
@ -387,7 +459,7 @@ index 43d2e43..2bbd401 100644
if opts["ContainerID"]: if opts["ContainerID"]:
container_inspect_raw = None container_inspect_raw = None
for backend in [ENGINE_PODMAN, ENGINE_DOCKER]: for backend in [ENGINE_PODMAN, ENGINE_DOCKER]:
@@ -167,8 +273,6 @@ def main(): @@ -167,8 +283,6 @@ def main():
if opts["JsonFile"]: if opts["JsonFile"]:
if opts["JsonFile"] == "-": if opts["JsonFile"] == "-":
@ -396,7 +468,7 @@ index 43d2e43..2bbd401 100644
container_inspect_raw = sys.stdin.read() container_inspect_raw = sys.stdin.read()
else: else:
import os.path import os.path
@@ -182,8 +286,6 @@ def main(): @@ -182,8 +296,6 @@ def main():
if (not opts["JsonFile"]) and (not opts["ContainerID"]): if (not opts["JsonFile"]) and (not opts["ContainerID"]):
try: try:
@ -407,7 +479,7 @@ index 43d2e43..2bbd401 100644
print("Couldn't parse inspect data from stdin:", e) print("Couldn't parse inspect data from stdin:", e)
diff --git a/udica/confined_user.py b/udica/confined_user.py diff --git a/udica/confined_user.py b/udica/confined_user.py
new file mode 100644 new file mode 100644
index 0000000..796f543 index 0000000..bd92378
--- /dev/null --- /dev/null
+++ b/udica/confined_user.py +++ b/udica/confined_user.py
@@ -0,0 +1,134 @@ @@ -0,0 +1,134 @@
@ -543,7 +615,7 @@ index 0000000..796f543
+ ) + )
+ print("Map the new selinux user to an existing user account") + print("Map the new selinux user to an existing user account")
+ print("# semanage login -a -s {}_u {}".format(opts["uname"], opts["uname"])) + print("# semanage login -a -s {}_u {}".format(opts["uname"], opts["uname"]))
+ print("Fix labels in the user's home direcotry") + print("Fix labels in the user's home directory")
+ print("# restorecon -RvF /home/{}".format(opts["uname"])) + print("# restorecon -RvF /home/{}".format(opts["uname"]))
diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil
new file mode 100644 new file mode 100644
@ -4919,5 +4991,5 @@ index 0000000..ddb5689
+;(call confined_ssh_connect_macro (u_t u_r u_ssh_agent_t)) +;(call confined_ssh_connect_macro (u_t u_r u_ssh_agent_t))
+;(call confined_use_basic_commands_macro (u_t u_r)) +;(call confined_use_basic_commands_macro (u_t u_r))
-- --
2.41.0 2.43.0

View File

@ -1,4 +1,4 @@
From bf1c8b2491b6f3eca2e519fb18d7d2143acc54fc Mon Sep 17 00:00:00 2001 From d444e67ead27266d57184ab8bc032c5528f7e26c Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com> From: Vit Mojzis <vmojzis@redhat.com>
Date: Wed, 20 Dec 2023 14:33:27 +0100 Date: Wed, 20 Dec 2023 14:33:27 +0100
Subject: [PATCH] Add tests covering confined user policy generation Subject: [PATCH] Add tests covering confined user policy generation
@ -166,5 +166,5 @@ index fb6a9ab..0c73861 100644
return mock_out.output return mock_out.output
-- --
2.41.0 2.43.0

View File

@ -0,0 +1,57 @@
From f411c146986fabe7375724528b2d4ba8cf78b904 Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com>
Date: Mon, 12 Feb 2024 19:38:14 +0100
Subject: [PATCH] confined: make "-l" non optional
The confinedom_user_login_macro is needed for all custom users.
Also, allow the new user type to be accessed via remote login.
Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
---
udica/__main__.py | 2 +-
udica/macros/confined_user_macros.cil | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/udica/__main__.py b/udica/__main__.py
index 1ba8515..801499c 100644
--- a/udica/__main__.py
+++ b/udica/__main__.py
@@ -92,7 +92,7 @@ def get_args():
"-l",
"--user_login",
action="store_true",
- default=False,
+ default=True,
dest="user_login",
help="Basic rules common to all users (tty, pty, ...)",
)
diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil
index ddb5689..06c4c56 100644
--- a/udica/macros/confined_user_macros.cil
+++ b/udica/macros/confined_user_macros.cil
@@ -2411,7 +2411,7 @@
(typetransition utype sudo_exec_t process sudo_type)
(allow sudo_type utype (fd (use)))
(allow sudo_type utype (fifo_file (ioctl read write getattr lock append)))
- (allow sudo_type utype (process (sigchld)))
+ (allow sudo_type utype (process (getpgid sigchld)))
(allow sudo_type bin_t (dir (getattr open search)))
(allow sudo_type bin_t (dir (ioctl read getattr lock open search)))
(allow sudo_type bin_t (dir (getattr open search)))
@@ -4006,6 +4006,12 @@
)
)
)
+ ; Telnet login
+ (optional confinedom_user_login_optional_3
+ (typeattributeset cil_gen_require remote_login_t)
+ (allow remote_login_t utype (process (signal transition)))
+ (allow utype self (bpf (prog_load)))
+ )
)
(macro confined_ssh_connect_macro ((type utype) (role urole) (type ssh_agent_type))
--
2.43.0

View File

@ -0,0 +1,31 @@
From 131d228c6a91eaaeccc1d000821beeccba69d134 Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com>
Date: Mon, 4 Mar 2024 12:59:53 +0100
Subject: [PATCH] confined: allow asynchronous I/O operations
Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
---
udica/macros/confined_user_macros.cil | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil
index 06c4c56..dcb5198 100644
--- a/udica/macros/confined_user_macros.cil
+++ b/udica/macros/confined_user_macros.cil
@@ -4012,6 +4012,13 @@
(allow remote_login_t utype (process (signal transition)))
(allow utype self (bpf (prog_load)))
)
+ ; asynchronous I/O operations RHEL 10
+ (optional confinedom_user_login_optional_4
+ (typeattributeset cil_gen_require io_uring_t)
+ (allow utype self (io_uring (sqpoll)))
+ (allow utype io_uring_t (anon_inode (create)))
+ (allow utype io_uring_t (anon_inode (read write getattr map)))
+ )
)
(macro confined_ssh_connect_macro ((type utype) (role urole) (type ssh_agent_type))
--
2.43.0

View File

@ -1,11 +1,13 @@
Summary: A tool for generating SELinux security policies for containers Summary: A tool for generating SELinux security policies for containers
Name: udica Name: udica
Version: 0.2.8 Version: 0.2.8
Release: 3%{?dist} Release: 4%{?dist}
Source0: https://github.com/containers/udica/archive/v%{version}.tar.gz Source0: https://github.com/containers/udica/archive/v%{version}.tar.gz
#git format-patch -N v0.2.8 -- . ':!.cirrus.yml' ':!.github' #git format-patch -N v0.2.8 -- . ':!.cirrus.yml' ':!.github'
Patch0001: 0001-Add-option-to-generate-custom-policy-for-a-confined-.patch Patch0001: 0001-Add-option-to-generate-custom-policy-for-a-confined-.patch
Patch0002: 0002-Add-tests-covering-confined-user-policy-generation.patch Patch0002: 0002-Add-tests-covering-confined-user-policy-generation.patch
Patch0003: 0003-confined-make-l-non-optional.patch
Patch0004: 0004-confined-allow-asynchronous-I-O-operations.patch
License: GPL-3.0-or-later License: GPL-3.0-or-later
BuildArch: noarch BuildArch: noarch
Url: https://github.com/containers/udica Url: https://github.com/containers/udica
@ -64,6 +66,10 @@ install -m 0644 udica/man/man8/udica.8 %{buildroot}%{_mandir}/man8/udica.8
%endif %endif
%changelog %changelog
* Mon Feb 12 2024 Vit Mojzis <vmojzis@redhat.com> - 0.2.8-4
- confined: make "-l" non optional
- confined: allow asynchronous I/O operations
* Sat Jan 27 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.2.8-3 * Sat Jan 27 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.2.8-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild