management.util.startup_strategies ================================== .. py:module:: management.util.startup_strategies .. autoapi-nested-parse:: Startup strategies for Trustpoint initialization and restoration. Module Contents --------------- .. py:data:: DEK_EXPECTED_LENGTH :value: 32 .. py:data:: DEFAULT_TOKEN_LABEL :value: 'Trustpoint-SoftHSM' .. py:class:: OutputWriter Bases: :py:obj:`Protocol` Protocol for output writing (stdout/stderr). .. py:method:: write(msg) Write a message to output. .. py:method:: success(msg) Format a success message. .. py:method:: error(msg) Format an error message. .. py:method:: warning(msg) Format a warning message. .. py:class:: WizardState(*args, **kwds) Bases: :py:obj:`enum.Enum` Enumeration of wizard completion states. .. py:attribute:: COMPLETED :value: 'COMPLETED' .. py:attribute:: INCOMPLETE :value: 'INCOMPLETE' .. py:class:: DekCacheState(*args, **kwds) Bases: :py:obj:`enum.Enum` Enumeration of DEK cache states (for HSM storage only). .. py:attribute:: CACHED :value: 'CACHED' .. py:attribute:: NOT_CACHED :value: 'NOT_CACHED' .. py:class:: StartupScenario(*args, **kwds) Bases: :py:obj:`enum.Enum` Enumeration of possible startup scenarios. .. py:attribute:: DB_NOT_INITIALIZED .. py:attribute:: DB_INITIALIZED_NO_VERSION .. py:attribute:: VERSION_MATCH .. py:attribute:: VERSION_UPGRADE .. py:attribute:: VERSION_DOWNGRADE .. py:attribute:: RESTORE_SOFTWARE_WIZARD_COMPLETED .. py:attribute:: RESTORE_SOFTWARE_WIZARD_INCOMPLETE .. py:attribute:: RESTORE_SOFTHSM_WIZARD_COMPLETED_DEK_CACHED .. py:attribute:: RESTORE_SOFTHSM_WIZARD_COMPLETED_DEK_NOT_CACHED .. py:attribute:: RESTORE_SOFTHSM_WIZARD_INCOMPLETE_DEK_CACHED .. py:attribute:: RESTORE_SOFTHSM_WIZARD_INCOMPLETE_DEK_NOT_CACHED .. py:attribute:: RESTORE_SOFTHSM_NEW_KEK_WIZARD_COMPLETED .. py:attribute:: RESTORE_PHYSICAL_HSM_WIZARD_COMPLETED_DEK_CACHED .. py:attribute:: RESTORE_PHYSICAL_HSM_WIZARD_COMPLETED_DEK_NOT_CACHED .. py:attribute:: RESTORE_PHYSICAL_HSM_WIZARD_INCOMPLETE_DEK_CACHED .. py:attribute:: RESTORE_PHYSICAL_HSM_WIZARD_INCOMPLETE_DEK_NOT_CACHED .. py:class:: StartupContext Context information for startup decisions. .. py:attribute:: db_initialized :type: bool .. py:attribute:: db_version :type: packaging.version.Version | None .. py:attribute:: current_version :type: packaging.version.Version .. py:attribute:: wizard_state_enum :type: WizardState .. py:attribute:: wizard_state_raw :type: setup_wizard.SetupWizardState | None .. py:attribute:: storage_type :type: management.models.KeyStorageConfig.StorageType | None .. py:attribute:: dek_cache_state :type: DekCacheState | None .. py:attribute:: output :type: OutputWriter .. py:attribute:: has_kek :type: bool :value: False .. py:attribute:: has_backup_encrypted_dek :type: bool :value: False .. py:property:: is_wizard_completed :type: bool Check if wizard is completed. .. py:property:: is_software_storage :type: bool Check if using software storage. .. py:property:: is_softhsm_storage :type: bool Check if using SoftHSM storage. .. py:property:: is_physical_hsm_storage :type: bool Check if using physical HSM storage. .. py:property:: is_hsm_storage :type: bool Check if using any HSM storage (SoftHSM or Physical). .. py:property:: is_dek_cached :type: bool Check if DEK is cached (only applicable for HSM storage). .. py:property:: is_new_kek_scenario :type: bool Check if this is a new KEK scenario (old KEK lost, requires backup password). This scenario occurs when: - Using HSM storage - DEK is not cached - KEK does NOT exist on the HSM (old KEK lost from previous installation) - Backup-encrypted DEK exists in the database Note: We don't check wizard_completed here because the wizard state might be inconsistent if restoring a database from a previous installation. :returns: True if this is a new KEK scenario requiring backup password recovery. .. py:class:: StartupStrategy Bases: :py:obj:`abc.ABC` Abstract base class for startup strategies. .. py:method:: execute(context) :abstractmethod: Execute the startup strategy. :param context: The startup context with all relevant information. .. py:method:: get_description() :abstractmethod: Get a human-readable description of this strategy. .. py:class:: TlsCredentialStrategy Bases: :py:obj:`abc.ABC` Abstract base class for TLS credential generation strategies. .. py:method:: handle_tls_credential(context) :abstractmethod: Generate and save TLS credentials. :param context: The startup context with all relevant information. .. py:class:: RecoverTlsCredentialStrategy Bases: :py:obj:`TlsCredentialStrategy` Standard TLS credential generation using TlsServerCredentialGenerator. .. py:method:: handle_tls_credential(context) Recover TLS credentials from database and save to files. .. py:class:: StandardTlsCredentialStrategy(*, save_to_db = True) Bases: :py:obj:`TlsCredentialStrategy` Standard TLS credential generation using TlsServerCredentialGenerator. .. py:attribute:: save_to_db :value: True .. py:method:: handle_tls_credential(context) Generate TLS credentials and save to database and files. .. py:class:: InitializationStrategy Bases: :py:obj:`abc.ABC` Abstract base class for Trustpoint initialization strategies. .. py:method:: initialize(context, *, with_tls = False) :abstractmethod: Initialize Trustpoint. :param context: The startup context with all relevant information. :param with_tls: Whether to initialize TLS credentials. .. py:class:: StandardInitializationStrategy(tls_strategy = None) Bases: :py:obj:`InitializationStrategy` Standard initialization: migrations, static files, messages. .. py:attribute:: tls_strategy .. py:method:: initialize(context, *, with_tls = False) Initialize Trustpoint with standard workflow. .. py:class:: DatabaseNotInitializedStrategy(init_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy for handling uninitialized database. .. py:attribute:: init_strategy .. py:method:: execute(context) Initialize database with TLS setup. .. py:method:: get_description() Get strategy description. .. py:class:: DatabaseInitializedNoVersionStrategy(init_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy for handling initialized database without version record. .. py:attribute:: init_strategy .. py:method:: execute(context) Initialize database with TLS setup. .. py:method:: get_description() Get strategy description. .. py:class:: VersionMatchStrategy(restore_strategy, init_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy for handling version match (normal startup). .. py:attribute:: restore_strategy .. py:attribute:: init_strategy .. py:method:: execute(context) Initialize Trustpoint and perform restoration. .. py:method:: get_description() Get strategy description. .. py:class:: VersionUpgradeStrategy(restore_strategy, app_version, init_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy for handling version upgrade. .. py:attribute:: restore_strategy .. py:attribute:: app_version .. py:attribute:: init_strategy .. py:method:: execute(context) Upgrade database version and perform restoration. .. py:method:: get_description() Get strategy description. .. py:class:: RestoreSoftwareWizardCompletedStrategy(tls_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy: Software storage + Wizard completed - extract TLS only. .. py:attribute:: tls_strategy .. py:method:: execute(context) Extract TLS certificates for software storage mode. .. py:method:: get_description() Get strategy description. .. py:method:: unwrap_dek_for_token(context, token_label = DEFAULT_TOKEN_LABEL) :staticmethod: Test KEK loading and unwrap DEK for the specified token to make it available in cache. This method follows the same logic as the unwrap_dek management command: 1. Get the token (or return gracefully if not found - software storage case) 2. Test KEK loading 3. Unwrap DEK (only if encrypted_dek exists) :param context: The startup context. :param token_label: The label of the PKCS11 token to unwrap DEK for. .. py:method:: extract_tls_from_database(context) :staticmethod: Extract TLS certificates from database and write to Nginx paths. .. py:class:: RestoreSoftwareWizardIncompleteStrategy(tls_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy: Software storage + Wizard incomplete - reset to beginning. .. py:attribute:: tls_strategy .. py:method:: execute(context) Reset wizard to WIZARD_SETUP_CRYPTO_STORAGE state and generate TLS certificates. .. py:method:: get_description() Get strategy description. .. py:class:: RestoreSoftHsmWizardCompletedDekCachedStrategy(tls_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy: SoftHSM + Wizard completed + DEK cached - extract TLS and unwrap DEK. .. py:attribute:: tls_strategy .. py:method:: execute(context) Extract TLS certificates and unwrap DEK for application use. .. py:method:: get_description() Get strategy description. .. py:class:: RestoreSoftHsmWizardCompletedDekNotCachedStrategy Bases: :py:obj:`StartupStrategy` Strategy: SoftHSM + Wizard completed + DEK not cached - needs auto restore. .. py:method:: execute(context) Trigger auto restore flow for SoftHSM with DEK not cached. .. py:method:: get_description() Get strategy description. .. py:class:: RestoreSoftHsmNewKekWizardCompletedStrategy(tls_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy: SoftHSM + New KEK (old KEK lost) + Wizard completed - generate temp TLS, wait for backup password. This scenario occurs when: - Trustpoint container and SoftHSM are new (fresh installation) - But there's an existing database with encrypted data - The database was encrypted with a KEK that no longer exists on the new SoftHSM - The wizard was previously completed The strategy: 1. Generates a temporary TLS certificate (since DB TLS cert is encrypted and inaccessible) 2. Transitions to WIZARD_AUTO_RESTORE_PASSWORD state 3. Waits for user to input backup password 4. BackupAutoRestorePasswordView will: - Generate a new KEK on the new SoftHSM - Decrypt the DEK using the backup password - Re-wrap the DEK with the new KEK - Extract and activate the actual TLS certificate from the database - Complete the wizard .. py:attribute:: tls_strategy .. py:method:: execute(context) Generate temporary TLS certificate and trigger auto restore flow. .. py:method:: get_description() Get strategy description. .. py:class:: RestoreSoftHsmWizardIncompleteDekCachedStrategy(tls_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy: SoftHSM + Wizard incomplete + DEK cached - reset to beginning. .. py:attribute:: tls_strategy .. py:method:: execute(context) Reset wizard to WIZARD_SETUP_CRYPTO_STORAGE state and generate TLS certificates. .. py:method:: get_description() Get strategy description. .. py:class:: RestoreSoftHsmWizardIncompleteDekNotCachedStrategy(tls_strategy = None) Bases: :py:obj:`StartupStrategy` Strategy: SoftHSM + Wizard incomplete + DEK not cached - reset to beginning. .. py:attribute:: tls_strategy .. py:method:: execute(context) Reset wizard to WIZARD_SETUP_CRYPTO_STORAGE state and generate TLS certificates. .. py:method:: get_description() Get strategy description. .. py:class:: RestorePhysicalHsmWizardCompletedDekCachedStrategy Bases: :py:obj:`StartupStrategy` Strategy: Physical HSM + Wizard completed + DEK cached - NOT SUPPORTED. .. py:method:: execute(context) Raise error as Physical HSM is not yet supported. .. py:method:: get_description() Get strategy description. .. py:class:: RestorePhysicalHsmWizardCompletedDekNotCachedStrategy Bases: :py:obj:`StartupStrategy` Strategy: Physical HSM + Wizard completed + DEK not cached - NOT SUPPORTED. .. py:method:: execute(context) Raise error as Physical HSM is not yet supported. .. py:method:: get_description() Get strategy description. .. py:class:: RestorePhysicalHsmWizardIncompleteDekCachedStrategy Bases: :py:obj:`StartupStrategy` Strategy: Physical HSM + Wizard incomplete + DEK cached - NOT SUPPORTED. .. py:method:: execute(context) Raise error as Physical HSM is not yet supported. .. py:method:: get_description() Get strategy description. .. py:class:: RestorePhysicalHsmWizardIncompleteDekNotCachedStrategy Bases: :py:obj:`StartupStrategy` Strategy: Physical HSM + Wizard incomplete + DEK not cached - NOT SUPPORTED. .. py:method:: execute(context) Raise error as Physical HSM is not yet supported. .. py:method:: get_description() Get strategy description. .. py:class:: StartupStrategySelector Selector for determining the appropriate startup strategy. .. py:method:: select_restore_strategy(context) :staticmethod: Select the appropriate restore strategy based on context. :param context: The startup context with all relevant information. :returns: The appropriate StartupStrategy instance. .. py:method:: select_version_strategy(context, app_version) :staticmethod: Select the appropriate version management strategy. :param context: The startup context with version information. :param app_version: The AppVersion model instance. :returns: The appropriate StartupStrategy instance. :raises RuntimeError: If version downgrade is detected. .. py:method:: select_startup_strategy(*, db_initialized, has_version, context = None, app_version = None) :staticmethod: Select the top-level startup strategy. :param db_initialized: Whether the database is initialized. :param has_version: Whether an app version record exists. :param context: The startup context (required if db is initialized). :param app_version: The AppVersion model instance (required if db is initialized). :returns: The appropriate StartupStrategy instance.