Files
govoplan-postbox/src/govoplan_postbox/backend/protection_profiles.py
T

107 lines
3.3 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
POSTBOX_PLAINTEXT_PROFILE = "plaintext_v1"
POSTBOX_MANAGED_ENVELOPE_PROFILE = "server_envelope_v1"
POSTBOX_EXTERNAL_E2EE_PROFILE = "external_e2ee_v1"
POSTBOX_LEGACY_EXTERNAL_ENVELOPE_PROFILE = "external_envelope_v1"
POSTBOX_STANDARD_PROFILE = POSTBOX_MANAGED_ENVELOPE_PROFILE
PostboxProtectionProfile = Literal[
"plaintext_v1",
"server_envelope_v1",
"external_e2ee_v1",
]
SUPPORTED_POSTBOX_PROTECTION_PROFILES = frozenset(
{
POSTBOX_PLAINTEXT_PROFILE,
POSTBOX_MANAGED_ENVELOPE_PROFILE,
POSTBOX_EXTERNAL_E2EE_PROFILE,
}
)
def normalize_postbox_protection_policy(
policy: dict[str, object] | None = None,
) -> dict[str, object]:
return {
"new_incumbent_history": "since_assignment",
"history_days": None,
"ordinary_rotation": "rewrap",
"compromise_rotation": "reencrypt",
"recovery_authority": "institutional_key_holders",
"recovery_quorum": 2,
"handover_authority": "dual_control",
"handover_quorum": 2,
"emergency_access": "dual_control",
"emergency_quorum": 2,
"export_authority": "dual_control",
"export_quorum": 2,
"destruction_authority": "dual_control",
"destruction_quorum": 2,
"external_recipient_assurance": "strong_identity",
"vacancy_escalation_content_access": "metadata_only",
**(policy or {}),
}
@dataclass(frozen=True, slots=True)
class PostboxProtectionProfileDefinition:
id: PostboxProtectionProfile
label: str
description: str
server_can_decrypt: bool
requires_encryption_module: bool
requires_external_client: bool
standard: bool = False
POSTBOX_PROTECTION_PROFILE_DEFINITIONS = (
PostboxProtectionProfileDefinition(
id=POSTBOX_MANAGED_ENVELOPE_PROFILE,
label="Institution-managed envelope",
description=(
"The Encryption provider protects content and authorized institutional "
"key holders can govern recovery. This is the standard profile."
),
server_can_decrypt=True,
requires_encryption_module=True,
requires_external_client=False,
standard=True,
),
PostboxProtectionProfileDefinition(
id=POSTBOX_EXTERNAL_E2EE_PROFILE,
label="External end-to-end envelope",
description=(
"A reviewed client or producer supplies ciphertext, a signed manifest, "
"and recipient-wrapped keys. GovOPlaN stores and routes them but cannot "
"decrypt the content."
),
server_can_decrypt=False,
requires_encryption_module=False,
requires_external_client=True,
),
PostboxProtectionProfileDefinition(
id=POSTBOX_PLAINTEXT_PROFILE,
label="No application-layer encryption",
description=(
"Postbox stores readable message content. Transport and storage controls "
"may still apply, but this profile is not encrypted by Postbox."
),
server_can_decrypt=True,
requires_encryption_module=False,
requires_external_client=False,
),
)
def is_e2ee_profile(profile: str) -> bool:
return profile in {
POSTBOX_EXTERNAL_E2EE_PROFILE,
POSTBOX_LEGACY_EXTERNAL_ENVELOPE_PROFILE,
}