49 lines
2.4 KiB
Python
49 lines
2.4 KiB
Python
"""Opt-in integration test using only a disposable Windows vault namespace."""
|
|
import ctypes
|
|
from ctypes import wintypes
|
|
import importlib.util
|
|
import os
|
|
from pathlib import Path
|
|
import secrets
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
SCRIPT = Path(__file__).resolve().parents[1] / "skills" / "updating-gitea-repositories" / "scripts" / "credential_migrate.py"
|
|
spec = importlib.util.spec_from_file_location("credential_migrate_vault_test", SCRIPT)
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
|
|
|
|
@unittest.skipUnless(sys.platform == "win32" and os.environ.get("GITEA_TEST_WINDOWS_VAULT") == "1", "opt-in Windows vault test")
|
|
class WindowsVaultTest(unittest.TestCase):
|
|
def test_secure_store_readback_and_trace_suppression(self):
|
|
namespace = "gitea-skill-test-" + secrets.token_hex(16)
|
|
host = "credential-migration-test.invalid"
|
|
target_name = namespace + ":https://" + host
|
|
api = ctypes.WinDLL("Advapi32.dll", use_last_error=True)
|
|
api.CredDeleteW.argtypes = [wintypes.LPCWSTR, wintypes.DWORD, wintypes.DWORD]
|
|
api.CredDeleteW.restype = wintypes.BOOL
|
|
class Source:
|
|
def get(self, request):
|
|
return {"username": b"fictional-alice", "password": b"fictional-secret"}
|
|
module._assert_windows_namespace_empty(namespace)
|
|
try:
|
|
with tempfile.TemporaryDirectory() as cwd:
|
|
trace = Path(cwd) / "trace.log"
|
|
config = Path(cwd) / "config"
|
|
config.write_text("[credential]\n trace = " + str(trace).replace("\\", "/") + "\n traceSecrets = true\n", encoding="utf-8")
|
|
env = module.safe_environment()
|
|
env.update({"GCM_NAMESPACE": namespace, "GCM_CREDENTIAL_STORE": "wincredman", "GIT_CONFIG_NOSYSTEM": "1", "GIT_CONFIG_GLOBAL": str(config), "XDG_CONFIG_HOME": cwd})
|
|
target = module.NewWindowsNamespace(["git", "credential-manager"], env, cwd, namespace)
|
|
module.migrate("https://" + host, "fictional-alice", Source(), target)
|
|
self.assertFalse(trace.exists() and b"fictional-secret" in trace.read_bytes(), "GCM traced the test credential")
|
|
finally:
|
|
if not api.CredDeleteW(target_name, 1, 0) and ctypes.get_last_error() != 1168:
|
|
self.fail("Could not remove the disposable test credential")
|
|
module._assert_windows_namespace_empty(namespace)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|