summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Kolberg <[email protected]>2024-01-01 08:44:02 -0600
committerGitHub <[email protected]>2024-01-01 15:44:02 +0100
commit98b2178c7d314a0c4f8d85bf4f5396c7704bc88d (patch)
tree623b5d7b421cf6df1084c97ba3f6e1672b6e901b
parent76a3f0f531ef0b28b1dc1aefe276a0863f7bbd6d (diff)
downloadvaultwarden-98b2178c7d314a0c4f8d85bf4f5396c7704bc88d.tar.gz
vaultwarden-98b2178c7d314a0c4f8d85bf4f5396c7704bc88d.zip
Allow customizing the featureStates (#4168)
* Allow customizing the featureStates Use a comma separated list of features to enable using the FEATURE_FLAGS env variable * Move feature flag parsing to util * Fix formatting * Update supported feature flags * Rename feature_flags to experimental_client_feature_flags Additionally, use a caret (^) instead of an exclamation mark (!) to disable features * Fix formatting issue. * Add documentation to env template * Remove functionality to disable feature flags * Fix JSON key for feature states * Convert error to warning when feature flag is unrecognized * Simplify parsing of feature flags * Fix default value of feature flags in env template * Fix formatting
-rw-r--r--.env.template11
-rw-r--r--src/api/core/mod.rs14
-rw-r--r--src/config.rs13
-rw-r--r--src/util.rs9
4 files changed, 36 insertions, 11 deletions
diff --git a/.env.template b/.env.template
index 3c177a26..ee781619 100644
--- a/.env.template
+++ b/.env.template
@@ -390,6 +390,17 @@
## In any case, if a code has been used it can not be used again, also codes which predates it will be invalid.
# AUTHENTICATOR_DISABLE_TIME_DRIFT=false
+## Client Settings
+## Enable experimental feature flags for clients.
+## This is a comma-separated list of flags, e.g. "flag1,flag2,flag3".
+##
+## The following flags are available:
+## - "autofill-overlay": Add an overlay menu to form fields for quick access to credentials.
+## - "autofill-v2": Use the new autofill implementation.
+## - "browser-fileless-import": Directly import credentials from other providers without a file.
+## - "fido2-vault-credentials": Enable the use of FIDO2 security keys as second factor.
+## EXPERIMENTAL_CLIENT_FEATURE_FLAGS=fido2-vault-credentials
+
## Rocket specific settings
## See https://rocket.rs/v0.4/guide/configuration/ for more details.
# ROCKET_ADDRESS=0.0.0.0
diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs
index 3919d2a6..7712ea82 100644
--- a/src/api/core/mod.rs
+++ b/src/api/core/mod.rs
@@ -46,15 +46,14 @@ pub fn events_routes() -> Vec<Route> {
//
// Move this somewhere else
//
-use rocket::{serde::json::Json, Catcher, Route};
-use serde_json::Value;
+use rocket::{serde::json::Json, serde::json::Value, Catcher, Route};
use crate::{
api::{JsonResult, JsonUpcase, Notify, UpdateType},
auth::Headers,
db::DbConn,
error::Error,
- util::get_reqwest_client,
+ util::{get_reqwest_client, parse_experimental_client_feature_flags},
};
#[derive(Serialize, Deserialize, Debug)]
@@ -192,6 +191,7 @@ fn version() -> Json<&'static str> {
#[get("/config")]
fn config() -> Json<Value> {
let domain = crate::CONFIG.domain();
+ let feature_states = parse_experimental_client_feature_flags(&crate::CONFIG.experimental_client_feature_flags());
Json(json!({
// Note: The clients use this version to handle backwards compatibility concerns
// This means they expect a version that closely matches the Bitwarden server version
@@ -212,13 +212,7 @@ fn config() -> Json<Value> {
"notifications": format!("{domain}/notifications"),
"sso": "",
},
- "featureStates": {
- // Any feature flags that we want the clients to use
- // Can check the enabled ones at:
- // https://vault.bitwarden.com/api/config
- "fido2-vault-credentials": true, // Passkey support
- "autofill-v2": false, // Disabled because it is causing issues https://github.com/dani-garcia/vaultwarden/discussions/4052
- },
+ "featureStates": feature_states,
"object": "config",
}))
}
diff --git a/src/config.rs b/src/config.rs
index 041e89a7..c1821798 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -9,7 +9,7 @@ use reqwest::Url;
use crate::{
db::DbConnType,
error::Error,
- util::{get_env, get_env_bool},
+ util::{get_env, get_env_bool, parse_experimental_client_feature_flags},
};
static CONFIG_FILE: Lazy<String> = Lazy::new(|| {
@@ -547,6 +547,9 @@ make_config! {
/// TOTP codes of the previous and next 30 seconds will be invalid.
authenticator_disable_time_drift: bool, true, def, false;
+ /// Customize the enabled feature flags on the clients |> This is a comma separated list of feature flags to enable.
+ experimental_client_feature_flags: String, false, def, "fido2-vault-credentials".to_string();
+
/// Require new device emails |> When a user logs in an email is required to be sent.
/// If sending the email fails the login attempt will fail.
require_device_email: bool, true, def, false;
@@ -751,6 +754,14 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
)
}
+ const KNOWN_FLAGS: &[&str] =
+ &["autofill-overlay", "autofill-v2", "browser-fileless-import", "fido2-vault-credentials"];
+ for flag in parse_experimental_client_feature_flags(&cfg.experimental_client_feature_flags).keys() {
+ if !KNOWN_FLAGS.contains(&flag.as_str()) {
+ warn!("The experimental client feature flag {flag:?} is unrecognized. Please ensure the feature flag is spelled correctly and that it is supported in this version.");
+ }
+ }
+
if cfg._enable_duo
&& (cfg.duo_host.is_some() || cfg.duo_ikey.is_some() || cfg.duo_skey.is_some())
&& !(cfg.duo_host.is_some() && cfg.duo_ikey.is_some() && cfg.duo_skey.is_some())
diff --git a/src/util.rs b/src/util.rs
index 9b43116f..b1535301 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -2,6 +2,7 @@
// Web Headers and caching
//
use std::{
+ collections::HashMap,
io::{Cursor, ErrorKind},
ops::Deref,
};
@@ -747,3 +748,11 @@ pub fn convert_json_key_lcase_first(src_json: Value) -> Value {
value => value,
}
}
+
+/// Parses the experimental client feature flags string into a HashMap.
+pub fn parse_experimental_client_feature_flags(experimental_client_feature_flags: &str) -> HashMap<String, bool> {
+ let feature_states =
+ experimental_client_feature_flags.to_lowercase().split(',').map(|f| (f.trim().to_owned(), true)).collect();
+
+ feature_states
+}