diff options
Diffstat (limited to 'hosts/vidhar/borg')
-rwxr-xr-x | hosts/vidhar/borg/copy.py | 68 |
1 files changed, 37 insertions, 31 deletions
diff --git a/hosts/vidhar/borg/copy.py b/hosts/vidhar/borg/copy.py index df77e4bb..d4edb09d 100755 --- a/hosts/vidhar/borg/copy.py +++ b/hosts/vidhar/borg/copy.py | |||
@@ -45,17 +45,10 @@ halo_args = { | |||
45 | 45 | ||
46 | borg_pwd = getpwnam('borg') | 46 | borg_pwd = getpwnam('borg') |
47 | 47 | ||
48 | def as_borg(caps=set(), withns=lambda: pass): | 48 | def as_borg(caps=set()): |
49 | if caps: | 49 | if caps: |
50 | for capset in [cap_permitted, cap_inheritable, cap_effective, cap_ambient]: | 50 | for capset in [cap_permitted, cap_inheritable, cap_effective, cap_ambient]: |
51 | capset.add(*caps) | 51 | capset.add(*caps) |
52 | |||
53 | unshare.unshare(unshare.CLONE_NEWNS) | ||
54 | subprocess.run(['mount', '--make-rprivate', '/'], check=True) | ||
55 | withns() | ||
56 | if os.environ.get('CREDENTIALS_DIRECTORY'): | ||
57 | creds_path = pathlib.Path(os.environ['CREDENTIALS_DIRECTORY']).relative_to('/') | ||
58 | subprocess.run(['bindfs', '-r', f'--force-user={borg_pwd.pw_uid}', f'--force-group={borg_pwd.pw_gid}', pathlib.Path('/') / creds_path, chroot / creds_path], check=True) | ||
59 | 52 | ||
60 | os.setgid(borg_pwd.pw_gid) | 53 | os.setgid(borg_pwd.pw_gid) |
61 | os.setuid(borg_pwd.pw_uid) | 54 | os.setuid(borg_pwd.pw_uid) |
@@ -114,29 +107,32 @@ def copy_archive(src_repo_path, dst_repo_path, entry): | |||
114 | dir = pathlib.Path('/borg') | 107 | dir = pathlib.Path('/borg') |
115 | 108 | ||
116 | def preexec_fn(): | 109 | def preexec_fn(): |
117 | def withns(): | 110 | unshare.unshare(unshare.CLONE_NEWNS) |
118 | chroot = pathlib.Path(tmpdir) / 'chroot' | 111 | subprocess.run(['mount', '--make-rprivate', '/'], check=True) |
119 | upper = pathlib.Path(tmpdir) / 'upper' | 112 | chroot = pathlib.Path(tmpdir) / 'chroot' |
120 | work = pathlib.Path(tmpdir) / 'work' | 113 | upper = pathlib.Path(tmpdir) / 'upper' |
121 | for path in [chroot,upper,work]: | 114 | work = pathlib.Path(tmpdir) / 'work' |
122 | path.mkdir() | 115 | for path in [chroot,upper,work]: |
123 | subprocess.run(['mount', '-t', 'overlay', 'overlay', '-o', f'lowerdir=/,upperdir={upper},workdir={work}', chroot], check=True) | 116 | path.mkdir() |
124 | bindMounts = ['nix', 'run', 'proc', 'dev', 'sys', pathlib.Path(os.path.expanduser('~')).relative_to('/')] | 117 | subprocess.run(['mount', '-t', 'overlay', 'overlay', '-o', f'lowerdir=/,upperdir={upper},workdir={work}', chroot], check=True) |
125 | if os.environ.get('BORG_BASE_DIR'): | 118 | bindMounts = ['nix', 'run', 'proc', 'dev', 'sys', pathlib.Path(os.path.expanduser('~')).relative_to('/')] |
126 | bindMounts.append(pathlib.Path(os.environ['BORG_BASE_DIR']).relative_to('/')) | 119 | if os.environ.get('BORG_BASE_DIR'): |
127 | if not ":" in src_repo_path: | 120 | bindMounts.append(pathlib.Path(os.environ['BORG_BASE_DIR']).relative_to('/')) |
128 | bindMounts.append(pathlib.Path(src_repo_path).relative_to('/')) | 121 | if not ":" in src_repo_path: |
129 | if 'SSH_AUTH_SOCK' in os.environ: | 122 | bindMounts.append(pathlib.Path(src_repo_path).relative_to('/')) |
130 | bindMounts.append(pathlib.Path(os.environ['SSH_AUTH_SOCK']).parent.relative_to('/')) | 123 | if 'SSH_AUTH_SOCK' in os.environ: |
131 | for bindMount in bindMounts: | 124 | bindMounts.append(pathlib.Path(os.environ['SSH_AUTH_SOCK']).parent.relative_to('/')) |
132 | (chroot / bindMount).mkdir(parents=True,exist_ok=True) | 125 | if 'CREDENTIALS_DIRECTORY' in os.environ: |
133 | # print(*['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], file=stderr) | 126 | bindMounts.append(pathlib.Path(os.environ['CREDENTIALS_DIRECTORY']).parent.relative_to('/')) |
134 | subprocess.run(['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], check=True) | 127 | for bindMount in bindMounts: |
135 | os.chroot(chroot) | 128 | (chroot / bindMount).mkdir(parents=True,exist_ok=True) |
136 | os.chdir('/') | 129 | # print(*['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], file=stderr) |
137 | dir.mkdir(parents=True,exist_ok=True,mode=750) | 130 | subprocess.run(['mount', '--bind', pathlib.Path('/') / bindMount, chroot / bindMount], check=True) |
138 | os.chown(dir, borg_pwd.pw_uid, borg_pwd.pw_gid) | 131 | os.chroot(chroot) |
139 | as_borg(withns=withns, caps={Cap.DAC_READ_SEARCH}) | 132 | os.chdir('/') |
133 | dir.mkdir(parents=True,exist_ok=True,mode=750) | ||
134 | os.chown(dir, borg_pwd.pw_uid, borg_pwd.pw_gid) | ||
135 | as_borg(caps={Cap.DAC_READ_SEARCH}) | ||
140 | 136 | ||
141 | total_size = None | 137 | total_size = None |
142 | total_files = None | 138 | total_files = None |
@@ -245,6 +241,16 @@ def sigterm(signum, frame): | |||
245 | 241 | ||
246 | def main(): | 242 | def main(): |
247 | signal.signal(signal.SIGTERM, sigterm) | 243 | signal.signal(signal.SIGTERM, sigterm) |
244 | |||
245 | if 'CREDENTIALS_DIRECTORY' in os.environ: | ||
246 | for root, dirs, files in os.walk(os.environ['CREDENTIALS_DIRECTORY']): | ||
247 | def do_chown(path): | ||
248 | os.chown(pathlib.Path(root) / pathlib.Path(path), borg_pwd.pw_uid, borg_pwd.pw_gid) | ||
249 | |||
250 | for dir in dirs: | ||
251 | do_chown(dir) | ||
252 | for file in files: | ||
253 | do_chown(file) | ||
248 | 254 | ||
249 | if "::" in args.source: | 255 | if "::" in args.source: |
250 | (src_repo_path, _, src_archive) = args.source.partition("::") | 256 | (src_repo_path, _, src_archive) = args.source.partition("::") |