"""Docker secret-file resolution. Standard library only; no stack required.""" import tempfile import unittest from pathlib import Path from app.core.secrets import SECRET_FILE_SETTINGS, load, read_secret class SecretFileTests(unittest.TestCase): def setUp(self): self.dir = tempfile.TemporaryDirectory() self.addCleanup(self.dir.cleanup) def secret(self, content, name='secret'): path = Path(self.dir.name) / name path.write_text(content, encoding='utf-8') return str(path) def test_resolves_file_into_plain_setting(self): env = {'DATABASE_URL_FILE': self.secret('postgresql://u:p@db:5432/dtf\n')} self.assertEqual(load(env), ['DATABASE_URL']) self.assertEqual(env['DATABASE_URL'], 'postgresql://u:p@db:5432/dtf') def test_strips_only_one_trailing_newline(self): # A generated password may legitimately end in whitespace, so only the # newline `docker secret` or an editor appends may be removed. self.assertEqual(read_secret(self.secret('p@ss \n')), 'p@ss ') self.assertEqual(read_secret(self.secret('p@ss\n\n')), 'p@ss\n') self.assertEqual(read_secret(self.secret('p@ss\r\n')), 'p@ss') self.assertEqual(read_secret(self.secret('p@ss')), 'p@ss') def test_preserves_characters_that_would_break_a_url(self): value = 'p@ss:w/rd?#[]&=+$ ,%' env = {'OPERATOR_PASSWORD_FILE': self.secret(value + '\n')} load(env) self.assertEqual(env['OPERATOR_PASSWORD'], value) def test_resolves_every_documented_production_setting(self): env = {f'{name}_FILE': self.secret(f'value-for-{name}', name) for name in SECRET_FILE_SETTINGS} load(env) for name in SECRET_FILE_SETTINGS: self.assertEqual(env[name], f'value-for-{name}') def test_missing_file_fails_closed(self): env = {'DATABASE_URL_FILE': str(Path(self.dir.name) / 'absent')} with self.assertRaises(RuntimeError) as caught: load(env) self.assertIn('DATABASE_URL_FILE', str(caught.exception)) self.assertNotIn('DATABASE_URL', env) def test_empty_secret_fails_closed(self): with self.assertRaises(RuntimeError): load({'OPERATOR_PASSWORD_FILE': self.secret('\n')}) def test_empty_path_fails_closed(self): with self.assertRaises(RuntimeError): load({'OPERATOR_PASSWORD_FILE': ' '}) def test_value_and_file_together_is_ambiguous(self): env = {'OPERATOR_PASSWORD': 'inline', 'OPERATOR_PASSWORD_FILE': self.secret('from-file')} with self.assertRaises(RuntimeError): load(env) self.assertEqual(env['OPERATOR_PASSWORD'], 'inline') def test_never_puts_a_secret_in_the_error_text(self): value = 'super-secret-value' env = {'TINY_TOKEN': value, 'TINY_TOKEN_FILE': self.secret(value)} with self.assertRaises(RuntimeError) as caught: load(env) self.assertNotIn(value, str(caught.exception)) def test_ignores_a_bare_suffix_and_leaves_other_settings_alone(self): env = {'_FILE': '/nowhere', 'APP_ENV': 'production'} self.assertEqual(load(env), []) self.assertEqual(env['APP_ENV'], 'production') def test_documented_list_matches_the_production_stack(self): stack = Path(__file__).resolve().parent.parent / 'deploy' / 'stack.yaml' if not stack.exists(): self.skipTest('production stack definition not present') text = stack.read_text() # POSTGRES_PASSWORD_FILE is consumed by the database image, not by us. used = {line.split(':')[0].strip() for line in text.splitlines() if '_FILE:' in line and 'POSTGRES_PASSWORD_FILE' not in line} for key in used: self.assertIn(key[:-len('_FILE')], SECRET_FILE_SETTINGS, f'{key} is passed by the stack but undocumented in secrets.py') if __name__ == '__main__': unittest.main()