Files
stapler/tests/test_token_manager.py
T
klemek c3131acc88
Docker CI / docker-build (push) Has been cancelled
Python Lint CI / ruff (push) Has been cancelled
Python Lint CI / ruff-format-check (push) Has been cancelled
Python Lint CI / ty (push) Has been cancelled
Python Test CI / coverage (push) Has been cancelled
refactor(token_manager): use pbkdf2 hmac
2026-06-02 23:07:30 +02:00

141 lines
4.9 KiB
Python

import logging
import typing
import unittest
import unittest.mock
from stapler.page import Page
from stapler.params import Parameters
from stapler.token_manager import TokenManager
from . import BaseTestCase
class TestTokenManager(BaseTestCase):
EMPTY_SALT_HASH = "5f88941ac5e26c430d97411ac1103af7a35c753f14aec088fbf34801c099135a"
SALT_HASH = "d71b1f52657c77d00b2a8c59b8d12d13c1c1bb2bcfbb85d2a9b804c36ad57a70"
SECRET_HASH = "38df428b309308e48c3687e7f90bda0e9cf253568c21ec754a0e076ab4ab6423" # noqa: S105
@typing.override
def setUp(self) -> None:
self.registry = self.new_mock()
self.token_manager = TokenManager(
Parameters(data_dir=self.get_tmp_dir(), token_salt="salt"), # noqa: S106
self.registry,
pbkdf2_iterations=1,
)
self.token_manager.logger = unittest.mock.Mock(logging.Logger)
self.tmp_tokens_file = self.tmp_path / TokenManager.FILE
super().setUp()
def test_init_no_hashes(self) -> None:
self.seal_mocks()
self.token_manager.init()
self.assert_file_content(self.tmp_tokens_file, self.SALT_HASH)
self.assertEqual(self.tmp_tokens_file.stat().st_mode, 0o100600)
self.assertListEqual(self.token_manager.token_hashes, [])
def test_init_weak_salt(self) -> None:
self.token_manager.token_salt = b""
self.seal_mocks()
self.token_manager.init()
self.assert_file_content(
self.tmp_tokens_file,
self.EMPTY_SALT_HASH,
)
self.assertListEqual(self.token_manager.token_hashes, [])
def test_init_load_hashes(self) -> None:
with self.tmp_tokens_file.open(mode="w") as file:
file.write(self.SALT_HASH + "\n" + self.SECRET_HASH)
self.seal_mocks()
self.token_manager.init()
self.assertListEqual(self.token_manager.token_hashes, [self.SECRET_HASH])
def test_init_invalid_salt(self) -> None:
with self.tmp_tokens_file.open(mode="w") as file:
file.write(self.EMPTY_SALT_HASH + "\n" + self.SECRET_HASH)
self.seal_mocks()
self.token_manager.init()
self.assertListEqual(self.token_manager.token_hashes, [])
def test_is_valid(self) -> None:
self.seal_mocks()
self.token_manager.token_hashes = [self.SECRET_HASH]
assert self.token_manager.is_valid("secret")
def test_is_valid_fail(self) -> None:
self.seal_mocks()
assert not self.token_manager.is_valid("secret")
def test_is_valid_for_path(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
Page("test_1", token_hash=self.SECRET_HASH),
),
self.seal_mocks(),
):
assert self.token_manager.is_valid_for_path("secret", "test_1")
def test_is_valid_for_path_no_token(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
Page("test_1"),
),
self.seal_mocks(),
):
assert self.token_manager.is_valid_for_path("secret", "test_1")
def test_is_valid_for_path_no_page(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
),
self.seal_mocks(),
):
assert self.token_manager.is_valid_for_path("secret", "test_1")
def test_is_valid_for_path_fail(self) -> None:
with (
self.mock_call(
self.registry.get_from_path,
["test_1"],
Page("test_1", token_hash=self.SALT_HASH),
),
self.seal_mocks(),
):
assert not self.token_manager.is_valid_for_path("secret", "test_1")
def test_set_token(self) -> None:
with (
self.mock_call(
self.registry.set_token_hash,
["test_1", self.SECRET_HASH],
),
self.seal_mocks(),
):
self.token_manager.set_token("test_1", "secret")
def test_detect_file_change(self) -> None:
self.tmp_tokens_file.touch()
self.seal_mocks()
assert self.token_manager.detect_file_change()
def test_detect_file_change_nothing(self) -> None:
self.tmp_tokens_file.touch()
self.token_manager.last_file_change = self.tmp_tokens_file.stat().st_mtime
self.seal_mocks()
assert not self.token_manager.detect_file_change()
@unittest.mock.patch("secrets.token_hex")
def test_new_token(self, mock_token_hex: unittest.mock.Mock) -> None:
mock_token_hex.return_value = "secret"
self.seal_mocks()
self.token_manager.new_token()
self.assertListEqual(self.token_manager.token_hashes, [self.SECRET_HASH])
self.assert_file_content(self.tmp_tokens_file, self.SALT_HASH, self.SECRET_HASH)