Skip to content

Commit c772e98

Browse files
committed
Fix spurious error messages with altered uid
1 parent 709206a commit c772e98

File tree

2 files changed

+69
-20
lines changed

2 files changed

+69
-20
lines changed

base-notebook/start.sh

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -172,49 +172,55 @@ if [ "$(id -u)" == 0 ] ; then
172172
# The container didn't start as the root user, so we will have to act as the
173173
# user we started as.
174174
else
175-
# Warn about misconfiguration of: desired username, user id, or group id
176-
if [[ -n "${NB_USER}" && "${NB_USER}" != "$(id -un)" ]]; then
177-
_log "WARNING: container must be started as root to change the desired user's name with NB_USER!"
178-
fi
179-
if [[ -n "${NB_UID}" && "${NB_UID}" != "$(id -u)" ]]; then
180-
_log "WARNING: container must be started as root to change the desired user's id with NB_UID!"
181-
fi
182-
if [[ -n "${NB_GID}" && "${NB_GID}" != "$(id -g)" ]]; then
183-
_log "WARNING: container must be started as root to change the desired user's group id with NB_GID!"
184-
fi
185-
186175
# Warn about misconfiguration of: granting sudo rights
187176
if [[ "${GRANT_SUDO}" == "1" || "${GRANT_SUDO}" == "yes" ]]; then
188177
_log "WARNING: container must be started as root to grant sudo permissions!"
189178
fi
190179

180+
JOVYAN_UID="$(id -u jovyan 2>/dev/null)" # The default UID for the jovyan user
181+
JOVYAN_GID="$(id -g jovyan 2>/dev/null)" # The default GID for the jovyan user
182+
191183
# Attempt to ensure the user uid we currently run as has a named entry in
192184
# the /etc/passwd file, as it avoids software crashing on hard assumptions
193185
# on such entry. Writing to the /etc/passwd was allowed for the root group
194186
# from the Dockerfile during build.
195187
#
196188
# ref: https://github.com/jupyter/docker-stacks/issues/552
197189
if ! whoami &> /dev/null; then
198-
_log "There is no entry in /etc/passwd for our UID. Attempting to fix..."
190+
_log "There is no entry in /etc/passwd for our UID=$(id -u). Attempting to fix..."
199191
if [[ -w /etc/passwd ]]; then
200192
_log "Renaming old jovyan user to nayvoj ($(id -u jovyan):$(id -g jovyan))"
201193

202194
# We cannot use "sed --in-place" since sed tries to create a temp file in
203195
# /etc/ and we may not have write access. Apply sed on our own temp file:
204196
sed --expression="s/^jovyan:/nayvoj:/" /etc/passwd > /tmp/passwd
205-
echo "jovyan:x:$(id -u):$(id -g):,,,:/home/jovyan:/bin/bash" >> /tmp/passwd
197+
echo "${NB_USER}:x:$(id -u):$(id -g):,,,:/home/jovyan:/bin/bash" >> /tmp/passwd
206198
cat /tmp/passwd > /etc/passwd
207199
rm /tmp/passwd
208200

209-
_log "Added new jovyan user ($(id -u):$(id -g)). Fixed UID!"
201+
_log "Added new ${NB_USER} user ($(id -u):$(id -g)). Fixed UID!"
210202
else
211-
_log "WARNING: unable to fix missing /etc/passwd entry because we don't have write permission."
203+
_log "WARNING: unable to fix missing /etc/passwd entry because we don't have write permission. Try setting gid=0 with \"--user=$(id -u):0\"."
212204
fi
213205
fi
214206

