Add bitwarden_item_id to bitwarden_login_credential (#1871)

Co-authored-by: Muhammed Salih Altun <muhammedsalihaltun@gmail.com>
This commit is contained in:
Shuchang Zheng 2025-03-03 11:45:50 -05:00 committed by GitHub
parent c7e6a5c84b
commit 8a1b0f3797
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 107 additions and 14 deletions

View file

@ -165,6 +165,7 @@ class WorkflowRunContext:
bw_organization_id=self.secrets[BitwardenConstants.BW_ORGANIZATION_ID],
bw_collection_ids=self.secrets[BitwardenConstants.BW_COLLECTION_IDS],
collection_id=self.secrets[BitwardenConstants.BW_COLLECTION_ID],
item_id=self.secrets[BitwardenConstants.BW_ITEM_ID],
)
return secret_credentials
@ -241,11 +242,17 @@ class WorkflowRunContext:
LOG.error(f"Failed to get Bitwarden login credentials from AWS secrets. Error: {e}")
raise e
if self.has_parameter(parameter.url_parameter_key) and self.has_value(parameter.url_parameter_key):
if (
parameter.url_parameter_key
and self.has_parameter(parameter.url_parameter_key)
and self.has_value(parameter.url_parameter_key)
):
url = self.values[parameter.url_parameter_key]
elif parameter.url_parameter_key:
# If a key can't be found within the parameter values dict, assume it's a URL (and not a URL Parameter)
url = parameter.url_parameter_key
elif parameter.bitwarden_item_id:
url = None
else:
LOG.error(f"URL parameter {parameter.url_parameter_key} not found or has no value")
raise SkyvernException("URL parameter for Bitwarden login credentials not found or has no value")
@ -259,6 +266,13 @@ class WorkflowRunContext:
else:
collection_id = parameter.bitwarden_collection_id
item_id = None
if parameter.bitwarden_item_id:
if self.has_parameter(parameter.bitwarden_item_id) and self.has_value(parameter.bitwarden_item_id):
item_id = self.values[parameter.bitwarden_item_id]
else:
item_id = parameter.bitwarden_item_id
try:
secret_credentials = await BitwardenService.get_secret_value_from_url(
client_id,
@ -268,6 +282,7 @@ class WorkflowRunContext:
organization.bw_collection_ids,
url,
collection_id=collection_id,
item_id=item_id,
)
if secret_credentials:
self.secrets[BitwardenConstants.BW_ORGANIZATION_ID] = organization.bw_organization_id
@ -277,6 +292,7 @@ class WorkflowRunContext:
self.secrets[BitwardenConstants.CLIENT_ID] = client_id
self.secrets[BitwardenConstants.MASTER_PASSWORD] = master_password
self.secrets[BitwardenConstants.BW_COLLECTION_ID] = parameter.bitwarden_collection_id
self.secrets[BitwardenConstants.BW_ITEM_ID] = item_id
random_secret_id = self.generate_random_secret_id()
# username secret
@ -410,7 +426,7 @@ class WorkflowRunContext:
self.secrets[BitwardenConstants.CLIENT_ID] = client_id
self.secrets[BitwardenConstants.CLIENT_SECRET] = client_secret
self.secrets[BitwardenConstants.MASTER_PASSWORD] = master_password
self.secrets[BitwardenConstants.ITEM_ID] = item_id
self.secrets[BitwardenConstants.BW_ITEM_ID] = item_id
fields_to_obfuscate = {
BitwardenConstants.CREDIT_CARD_NUMBER: "card_number",

View file

@ -56,10 +56,12 @@ class BitwardenLoginCredentialParameter(Parameter):
bitwarden_client_secret_aws_secret_key: str
bitwarden_master_password_aws_secret_key: str
# url to request the login credentials from bitwarden
url_parameter_key: str
url_parameter_key: str | None = None
# bitwarden collection id to filter the login credentials from,
# if not provided, no filtering will be done
bitwarden_collection_id: str | None = None
# bitwarden item id to request the login credential
bitwarden_item_id: str | None = None
created_at: datetime
modified_at: datetime

View file

@ -37,10 +37,12 @@ class BitwardenLoginCredentialParameterYAML(ParameterYAML):
bitwarden_client_secret_aws_secret_key: str
bitwarden_master_password_aws_secret_key: str
# parameter key for the url to request the login credentials from bitwarden
url_parameter_key: str
url_parameter_key: str | None = None
# bitwarden collection id to filter the login credentials from,
# if not provided, no filtering will be done
bitwarden_collection_id: str | None = None
# bitwarden item id to request the login credential
bitwarden_item_id: str | None = None
class CredentialParameterYAML(ParameterYAML):

View file

@ -804,20 +804,22 @@ class WorkflowService:
bitwarden_client_id_aws_secret_key: str,
bitwarden_client_secret_aws_secret_key: str,
bitwarden_master_password_aws_secret_key: str,
url_parameter_key: str,
key: str,
url_parameter_key: str | None = None,
description: str | None = None,
bitwarden_collection_id: str | None = None,
bitwarden_item_id: str | None = None,
) -> Parameter:
return await app.DATABASE.create_bitwarden_login_credential_parameter(
workflow_id=workflow_id,
bitwarden_client_id_aws_secret_key=bitwarden_client_id_aws_secret_key,
bitwarden_client_secret_aws_secret_key=bitwarden_client_secret_aws_secret_key,
bitwarden_master_password_aws_secret_key=bitwarden_master_password_aws_secret_key,
url_parameter_key=url_parameter_key,
key=key,
url_parameter_key=url_parameter_key,
description=description,
bitwarden_collection_id=bitwarden_collection_id,
bitwarden_item_id=bitwarden_item_id,
)
async def create_credential_parameter(
@ -1397,11 +1399,17 @@ class WorkflowService:
credential_id=parameter.credential_id,
)
elif parameter.parameter_type == ParameterType.BITWARDEN_LOGIN_CREDENTIAL:
if not parameter.bitwarden_collection_id:
if not parameter.bitwarden_collection_id and not parameter.bitwarden_item_id:
raise WorkflowParameterMissingRequiredValue(
workflow_parameter_type=ParameterType.BITWARDEN_LOGIN_CREDENTIAL,
workflow_parameter_key=parameter.key,
required_value="bitwarden_collection_id",
required_value="bitwarden_collection_id or bitwarden_item_id",
)
if parameter.bitwarden_collection_id and not parameter.url_parameter_key:
raise WorkflowParameterMissingRequiredValue(
workflow_parameter_type=ParameterType.BITWARDEN_LOGIN_CREDENTIAL,
workflow_parameter_key=parameter.key,
required_value="url_parameter_key",
)
parameters[parameter.key] = await self.create_bitwarden_login_credential_parameter(
workflow_id=workflow.workflow_id,
@ -1412,6 +1420,7 @@ class WorkflowService:
key=parameter.key,
description=parameter.description,
bitwarden_collection_id=parameter.bitwarden_collection_id,
bitwarden_item_id=parameter.bitwarden_item_id,
)
elif parameter.parameter_type == ParameterType.BITWARDEN_SENSITIVE_INFORMATION:
parameters[parameter.key] = await self.create_bitwarden_sensitive_information_parameter(
@ -1434,7 +1443,7 @@ class WorkflowService:
bitwarden_master_password_aws_secret_key=parameter.bitwarden_master_password_aws_secret_key,
# TODO: remove "# type: ignore" after ensuring bitwarden_collection_id is always set
bitwarden_collection_id=parameter.bitwarden_collection_id, # type: ignore
bitwarden_item_id=parameter.bitwarden_item_id,
bitwarden_item_id=parameter.bitwarden_item_id, # type: ignore
key=parameter.key,
description=parameter.description,
)