2022-08-15 22:38:15 +02:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
import os
|
2022-08-16 16:37:53 +02:00
|
|
|
import stat
|
2022-08-15 22:38:15 +02:00
|
|
|
|
|
|
|
from typing import Union, Generator
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
|
|
from .cmd import run_root_cmd
|
2022-08-16 16:37:53 +02:00
|
|
|
from .file import chmod, chown, get_temp_dir, write_file
|
2022-08-15 22:38:15 +02:00
|
|
|
from utils import get_gid, get_uid
|
|
|
|
|
2022-08-16 16:37:53 +02:00
|
|
|
TEMPDIR_MODE = 0o755
|
|
|
|
|
2022-08-15 22:38:15 +02:00
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class TempdirFillInfo():
|
|
|
|
path: str
|
|
|
|
files: dict[str, str]
|
|
|
|
|
|
|
|
|
2022-08-16 16:37:53 +02:00
|
|
|
def _get_tempdir():
|
|
|
|
d = get_temp_dir(register_cleanup=False, mode=TEMPDIR_MODE)
|
2022-08-15 22:38:15 +02:00
|
|
|
assert os.path.exists(d)
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
def remove_dir(d):
|
|
|
|
run_root_cmd(['rm', '-rf', d]).check_returncode()
|
|
|
|
|
|
|
|
|
|
|
|
def create_file(filepath, owner='root', group='root'):
|
|
|
|
assert not os.path.exists(filepath)
|
|
|
|
run_root_cmd(['touch', filepath]).check_returncode()
|
|
|
|
run_root_cmd(['chown', f'{owner}:{group}', filepath]).check_returncode()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def tempdir():
|
2022-08-16 16:37:53 +02:00
|
|
|
d = _get_tempdir()
|
2022-08-15 22:38:15 +02:00
|
|
|
yield d
|
|
|
|
# cleanup, gets run after the test since we yield above
|
|
|
|
remove_dir(d)
|
|
|
|
|
|
|
|
|
2022-08-16 16:37:53 +02:00
|
|
|
def test_get_tempdir(tempdir):
|
|
|
|
mode = os.stat(tempdir).st_mode
|
|
|
|
assert stat.S_ISDIR(mode)
|
|
|
|
assert stat.S_IMODE(mode) == TEMPDIR_MODE
|
|
|
|
|
|
|
|
|
2022-08-15 22:38:15 +02:00
|
|
|
@pytest.fixture
|
|
|
|
def tempdir_filled() -> Generator[TempdirFillInfo, None, None]:
|
2022-08-16 16:37:53 +02:00
|
|
|
d = _get_tempdir()
|
2022-08-15 22:38:15 +02:00
|
|
|
contents = {
|
|
|
|
'rootfile': {
|
|
|
|
'owner': 'root',
|
|
|
|
'group': 'root',
|
|
|
|
},
|
|
|
|
'userfile': {
|
|
|
|
'owner': 'nobody',
|
|
|
|
'group': 'nobody',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
res = TempdirFillInfo(path=d, files={})
|
|
|
|
for p, opts in contents.items():
|
|
|
|
path = os.path.join(d, p)
|
|
|
|
res.files[p] = path
|
|
|
|
create_file(path, **opts)
|
|
|
|
yield res
|
|
|
|
# cleanup, gets run after the test since we yield above
|
|
|
|
remove_dir(d)
|
|
|
|
|
|
|
|
|
|
|
|
def verify_ownership(filepath, user: Union[str, int], group: Union[str, int]):
|
|
|
|
uid = get_uid(user)
|
|
|
|
gid = get_gid(group)
|
|
|
|
assert os.path.exists(filepath)
|
|
|
|
fstat = os.stat(filepath)
|
|
|
|
assert fstat.st_uid == uid
|
|
|
|
assert fstat.st_gid == gid
|
|
|
|
|
|
|
|
|
2022-08-16 16:37:53 +02:00
|
|
|
def verify_mode(filepath, mode: int = TEMPDIR_MODE):
|
|
|
|
assert stat.S_IMODE(os.stat(filepath).st_mode) == mode
|
|
|
|
|
|
|
|
|
2022-08-15 22:38:15 +02:00
|
|
|
def verify_content(filepath, content):
|
|
|
|
assert os.path.exists(filepath)
|
|
|
|
with open(filepath, 'r') as f:
|
|
|
|
assert f.read().strip() == content.strip()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("user,group", [('root', 'root'), ('nobody', 'nobody')])
|
|
|
|
def test_chown(tempdir: str, user: str, group: str):
|
|
|
|
assert os.path.exists(tempdir)
|
|
|
|
target_uid = get_uid(user)
|
|
|
|
target_gid = get_gid(group)
|
|
|
|
chown(tempdir, target_uid, target_gid)
|
|
|
|
verify_ownership(tempdir, target_uid, target_gid)
|
|
|
|
|
|
|
|
|
2022-08-16 16:37:53 +02:00
|
|
|
@pytest.mark.parametrize("mode", [0, 0o700, 0o755, 0o600, 0o555])
|
|
|
|
def test_chmod(tempdir_filled, mode: int):
|
|
|
|
for filepath in tempdir_filled.files.values():
|
|
|
|
chmod(filepath, mode)
|
|
|
|
verify_mode(filepath, mode)
|
|
|
|
|
|
|
|
|
2022-08-15 22:38:15 +02:00
|
|
|
def test_tempdir_filled_fixture(tempdir_filled: TempdirFillInfo):
|
|
|
|
files = tempdir_filled.files
|
|
|
|
assert files
|
|
|
|
assert 'rootfile' in files
|
|
|
|
assert 'userfile' in files
|
|
|
|
verify_ownership(files['rootfile'], 'root', 'root')
|
|
|
|
verify_ownership(files['userfile'], 'nobody', 'nobody')
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_new_file_naive(tempdir: str):
|
|
|
|
assert os.path.exists(tempdir)
|
|
|
|
new = os.path.join(tempdir, 'newfiletest')
|
|
|
|
content = 'test12345'
|
|
|
|
assert not os.path.exists(new)
|
|
|
|
write_file(new, content)
|
|
|
|
verify_content(new, content)
|
|
|
|
verify_ownership(new, user=os.getuid(), group=os.getgid())
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_new_file_root(tempdir: str):
|
|
|
|
assert os.path.exists(tempdir)
|
|
|
|
new = os.path.join(tempdir, 'newfiletest')
|
|
|
|
content = 'test12345'
|
|
|
|
assert not os.path.exists(new)
|
|
|
|
write_file(new, content, user='root', group='root')
|
|
|
|
verify_content(new, content)
|
|
|
|
verify_ownership(new, user=0, group=0)
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_new_file_user(tempdir: str):
|
|
|
|
user = 'nobody'
|
|
|
|
group = 'nobody'
|
|
|
|
assert os.path.exists(tempdir)
|
|
|
|
new = os.path.join(tempdir, 'newfiletest')
|
|
|
|
content = 'test12345'
|
|
|
|
assert not os.path.exists(new)
|
|
|
|
write_file(new, content, user=user, group=group)
|
|
|
|
assert os.path.exists(new)
|
|
|
|
verify_content(new, content)
|
|
|
|
verify_ownership(new, user=user, group=group)
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_new_file_user_in_root_dir(tempdir: str):
|
|
|
|
assert os.path.exists(tempdir)
|
|
|
|
chown(tempdir, user='root', group='root')
|
|
|
|
verify_ownership(tempdir, 'root', 'root')
|
|
|
|
test_write_new_file_user(tempdir)
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_rootfile_naive(tempdir_filled: TempdirFillInfo):
|
|
|
|
files = tempdir_filled.files
|
|
|
|
assert 'rootfile' in files
|
|
|
|
p = files['rootfile']
|
|
|
|
assert os.path.exists(p)
|
|
|
|
verify_ownership(p, 'root', 'root')
|
|
|
|
content = 'test123'
|
|
|
|
write_file(p, content)
|
|
|
|
verify_content(p, 'test123')
|
|
|
|
verify_ownership(p, 'root', 'root')
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("user,group", [('root', 'root'), ('nobody', 'nobody')])
|
|
|
|
def test_write_rootfile(tempdir_filled: TempdirFillInfo, user: str, group: str):
|
|
|
|
files = tempdir_filled.files
|
|
|
|
assert 'rootfile' in files
|
|
|
|
p = files['rootfile']
|
|
|
|
assert os.path.exists(p)
|
|
|
|
verify_ownership(p, 'root', 'root')
|
|
|
|
content = 'test123'
|
|
|
|
write_file(p, content)
|
|
|
|
verify_content(p, 'test123')
|
|
|
|
verify_ownership(p, 'root', 'root')
|