|
|
|
@ -1,15 +1,42 @@
|
|
|
|
import anyio
|
|
|
|
import anyio
|
|
|
|
from licaeros import LicensedSession, device_fingerprint_hex
|
|
|
|
|
|
|
|
from src.config import AEROS_BASE_URL, WINDOWS_AEROS_BASE_URL, VAULT_URL, ROLE_ID, SECRET_ID, AEROS_SECRET_PATH, AEROS_LICENSE_ID, AEROS_LICENSE_SECRET
|
|
|
|
|
|
|
|
import logging
|
|
|
|
import logging
|
|
|
|
|
|
|
|
import httpx
|
|
|
|
|
|
|
|
from src.config import (
|
|
|
|
|
|
|
|
AEROS_BASE_URL,
|
|
|
|
|
|
|
|
WINDOWS_AEROS_BASE_URL,
|
|
|
|
|
|
|
|
VAULT_URL,
|
|
|
|
|
|
|
|
ROLE_ID,
|
|
|
|
|
|
|
|
SECRET_ID,
|
|
|
|
|
|
|
|
AEROS_SECRET_PATH,
|
|
|
|
|
|
|
|
AEROS_LICENSE_ID,
|
|
|
|
|
|
|
|
AEROS_LICENSE_SECRET,
|
|
|
|
|
|
|
|
USE_LICENSE_APP
|
|
|
|
|
|
|
|
)
|
|
|
|
from src.utils import get_vault_secrets
|
|
|
|
from src.utils import get_vault_secrets
|
|
|
|
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Try to import licaeros gracefully
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
from licaeros import LicensedSession, device_fingerprint_hex
|
|
|
|
|
|
|
|
HAS_LICAEROS = True
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
HAS_LICAEROS = False
|
|
|
|
|
|
|
|
log.warning("licaeros library not found. Falling back to direct httpx calls if enabled.")
|
|
|
|
|
|
|
|
|
|
|
|
# Initialize a global session if possible, or create on demand
|
|
|
|
# Initialize a global session if possible, or create on demand
|
|
|
|
_aeros_session = None
|
|
|
|
_aeros_session = None
|
|
|
|
|
|
|
|
|
|
|
|
def get_aeros_session(base_url):
|
|
|
|
def get_aeros_session(base_url):
|
|
|
|
|
|
|
|
global _aeros_session
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not USE_LICENSE_APP or not HAS_LICAEROS:
|
|
|
|
|
|
|
|
if _aeros_session is None or not isinstance(_aeros_session, httpx.Client):
|
|
|
|
|
|
|
|
log.info(f"Using direct httpx.Client for base URL: {base_url}")
|
|
|
|
|
|
|
|
_aeros_session = httpx.Client(base_url=base_url, timeout=300.0)
|
|
|
|
|
|
|
|
return _aeros_session
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# License App path - only proceed if USE_LICENSE_APP is True
|
|
|
|
license_id = AEROS_LICENSE_ID
|
|
|
|
license_id = AEROS_LICENSE_ID
|
|
|
|
license_secret = AEROS_LICENSE_SECRET
|
|
|
|
license_secret = AEROS_LICENSE_SECRET
|
|
|
|
|
|
|
|
|
|
|
|
@ -30,10 +57,12 @@ def get_aeros_session(base_url):
|
|
|
|
log.warning("Failed to get Aeros license from Vault, trying local env fallback")
|
|
|
|
log.warning("Failed to get Aeros license from Vault, trying local env fallback")
|
|
|
|
|
|
|
|
|
|
|
|
if not license_id or not license_secret:
|
|
|
|
if not license_id or not license_secret:
|
|
|
|
raise Exception("Aeros license ID or Secret not provided (checked Vault and local .env)")
|
|
|
|
log.warning("Aeros license ID or Secret not provided. Falling back to direct httpx.")
|
|
|
|
|
|
|
|
if _aeros_session is None or not isinstance(_aeros_session, httpx.Client):
|
|
|
|
|
|
|
|
_aeros_session = httpx.Client(base_url=base_url, timeout=300.0)
|
|
|
|
|
|
|
|
return _aeros_session
|
|
|
|
|
|
|
|
|
|
|
|
global _aeros_session
|
|
|
|
if _aeros_session is None or isinstance(_aeros_session, httpx.Client):
|
|
|
|
if _aeros_session is None:
|
|
|
|
|
|
|
|
log.info(f"Initializing LicensedSession with base URL: {base_url}")
|
|
|
|
log.info(f"Initializing LicensedSession with base URL: {base_url}")
|
|
|
|
log.info(f"Encrypted Device ID: {device_fingerprint_hex()}")
|
|
|
|
log.info(f"Encrypted Device ID: {device_fingerprint_hex()}")
|
|
|
|
_aeros_session = LicensedSession(
|
|
|
|
_aeros_session = LicensedSession(
|
|
|
|
@ -46,21 +75,48 @@ def get_aeros_session(base_url):
|
|
|
|
|
|
|
|
|
|
|
|
async def aeros_post(path: str, json=None, data=None, **kwargs):
|
|
|
|
async def aeros_post(path: str, json=None, data=None, **kwargs):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Asynchronous wrapper for LicensedSession.post
|
|
|
|
Asynchronous wrapper for Aeros requests (Licensed or Direct)
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
session = get_aeros_session(WINDOWS_AEROS_BASE_URL)
|
|
|
|
# If not using license app, fetch from AEROS_BASE_URL direcly
|
|
|
|
|
|
|
|
target_base_url = WINDOWS_AEROS_BASE_URL if USE_LICENSE_APP and HAS_LICAEROS else AEROS_BASE_URL
|
|
|
|
|
|
|
|
session = get_aeros_session(target_base_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Path logic: License app often uses /api/aeros prefix, direct might not.
|
|
|
|
|
|
|
|
# However, to maintain compatibility with existing code calling this with path="/api/Project/ImportAROFile"
|
|
|
|
|
|
|
|
# we should decide if we need to adjust the path.
|
|
|
|
|
|
|
|
# User said: "system still fetch to aeros direcly not to licence app then lincense app forward it to aeros"
|
|
|
|
|
|
|
|
# This implies the license app acts as a proxy for /api/aeros/ paths.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if USE_LICENSE_APP and HAS_LICAEROS:
|
|
|
|
url = f"/api/aeros{path}"
|
|
|
|
url = f"/api/aeros{path}"
|
|
|
|
# LicensedSession might not be async-compatible, so we run it in a thread
|
|
|
|
|
|
|
|
response = await anyio.to_thread.run_sync(
|
|
|
|
response = await anyio.to_thread.run_sync(
|
|
|
|
lambda: session.post(url, json_data=json, data=data, headers=kwargs.get("headers"))
|
|
|
|
lambda: session.post(url, json_data=json, data=data, headers=kwargs.get("headers"))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
# Direct fetch from Aeros might have different path structure?
|
|
|
|
|
|
|
|
# Assuming direct Aeros path is same as what the license app proxies to.
|
|
|
|
|
|
|
|
url = path
|
|
|
|
|
|
|
|
response = await anyio.to_thread.run_sync(
|
|
|
|
|
|
|
|
lambda: session.post(url, json=json, data=data, headers=kwargs.get("headers"))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def aeros_file_upload(path, file, field_name, filename):
|
|
|
|
async def aeros_file_upload(path, file, field_name, filename):
|
|
|
|
session = get_aeros_session(WINDOWS_AEROS_BASE_URL)
|
|
|
|
target_base_url = WINDOWS_AEROS_BASE_URL if USE_LICENSE_APP and HAS_LICAEROS else AEROS_BASE_URL
|
|
|
|
|
|
|
|
session = get_aeros_session(target_base_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if USE_LICENSE_APP and HAS_LICAEROS:
|
|
|
|
url = f"/api/aeros{path}"
|
|
|
|
url = f"/api/aeros{path}"
|
|
|
|
response = await anyio.to_thread.run_sync(
|
|
|
|
response = await anyio.to_thread.run_sync(
|
|
|
|
lambda: session.post_multipart(url, file, field_name, filename)
|
|
|
|
lambda: session.post_multipart(url, file, field_name, filename)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
url = path
|
|
|
|
|
|
|
|
files = {field_name: (filename, file)}
|
|
|
|
|
|
|
|
response = await anyio.to_thread.run_sync(
|
|
|
|
|
|
|
|
lambda: session.post(url, files=files)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
return response
|