Skip to content
Open
2 changes: 2 additions & 0 deletions src/common-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion src/common-utils/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "common-utils",
"version": "2.5.9",
"version": "2.6.0",
"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.",
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions src/common-utils/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"}"

Expand Down
26 changes: 25 additions & 1 deletion src/common-utils/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"}"

Expand Down Expand Up @@ -470,6 +472,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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi @the78mole

Would you kindly provide some background/ use cases where the ADD_GROUPS functionality could be useful?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Quite easy to explain... If you do embedded development, you usually need to map /dev into your devcontainer to access e.g. /dev/ttyUSB0 to flash your device. To access such devices, your user needs to be member of dialup group... Other devices need plugdev group membership...

# 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
Expand Down Expand Up @@ -593,7 +611,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
Expand Down
13 changes: 13 additions & 0 deletions test/common-utils/add-groups.sh
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions test/common-utils/custom-zsh-theme.sh
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions test/common-utils/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@
}
}
},
"add-groups": {
"image": "debian:bullseye",
"features": {
"common-utils": {
"username": "alternate",
"addGroups": "dialout,plugdev"
}
}
},
"username-default": {
"image": "debian:bullseye",
"features": {
Expand Down Expand Up @@ -285,6 +294,18 @@
"common-utils": {}
}
},
"custom-zsh-theme": {
"image": "ubuntu:jammy",
"remoteUser": "devcontainer",
"features": {
"common-utils": {
"installZsh": true,
"installOhMyZsh": true,
"ohMyZshTheme": "fino",
"configureZshAsDefaultShell": true
}
}
},
"ubi-8": {
"image": "registry.access.redhat.com/ubi8/ubi:8.10",
"remoteUser": "devcontainer",
Expand Down
Loading