43 lines
2.4 KiB
Python
43 lines
2.4 KiB
Python
"""Run inside API container: permissions, hashing and fail-closed scanner unit checks."""
|
|
import hashlib
|
|
from unittest.mock import patch
|
|
from botocore.exceptions import ClientError
|
|
from .db import connect
|
|
from .adapters import LocalS3Storage
|
|
from .auth import password_hash, password_matches
|
|
from .scanning import ClamAV, require_clean
|
|
from fastapi import HTTPException
|
|
|
|
def run():
|
|
with connect() as c:
|
|
role=c.execute('SELECT rolsuper,rolcreatedb,rolcreaterole,rolbypassrls FROM pg_roles WHERE rolname=current_user').fetchone()
|
|
assert not any(role.values()),role
|
|
assert not c.execute("SELECT has_schema_privilege(current_user,'dtf_local','CREATE') AS allowed").fetchone()['allowed']
|
|
storage=LocalS3Storage()
|
|
storage.health()
|
|
visible={bucket['Name'] for bucket in storage.client.list_buckets()['Buckets']}
|
|
assert visible=={storage.bucket},visible
|
|
for call in (lambda:storage.client.get_bucket_policy(Bucket=storage.bucket),
|
|
lambda:storage.client.get_object(Bucket=storage.bucket,Key='outside-runtime-prefix/test.cdr')):
|
|
try:call();raise AssertionError('Runtime storage credentials have excessive privilege')
|
|
except ClientError as error:assert error.response['ResponseMetadata']['HTTPStatusCode']==403
|
|
password='test-password-for-hash'
|
|
salt='00'*16
|
|
old='scrypt$'+salt+'$'+hashlib.scrypt(password.encode(),salt=bytes.fromhex(salt),n=16384,r=8,p=1).hex()
|
|
assert password_matches(password,old)
|
|
new=password_hash(password)
|
|
assert new.startswith('scrypt-v2$') and password_matches(password,new)
|
|
assert not password_matches('wrong',new)
|
|
for state in ('pending','error','rejected'):
|
|
try:require_clean({'complete':True,'scan_state':state});raise AssertionError('Unscanned file released')
|
|
except HTTPException as error:assert error.status_code==409
|
|
require_clean({'complete':True,'scan_state':'clean'})
|
|
assert ClamAV().ping() and ClamAV().version().startswith('ClamAV ')
|
|
assert ClamAV().scan(None,134217729)[0]=='rejected'
|
|
with patch('local.scanning.socket.create_connection',side_effect=OSError('offline')):
|
|
try:ClamAV().scan(None,1);raise AssertionError('Offline scanner returned success')
|
|
except OSError:pass
|
|
print('PASS: runtime DB/S3 least privilege, legacy/current password hashes, quarantine states and scanner size/offline behavior')
|
|
|
|
if __name__=='__main__':run()
|