-
-
Notifications
You must be signed in to change notification settings - Fork 140
Implement optional admin authorization via qrexec #613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
HW42
wants to merge
1
commit into
QubesOS:main
Choose a base branch
from
HW42:simon/admin-authz
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| etc/polkit-1/rules.d/00-qubes-allow-all.rules | ||
| etc/qubes/admin-authzd.conf | ||
| etc/sudoers.d/qubes | ||
| usr/share/pam-configs/su.qubes | ||
| usr/share/pam-configs/qubes-admin-authz | ||
| usr/bin/qubes-admin-authzd | ||
| usr/lib/*/security/pam_qubes_admin_authz.so | ||
| lib/systemd/system/qubes-admin-authzd.service | ||
| usr/share/doc/qubes-core-agent-passwordless-root/README.md |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| pam_qubes_admin_authz.so | ||
| qubes-admin-authzd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # This will be re-preset on package upgrade. If you really want you can | ||
| # override this with a higher-priority preset file but that is probably a bad | ||
| # idea since it will break the pam module. | ||
| enable qubes-admin-authzd.service |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # Passwordless in-qube admin authorization | ||
|
|
||
| By default all users in the `qubes` group (usually only the standard `user` | ||
| user) are allowed to execute things as root via sudo/su/pkexec. This is allowed | ||
| without a password prompt. | ||
|
|
||
| Separating the user isn't that meaningfull since Qubes' primary | ||
| compartimentalization layer are qubes and `user` in a qube has access most | ||
| things there anyway (user data, GUI I/O, etc). But some advanced users want | ||
| more options therefore this mechanism has been extended. | ||
|
|
||
| ## Modes | ||
|
|
||
| There are 3 modes: | ||
|
|
||
| - `allow`: Always allow admin access. | ||
| - `deny`: Always deny admin access. | ||
| - `qrexec`: Make a qrexec call and use it's result to allow/deny. The main | ||
| usage is to have a trivial qrexec service in dom0 and use the qrexec policy | ||
| with the ask action to allow only after prompting. | ||
|
|
||
| "Admin access" here means being able to run things as another user (including | ||
| root), via sudo, su and polkit. This is always limited to users in the `qubes` | ||
| group. | ||
|
|
||
|
|
||
| ## Config | ||
|
|
||
| When the `qubes-core-agent-passwordless-root` is installed the | ||
| `pam_qubes_admin_authz.so` PAM module is always enabled. This module asks the | ||
| `qubes-admin-authzd` daemon which does the actual logic (see below for | ||
| technical details). | ||
|
|
||
| The mode can be set via /usr/local/etc/qubes/admin-authzd.conf for per-qube | ||
| setting or more common via /etc/qubes/admin-authzd.conf in a template (setting | ||
| in /usr/local has precendce). | ||
|
marmarek marked this conversation as resolved.
|
||
|
|
||
| There config file have a very simple syntax. The first line needs to contain | ||
| one of the listed mode above without anythings else. Currently the rest of the | ||
| file is ignored. Please prefix comments with `#` to allow extension of this | ||
| configuration file should the need arise. | ||
|
|
||
| Additionally the mode can be set by setting the `admin-authz-mode` feature on a | ||
| qube or it's template. This setting override the above config files (internally | ||
| the feature sets a qubesdb entry, which is read on boot and written to | ||
| /run/qubes-admin-authzd.conf). | ||
|
|
||
|
|
||
| ## qrexec policy | ||
|
|
||
| After setting the mode to qrexec, you need to configure the qrexec policy in | ||
| dom0. For example: | ||
|
|
||
| ``` | ||
| qubes.AuthorizeAdminAccess * * @default ask target=dom0 default_target=dom0 | ||
| ``` | ||
|
|
||
| asks for requests from any VM. | ||
|
|
||
| Note that in dom0 only a trivial service is run that returns a fixed string | ||
| such that the qube knows the result of the policy evaluation. The idea here is | ||
| that this way the existing qrexec policy can be reused, including it's ask | ||
| prompt. | ||
|
|
||
|
|
||
| ## Limitaions | ||
|
|
||
| Keep in mind that if you have allowed admin access and the qube was compromised | ||
| after that point persistence is trivial. | ||
|
|
||
|
|
||
| ## Technical details | ||
|
|
||
| We implement a PAM module named `pam_qubes_admin_authz.so` to permit the | ||
| access. Since PAM modules can be run in a setuid context (when called by | ||
| sudo/su) we want to keep the code simple there. Therefore we use just some | ||
| existing PAM helper functions to check for the requesting users group | ||
| membership and check the PAM "service" (`sudo`, `su-l`, etc.) and if they match | ||
| we make a connection to an abstract Unix socket. With `SO_PEERCRED` we check | ||
| that this socket has been opened by root. The rest, including config file | ||
| handling and invoking qrexec-client-vm is then handled by the | ||
| `qubes-admin-authzd` at the other end of the socket (started by | ||
| qubes-admin-authzd.service). | ||
|
|
||
| ## Recovery | ||
|
|
||
| Should you have locked you self out you should still be able to use | ||
| `qvm-console-dispvm` and login as root there without a password. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| allow | ||
|
|
||
| # The first line of this file needs to be 'deny', 'allow' or 'qrexec'. | ||
| # For more details see /usr/share/doc/qubes-core-agent-passwordless-root/README |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| auth required pam_env.so | ||
| auth required pam_faildelay.so delay=2000000 | ||
| auth required pam_faillock.so preauth silent {include if "with-faillock"} | ||
| auth sufficient pam_qubes_admin_authz.so group=qubes services=su,su-l,sudo,sudo-i,polkit-1 | ||
| auth sufficient pam_u2f.so cue {include if "with-pam-u2f"} | ||
| auth required pam_u2f.so cue {if not "without-pam-u2f-nouserok":nouserok} {include if "with-pam-u2f-2fa"} | ||
| auth sufficient pam_unix.so {if not "without-nullok":nullok} | ||
| auth sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| auth required pam_faillock.so authfail {include if "with-faillock"} | ||
| auth optional pam_gnome_keyring.so only_if=login auto_start {include if "with-pam-gnome-keyring"} | ||
| auth required pam_deny.so | ||
|
|
||
| account required pam_access.so {include if "with-pamaccess"} | ||
| account required pam_faillock.so {include if "with-faillock"} | ||
| account sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| account required pam_unix.so | ||
|
|
||
| password sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| password requisite pam_pwquality.so | ||
| password [default=1 ignore=ignore success=ok] pam_localuser.so {include if "with-pwhistory"} | ||
| password requisite pam_pwhistory.so use_authtok {include if "with-pwhistory"} | ||
| password sufficient pam_unix.so yescrypt shadow {if not "without-nullok":nullok} use_authtok | ||
| password required pam_deny.so | ||
|
|
||
| session optional pam_keyinit.so revoke | ||
| session required pam_limits.so | ||
| session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} | ||
| session optional pam_systemd_home.so {include if "with-systemd-homed"} | ||
| -session optional pam_systemd.so | ||
| session optional pam_oddjob_mkhomedir.so {include if "with-mkhomedir"} | ||
| session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid | ||
| session required pam_unix.so | ||
| session optional pam_gnome_keyring.so only_if=login auto_start {include if "with-pam-gnome-keyring"} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| auth required pam_env.so | ||
| auth required pam_faildelay.so delay=2000000 | ||
| auth required pam_faillock.so preauth silent {include if "with-faillock"} | ||
| auth sufficient pam_qubes_admin_authz.so group=qubes services=su,su-l,sudo,sudo-i,polkit-1 | ||
| auth sufficient pam_fprintd.so {include if "with-fingerprint"} | ||
| auth sufficient pam_u2f.so cue {include if "with-pam-u2f"} | ||
| auth required pam_u2f.so cue {if not "without-pam-u2f-nouserok":nouserok} {include if "with-pam-u2f-2fa"} | ||
| auth sufficient pam_unix.so {if not "without-nullok":nullok} | ||
| auth sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| auth required pam_faillock.so authfail {include if "with-faillock"} | ||
| auth optional pam_gnome_keyring.so only_if=login auto_start {include if "with-pam-gnome-keyring"} | ||
| auth required pam_deny.so | ||
|
|
||
| account required pam_access.so {include if "with-pamaccess"} | ||
| account required pam_faillock.so {include if "with-faillock"} | ||
| account sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| account required pam_unix.so | ||
|
|
||
| password sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| password requisite pam_pwquality.so | ||
| password [default=1 ignore=ignore success=ok] pam_localuser.so {include if "with-pwhistory"} | ||
| password requisite pam_pwhistory.so use_authtok {include if "with-pwhistory"} | ||
| password sufficient pam_unix.so yescrypt shadow {if not "without-nullok":nullok} use_authtok | ||
| password required pam_deny.so | ||
|
|
||
| session optional pam_keyinit.so revoke | ||
| session required pam_limits.so | ||
| session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} | ||
| session optional pam_systemd_home.so {include if "with-systemd-homed"} | ||
| -session optional pam_systemd.so | ||
| session optional pam_oddjob_mkhomedir.so {include if "with-mkhomedir"} | ||
| session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid | ||
| session required pam_unix.so | ||
| session optional pam_gnome_keyring.so only_if=login auto_start {include if "with-pam-gnome-keyring"} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| auth required pam_env.so | ||
| auth required pam_faildelay.so delay=2000000 | ||
| auth required pam_faillock.so preauth silent {include if "with-faillock"} | ||
| auth sufficient pam_qubes_admin_authz.so group=qubes services=su,su-l,sudo,sudo-i,polkit-1 | ||
| auth sufficient pam_u2f.so cue {include if "with-pam-u2f"} | ||
| auth required pam_u2f.so cue {if not "without-pam-u2f-nouserok":nouserok} {include if "with-pam-u2f-2fa"} | ||
| auth sufficient pam_unix.so {if not "without-nullok":nullok} | ||
| auth sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| auth required pam_faillock.so authfail {include if "with-faillock"} | ||
| auth optional pam_gnome_keyring.so only_if=login auto_start {include if "with-pam-gnome-keyring"} | ||
| auth required pam_deny.so | ||
|
|
||
| account required pam_access.so {include if "with-pamaccess"} | ||
| account required pam_faillock.so {include if "with-faillock"} | ||
| account sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| account required pam_unix.so broken_shadow | ||
|
|
||
| password sufficient pam_systemd_home.so {include if "with-systemd-homed"} | ||
| password requisite pam_pwquality.so {if not "with-nispwquality":local_users_only} | ||
| password [default=1 ignore=ignore success=ok] pam_localuser.so {include if "with-pwhistory"} | ||
| password requisite pam_pwhistory.so use_authtok {include if "with-pwhistory"} | ||
| password sufficient pam_unix.so yescrypt shadow {if not "without-nullok":nullok} use_authtok nis | ||
| password required pam_deny.so | ||
|
|
||
| session optional pam_keyinit.so revoke | ||
| session required pam_limits.so | ||
| session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} | ||
| session optional pam_systemd_home.so {include if "with-systemd-homed"} | ||
| -session optional pam_systemd.so | ||
| session optional pam_oddjob_mkhomedir.so {include if "with-mkhomedir"} | ||
| session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid | ||
| session required pam_unix.so | ||
| session optional pam_gnome_keyring.so only_if=login auto_start {include if "with-pam-gnome-keyring"} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a concrete scenario where
policy-rc.dblocks startup of something incorrectly? I'm a bit worried about assuming the user's intentions here, since Kicksecure's build system uses a "deny everything" policy-rc.d to prevent everything from starting, because of the fallout it can have on the rest of the build. Bypassing this mechanism seems dangerous at best. If a user does end up blocked, they can always open a DispVM console and log in as root, or useqvm-run -u root ....There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have this in (some of) my Debian templates as a stopgap solution to allow disabling services of newly installed packages before they are run (Debian's default policy).
But in that case you don't have a running systemd, right? So this is a nop.
That being said I don't feel too strongly about handling this corner case. So would be fine with dropping it, if preferred.