introduce pyotp and support generating totp within skyvern (#1176)

This commit is contained in:
Shuchang Zheng
2024-11-12 02:17:22 -08:00
committed by GitHub
parent 79bc51ba54
commit efdf4b5cab
5 changed files with 26 additions and 24 deletions

View File

@@ -16,7 +16,6 @@ from skyvern.exceptions import (
BitwardenLoginError,
BitwardenLogoutError,
BitwardenSyncError,
BitwardenTOTPError,
BitwardenUnlockError,
)
@@ -211,27 +210,12 @@ class BitwardenService:
collection_id_str = f" in collection with ID: {collection_id}" if collection_id else ""
raise BitwardenListItemsError(f"No items found in Bitwarden for URL: {url}{collection_id_str}")
# TODO (kerem): To make this more robust, we need to store the item id of the totp login item
# and use it here to get the TOTP code for that specific item
totp_command = ["bw", "get", "totp", domain, "--session", session_key]
if bw_organization_id:
# We need to add this filter because the TOTP command fails if there are multiple results
# For now, we require that the bitwarden organization id has only one totp login item for the domain
totp_command.extend(["--organizationid", bw_organization_id])
totp_result = BitwardenService.run_command(totp_command)
if totp_result.stderr and "Event post failed" not in totp_result.stderr:
LOG.warning(
"Bitwarden TOTP Error",
error=totp_result.stderr,
e=BitwardenTOTPError(totp_result.stderr),
)
totp_code = totp_result.stdout
bitwarden_result: list[BitwardenQueryResult] = [
BitwardenQueryResult(
credential={
BitwardenConstants.USERNAME: item.get("login", {}).get("username", ""),
BitwardenConstants.PASSWORD: item.get("login", {}).get("password", ""),
BitwardenConstants.TOTP: item.get("login", {}).get("totp", ""),
},
uris=[uri.get("uri") for uri in item.get("login", {}).get("uris", []) if "uri" in uri],
)
@@ -239,10 +223,6 @@ class BitwardenService:
if "login" in item
]
if totp_code:
for single_result in bitwarden_result:
single_result.credential[BitwardenConstants.TOTP] = totp_code
if len(bitwarden_result) == 0:
return {}

View File

@@ -199,6 +199,8 @@ class WorkflowRunContext:
if BitwardenConstants.TOTP in secret_credentials and secret_credentials[BitwardenConstants.TOTP]:
totp_secret_id = f"{random_secret_id}_totp"
self.secrets[totp_secret_id] = BitwardenConstants.TOTP
totp_secret_value = self.totp_secret_value_key(totp_secret_id)
self.secrets[totp_secret_value] = secret_credentials[BitwardenConstants.TOTP]
self.values[parameter.key]["totp"] = totp_secret_id
except BitwardenBaseError as e:
@@ -451,6 +453,9 @@ class WorkflowRunContext:
self.parameters[parameter.key] = parameter
await self.register_parameter_value(aws_client, parameter, organization)
def totp_secret_value_key(self, totp_secret_id: str) -> str:
return f"{totp_secret_id}_value"
class WorkflowContextManager:
aws_client: AsyncAWSClient