-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-entrypoint.py
More file actions
89 lines (73 loc) · 2.76 KB
/
Copy pathdocker-entrypoint.py
File metadata and controls
89 lines (73 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""Initialize container permissions before starting Spectrum."""
import os
import sys
from pathlib import Path
ID_MAX = 2**32 - 2
WRITABLE_DIRECTORIES = (Path("/data"),)
chown = getattr(os, "chown")
getegid = getattr(os, "getegid")
geteuid = getattr(os, "geteuid")
setgid = getattr(os, "setgid")
setgroups = getattr(os, "setgroups")
setuid = getattr(os, "setuid")
def linux_id(name: str) -> int:
"""Read and validate a positive numeric Linux user or group ID."""
value = os.environ.get(name, "")
if not value.isascii() or not value.isdigit():
raise ValueError(
f"{name} must be a positive decimal Linux ID between 1 and {ID_MAX}; got {value!r}"
)
parsed = int(value)
if not 1 <= parsed <= ID_MAX:
raise ValueError(
f"{name} must be a positive decimal Linux ID between 1 and {ID_MAX}; got {value!r}"
)
return parsed
def chown_tree(path: Path, uid: int, gid: int) -> None:
"""Recursively assign ownership without following symbolic links."""
chown(path, uid, gid, follow_symlinks=False)
for root, directories, files in os.walk(path, followlinks=False):
root_path = Path(root)
for name in directories + files:
chown(root_path / name, uid, gid, follow_symlinks=False)
def main() -> None:
"""Prepare writable storage, drop privileges, and replace this process."""
try:
uid = linux_id("PUID")
gid = linux_id("PGID")
except ValueError as error:
print(f"container initialization error: {error}", file=sys.stderr)
raise SystemExit(64) from error
if not sys.argv[1:]:
print(
"container initialization error: no application command provided",
file=sys.stderr,
)
raise SystemExit(64)
if geteuid() == 0:
for directory in WRITABLE_DIRECTORIES:
if directory.is_symlink():
print(
f"container initialization error: writable directory cannot be a symbolic link: {directory}",
file=sys.stderr,
)
raise SystemExit(73)
directory.mkdir(parents=True, exist_ok=True)
chown_tree(directory, uid, gid)
setgroups([])
setgid(gid)
setuid(uid)
print(f"Starting Spectrum as UID {uid} and GID {gid}", file=sys.stderr)
else:
current_uid = geteuid()
current_gid = getegid()
if (current_uid, current_gid) != (uid, gid):
print(
"Container started as non-root "
f"UID {current_uid} and GID {current_gid}; "
f"PUID={uid} and PGID={gid} were not applied.",
file=sys.stderr,
)
os.execvp(sys.argv[1], sys.argv[1:])
if __name__ == "__main__":
main()