diff --git a/src/common-utils/README.md b/src/common-utils/README.md index 3d21e8b3f..25538d9ef 100644 --- a/src/common-utils/README.md +++ b/src/common-utils/README.md @@ -19,10 +19,12 @@ Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-r | configureZshAsDefaultShell | Change default shell to ZSH? | boolean | false | | installOhMyZsh | Install Oh My Zsh!? | boolean | true | | installOhMyZshConfig | Allow installing the default dev container .zshrc templates? | boolean | true | +| ohMyZshTheme | Oh My Zsh theme to use (e.g., 'robbyrussell', 'agnoster', 'fino'). Default is 'devcontainers'. | string | devcontainers | | upgradePackages | Upgrade OS packages? | boolean | true | | username | Enter name of a non-root user to configure or none to skip | string | automatic | | userUid | Enter UID for non-root user | string | automatic | | userGid | Enter GID for non-root user | string | automatic | +| addGroups | Comma-separated list of additional groups to add the non-root user to. Groups are created if needed. | string | | | nonFreePackages | Add packages from non-free Debian repository? (Debian only) | boolean | false | ## OS Support diff --git a/src/common-utils/devcontainer-feature.json b/src/common-utils/devcontainer-feature.json index 4ebbd3074..b3c136044 100644 --- a/src/common-utils/devcontainer-feature.json +++ b/src/common-utils/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "common-utils", - "version": "2.5.7", + "version": "2.5.9", "name": "Common Utilities", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/common-utils", "description": "Installs a set of common command line utilities, Oh My Zsh!, and sets up a non-root user.", @@ -25,6 +25,11 @@ "default": true, "description": "Allow installing the default dev container .zshrc templates?" }, + "ohMyZshTheme": { + "type": "string", + "default": "devcontainers", + "description": "Oh My Zsh theme to use (e.g., 'robbyrussell', 'agnoster', 'fino'). Default is 'devcontainers'." + }, "upgradePackages": { "type": "boolean", "default": true, @@ -60,6 +65,11 @@ "default": "automatic", "description": "Enter GID for non-root user" }, + "addGroups": { + "type": "string", + "default": "", + "description": "Comma-separated list of additional groups to add the non-root user to. Groups are created if needed." + }, "nonFreePackages": { "type": "boolean", "default": false, diff --git a/src/common-utils/install.sh b/src/common-utils/install.sh index 313271d0a..274623f0d 100755 --- a/src/common-utils/install.sh +++ b/src/common-utils/install.sh @@ -13,10 +13,12 @@ INSTALL_ZSH="${INSTALLZSH:-"true"}" CONFIGURE_ZSH_AS_DEFAULT_SHELL="${CONFIGUREZSHASDEFAULTSHELL:-"false"}" INSTALL_OH_MY_ZSH="${INSTALLOHMYZSH:-"true"}" INSTALL_OH_MY_ZSH_CONFIG="${INSTALLOHMYZSHCONFIG:-"true"}" +OH_MY_ZSH_THEME="${OHMYZSHTHEME:-"devcontainers"}" UPGRADE_PACKAGES="${UPGRADEPACKAGES:-"true"}" USERNAME="${USERNAME:-"automatic"}" USER_UID="${UID:-"automatic"}" USER_GID="${GID:-"automatic"}" +ADD_GROUPS="${ADDGROUPS:-""}" ADD_NON_FREE_PACKAGES="${NONFREEPACKAGES:-"false"}" INSTALL_SSL="${INSTALLSSL:-"true"}" diff --git a/src/common-utils/main.sh b/src/common-utils/main.sh index 3f6b13477..96adf8dca 100644 --- a/src/common-utils/main.sh +++ b/src/common-utils/main.sh @@ -13,10 +13,12 @@ INSTALL_ZSH="${INSTALLZSH:-"true"}" CONFIGURE_ZSH_AS_DEFAULT_SHELL="${CONFIGUREZSHASDEFAULTSHELL:-"false"}" INSTALL_OH_MY_ZSH="${INSTALLOHMYZSH:-"true"}" INSTALL_OH_MY_ZSH_CONFIG="${INSTALLOHMYZSHCONFIG:-"true"}" +OH_MY_ZSH_THEME="${OHMYZSHTHEME:-"devcontainers"}" UPGRADE_PACKAGES="${UPGRADEPACKAGES:-"true"}" USERNAME="${USERNAME:-"automatic"}" USER_UID="${USERUID:-"automatic"}" USER_GID="${USERGID:-"automatic"}" +ADD_GROUPS="${ADDGROUPS:-""}" ADD_NON_FREE_PACKAGES="${NONFREEPACKAGES:-"false"}" INSTALL_SSL="${INSTALLSSL:-"true"}" @@ -439,6 +441,22 @@ else fi fi +if [ "${USERNAME}" != "root" ] && [ -n "${ADD_GROUPS}" ]; then + IFS=',' read -ra EXTRA_GROUPS <<< "${ADD_GROUPS}" + for extra_group in "${EXTRA_GROUPS[@]}"; do + extra_group="$(echo "${extra_group}" | xargs)" + if [ -z "${extra_group}" ]; then + continue + fi + + if ! getent group "${extra_group}" > /dev/null 2>&1; then + groupadd "${extra_group}" + fi + + usermod -a -G "${extra_group}" "${USERNAME}" + done +fi + # Add add sudo support for non-root user if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME @@ -562,7 +580,13 @@ if [ "${INSTALL_ZSH}" = "true" ]; then if ! [ -f "${template_path}" ] || ! grep -qF "$(head -n 1 "${template_path}")" "${user_rc_file}"; then echo -e "$(cat "${template_path}")\nzstyle ':omz:update' mode disabled" > ${user_rc_file} fi - sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="devcontainers"/g' ${user_rc_file} + # Validate theme name to prevent injection (allow alphanumeric, hyphens, underscores, and dots) + if echo "${OH_MY_ZSH_THEME}" | grep -qE '^[a-zA-Z0-9_.-]+$'; then + sed -i -e "s/ZSH_THEME=.*/ZSH_THEME=\"${OH_MY_ZSH_THEME}\"/g" ${user_rc_file} + else + echo "Warning: Invalid theme name '${OH_MY_ZSH_THEME}'. Using default 'devcontainers' theme." + sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="devcontainers"/g' ${user_rc_file} + fi fi # Copy to non-root user if one is specified diff --git a/test/common-utils/add-groups.sh b/test/common-utils/add-groups.sh new file mode 100644 index 000000000..c0e14372e --- /dev/null +++ b/test/common-utils/add-groups.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +source dev-container-features-test-lib + +check "non-root user" id alternate +check "dialout group exists" getent group dialout +check "plugdev group exists" getent group plugdev +check "alternate in dialout" bash -lc "id -nG alternate | tr ' ' '\n' | grep -Fx dialout" +check "alternate in plugdev" bash -lc "id -nG alternate | tr ' ' '\n' | grep -Fx plugdev" + +reportResults \ No newline at end of file diff --git a/test/common-utils/custom-zsh-theme.sh b/test/common-utils/custom-zsh-theme.sh new file mode 100755 index 000000000..6d8dd90da --- /dev/null +++ b/test/common-utils/custom-zsh-theme.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Definition specific tests +check "zsh" zsh --version +check "oh-my-zsh installed" test -d $HOME/.oh-my-zsh +check "zsh theme is fino" grep 'ZSH_THEME="fino"' ~/.zshrc +check "default shell is zsh" bash -c "getent passwd $(whoami) | awk -F: '{ print \$7 }' | grep '/bin/zsh'" + +# Report result +reportResults diff --git a/test/common-utils/scenarios.json b/test/common-utils/scenarios.json index ee138ca22..7a1f11c01 100644 --- a/test/common-utils/scenarios.json +++ b/test/common-utils/scenarios.json @@ -126,6 +126,15 @@ } } }, + "add-groups": { + "image": "debian:bullseye", + "features": { + "common-utils": { + "username": "alternate", + "addGroups": "dialout,plugdev" + } + } + }, "username-default": { "image": "debian:bullseye", "features": { @@ -284,5 +293,17 @@ "features": { "common-utils": {} } + }, + "custom-zsh-theme": { + "image": "ubuntu:jammy", + "remoteUser": "devcontainer", + "features": { + "common-utils": { + "installZsh": true, + "installOhMyZsh": true, + "ohMyZshTheme": "fino", + "configureZshAsDefaultShell": true + } + } } } \ No newline at end of file