diff --git a/skyvern/forge/sdk/services/bitwarden.py b/skyvern/forge/sdk/services/bitwarden.py index 0465307fe..94b68c0de 100644 --- a/skyvern/forge/sdk/services/bitwarden.py +++ b/skyvern/forge/sdk/services/bitwarden.py @@ -41,6 +41,21 @@ def run_command(command: list[str], additional_env: dict[str, str] | None = None return subprocess.run(command, capture_output=True, text=True, env=env) + @staticmethod + def _extract_session_key(unlock_cmd_output: str) -> str | None: + # Split the text by lines + lines = unlock_cmd_output.split("\n") + + # Look for the line containing the BW_SESSION + for line in lines: + if 'BW_SESSION="' in line: + # Find the start and end positions of the session key + start = line.find('BW_SESSION="') + len('BW_SESSION="') + end = line.rfind('"', start) + return line[start:end] + + return None + @staticmethod def get_secret_value_from_url( client_id: str, @@ -61,25 +76,42 @@ def get_secret_value_from_url( login_command = ["bw", "login", "--apikey"] login_result = BitwardenService.run_command(login_command, env) - # Print both stdout and stderr for debugging + # Validate the login result + if login_result.stdout and "You are logged in!" not in login_result.stdout: + raise BitwardenLoginError( + f"Failed to log in. stdout: {login_result.stdout} stderr: {login_result.stderr}" + ) + if login_result.stderr and "You are already logged in as" not in login_result.stderr: - raise BitwardenLoginError(login_result.stderr) + raise BitwardenLoginError( + f"Failed to log in. stdout: {login_result.stdout} stderr: {login_result.stderr}" + ) + + LOG.info("Bitwarden login successful") # Step 2: Unlock the vault unlock_command = ["bw", "unlock", "--passwordenv", "BW_PASSWORD"] unlock_result = BitwardenService.run_command(unlock_command, env) + # Validate the unlock result + if unlock_result.stdout and "Your vault is now unlocked!" not in unlock_result.stdout: + raise BitwardenUnlockError( + f"Failed to unlock vault. stdout: {unlock_result.stdout} stderr: {unlock_result.stderr}" + ) + # This is a part of Bitwarden's client-side telemetry # TODO -- figure out how to disable this telemetry so we never get this error # https://github.com/bitwarden/clients/blob/9d10825dbd891c0f41fe1b4c4dd3ca4171f63be5/libs/common/src/services/api.service.ts#L1473 if unlock_result.stderr and "Event post failed" not in unlock_result.stderr: - raise BitwardenUnlockError(unlock_result.stderr) + raise BitwardenUnlockError( + f"Failed to unlock vault. stdout: {unlock_result.stdout} stderr: {unlock_result.stderr}" + ) # Extract session key try: - session_key = unlock_result.stdout.split('"')[1] - except IndexError: - raise BitwardenUnlockError("Unable to extract session key.") + session_key = BitwardenService._extract_session_key(unlock_result.stdout) + except Exception as e: + raise BitwardenUnlockError(f"Unable to extract session key: {str(e)}") if not session_key: raise BitwardenUnlockError("Session key is empty.")