Skip to content
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

adduser(8): support creation of ZFS dataset #881

Closed
wants to merge 1 commit into from

Conversation

jgrafton
Copy link
Contributor

@jgrafton jgrafton commented Oct 31, 2023

On systems utilizing ZFS, default to creating a ZFS dataset for a new user's home directory if the parent directory resides on a ZFS dataset. Add a flag that disables this behavior if the administrator explicitly does not want it.

If run during installation from within a chroot, set mountpoint to legacy after dataset creation and mount directly into the chroot. Then umount and reset the mountpoint to inherit from parent.

Also support ZFS default encryption on user's home directory.

Requested here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263234

@no-usernames-left
Copy link

no-usernames-left commented Oct 31, 2023

Failed to start an instance: FAILED_PRECONDITION: Monthly compute limit exceeded!

Whoops. Maybe resubmit in a few hours? 😅

usr.sbin/adduser/adduser.8 Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.8 Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.conf.5 Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.conf.5 Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.sh Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.sh Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.sh Show resolved Hide resolved
usr.sbin/adduser/adduser.sh Outdated Show resolved Hide resolved
usr.sbin/adduser/adduser.sh Outdated Show resolved Hide resolved
@jgrafton
Copy link
Contributor Author

jgrafton commented Nov 1, 2023

I simplified the code with your suggestions @delphij. This revision just adds a dataset if the parent resides on a dataset like you mentioned. I'll get to work on adding encryption in a later revision. Thanks again!

@jgrafton jgrafton marked this pull request as draft November 8, 2023 13:54
@jgrafton
Copy link
Contributor Author

jgrafton commented Nov 8, 2023

Discovered bug during installation in chrooted environment. The skeleton data for the user's home directory is copied into the underlying user directory instead of the mounted dataset. Marking this draft until I resolve the issue.

