2024-11-19 11:18:12 +03:00
|
|
|
import sys
|
2022-12-28 16:30:54 +03:00
|
|
|
from base64 import b64encode as b64enc
|
|
|
|
from calendar import timegm
|
|
|
|
from datetime import datetime
|
2024-11-19 11:18:12 +03:00
|
|
|
from hashlib import sha256
|
2022-12-28 16:30:54 +03:00
|
|
|
from os.path import dirname, join
|
2023-01-03 15:05:05 +03:00
|
|
|
from uuid import uuid4, UUID
|
2022-12-23 15:42:02 +03:00
|
|
|
|
2022-12-28 16:30:54 +03:00
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from jose import jwt, jwk
|
|
|
|
from jose.constants import ALGORITHMS
|
2022-12-23 09:35:37 +03:00
|
|
|
from starlette.testclient import TestClient
|
|
|
|
|
2022-12-23 13:24:40 +03:00
|
|
|
# add relative path to use packages as they were in the app/ dir
|
|
|
|
sys.path.append('../')
|
|
|
|
sys.path.append('../app')
|
2022-12-23 09:35:37 +03:00
|
|
|
|
2022-12-23 13:24:40 +03:00
|
|
|
from app import main
|
2022-12-29 22:40:42 +03:00
|
|
|
from app.util import load_key
|
2022-12-23 09:35:37 +03:00
|
|
|
|
2024-11-20 11:10:43 +03:00
|
|
|
# main.app.add_middleware(PatchMalformedJsonMiddleware, enabled=True)
|
2022-12-23 09:35:37 +03:00
|
|
|
client = TestClient(main.app)
|
|
|
|
|
2023-01-03 15:05:05 +03:00
|
|
|
ORIGIN_REF, ALLOTMENT_REF, SECRET = str(uuid4()), '20000000-0000-0000-0000-000000000001', 'HelloWorld'
|
2022-12-28 16:30:54 +03:00
|
|
|
|
|
|
|
# INSTANCE_KEY_RSA = generate_key()
|
|
|
|
# INSTANCE_KEY_PUB = INSTANCE_KEY_RSA.public_key()
|
|
|
|
|
|
|
|
INSTANCE_KEY_RSA = load_key(str(join(dirname(__file__), '../app/cert/instance.private.pem')))
|
|
|
|
INSTANCE_KEY_PUB = load_key(str(join(dirname(__file__), '../app/cert/instance.public.pem')))
|
|
|
|
|
|
|
|
jwt_encode_key = jwk.construct(INSTANCE_KEY_RSA.export_key().decode('utf-8'), algorithm=ALGORITHMS.RS256)
|
|
|
|
jwt_decode_key = jwk.construct(INSTANCE_KEY_PUB.export_key().decode('utf-8'), algorithm=ALGORITHMS.RS256)
|
2022-12-23 15:42:02 +03:00
|
|
|
|
2022-12-23 09:35:37 +03:00
|
|
|
|
2022-12-29 21:07:30 +03:00
|
|
|
def __bearer_token(origin_ref: str) -> str:
|
|
|
|
token = jwt.encode({"origin_ref": origin_ref}, key=jwt_encode_key, algorithm=ALGORITHMS.RS256)
|
|
|
|
token = f'Bearer {token}'
|
|
|
|
return token
|
|
|
|
|
|
|
|
|
2022-12-23 09:35:37 +03:00
|
|
|
def test_index():
|
|
|
|
response = client.get('/')
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
2022-12-29 12:37:47 +03:00
|
|
|
def test_health():
|
|
|
|
response = client.get('/-/health')
|
|
|
|
assert response.status_code == 200
|
2023-01-03 11:20:18 +03:00
|
|
|
assert response.json().get('status') == 'up'
|
2022-12-29 12:37:47 +03:00
|
|
|
|
|
|
|
|
2023-01-02 21:14:25 +03:00
|
|
|
def test_config():
|
2023-01-03 19:39:10 +03:00
|
|
|
response = client.get('/-/config')
|
2023-01-02 21:14:25 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
2022-12-29 12:37:47 +03:00
|
|
|
def test_readme():
|
|
|
|
response = client.get('/-/readme')
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
2023-01-03 22:55:23 +03:00
|
|
|
def test_dashboard():
|
|
|
|
response = client.get('/-/dashboard')
|
2022-12-29 12:37:47 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
2022-12-23 09:48:47 +03:00
|
|
|
def test_client_token():
|
2022-12-29 22:41:02 +03:00
|
|
|
response = client.get('/-/client-token')
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
2022-12-29 12:37:47 +03:00
|
|
|
def test_origins():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_origins_delete():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_leases():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_lease_delete():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2022-12-23 09:48:47 +03:00
|
|
|
def test_auth_v1_origin():
|
|
|
|
payload = {
|
|
|
|
"registration_pending": False,
|
|
|
|
"environment": {
|
|
|
|
"guest_driver_version": "guest_driver_version",
|
|
|
|
"hostname": "myhost",
|
|
|
|
"ip_address_list": ["192.168.1.123"],
|
|
|
|
"os_version": "os_version",
|
|
|
|
"os_platform": "os_platform",
|
|
|
|
"fingerprint": {"mac_address_list": ["ff:ff:ff:ff:ff:ff"]},
|
|
|
|
"host_driver_version": "host_driver_version"
|
|
|
|
},
|
|
|
|
"update_pending": False,
|
2022-12-23 15:42:02 +03:00
|
|
|
"candidate_origin_ref": ORIGIN_REF,
|
2022-12-23 09:48:47 +03:00
|
|
|
}
|
2022-12-23 15:42:02 +03:00
|
|
|
|
2022-12-23 09:48:47 +03:00
|
|
|
response = client.post('/auth/v1/origin', json=payload)
|
|
|
|
assert response.status_code == 200
|
2023-01-03 11:20:18 +03:00
|
|
|
assert response.json().get('origin_ref') == ORIGIN_REF
|
2022-12-23 09:48:47 +03:00
|
|
|
|
|
|
|
|
2024-11-19 11:18:12 +03:00
|
|
|
def test_auth_v1_origin_malformed_json(): # see oscar.krause/fastapi-dls#1
|
2024-11-19 11:40:59 +03:00
|
|
|
from middleware import PatchMalformedJsonMiddleware
|
2024-11-19 11:18:12 +03:00
|
|
|
|
2024-11-18 20:52:39 +03:00
|
|
|
# test regex (temporary, until this section is merged into main.py
|
2024-11-20 11:10:43 +03:00
|
|
|
s = '{"environment": {"fingerprint": {"mac_address_list": [ff:ff:ff:ff:ff:ff"]}}'
|
|
|
|
replaced = PatchMalformedJsonMiddleware.fix_json(s)
|
2024-11-18 20:52:39 +03:00
|
|
|
assert replaced == '{"environment": {"fingerprint": {"mac_address_list": ["ff:ff:ff:ff:ff:ff"]}}'
|
|
|
|
|
|
|
|
|
2022-12-28 16:53:17 +03:00
|
|
|
def auth_v1_origin_update():
|
|
|
|
payload = {
|
|
|
|
"registration_pending": False,
|
|
|
|
"environment": {
|
|
|
|
"guest_driver_version": "guest_driver_version",
|
|
|
|
"hostname": "myhost",
|
|
|
|
"ip_address_list": ["192.168.1.123"],
|
|
|
|
"os_version": "os_version",
|
|
|
|
"os_platform": "os_platform",
|
|
|
|
"fingerprint": {"mac_address_list": ["ff:ff:ff:ff:ff:ff"]},
|
|
|
|
"host_driver_version": "host_driver_version"
|
|
|
|
},
|
|
|
|
"update_pending": False,
|
|
|
|
"candidate_origin_ref": ORIGIN_REF,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = client.post('/auth/v1/origin/update', json=payload)
|
|
|
|
assert response.status_code == 200
|
2023-01-03 11:20:18 +03:00
|
|
|
assert response.json().get('origin_ref') == ORIGIN_REF
|
2022-12-28 16:53:17 +03:00
|
|
|
|
|
|
|
|
2022-12-23 09:48:47 +03:00
|
|
|
def test_auth_v1_code():
|
2022-12-23 15:42:02 +03:00
|
|
|
payload = {
|
2022-12-28 16:30:54 +03:00
|
|
|
"code_challenge": b64enc(sha256(SECRET.encode('utf-8')).digest()).rstrip(b'=').decode('utf-8'),
|
2022-12-23 15:42:02 +03:00
|
|
|
"origin_ref": ORIGIN_REF,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = client.post('/auth/v1/code', json=payload)
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 11:20:18 +03:00
|
|
|
payload = jwt.get_unverified_claims(token=response.json().get('auth_code'))
|
|
|
|
assert payload.get('origin_ref') == ORIGIN_REF
|
2022-12-23 09:48:47 +03:00
|
|
|
|
|
|
|
|
|
|
|
def test_auth_v1_token():
|
2022-12-28 16:30:54 +03:00
|
|
|
cur_time = datetime.utcnow()
|
|
|
|
access_expires_on = cur_time + relativedelta(hours=1)
|
|
|
|
|
|
|
|
payload = {
|
|
|
|
"iat": timegm(cur_time.timetuple()),
|
|
|
|
"exp": timegm(access_expires_on.timetuple()),
|
|
|
|
"challenge": b64enc(sha256(SECRET.encode('utf-8')).digest()).rstrip(b'=').decode('utf-8'),
|
|
|
|
"origin_ref": ORIGIN_REF,
|
|
|
|
"key_ref": "00000000-0000-0000-0000-000000000000",
|
|
|
|
"kid": "00000000-0000-0000-0000-000000000000"
|
|
|
|
}
|
|
|
|
payload = {
|
|
|
|
"auth_code": jwt.encode(payload, key=jwt_encode_key, headers={'kid': payload.get('kid')},
|
|
|
|
algorithm=ALGORITHMS.RS256),
|
|
|
|
"code_verifier": SECRET,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = client.post('/auth/v1/token', json=payload)
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 11:20:18 +03:00
|
|
|
token = response.json().get('auth_token')
|
2022-12-28 16:30:54 +03:00
|
|
|
payload = jwt.decode(token=token, key=jwt_decode_key, algorithms=ALGORITHMS.RS256, options={'verify_aud': False})
|
2023-01-03 11:20:18 +03:00
|
|
|
assert payload.get('origin_ref') == ORIGIN_REF
|
2022-12-23 09:48:47 +03:00
|
|
|
|
|
|
|
|
|
|
|
def test_leasing_v1_lessor():
|
2022-12-28 16:53:17 +03:00
|
|
|
payload = {
|
|
|
|
'fulfillment_context': {
|
|
|
|
'fulfillment_class_ref_list': []
|
|
|
|
},
|
|
|
|
'lease_proposal_list': [{
|
|
|
|
'license_type_qualifiers': {'count': 1},
|
|
|
|
'product': {'name': 'NVIDIA RTX Virtual Workstation'}
|
|
|
|
}],
|
|
|
|
'proposal_evaluation_mode': 'ALL_OF',
|
2023-01-03 15:05:05 +03:00
|
|
|
'scope_ref_list': [ALLOTMENT_REF]
|
2022-12-28 16:53:17 +03:00
|
|
|
}
|
|
|
|
|
2022-12-29 21:07:30 +03:00
|
|
|
response = client.post('/leasing/v1/lessor', json=payload, headers={'authorization': __bearer_token(ORIGIN_REF)})
|
2022-12-28 16:53:17 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 15:05:05 +03:00
|
|
|
lease_result_list = response.json().get('lease_result_list')
|
2022-12-28 16:53:17 +03:00
|
|
|
assert len(lease_result_list) == 1
|
2023-01-03 20:05:12 +03:00
|
|
|
assert len(lease_result_list[0]['lease']['ref']) == 36
|
2023-01-03 15:05:05 +03:00
|
|
|
assert str(UUID(lease_result_list[0]['lease']['ref'])) == lease_result_list[0]['lease']['ref']
|
2023-01-03 20:05:12 +03:00
|
|
|
|
2023-01-03 15:05:05 +03:00
|
|
|
return lease_result_list[0]['lease']['ref']
|
2022-12-23 09:48:47 +03:00
|
|
|
|
|
|
|
|
|
|
|
def test_leasing_v1_lessor_lease():
|
2022-12-29 21:07:30 +03:00
|
|
|
response = client.get('/leasing/v1/lessor/leases', headers={'authorization': __bearer_token(ORIGIN_REF)})
|
2022-12-28 16:53:17 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 11:20:18 +03:00
|
|
|
active_lease_list = response.json().get('active_lease_list')
|
2022-12-28 16:53:17 +03:00
|
|
|
assert len(active_lease_list) == 1
|
2023-01-03 20:05:12 +03:00
|
|
|
assert len(active_lease_list[0]) == 36
|
2023-01-03 15:05:05 +03:00
|
|
|
assert str(UUID(active_lease_list[0])) == active_lease_list[0]
|
2022-12-23 09:48:47 +03:00
|
|
|
|
|
|
|
|
|
|
|
def test_leasing_v1_lease_renew():
|
2023-01-03 15:05:05 +03:00
|
|
|
response = client.get('/leasing/v1/lessor/leases', headers={'authorization': __bearer_token(ORIGIN_REF)})
|
|
|
|
active_lease_list = response.json().get('active_lease_list')
|
2023-01-03 20:05:12 +03:00
|
|
|
active_lease_ref = active_lease_list[0]
|
2023-01-03 15:05:05 +03:00
|
|
|
|
|
|
|
###
|
|
|
|
|
2023-01-03 20:05:12 +03:00
|
|
|
response = client.put(f'/leasing/v1/lease/{active_lease_ref}', headers={'authorization': __bearer_token(ORIGIN_REF)})
|
2022-12-28 16:53:17 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 20:05:12 +03:00
|
|
|
lease_ref = response.json().get('lease_ref')
|
|
|
|
assert len(lease_ref) == 36
|
|
|
|
assert lease_ref == active_lease_ref
|
2022-12-23 09:48:47 +03:00
|
|
|
|
|
|
|
|
2022-12-29 21:03:09 +03:00
|
|
|
def test_leasing_v1_lease_delete():
|
2023-01-03 15:05:05 +03:00
|
|
|
response = client.get('/leasing/v1/lessor/leases', headers={'authorization': __bearer_token(ORIGIN_REF)})
|
|
|
|
active_lease_list = response.json().get('active_lease_list')
|
2023-01-03 20:05:12 +03:00
|
|
|
active_lease_ref = active_lease_list[0]
|
2023-01-03 15:05:05 +03:00
|
|
|
|
|
|
|
###
|
|
|
|
|
2023-01-03 20:05:12 +03:00
|
|
|
response = client.delete(f'/leasing/v1/lease/{active_lease_ref}', headers={'authorization': __bearer_token(ORIGIN_REF)})
|
2022-12-29 21:03:09 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 20:05:12 +03:00
|
|
|
lease_ref = response.json().get('lease_ref')
|
|
|
|
assert len(lease_ref) == 36
|
|
|
|
assert lease_ref == active_lease_ref
|
2022-12-29 21:03:09 +03:00
|
|
|
|
|
|
|
|
2022-12-23 09:48:47 +03:00
|
|
|
def test_leasing_v1_lessor_lease_remove():
|
2023-01-03 15:05:05 +03:00
|
|
|
lease_ref = test_leasing_v1_lessor()
|
2022-12-29 21:07:30 +03:00
|
|
|
|
|
|
|
response = client.delete('/leasing/v1/lessor/leases', headers={'authorization': __bearer_token(ORIGIN_REF)})
|
2022-12-28 16:53:17 +03:00
|
|
|
assert response.status_code == 200
|
|
|
|
|
2023-01-03 11:20:18 +03:00
|
|
|
released_lease_list = response.json().get('released_lease_list')
|
2022-12-28 16:53:17 +03:00
|
|
|
assert len(released_lease_list) == 1
|
2023-01-03 20:05:12 +03:00
|
|
|
assert len(released_lease_list[0]) == 36
|
2023-01-03 15:05:05 +03:00
|
|
|
assert released_lease_list[0] == lease_ref
|