207+
# Warn about misconfiguration of: desired username, user id, or group id.
208+
# A misconfiguration occurs when the user modifies the default values of
209+
# NB_USER, NB_UID, or NB_GID, but we cannot update those values because we
210+
# are not root.
211+
if [[ "${NB_USER}" != "jovyan" && "${NB_USER}" != "$(id -un)" ]]; then
212+
_log "WARNING: container must be started as root to change the desired user's name with NB_USER=\"${NB_USER}\"!"
213+
fi
214+
if [[ "${NB_UID}" != "${JOVYAN_UID}" && "${NB_UID}" != "$(id -u)" ]]; then
215+
_log "WARNING: container must be started as root to change the desired user's id with NB_UID=\"${NB_UID}\"!"
216+
fi
217+
if [[ "${NB_GID}" != "${JOVYAN_GID}" && "${NB_GID}" != "$(id -g)" ]]; then
218+
_log "WARNING: container must be started as root to change the desired user's group id with NB_GID=\"${NB_GID}\"!"
219+
fi
220+
215221
# Warn if the user isn't able to write files to ${HOME}
216222
if [[ ! -w /home/jovyan ]]; then
217-
_log "WARNING: no write access to /home/jovyan. Try starting the container with group 'users' (100)."
223+
_log "WARNING: no write access to /home/jovyan. Try starting the container with group 'users' (100), e.g. using \"--group-add=users\"."
218224
fi
219225

220226
# NOTE: This hook is run as the user we started the container as!

base-notebook/test/test_container_options.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,23 +230,66 @@ def test_sudo_path_without_grant(container):
230230
assert logs.rstrip().endswith("/opt/conda/bin/jupyter")
231231

232232

233-
def test_group_add(container, tmpdir):
233+
def test_group_add(container):
234234
"""Container should run with the specified uid, gid, and secondary
235-
group.
235+
group. It won't be possible to modify /etc/passwd since gid is nonzero, so
236+
additionally verify that setting gid=0 is suggested in a warning.
236237
"""
237238
c = container.run(
238239
user="1010:1010",
239-
group_add=["users"],
240+
group_add=["users"], # Ensures write access to /home/jovyan
240241
command=["start.sh", "id"],
241242
)
242243
rv = c.wait(timeout=5)
243244
assert rv == 0 or rv["StatusCode"] == 0
244245
logs = c.logs(stdout=True).decode("utf-8")
245246
assert "ERROR" not in logs
246-
assert "WARNING" not in logs
247+
warnings = [
248+
warning for warning in logs.split("\n") if warning.startswith("WARNING")
249+
]
250+
assert len(warnings) == 1
251+
assert "Try setting gid=0" in warnings[0]
247252
assert "uid=1010 gid=1010 groups=1010,100(users)" in logs
248253

249254

255+
def test_set_uid(container):
256+
"""Container should run with the specified uid and NB_USER.
257+
The /home/jovyan directory will not be writable since it's owned by 1000:users.
258+
Additionally verify that "--group-add=users" is suggested in a warning to restore
259+
write access.
260+
"""
261+
c = container.run(
262+
user="1010",
263+
command=["start.sh", "id"],
264+
)
265+
rv = c.wait(timeout=5)
266+
assert rv == 0 or rv["StatusCode"] == 0
267+
logs = c.logs(stdout=True).decode("utf-8")
268+
assert "ERROR" not in logs
269+
assert "uid=1010(jovyan) gid=0(root)" in logs
270+
warnings = [
271+
warning for warning in logs.split("\n") if warning.startswith("WARNING")
272+
]
273+
assert len(warnings) == 1
274+
assert "--group-add=users" in warnings[0]
275+
276+
277+
def test_set_uid_and_nb_user(container):
278+
"""Container should run with the specified uid and NB_USER."""
279+
c = container.run(
280+
user="1010",
281+
environment=["NB_USER=kitten"],
282+
group_add=["users"], # Ensures write access to /home/jovyan
283+
command=["start.sh", "id"],
284+
)
285+
rv = c.wait(timeout=5)
286+
assert rv == 0 or rv["StatusCode"] == 0
287+
logs = c.logs(stdout=True).decode("utf-8")
288+
assert "ERROR" not in logs
289+
assert "WARNING" not in logs
290+
assert "uid=1010(kitten) gid=0(root)" in logs
291+
292+
250293
def test_container_not_delete_bind_mount(container, tmp_path):
251294
"""Container should not delete host system files when using the (docker)
252295
-v bind mount flag and mapping to /home/jovyan.

0 commit comments

Comments
 (0)