class OrganizationBootstrapReqSchema(BaseReqSchema): bootstrap_token = fields.String(required=True) root_verify_key = fields.VerifyKey(required=True) user_certificate = fields.Bytes(required=True) device_certificate = fields.Bytes(required=True) redacted_user_certificate = fields.Bytes(required=True) redacted_device_certificate = fields.Bytes(required=True)
class UserGetRepSchema(BaseRepSchema): user_certificate = fields.Bytes(required=True) revoked_user_certificate = fields.Bytes(required=True, allow_none=True) device_certificates = fields.List(fields.Bytes(required=True), required=True) trustchain = fields.Nested(TrustchainSchema, required=True)
class PkiEnrollmentListItemSchema(BaseSchema): enrollment_id = fields.UUID(required=True) submitted_on = fields.DateTime(required=True) submitter_der_x509_certificate = fields.Bytes(required=True) submit_payload_signature = fields.Bytes(required=True) submit_payload = fields.Bytes( required=True) # Signature should be checked before loading
class DeviceCreatedSchema(BaseSchema): __id__ = fields.String(required=True) __signal__ = fields.EnumCheckedConstant(BackendEvent.DEVICE_CREATED, required=True) organization_id = OrganizationIDField(required=True) device_id = DeviceIDField(required=True) device_certificate = fields.Bytes(required=True) encrypted_answer = fields.Bytes(required=True)
class UserCreatedSchema(BaseSchema): __id__ = fields.String(required=True) __signal__ = fields.EnumCheckedConstant(BackendEvent.USER_CREATED, required=True) organization_id = OrganizationIDField(required=True) user_id = UserIDField(required=True) user_certificate = fields.Bytes(required=True) first_device_id = DeviceIDField(required=True) first_device_certificate = fields.Bytes(required=True)
class PkiEnrollmentInfoRepAcceptedSchema(BaseRepSchema): enrollment_status = fields.EnumCheckedConstant( PkiEnrollmentStatus.ACCEPTED, required=True) submitted_on = fields.DateTime(required=True) accepted_on = fields.DateTime(required=True) accepter_der_x509_certificate = fields.Bytes(required=True) accept_payload_signature = fields.Bytes(required=True) accept_payload = fields.Bytes( required=True) # Signature should be checked before loading
class DeviceSchema(UnknownCheckedSchema): device_id = fields.DeviceID(required=True) created_on = fields.DateTime(required=True) revocated_on = fields.DateTime(allow_none=True) certified_revocation = fields.Bytes(allow_none=True) revocation_certifier = fields.DeviceID(allow_none=True) certified_device = fields.Bytes(required=True) device_certifier = fields.DeviceID(allow_none=True)
class DeviceFileSchema(BaseSchema): type = fields.CheckedConstant("password", required=True) salt = fields.Bytes(required=True) ciphertext = fields.Bytes(required=True) # Since human_handle/device_label has been introduced, device_id is # redacted (i.e. user_id and device_name are 2 random uuids), hence # those fields have been added to the device file so the login page in # the GUI can use them to provide useful information. human_handle = HumanHandleField(allow_none=True, missing=None) device_label = fields.String(allow_none=True, missing=None)
class SCHEMA_CLS(BaseSchema): type = fields.CheckedConstant("x509_certificate", required=True) issuer = fields.Dict(required=True) subject = fields.Dict(required=True) der_x509_certificate = fields.Bytes(required=True) certificate_sha1 = fields.Bytes(required=True) certificate_id = fields.String(required=True, allow_none=True) @post_load def make_obj(self, data): data.pop("type", None) return X509Certificate(**data)
class PkiEnrollmentSubmitReqSchema(BaseReqSchema): enrollment_id = fields.UUID(required=True) # Existing enrollment with SUMBITTED status prevent submitting new # enrollment with similir x509 certificate unless force flag is set. force = fields.Boolean(required=True) submitter_der_x509_certificate = fields.Bytes(required=True) # Duplicated certificate email field. (The backend need to check if the email is used without loading the certificate) submitter_der_x509_certificate_email = fields.String(required=False, missing=None, allow_none=True) submit_payload_signature = fields.Bytes(required=True) submit_payload = fields.Bytes( required=True) # Signature should be checked before loading
class SCHEMA_CLS(BaseSchema): type = fields.CheckedConstant("local_pending_enrollment", required=True) x509_certificate = fields.Nested(X509Certificate.SCHEMA_CLS, required=True) addr = BackendPkiEnrollmentAddrField(required=True) submitted_on = fields.DateTime(required=True) enrollment_id = fields.UUID(required=True) submit_payload = fields.Nested(PkiEnrollmentSubmitPayload.SCHEMA_CLS, required=True) encrypted_key = fields.Bytes(required=True) ciphertext = fields.Bytes(required=True) # An encrypted PendingDeviceKeys @post_load def make_obj(self, data): data.pop("type", None) return LocalPendingEnrollment(**data)
class APIV1_OrganizationBootstrapReqSchema(BaseReqSchema): bootstrap_token = fields.String(required=True) root_verify_key = fields.VerifyKey(required=True) user_certificate = fields.Bytes(required=True) device_certificate = fields.Bytes(required=True) # Same certificates than above, but expurged of human_handle/device_label # Backward compatibility prevent those field to be required, however # they should be considered so by recent version of Parsec (hence the # `allow_none=False`). # Hence only old version of Parsec will provide a payload with missing # redacted fields. In such case we consider the non-redacted can also # be used as redacted given the to-be-redacted fields have been introduce # in later version of Parsec. redacted_user_certificate = fields.Bytes(allow_none=False) redacted_device_certificate = fields.Bytes(allow_none=False)
class RealmStartReencryptionMaintenanceReqSchema(BaseReqSchema): realm_id = fields.UUID(required=True) encryption_revision = fields.Integer(required=True) timestamp = fields.DateTime(required=True) per_participant_message = fields.Map(UserIDField(), fields.Bytes(required=True), required=True)
class APIV1_HandshakeAuthenticatedAnswerSchema(BaseSchema): handshake = fields.CheckedConstant("answer", required=True) type = fields.EnumCheckedConstant(APIV1_HandshakeType.AUTHENTICATED, required=True) client_api_version = ApiVersionField(required=True) organization_id = OrganizationIDField(required=True) device_id = DeviceIDField(required=True) rvk = fields.VerifyKey(required=True) answer = fields.Bytes(required=True)
class LegacyDeviceFileSchema(BaseSchema): """Schema for legacy device files where the filename contains complementary information.""" type = fields.EnumCheckedConstant(DeviceFileType.PASSWORD, required=True) salt = fields.Bytes(required=True) ciphertext = fields.Bytes(required=True) # Since human_handle/device_label has been introduced, device_id is # redacted (i.e. user_id and device_name are 2 random uuids), hence # those fields have been added to the device file so the login page in # the GUI can use them to provide useful information. # Added in Parsec v1.14 human_handle = HumanHandleField(required=False, allow_none=True, missing=None) # Added in Parsec v1.14 device_label = DeviceLabelField(required=False, allow_none=True, missing=None)
class UserSchema(UnknownCheckedSchema): user_id = fields.String(required=True) is_admin = fields.Boolean(required=True) created_on = fields.DateTime(required=True) certified_user = fields.Bytes(required=True) user_certifier = fields.DeviceID(allow_none=True) devices = fields.Map(fields.DeviceName(), fields.Nested(DeviceSchema), required=True)
class VlobReadRepSchema(BaseRepSchema): version = fields.Integer(required=True, validate=_validate_version) blob = fields.Bytes(required=True) author = DeviceIDField(required=True) timestamp = fields.DateTime(required=True) # This field is used by the client to figure out if its role certificate cache is up-to-date enough # to be able to perform the proper integrity checks on the manifest timestamp. # The `missing=None` argument is used to provide compatibilty of new clients with old backends. # New in API version 2.3 (Parsec 2.6.0) author_last_role_granted_on = fields.DateTime(required=False, allow_none=True, missing=None)
class VlobCreateReqSchema(BaseReqSchema): realm_id = fields.UUID(required=True) encryption_revision = fields.Integer(required=True) vlob_id = fields.UUID(required=True) # If blob contains a signed message, it timestamp cannot be directly enforced # by the backend (given the message is probably also encrypted). # Hence the timestamp is passed in clear so backend can reject the message # if it considers the timestamp invalid. On top of that each client asking # for the message will receive the declared timestamp to check against # the actual timestamp within the message. timestamp = fields.DateTime(required=True) blob = fields.Bytes(required=True)
class BaseDeviceFileSchema(BaseSchema): """Schema for device files that does not rely on the filename for complementary information.""" ciphertext = fields.Bytes(required=True) # Override those fields to make them required (although `None` is still valid) human_handle = HumanHandleField(required=True, allow_none=True) device_label = DeviceLabelField(required=True, allow_none=True) # Store device ID, organization ID and slug in the device file # For legacy versions, this information is available in the file name device_id = DeviceIDField(required=True) organization_id = OrganizationIDField(required=True) slug = fields.String(required=True)
class PkiEnrollmentAcceptReqSchema(BaseReqSchema): enrollment_id = fields.UUID(required=True) accepter_der_x509_certificate = fields.Bytes(required=True) accept_payload_signature = fields.Bytes(required=True) accept_payload = fields.Bytes( required=True) # Signature should be checked before loading user_certificate = fields.Bytes(required=True) device_certificate = fields.Bytes(required=True) # Same certificates than above, but expurged of human_handle/device_label redacted_user_certificate = fields.Bytes(required=True) redacted_device_certificate = fields.Bytes(required=True)
class HandshakeChallengeSchema(BaseSchema): handshake = fields.CheckedConstant("challenge", required=True) challenge = fields.Bytes(required=True) supported_api_versions = fields.List(ApiVersionField(), required=True) # Those fields have been added to API version 2.4 (Parsec 2.7.0) # They are provided to the client in order to allow them to detect whether # their system clock is out of sync and let them close the connection. # They will be missing for older backend so they cannot be strictly required. # TODO: This backward compatibility should be removed once Parsec < 2.4 support is dropped ballpark_client_early_offset = fields.Float(required=False, allow_none=False) ballpark_client_late_offset = fields.Float(required=False, allow_none=False) backend_timestamp = fields.DateTime(required=False, allow_none=False) @post_load def make_obj(self, data: Dict[str, Any]) -> Dict[str, Any]: # type: ignore[misc] # Cannot use `missing=None` with `allow_none=False` data.setdefault("ballpark_client_early_offset", None) data.setdefault("ballpark_client_late_offset", None) data.setdefault("backend_timestamp", None) return data
class BlockReadRepSchema(BaseRepSchema): block = fields.Bytes(required=True)
class MessageSchema(BaseSchema): count = fields.Integer(required=True) sender = DeviceIDField(required=True) timestamp = fields.DateTime(required=True) body = fields.Bytes(required=True)
class HandshakeChallengeSchema(BaseSchema): handshake = fields.CheckedConstant("challenge", required=True) challenge = fields.Bytes(required=True) supported_api_versions = fields.List(ApiVersionField(), required=True)
class HandshakeChallengeSchema(UnknownCheckedSchema): handshake = fields.CheckedConstant("challenge", required=True) challenge = fields.Bytes(required=True)
class PasswordDeviceFileSchema(BaseDeviceFileSchema): type = fields.EnumCheckedConstant(DeviceFileType.PASSWORD, required=True) salt = fields.Bytes(required=True)
class Schema(BaseSchema): data = fields.Bytes()
class BlockCreateReqSchema(BaseReqSchema): block_id = fields.UUID(required=True) realm_id = fields.UUID(required=True) block = fields.Bytes(required=True)
class SmartcardDeviceFileSchema(BaseDeviceFileSchema): type = fields.EnumCheckedConstant(DeviceFileType.SMARTCARD, required=True) encrypted_key = fields.Bytes(required=True) certificate_id = fields.String(required=True) certificate_sha1 = fields.Bytes(required=True, allow_none=True)
class HandshakeAnswerSchema(UnknownCheckedSchema): handshake = fields.CheckedConstant("answer", required=True) organization_id = fields.OrganizationID(required=True) device_id = fields.DeviceID(allow_none=True, missing=None) rvk = fields.VerifyKey(allow_none=True, missing=None) answer = fields.Bytes(allow_none=True, missing=None)