From 3074671554cc06fb25869991abca1b7e26adc45a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 28 Jan 2017 21:23:24 -0500 Subject: [PATCH] Add proof-of-concept sys-user eclass for installing users/groups. --- eclass/sys-user.eclass | 236 +++++++++++++++++++++++++++++ profiles/categories | 2 + sys-group/tcpdump/Manifest | 2 + sys-group/tcpdump/metadata.xml | 20 +++ sys-group/tcpdump/tcpdump-0.ebuild | 17 +++ sys-user/tcpdump/Manifest | 2 + sys-user/tcpdump/metadata.xml | 20 +++ sys-user/tcpdump/tcpdump-0.ebuild | 18 +++ 8 files changed, 317 insertions(+) create mode 100644 eclass/sys-user.eclass create mode 100644 profiles/categories create mode 100644 sys-group/tcpdump/Manifest create mode 100644 sys-group/tcpdump/metadata.xml create mode 100644 sys-group/tcpdump/tcpdump-0.ebuild create mode 100644 sys-user/tcpdump/Manifest create mode 100644 sys-user/tcpdump/metadata.xml create mode 100644 sys-user/tcpdump/tcpdump-0.ebuild diff --git a/eclass/sys-user.eclass b/eclass/sys-user.eclass new file mode 100644 index 0000000..65b731f --- /dev/null +++ b/eclass/sys-user.eclass @@ -0,0 +1,236 @@ +# Copyright 1999-2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +# @ECLASS: sys-user.eclass +# @MAINTAINER: +# Michael Orlitzky +# @BLURB: handle installation and removal of system users. +# @DESCRIPTION: +# This eclass does most of the work for the sys-user/ packages that +# supply system user accounts. + +inherit user + +EXPORT_FUNCTIONS src_unpack src_prepare src_configure src_compile src_install src_test pkg_preinst pkg_postinst pkg_prerm + +# This is hard-coded to the package name. If you want a different +# username, use a different package name. This is a nice way to prevent +# different people from claiming the same username. +SYS_USER_NAME="${PN}" + +# @ECLASS-VARIABLE: SYS_USER_GROUPS +# @DESCRIPTION: +# etc. +: ${SYS_USER_GROUPS:=${PN}} + +# @ECLASS-VARIABLE: SYS_USER_UID +# @DESCRIPTION: +# etc. (use -1 to get next available using user.eclass) +: ${SYS_USER_UID:=-1} + +# In many cases, if the UID of a user changes, packages depending on it +# will want to rebuild. We always use SLOT=0, because you can't install +# the same user twice. Then we use the UID as our subslot so that +# subslot deps can be used to rebuild packages when our UID changes. +SLOT="0/${SYS_USER_UID}" + +# @ECLASS-VARIABLE: SYS_USER_HOME +# @DESCRIPTION: +# etc. (use -1 to get user.eclass default) +: ${SYS_USER_HOME:=-1} + +# @ECLASS-VARIABLE: SYS_USER_SHELL +# @DESCRIPTION: +# etc. (use -1 to get user.eclass default) +: ${SYS_USER_SHELL:=-1} + +case ${EAPI} in + 6) ;; + *) + die "${ECLASS} is not compatible with EAPI=${EAPI}" +esac + +# Depend on any groups we might need. +for _group in ${SYS_USER_GROUPS}; do + DEPEND+=" sys-group/${_group} " + RDEPEND+=" sys-group/${_group}:= " +done +unset _group + +S="${WORKDIR}" + +sys-user_src_unpack() { :; } +sys-user_src_prepare() { :; } +sys-user_src_configure() { :; } +sys-user_src_compile() { :; } +sys-user_src_test() { :; } + +sys-user_next_uid() { + local euid; + for (( euid = 101; euid <= 999; euid++ )); do + [[ -z $(egetent passwd "${euid}") ]] && break + done + if (( "${euid}" == 999 )); then + die "out of available UIDs!" + else + echo "${euid}" + fi +} + +sys-user_src_prepare() { + eapply_user # whatever + + if [[ -n $(egetent passwd "${SYS_USER_NAME}") ]]; then + # UPGRADE PATH: This user already exists, so if the eclass + # consumer doesn't care about some settings, we can reuse the + # pre-existing ones. + # + # This is also useful for sys-user package upgrades, becaused it + # prevents us from incrementing the UID pointlessly on a + # reinstall. Usually that will prevent rebuilds of depending + # packages, and is crucial to our ability to use subslot deps to + # cause rebuilds when the UID changes. We don't want the UID to + # change if the subslot doesn't change, and the subslot for "I + # don't care about the UID" will always be "-1", so the UID + # shouldn't generally change either when SYS_USER_UID=-1. + if (( "${SYS_USER_UID}" == -1 )); then + SYS_USER_UID=$(id --real --user "${SYS_USER_NAME}") + fi + + if (( "${SYS_USER_HOME}" == -1 )); then + SYS_USER_HOME=$(egethome "${SYS_USER_NAME}") + fi + + if (( "${SYS_USER_SHELL}" == -1 )); then + SYS_USER_SHELL=$(egetshell "${SYS_USER_NAME}") + + if [[ ${SYS_USER_SHELL} == */false ]] || \ + [[ ${SYS_USER_SHELL} == */nologin ]]; then + # WHYYYYY? enewuser complains if we try to set a default + # shell explicitly. + SYS_USER_SHELL="-1" + fi + fi + elif (( "${SYS_USER_UID}" == -1 )); then + # There is no pre-existing user (i.e. this isn't along the + # upgrade path), and the consumer says he doesn't care about the + # UID, so pick the next one. + SYS_USER_UID=$(sys-user_next_uid) + fi + + # We do something with this in src_install. + touch "${T}/${SYS_USER_UID}" || die +} + +sys-user_src_install() { + # Install a placeholder file to /var/lib/sys-user/$uid. This will + # cause collisions if two packages try to install users with the + # same UID. The same problem potentially exists with the username, + # but as long as SYS_USER_NAME is hard-coded to $PN, that shouldn't + # be possible. + # + # Beware, this only works if SYS_USER_UID is guaranteed to have a + # real UID and not, for example, -1. That is taken care of in + # src_prepare() for now. + insinto "/var/lib/sys-user" + doins "${T}/${SYS_USER_UID}" + + # TODO: do we want to try to create the user's home directory within + # the package manager so that it can be cleaned up later? The + # obvious problem with that plan is that we need to be careful not + # to give the new user ownership of e.g. /dev/null. +} + +sys-user_pkg_preinst() { + if [[ -z $(egetent passwd "${SYS_USER_NAME}") ]]; then + # The user does not already exist. This is the nice and easy + # case because no matter how we got here, we want to go ahead + # and create the (new) user. + enewuser "${SYS_USER_NAME}" \ + "${SYS_USER_UID}" \ + "${SYS_USER_SHELL}" \ + "${SYS_USER_HOME}" \ + "${SYS_USER_GROUPS}" \ + || die "failed to add user ${SYS_USER_NAME}" + elif [[ -n "${REPLACING_VERSIONS}" ]]; then + # This is an upgrade from an existing sys-user package. This + # case is a little bit weird. If we do it in preinst(), then it + # will happen before the "old" user is removed in + # pkg_prerm(). Except the old user and the new user are the + # same, so if we overwrite the existing user here, then prerm + # for the version that created it will clobber our new entry. + # + # We also can't just LEAVE the old user there, because then no + # upgrade happens. + # + # Uh, let's do this case in pkg_postinst so that it happens + # after the old version's prerm. + : + else + # UPGRADE PATH: Ok, the user exists but this isn't an upgrade of + # a sys-user package. This is the upgrade path from the old + # style of user/group management to the new style. What can we + # do? We could make it policy that old users must be compatible + # with the new ones, but that entails hard-coding UIDs that + # don't need to be hard-coded. + # + # Instead lets see if the new user is compatible with the old + # (it usually will be), and then only bail out if there's a real + # problem. + local oldhome=$(egethome "${SYS_USER_NAME}") + local oldshell=$(egetshell "${SYS_USER_NAME}") + local olduid=$(id --real --user "${SYS_USER_NAME}") + + if [[ "${oldhome}" -ne "${SYS_USER_HOME}" ]]; then + die "home directory conflict for new user ${SYS_USER_HOME}" + fi + + if [[ "${oldhshell}" -ne "${SYS_USER_SHELL}" ]]; then + die "shell conflict for new user ${SYS_USER_HOME}" + fi + + if [[ "${olduid}" -ne "${SYS_USER_UID}" ]]; then + die "UID conflict for new user ${SYS_USER_NAME}" + fi + + # The user already exists, so all we have left to do is to try + # to append SYS_USER_GROUPS to the existing groups. The "usermod" + # tool expects a comma-separated list, so change our spaces to + # commas. This does succeed if you append duplicates. + usermod --append --groups "${SYS_USER_GROUPS// /,}" \ + || die "failed to append groups to existing user ${SYS_USER_NAME}" + fi +} + +sys-user_pkg_postinst() { + if [[ -n "${REPLACING_VERSIONS}" ]]; then + # This is an upgrade from a previous version of a sys-user + # package. This case has to be handled carefully to make sure + # that the pkg_prerm() of the old version doesn't remove the user + # that this new version is going to add. At this point, in our + # pkg_postinst(), the old version's pkg_prerm() phase should have + # already happened. + if [[ -n $(egetent passwd "${SYS_USER_NAME}") ]]; then + die "User ${SYS_USER_NAME} already exists during an upgrade." + else + enewuser "${SYS_USER_NAME}" \ + "${SYS_USER_UID}" \ + "${SYS_USER_SHELL}" \ + "${SYS_USER_HOME}" \ + "${SYS_USER_GROUPS}" \ + || die "failed to add user ${SYS_USER_NAME}" + fi + fi +} + +sys-user_pkg_prerm() { + if [[ -z $(egetent passwd "${SYS_USER_NAME}") ]]; then + # We have successfully done nothing. + ewarn "Tried to remove nonexistent user ${SYS_USER_NAME}." + else + userdel "${SYS_USER_NAME}" || \ + die "failed to remove user ${SYS_USER_NAME}" + einfo "Removed user ${SYS_USER_NAME} from the system." + fi +} diff --git a/profiles/categories b/profiles/categories new file mode 100644 index 0000000..3d1160f --- /dev/null +++ b/profiles/categories @@ -0,0 +1,2 @@ +sys-user +sys-group diff --git a/sys-group/tcpdump/Manifest b/sys-group/tcpdump/Manifest new file mode 100644 index 0000000..533fca4 --- /dev/null +++ b/sys-group/tcpdump/Manifest @@ -0,0 +1,2 @@ +EBUILD tcpdump-0.ebuild 296 SHA256 5e8e06824597b8e566c1e02caac20527f402c9172b80305e94144d7c14f4ce3a SHA512 3aebd8e0f0932fe9af7635d34894fe68103e862af8ec93b4ac611a20c0079123a479b03a3e71c5cf489349ae1353f576d0977f557656ad93786b09009d344a25 WHIRLPOOL 45bf28123ba735000f449aa1e6fdc5f142016831bdbe4d43f716a71cbfe02cad3b8c7a9876930107eca131b24f147b504be42604fbb7a50ce7a98ba17f0f852e +MISC metadata.xml 533 SHA256 f0a9810780f90804554690040776736f8f95d79fb5225d1df8f9e1b94f2a94f2 SHA512 3303989855dc26af76cd2fd5ad93fcb70d5484886a122c72a2c71f7dc2070b23bf8c25a46180a4ebc6ffb6537e2b78354e8f24a1167a831a7498475b12712827 WHIRLPOOL e6e19f8dc8e0e88382e11e20c1a68e418469297dad2b34e98998e44eeeb6c374c012c39b1ce6f38c0614e3f360696864247daa0ebf5107b0bff61f994f7088a7 diff --git a/sys-group/tcpdump/metadata.xml b/sys-group/tcpdump/metadata.xml new file mode 100644 index 0000000..a7ca9ec --- /dev/null +++ b/sys-group/tcpdump/metadata.xml @@ -0,0 +1,20 @@ + + + + + + mjo@gentoo.org + Michael Orlitzky + + + diff --git a/sys-group/tcpdump/tcpdump-0.ebuild b/sys-group/tcpdump/tcpdump-0.ebuild new file mode 100644 index 0000000..e05878c --- /dev/null +++ b/sys-group/tcpdump/tcpdump-0.ebuild @@ -0,0 +1,17 @@ +# Copyright 1999-2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +EAPI=6 + +DESCRIPTION="The tcpdump system group" +HOMEPAGE="https://www.gentoo.org/" +SRC_URI="" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64 ~x86" +IUSE="" + +DEPEND="" +RDEPEND="${DEPEND}" diff --git a/sys-user/tcpdump/Manifest b/sys-user/tcpdump/Manifest new file mode 100644 index 0000000..d77a09c --- /dev/null +++ b/sys-user/tcpdump/Manifest @@ -0,0 +1,2 @@ +EBUILD tcpdump-0.ebuild 313 SHA256 1e33bfc902f64357bf6d97d749743ebf9cc61a4b995777bff055020c9c1c74cf SHA512 5cbdf67fc8f6efa417107e20062c7a1c169edf7bd012014f9692944ef2ae78624dad81cedb9935422beaa97122bb353a9baf5e44b920bcb135db68d84c4d9fb6 WHIRLPOOL 15d9e0df558a1487a05d517590077de187839edd6eeec0ce81dfc8d88a566734ac930732808828330c4d0ffd336d12e70933614245da8829dd19e0705eed2948 +MISC metadata.xml 533 SHA256 f0a9810780f90804554690040776736f8f95d79fb5225d1df8f9e1b94f2a94f2 SHA512 3303989855dc26af76cd2fd5ad93fcb70d5484886a122c72a2c71f7dc2070b23bf8c25a46180a4ebc6ffb6537e2b78354e8f24a1167a831a7498475b12712827 WHIRLPOOL e6e19f8dc8e0e88382e11e20c1a68e418469297dad2b34e98998e44eeeb6c374c012c39b1ce6f38c0614e3f360696864247daa0ebf5107b0bff61f994f7088a7 diff --git a/sys-user/tcpdump/metadata.xml b/sys-user/tcpdump/metadata.xml new file mode 100644 index 0000000..a7ca9ec --- /dev/null +++ b/sys-user/tcpdump/metadata.xml @@ -0,0 +1,20 @@ + + + + + + mjo@gentoo.org + Michael Orlitzky + + + diff --git a/sys-user/tcpdump/tcpdump-0.ebuild b/sys-user/tcpdump/tcpdump-0.ebuild new file mode 100644 index 0000000..b812dab --- /dev/null +++ b/sys-user/tcpdump/tcpdump-0.ebuild @@ -0,0 +1,18 @@ +# Copyright 1999-2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +EAPI=6 + +inherit sys-user + +DESCRIPTION="The tcpdump system user" +HOMEPAGE="https://www.gentoo.org/" +SRC_URI="" + +LICENSE="GPL-2" +KEYWORDS="~amd64 ~x86" +IUSE="" + +DEPEND="" +RDEPEND="${DEPEND}" -- 2.44.2