fix bitwarden credential search (#932)
This commit is contained in:
@@ -7,6 +7,7 @@ from enum import StrEnum
|
|||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
import tldextract
|
import tldextract
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from skyvern.config import settings
|
from skyvern.config import settings
|
||||||
from skyvern.exceptions import (
|
from skyvern.exceptions import (
|
||||||
@@ -53,6 +54,11 @@ class BitwardenConstants(StrEnum):
|
|||||||
CREDIT_CARD_BRAND = "BW_CREDIT_CARD_BRAND"
|
CREDIT_CARD_BRAND = "BW_CREDIT_CARD_BRAND"
|
||||||
|
|
||||||
|
|
||||||
|
class BitwardenQueryResult(BaseModel):
|
||||||
|
credential: dict[str, str]
|
||||||
|
uris: list[str]
|
||||||
|
|
||||||
|
|
||||||
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) -> subprocess.CompletedProcess:
|
||||||
@@ -157,8 +163,9 @@ class BitwardenService:
|
|||||||
BitwardenService.sync()
|
BitwardenService.sync()
|
||||||
session_key = BitwardenService.unlock(master_password)
|
session_key = BitwardenService.unlock(master_password)
|
||||||
|
|
||||||
# Extract the domain(with suffix) from the URL and search for items in Bitwarden with that domain
|
# Extract the domain from the URL and search for items in Bitwarden with that domain
|
||||||
domain = tldextract.extract(url).registered_domain
|
extract_url = tldextract.extract(url)
|
||||||
|
domain = extract_url.domain
|
||||||
list_command = [
|
list_command = [
|
||||||
"bw",
|
"bw",
|
||||||
"list",
|
"list",
|
||||||
@@ -217,33 +224,40 @@ class BitwardenService:
|
|||||||
e=BitwardenTOTPError(totp_result.stderr),
|
e=BitwardenTOTPError(totp_result.stderr),
|
||||||
)
|
)
|
||||||
totp_code = totp_result.stdout
|
totp_code = totp_result.stdout
|
||||||
|
bitwarden_result: list[BitwardenQueryResult] = [
|
||||||
credentials: list[dict[str, str]] = [
|
BitwardenQueryResult(
|
||||||
{
|
credential={
|
||||||
BitwardenConstants.USERNAME: item["login"]["username"],
|
BitwardenConstants.USERNAME: item.get("login", {}).get("username", ""),
|
||||||
BitwardenConstants.PASSWORD: item["login"]["password"],
|
BitwardenConstants.PASSWORD: item.get("login", {}).get("password", ""),
|
||||||
}
|
},
|
||||||
|
uris=[uri.get("uri") for uri in item.get("login", {}).get("uris", []) if "uri" in uri],
|
||||||
|
)
|
||||||
for item in items
|
for item in items
|
||||||
if "login" in item
|
if "login" in item
|
||||||
]
|
]
|
||||||
if totp_code:
|
|
||||||
for credential in credentials:
|
|
||||||
credential[BitwardenConstants.TOTP] = totp_code
|
|
||||||
|
|
||||||
if len(credentials) == 0:
|
if totp_code:
|
||||||
|
for single_result in bitwarden_result:
|
||||||
|
single_result.credential[BitwardenConstants.TOTP] = totp_code
|
||||||
|
|
||||||
|
if len(bitwarden_result) == 0:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
if len(credentials) == 1:
|
if len(bitwarden_result) == 1:
|
||||||
return credentials[0]
|
return bitwarden_result[0].credential
|
||||||
|
|
||||||
# Choose multiple credentials according to the defined rule,
|
# Choose multiple credentials according to the defined rule,
|
||||||
# if no cred matches the rule, return the first one.
|
# if no cred matches the rule, return the first one.
|
||||||
# TODO: For now hard code to choose the first valid email username
|
# TODO: For now hard code to choose the first matched result
|
||||||
for cred in credentials:
|
for single_result in bitwarden_result:
|
||||||
if is_valid_email(cred.get(BitwardenConstants.USERNAME)):
|
# check the username is a valid email
|
||||||
return cred
|
if is_valid_email(single_result.credential.get(BitwardenConstants.USERNAME)):
|
||||||
|
for uri in single_result.uris:
|
||||||
|
# check if the register_domain is the same
|
||||||
|
if extract_url.registered_domain == tldextract.extract(uri).registered_domain:
|
||||||
|
return single_result.credential
|
||||||
LOG.warning("No credential in Bitwarden matches the rule, returning the first match")
|
LOG.warning("No credential in Bitwarden matches the rule, returning the first match")
|
||||||
return credentials[0]
|
return bitwarden_result[0].credential
|
||||||
finally:
|
finally:
|
||||||
# Step 4: Log out
|
# Step 4: Log out
|
||||||
BitwardenService.logout()
|
BitwardenService.logout()
|
||||||
|
|||||||
Reference in New Issue
Block a user