try to fix bitwarden issue (#1448)

This commit is contained in:
LawyZheng
2024-12-30 17:03:28 +08:00
committed by GitHub
parent 12da878eb2
commit 15ecec6d8d

View File

@@ -60,7 +60,9 @@ class BitwardenQueryResult(BaseModel):
class BitwardenService: class BitwardenService:
@staticmethod @staticmethod
def run_command(command: list[str], additional_env: dict[str, str] | None = None) -> subprocess.CompletedProcess: def run_command(
command: list[str], additional_env: dict[str, str] | None = None, timeout: int = 60
) -> subprocess.CompletedProcess:
""" """
Run a CLI command with the specified additional environment variables and return the result. Run a CLI command with the specified additional environment variables and return the result.
""" """
@@ -71,9 +73,9 @@ class BitwardenService:
env.update(additional_env) # Update with any additional environment variables env.update(additional_env) # Update with any additional environment variables
try: try:
return subprocess.run(command, capture_output=True, text=True, env=env, timeout=60) return subprocess.run(command, capture_output=True, text=True, env=env, timeout=timeout)
except subprocess.TimeoutExpired as e: except subprocess.TimeoutExpired as e:
LOG.error("Bitwarden command timed out after 60 seconds", stdout=e.stdout, stderr=e.stderr) LOG.error(f"Bitwarden command timed out after {timeout} seconds", stdout=e.stdout, stderr=e.stderr)
raise e raise e
@staticmethod @staticmethod
@@ -100,48 +102,39 @@ class BitwardenService:
bw_collection_ids: list[str] | None, bw_collection_ids: list[str] | None,
url: str, url: str,
collection_id: str | None = None, collection_id: str | None = None,
remaining_retries: int = settings.BITWARDEN_MAX_RETRIES, max_retries: int = settings.BITWARDEN_MAX_RETRIES,
timeout: int = settings.BITWARDEN_TIMEOUT_SECONDS, timeout: int = settings.BITWARDEN_TIMEOUT_SECONDS,
fail_reasons: list[str] = [],
) -> dict[str, str]: ) -> dict[str, str]:
""" """
Get the secret value from the Bitwarden CLI. Get the secret value from the Bitwarden CLI.
""" """
fail_reasons: list[str] = []
if not bw_organization_id and bw_collection_ids and collection_id not in bw_collection_ids: if not bw_organization_id and bw_collection_ids and collection_id not in bw_collection_ids:
raise BitwardenAccessDeniedError() raise BitwardenAccessDeniedError()
try:
async with asyncio.timeout(timeout):
return await BitwardenService._get_secret_value_from_url(
client_id=client_id,
client_secret=client_secret,
master_password=master_password,
bw_organization_id=bw_organization_id,
bw_collection_ids=bw_collection_ids,
url=url,
collection_id=collection_id,
)
except BitwardenAccessDeniedError as e:
raise e
except Exception as e:
if remaining_retries <= 0:
raise BitwardenListItemsError(
f"Bitwarden CLI failed after all retry attempts. Fail reasons: {fail_reasons}"
)
remaining_retries -= 1 for i in range(max_retries):
LOG.info("Retrying to get secret value from Bitwarden", remaining_retries=remaining_retries) # FIXME: just simply double the timeout for the second try. maybe a better backoff policy when needed
return await BitwardenService.get_secret_value_from_url( timeout = (i + 1) * timeout
client_id=client_id, try:
client_secret=client_secret, async with asyncio.timeout(timeout):
master_password=master_password, return await BitwardenService._get_secret_value_from_url(
bw_organization_id=bw_organization_id, client_id=client_id,
bw_collection_ids=bw_collection_ids, client_secret=client_secret,
url=url, master_password=master_password,
collection_id=collection_id, bw_organization_id=bw_organization_id,
remaining_retries=remaining_retries, bw_collection_ids=bw_collection_ids,
# Double the timeout for the next retry url=url,
timeout=timeout * 2, collection_id=collection_id,
fail_reasons=fail_reasons + [f"{type(e).__name__}: {str(e)}"], timeout=timeout,
)
except BitwardenAccessDeniedError as e:
raise e
except Exception as e:
LOG.info("Failed to get secret value from Bitwarden", tried_times=i + 1, exc_info=True)
fail_reasons.append(f"{type(e).__name__}: {str(e)}")
else:
raise BitwardenListItemsError(
f"Bitwarden CLI failed after all retry attempts. Fail reasons: {fail_reasons}"
) )
@staticmethod @staticmethod
@@ -153,6 +146,7 @@ class BitwardenService:
bw_collection_ids: list[str] | None, bw_collection_ids: list[str] | None,
url: str, url: str,
collection_id: str | None = None, collection_id: str | None = None,
timeout: int = 60,
) -> dict[str, str]: ) -> dict[str, str]:
""" """
Get the secret value from the Bitwarden CLI. Get the secret value from the Bitwarden CLI.
@@ -186,7 +180,7 @@ class BitwardenService:
else: else:
LOG.error("No collection ID or organization ID provided -- this is required") LOG.error("No collection ID or organization ID provided -- this is required")
raise BitwardenListItemsError("No collection ID or organization ID provided -- this is required") raise BitwardenListItemsError("No collection ID or organization ID provided -- this is required")
items_result = BitwardenService.run_command(list_command) items_result = BitwardenService.run_command(list_command, timeout=timeout)
if items_result.stderr and "Event post failed" not in items_result.stderr: if items_result.stderr and "Event post failed" not in items_result.stderr:
raise BitwardenListItemsError(items_result.stderr) raise BitwardenListItemsError(items_result.stderr)