Add first-run admin setup and independent password and API token rotation

This commit is contained in:
Mikei386
2026-09-28 15:02:41 +02:00
parent e86e540ae4
commit 9f3a13e45f
20 changed files with 651 additions and 76 deletions
+13 -6
View File
@@ -5,6 +5,9 @@ import os
import secrets
import threading
import unittest
import tempfile
import secrets
import time
import urllib.request
import urllib.error
from unittest.mock import patch
@@ -74,14 +77,20 @@ class PolicyTests(unittest.TestCase):
class APITests(unittest.TestCase):
def setUp(self):
self.server=Server(0)
self.state=tempfile.TemporaryDirectory()
self.server=Server(0,state_dir=self.state.name)
self.password=secrets.token_urlsafe(32)
self.api_token=secrets.token_urlsafe(32)
record=self.server.credentials.setup(self.password,self.api_token)
self.server.sessions['test-session']=dict(expires=time.monotonic()+300,revision=record['password']['hash'])
self.cookie='deck_session=test-session'
self.thread=threading.Thread(target=self.server.serve_forever)
self.thread.start()
self.base=f'http://127.0.0.1:{self.server.server_port}'
def tearDown(self):
self.server.shutdown();self.server.demo.stop();self.server.server_close();self.thread.join()
self.server.shutdown();self.server.demo.stop();self.server.server_close();self.thread.join();self.state.cleanup()
def post(self,path,body,headers=None):
req=urllib.request.Request(self.base+'/api/v1/'+path,data=json.dumps(body).encode(),headers={'Content-Type':'application/json','X-Athena-Deck':'1',**(headers or {})})
req=urllib.request.Request(self.base+'/api/v1/'+path,data=json.dumps(body).encode(),headers={'Content-Type':'application/json','X-Athena-Deck':'1','Cookie':self.cookie,**(headers or {})})
return urllib.request.urlopen(req)
def test_import_rejects_before_transport(self):
with patch.object(self.server.network,'call') as transport:
@@ -95,9 +104,7 @@ class APITests(unittest.TestCase):
with self.assertRaises(urllib.error.HTTPError) as error:self.post('network/confirm',{'trial_id':'test','ingress':'tunnel'})
self.assertEqual(error.exception.code,400);error.exception.close()
def test_authentication(self):
salt=secrets.token_bytes(16)
password='test-only-'+secrets.token_hex(20)
self.server.auth={'salt':salt.hex(),'hash':hashlib.pbkdf2_hmac('sha256',password.encode(),salt,600000).hex()}
password=self.password
with self.assertRaises(urllib.error.HTTPError) as error:urllib.request.urlopen(self.base+'/api/v1/status')
self.assertEqual(error.exception.code,401);error.exception.close()
with self.post('login',{'password':password}) as response:cookie=response.headers['Set-Cookie'].split(';')[0]