mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-10-31 09:05:23 +00:00
Add configurable Fill Assist rules URL (#7791)
This commit is contained in:
6 files changed
+94
-5
No files matched your search
@@ -386,6 +386,11 @@
|
||||
# HTTP_REQUEST_BLOCK_NON_GLOBAL_IPS=true
|
||||
|
||||
## Client Settings
|
||||
## Server-wide Fill Assist rules feed base directory URL, not a JSON file.
|
||||
## Defaults to https://fillassist.bitwarden.com.
|
||||
## Must be a valid HTTPS URL without credentials, query parameters, fragments, or surrounding whitespace.
|
||||
# FILL_ASSIST_RULES_URL=https://fillassist.bitwarden.com
|
||||
|
||||
## Enable experimental feature flags for clients.
|
||||
## This is a comma-separated list of flags, e.g. "flag1,flag2,flag3".
|
||||
## Note that clients cache the /api/config endpoint for about 1 hour and it could take some time before they are enabled or disabled!
|
||||
|
||||
@@ -247,6 +247,7 @@ fn config() -> Json<Value> {
|
||||
"notifications": format!("{domain}/notifications"),
|
||||
"sso": "",
|
||||
"cloudRegion": null,
|
||||
"fillAssistRules": CONFIG.fill_assist_rules_url(),
|
||||
},
|
||||
// Bitwarden uses this for the self-hosted servers to indicate the default push technology
|
||||
"push": {
|
||||
|
||||
@@ -16,9 +16,9 @@ use crate::{
|
||||
DbConn,
|
||||
models::{
|
||||
Cipher, CipherId, Collection, CollectionCipher, CollectionGroup, CollectionId, CollectionUser, Device,
|
||||
EventType, Group, GroupId, GroupUser, Invitation, Membership, MembershipId, MembershipStatus,
|
||||
MembershipType, OrgPolicy, OrgPolicyType, Organization, OrganizationApiKey, OrganizationId, TwoFactor,
|
||||
TwoFactorType, User, UserId,
|
||||
EventType, FillAssistPolicyData, Group, GroupId, GroupUser, Invitation, Membership, MembershipId,
|
||||
MembershipStatus, MembershipType, OrgPolicy, OrgPolicyType, Organization, OrganizationApiKey,
|
||||
OrganizationId, TwoFactor, TwoFactorType, User, UserId,
|
||||
},
|
||||
},
|
||||
mail,
|
||||
@@ -2048,6 +2048,29 @@ async fn put_policy(
|
||||
err!("Invalid or unsupported policy type")
|
||||
};
|
||||
|
||||
let current_policy = OrgPolicy::find_by_org_and_type(&org_id, pol_type_enum, &conn).await;
|
||||
let is_currently_enabled = current_policy.as_ref().is_some_and(|policy| policy.enabled);
|
||||
|
||||
// Fill Assist depends on Single Organization. Match Bitwarden's dependency checks by only checking when the
|
||||
// policy changes state.
|
||||
if pol_type_enum == OrgPolicyType::FillAssist && data.enabled && !is_currently_enabled {
|
||||
let single_org_policy_enabled =
|
||||
OrgPolicy::find_by_org_and_type(&org_id, OrgPolicyType::SingleOrg, &conn).await.is_some_and(|p| p.enabled);
|
||||
|
||||
if !single_org_policy_enabled {
|
||||
err!("Turn on the Single organization policy because it is required for the Activate fill assist policy.")
|
||||
}
|
||||
}
|
||||
|
||||
if pol_type_enum == OrgPolicyType::SingleOrg && !data.enabled && is_currently_enabled {
|
||||
let fill_assist_policy_enabled =
|
||||
OrgPolicy::find_by_org_and_type(&org_id, OrgPolicyType::FillAssist, &conn).await.is_some_and(|p| p.enabled);
|
||||
|
||||
if fill_assist_policy_enabled {
|
||||
err!("Turn off the Activate fill assist policy because it requires the Single organization policy.")
|
||||
}
|
||||
}
|
||||
|
||||
// Bitwarden only allows the Reset Password policy when Single Org policy is enabled
|
||||
// Vaultwarden encouraged to use multiple orgs instead of groups because groups were not available in the past
|
||||
// Now that groups are available we can enforce this option when wanted.
|
||||
@@ -2080,6 +2103,37 @@ async fn put_policy(
|
||||
}
|
||||
}
|
||||
|
||||
if pol_type_enum == OrgPolicyType::FillAssist {
|
||||
let fill_assist_data = match data.data.as_ref() {
|
||||
None | Some(Value::Null) => FillAssistPolicyData {
|
||||
rules_url: None,
|
||||
},
|
||||
Some(data) => {
|
||||
let Ok(data) = serde_json::from_value::<FillAssistPolicyData>(data.clone()) else {
|
||||
err!("Invalid data for FillAssist policy: rulesUrl has an invalid value.")
|
||||
};
|
||||
data
|
||||
}
|
||||
};
|
||||
|
||||
if data.enabled {
|
||||
let Some(rules_url) = fill_assist_data.rules_url.filter(|url| !url.trim().is_empty()) else {
|
||||
err!("The RulesUrl field is required.")
|
||||
};
|
||||
let Ok(rules_url) = url::Url::parse(&rules_url) else {
|
||||
err!("The RulesUrl field is not a valid fully-qualified http, https, or ftp URL.")
|
||||
};
|
||||
|
||||
if !rules_url.has_host() || !matches!(rules_url.scheme(), "http" | "https" | "ftp") {
|
||||
err!("The RulesUrl field is not a valid fully-qualified http, https, or ftp URL.")
|
||||
}
|
||||
|
||||
if rules_url.scheme() != "https" {
|
||||
err!("RulesUrl must use HTTPS.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When enabling the TwoFactorAuthentication policy, revoke all members that do not have 2FA
|
||||
if pol_type_enum == OrgPolicyType::TwoFactorAuthentication && data.enabled {
|
||||
two_factor::enforce_2fa_policy_for_org(
|
||||
@@ -2127,7 +2181,7 @@ async fn put_policy(
|
||||
}
|
||||
}
|
||||
|
||||
let mut policy = match OrgPolicy::find_by_org_and_type(&org_id, pol_type_enum, &conn).await {
|
||||
let mut policy = match current_policy {
|
||||
Some(p) => p,
|
||||
None => OrgPolicy::new(org_id.clone(), pol_type_enum, false, "{}".to_owned()),
|
||||
};
|
||||
|
||||
@@ -603,6 +603,9 @@ make_config! {
|
||||
/// This setting applies globally to all users. To control this on a per-org basis instead, use the "Disable Send" org policy.
|
||||
sends_allowed: bool, true, def, true;
|
||||
|
||||
/// Fill Assist Rules URL |> HTTPS URL for the server-wide Fill Assist rules feed base directory.
|
||||
fill_assist_rules_url: String, true, def, "https://fillassist.bitwarden.com".to_owned();
|
||||
|
||||
/// HIBP Api Key |> HaveIBeenPwned API Key, request it here: https://haveibeenpwned.com/API/Key
|
||||
hibp_api_key: Pass, true, option;
|
||||
|
||||
@@ -1023,6 +1026,21 @@ fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> {
|
||||
);
|
||||
}
|
||||
|
||||
let valid_fill_assist_rules_url = Url::parse(&cfg.fill_assist_rules_url).is_ok_and(|url| {
|
||||
url.scheme() == "https"
|
||||
&& url.has_host()
|
||||
&& url.username().is_empty()
|
||||
&& url.password().is_none()
|
||||
&& url.query().is_none()
|
||||
&& url.fragment().is_none()
|
||||
&& cfg.fill_assist_rules_url.trim() == cfg.fill_assist_rules_url
|
||||
});
|
||||
if !valid_fill_assist_rules_url {
|
||||
err!(
|
||||
"`FILL_ASSIST_RULES_URL` must be a valid HTTPS URL without credentials, query parameters, fragments, or surrounding whitespace."
|
||||
);
|
||||
}
|
||||
|
||||
let connect_src = cfg.allowed_connect_src.to_lowercase();
|
||||
for url in connect_src.split_whitespace() {
|
||||
if !url.starts_with("https://") || Url::parse(url).is_err() {
|
||||
@@ -1477,6 +1495,7 @@ pub const SUPPORTED_FEATURE_FLAGS: &[&str] = &[
|
||||
// Autofill Team
|
||||
"undetermined-cipher-scenario-logic",
|
||||
"enable-basic-auth-response",
|
||||
"fill-assist-targeting-rules",
|
||||
"ssh-agent-v2",
|
||||
"windows-desktop-autotype",
|
||||
"windows-desktop-autotype-ga",
|
||||
|
||||
@@ -31,7 +31,7 @@ pub use self::event::{Event, EventType};
|
||||
pub use self::favorite::Favorite;
|
||||
pub use self::folder::{Folder, FolderCipher, FolderId};
|
||||
pub use self::group::{CollectionGroup, Group, GroupId, GroupUser};
|
||||
pub use self::org_policy::{OrgPolicy, OrgPolicyId, OrgPolicyType};
|
||||
pub use self::org_policy::{FillAssistPolicyData, OrgPolicy, OrgPolicyId, OrgPolicyType};
|
||||
pub use self::organization::{
|
||||
Membership, MembershipId, MembershipStatus, MembershipType, OrgApiKeyId, Organization, OrganizationApiKey,
|
||||
OrganizationId,
|
||||
|
||||
@@ -53,6 +53,8 @@ pub enum OrgPolicyType {
|
||||
// AutoConfirm = 18, // Not supported (not implemented yet)
|
||||
// BlockClaimedDomainAccountCreation = 19, // Not supported (Not AGPLv3 Licensed)
|
||||
OrganizationUserNotification = 20,
|
||||
// SendControls = 21, // Not supported yet
|
||||
FillAssist = 22,
|
||||
}
|
||||
|
||||
// https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Core/AdminConsole/Models/Data/Organizations/Policies/SendOptionsPolicyData.cs#L5
|
||||
@@ -71,6 +73,14 @@ pub struct ResetPasswordDataModel {
|
||||
pub auto_enroll_enabled: bool,
|
||||
}
|
||||
|
||||
// https://github.com/bitwarden/server/blob/13bc813de8e715a71d3410f1e584e87ccdf76025/src/Core/AdminConsole/Models/Data/Organizations/Policies/FillAssistPolicyData.cs
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FillAssistPolicyData {
|
||||
#[serde(alias = "RulesUrl")]
|
||||
pub rules_url: Option<String>,
|
||||
}
|
||||
|
||||
/// Local methods
|
||||
impl OrgPolicy {
|
||||
pub fn new(org_uuid: OrganizationId, atype: OrgPolicyType, enabled: bool, data: String) -> Self {
|
||||
|
||||
Reference in new issue
Block a user