import hashlib import importlib.metadata import json import os import pathlib import tempfile from datetime import datetime, timedelta, timezone import approval_engine.store as store from approval_engine.errors import Forbidden assert os.getuid() == 10001 assert store.LATEST_SCHEMA_VERSION == 5 now = datetime.now(timezone.utc) binding = dict(action='fixture.consume', target={'id': 'fixture'}, actor='service:fixture', principal='human:fixture', purpose='disposable-image-verification') validity = {'not_before': (now-timedelta(minutes=1)).isoformat(), 'expires_at': (now+timedelta(minutes=5)).isoformat()} with tempfile.TemporaryDirectory() as directory: path = pathlib.Path(directory)/'approvals.sqlite' engine = store.Engine(path) legacy = engine.create(binding, validity) engine.add_entry(legacy.id, 'human:legacy', principal_type='human') engine._conn().execute('ALTER TABLE approvals DROP COLUMN human_control') engine._conn().execute('PRAGMA user_version=4') engine._conn().commit() engine.close() engine = store.Engine(path) assert engine.storage_status()['schema_version'] == 5 assert engine.get(legacy.id).human_control is False assert engine.claim(legacy.id)['valid_now'] is True controlled = engine.create(binding, validity, human_control=True) for principal_type in ('service', 'agent', None): try: engine.add_entry(controlled.id, 'nonhuman', principal_type=principal_type) except Forbidden: pass else: raise AssertionError('nonhuman binding admitted') assert engine.get(controlled.id).entries == [] engine.add_entry(controlled.id, 'human:fixture', principal_type='human') assert engine.claim(controlled.id)['binding']['human_control'] is True assert engine.claim(controlled.id)['valid_now'] is True engine.consume(controlled.id, controlled.binding_digest) assert engine.get(controlled.id).status == 'consumed' engine.close() reopened = store.Engine(path) assert reopened.get(controlled.id).human_control is True assert reopened.get(controlled.id).status == 'consumed' reopened.close() print(json.dumps({ 'status': 'passed', 'uid': os.getuid(), 'schema_version': 5, 'store_sha256': hashlib.sha256(pathlib.Path(store.__file__).read_bytes()).hexdigest(), 'checks': ['nonroot', 'v4-to-v5-persistent-migration', 'legacy-declaration-false', 'service-agent-unknown-refusal', 'human-bind-claim-consume', 'restart-persistence'], 'native_identity_or_credential_calls': 0, 'network': 'none', 'packages': {name: importlib.metadata.version(name) for name in ('approval-engine', 'PyJWT', 'cryptography', 'waitress')}, }, indent=2))