Implement audited lost-factor recovery and track remaining P04 acceptance
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
parent
244e7e096f
commit
3b7df9047e
5 changed files with 229 additions and 1 deletions
|
|
@ -13,6 +13,7 @@ def run():
|
|||
with tempfile.TemporaryDirectory(prefix="provider-contract-") as d:
|
||||
root=Path(d);(root/'enckey').write_bytes(os.urandom(96))
|
||||
cfg=root/'fixture.cfg';cfg.write_text("SQLALCHEMY_DATABASE_URI='sqlite:///:memory:'\nSECRET_KEY='isolated-fixture-only'\nPI_PEPPER='isolated-fixture-only'\nPI_NO_RESPONSE_SIGN=True\nPI_AUDIT_NO_SIGN=True\nPI_LOGFILE="+repr(str(root/'log'))+"\nPI_ENCFILE="+repr(str(root/'enckey'))+"\nPI_TRUSTED_JWT=[]\n")
|
||||
with cfg.open('a') as f:f.write('PI_AUDIT_SQL_URI='+repr('sqlite:///'+str(root/'audit.sqlite'))+'\n')
|
||||
from privacyidea.app import create_app
|
||||
from privacyidea.models import db
|
||||
from privacyidea.lib.policy import set_policy,enable_policy
|
||||
|
|
@ -24,6 +25,9 @@ def run():
|
|||
phase="fixture_database"
|
||||
with app.app_context():
|
||||
check('database_isolated',str(db.engine.url)=='sqlite:///:memory:');db.create_all()
|
||||
from privacyidea.lib.audit import getAudit
|
||||
from privacyidea.lib.auditmodules.sqlaudit import LogEntry
|
||||
LogEntry.__table__.create(getAudit(app.config).engine,checkfirst=True)
|
||||
passwd=root/'users';passwd.write_text('alice:'+crypt_ctx.hash('fixture-password',scheme='sha512_crypt')+':1001:1001:Fixture:/tmp:/bin/false\n')
|
||||
save_resolver({'resolver':'fixture-users','type':'passwdresolver','fileName':str(passwd)})
|
||||
set_realm('fixture',[{'name':'fixture-users'}])
|
||||
|
|
@ -85,6 +89,18 @@ def run():
|
|||
time.sleep(3)
|
||||
code,_=req('GET','/token/',token=short)
|
||||
check('expired_provider_jwt_rejected',code==401)
|
||||
phase='platform_admin_recovery'
|
||||
from factor_recovery import ProviderStore,recover,RecoveryError
|
||||
with app.app_context():
|
||||
store=ProviderStore(app,realm='fixture')
|
||||
request=dict(user='alice',serial=serial,realm='fixture',actor='fixture-platform-operator',reference='fixture-recovery-001')
|
||||
preview=recover(store,request)
|
||||
check('recovery_preview_preserves_factor',preview['active'] is True and preview['changes_applied'] is False)
|
||||
approved=dict(request,apply=True,identity_verified=True,expected_version=preview['version'])
|
||||
applied=recover(store,approved)
|
||||
check('platform_recovery_disabled_factor',applied['status']=='recovered' and store.snapshot('alice',serial)['active'] is False)
|
||||
check('platform_recovery_audit_durable',store.receipt(request['reference'])['complete'] is True)
|
||||
check('platform_recovery_replay_no_mutation',recover(store,approved)['replayed'] is True)
|
||||
phase='finished';result['success']=True
|
||||
with contextlib.redirect_stdout(io.StringIO()),contextlib.redirect_stderr(io.StringIO()):
|
||||
try:run()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue