Files
vaultwarden/src/db/models/mod.rs
T
Daniel García 7c82fbed0c Implement V2 key rotation support (#7766)
* Implement V2 key rotation support

* Clear user key ids left stale by key rotations

* Refuse key ids that aren't 32 lowercase hex characters, like upstream

* Save the signature key pair before the v2 account state

* Gate v2 logins on upstream's v2 encryption check

* Document the v2 encryption feature flags

* Remove the v2 upgrade feature flags

With force-upgrade-v2-encryption on, the clients loop on any v1 account that stays v1 on a vault route: the migration check runs fullSync(false), which writes lastSync, which triggers the scheduler again. No server response stops it, so don't serve the flag until the clients fix it.

pm-30144-sdk-key-rotation and pm-31050-no-logout-key-upgrade-rotation only serve that upgrade, so they go too.

* Move the v2 upgrade token migration to its own version

Diesel identifies a migration by the date in its folder name alone, and silently drops one of two folders that share it. The Custom Roles migration uses the same date.

* Refuse rotations from a replaced user key, like upstream

Both rotation endpoints accept the optional oldUserKeyId. When it and the
stored key id are both set and differ, the rotation is refused with a 409
asking the client to sync, before the account keys are checked or anything
is written.

Also correct the comment on saving the signature key pair first: by then the
vault data is already re-encrypted, so a failure there doesn't keep the
account usable.

* Update the v2 client minimum in .env.template and the key pair comments

V2 accounts need 2026.10.1, or 2026.10.2 for the desktop app, so the per-flag versions are only enough to create one. The comments on saving the signature key pair now cover the rotation of an account that is already v2.
2026-11-12 22:30:39 +01:00

47 lines
1.8 KiB
Rust

mod archive;
mod attachment;
mod auth_request;
mod cipher;
mod collection;
mod device;
mod emergency_access;
mod event;
mod favorite;
mod folder;
mod group;
mod org_policy;
mod organization;
mod send;
mod sso_auth;
mod two_factor;
mod two_factor_duo_context;
mod two_factor_incomplete;
mod user;
mod user_signature_key_pair;
pub use self::archive::Archive;
pub use self::attachment::{Attachment, AttachmentId};
pub use self::auth_request::{AuthRequest, AuthRequestId};
pub use self::cipher::{Cipher, CipherId, RepromptType, is_data_blob_encrypted};
pub use self::collection::{Collection, CollectionCipher, CollectionId, CollectionUser};
pub use self::device::{Device, DeviceId, DeviceType, DeviceWithAuthRequest, PushId};
pub use self::emergency_access::{
EMERGENCY_ACCESS_TIMEOUT_RANGE, EmergencyAccess, EmergencyAccessId, EmergencyAccessStatus, EmergencyAccessType,
};
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::{FillAssistPolicyData, OrgPolicy, OrgPolicyId, OrgPolicyType};
pub use self::organization::{
CustomPermission, Membership, MembershipId, MembershipStatus, MembershipType, OrgApiKeyId, Organization,
OrganizationApiKey, OrganizationId, custom_roles_enabled,
};
pub use self::send::{Send, SendFileId, SendId, SendType};
pub use self::sso_auth::{OIDCAuthenticatedUser, OIDCCodeResponseError, SsoAuth};
pub use self::two_factor::{TwoFactor, TwoFactorType};
pub use self::two_factor_duo_context::TwoFactorDuoContext;
pub use self::two_factor_incomplete::TwoFactorIncomplete;
pub use self::user::{Invitation, KeyId, SsoUser, User, UserId, UserKdfType};
pub use self::user_signature_key_pair::{SignatureAlgorithm, UserSignatureKeyPair};