@jgrafton jgrafton marked this pull request as ready for review December 7, 2023 20:58
@@ -202,6 +203,8 @@ save_config() {
echo "msgfile=$msgfile" >> ${ADDUSERCONF}
echo "disableflag=$disableflag" >> ${ADDUSERCONF}
echo "uidstart=$uidstart" >> ${ADDUSERCONF}
echo "Zflag=$Zflag" >> ${ADDUSERCONF}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd maybe call this zfscreate=no, just to be a little more obvious from the name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I changed both Zencrypt and Zcreate to yes/no bools to remove confusion.

@@ -202,6 +203,8 @@ save_config() {
echo "msgfile=$msgfile" >> ${ADDUSERCONF}
echo "disableflag=$disableflag" >> ${ADDUSERCONF}
echo "uidstart=$uidstart" >> ${ADDUSERCONF}
echo "Zflag=$Zflag" >> ${ADDUSERCONF}
echo "Zencrypt=$Zencrypt" >> ${ADDUSERCONF}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a manpage addition for Zencrypt, but with a more descriptive name for Zflag you could make that instead a tri-state: zfscreate=yes|no|encrypted

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, Zflag is super confusing! I set Zcreate and Zencrypt to yes/no bools but didn't implement the tri-state since the two booleans seem to "flow" better in the script.

# Determine if homeprefix is located on a ZFS filesystem and if
# so, enable ZFS home dataset creation.
#
get_zfs_home() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it would override a configured Zflag=no, but I'm also not sure I understand the logic; zfs list would exit 0 if it found a prefix, and -z "${zfs_homeprefix} would flip Zflag on if we didn't detect a prefix.

There's an additional caveat that using zfs will trigger a load of zfs.ko on purely ufs systems; I'd recommend bailing out before calling it if kldstat -q -m zfs indicates that zfs isn't there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right, Zflag means "no zfs dataset"... the name is definitely getting me here.

Zencrypt=
break
;;
[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think accepting "ye" is a little nonstandard; this should probably just be a case-insensitive "yes" or case-insensitive "y"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it's a bit strange. However, I followed the user input convention already used in the script.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, indeed- funky

echo -n "$_prompt"
read _input

[ -z "$_input" ] && _input=Zencrypt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prompt describes "no" as the default, but this seems to be trying to use the current value of Zencrypt as the default? (But it should have been $Zencrypt... this should probably be no to match the prompt, though)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a bug, fixed.

#
create_zfs_chrooted_dataset() {
${ZFSCMD} create -u ${zfsopt} "${zhome}"
if [ "$?" -ne 0 ]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More concisely written as:

if ! ${ZFSCMD} create ...

# Create ZFS dataset owned by the user that was just added.
#
create_zfs_dataset() {
${ZFSCMD} create ${zfsopt} "${zhome}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto above; you're not using the exit code otherwise, might as well just test it directly

# Give new user ownership of newly created zfs dataset.
#
set_zfs_perms() {
${ZFSCMD} allow "${username}" create,destroy,mount,snapshot "${zhome}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto above w/ exit code

Copy link
Contributor

@kevans91 kevans91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this LGTM- thanks!

@jgrafton
Copy link
Contributor Author

jgrafton commented Jan 2, 2024

I think this LGTM- thanks!

Thanks Kyle!

@igalic
Copy link
Contributor

igalic commented Jan 16, 2024

@kevans91 and go ahead and commit this?

@@ -32,7 +32,7 @@
.Nd command for adding new users
.Sh SYNOPSIS
.Nm
.Op Fl CDENShq
.Op Fl CDENSZhq
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This man page needs a .Dd bump.

# create ZFS dataset before home directory is created with pw
if [ "${Zcreate}" = "yes" ]; then
if [ "${Zencrypt}" = "yes" ]; then
echo "Enter encryption keyphrase for ZFS dataset (${zhome}):"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look like it is prompting for anything or passing the results along, why not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"zfs create" actually asks for the passphrase when encryption is requested but doesn't give any indication on what it's for. The echo lets the user know what the coming password request is for.

@bsdimp
Copy link
Member

bsdimp commented Jan 17, 2024

Just a nit an a quick question

On systems utilizing ZFS, default to creating a ZFS dataset for a new
user's home directory if the parent directory resides on a ZFS dataset.
Add a flag that disables this behavior if the administrator explicitly
does not want it.

If run during installation from within a chroot, set mountpoint to legacy
after dataset creation and mount directly into the chroot.  Then umount
and reset the mountpoint to inherit from parent.

Also support ZFS default encryption on user's home directory.
@bsdimp
Copy link
Member

bsdimp commented Apr 11, 2024

merged. Thanks!

@bsdimp bsdimp closed this Apr 11, 2024
freebsd-git pushed a commit that referenced this pull request Apr 11, 2024
On systems utilizing ZFS, default to creating a ZFS dataset for a new
user's home directory if the parent directory resides on a ZFS dataset.
Add a flag that disables this behavior if the administrator explicitly
does not want it.

If run during installation from within a chroot, set mountpoint to legacy
after dataset creation and mount directly into the chroot.  Then umount
and reset the mountpoint to inherit from parent.

Also support ZFS default encryption on user's home directory.

Feedback by: delphij
Reviewed by: imp, kevans
Pull Request: #881
freebsd-git pushed a commit that referenced this pull request Apr 29, 2024
On systems utilizing ZFS, default to creating a ZFS dataset for a new
user's home directory if the parent directory resides on a ZFS dataset.
Add a flag that disables this behavior if the administrator explicitly
does not want it.

If run during installation from within a chroot, set mountpoint to legacy
after dataset creation and mount directly into the chroot.  Then umount
and reset the mountpoint to inherit from parent.

Also support ZFS default encryption on user's home directory.

Feedback by: delphij
Reviewed by: imp, kevans
Pull Request: #881

(cherry picked from commit 215c0a5)
freebsd-git pushed a commit that referenced this pull request Apr 29, 2024
On systems utilizing ZFS, default to creating a ZFS dataset for a new
user's home directory if the parent directory resides on a ZFS dataset.
Add a flag that disables this behavior if the administrator explicitly
does not want it.

If run during installation from within a chroot, set mountpoint to legacy
after dataset creation and mount directly into the chroot.  Then umount
and reset the mountpoint to inherit from parent.

Also support ZFS default encryption on user's home directory.

Feedback by: delphij
Reviewed by: imp, kevans
Pull Request: #881

(cherry picked from commit 215c0a5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants