management.models

Models for the Trustpoint Management app.

Classes

SecurityConfig

Security Configuration model.

TlsSettings

TLS settings model.

AppVersion

Model representing the application version and its last update timestamp.

BackupOptions

A singleton model (we always operate with pk=1) for backup settings.

KeyStorageConfig

Configuration model for cryptographic material storage.

PKCS11Token

Model representing a PKCS#11 token (e.g., a SoftHSM slot/token pair).

LoggingConfig

Logging Configuration model.

Module Contents

class management.models.SecurityConfig(*args, **kwargs)[source]

Bases: django.db.models.Model

Security Configuration model.

class SecurityModeChoices(*args, **kwds)[source]

Bases: django.db.models.TextChoices

Types of security modes.

DEV[source]
LOW[source]
MEDIUM[source]
HIGH[source]
HIGHEST[source]
security_mode[source]
auto_gen_pki[source]
auto_gen_pki_key_algorithm[source]
NOTIFICATION_CONFIGURATIONS: ClassVar[dict[str, dict[str, Any]]][source]
notification_config[source]
__str__()[source]

Output as string.

Return type:

str

apply_security_settings()[source]

Apply appropriate configuration values based on the security mode.

Return type:

None

class management.models.TlsSettings(*args, **kwargs)[source]

Bases: django.db.models.Model

TLS settings model.

ipv4_address[source]
__str__()[source]

Return a string representation of the TLS settings.

Return type:

str

classmethod get_first_ipv4_address()[source]

Get the first IPv4 address or a default value.

Return type:

str

class management.models.AppVersion(*args, **kwargs)[source]

Bases: django.db.models.Model

Model representing the application version and its last update timestamp.

objects: django.db.models.Manager[AppVersion][source]
version[source]
container_id[source]
last_updated[source]
class Meta[source]

Meta options for the AppVersion model.

verbose_name = 'App Version'[source]
__str__()[source]

Return a string representation for the AppVersion.

Return type:

str

class management.models.BackupOptions(*args, **kwargs)[source]

Bases: django.db.models.Model

A singleton model (we always operate with pk=1) for backup settings.

We store host/port/user/local_storage, plus either a password or an SSH key.

class AuthMethod(*args, **kwds)[source]

Bases: django.db.models.TextChoices

Authentication methods for backup options.

PASSWORD = ('password', 'Password')[source]
SSH_KEY = ('ssh_key', 'SSH Key')[source]
enable_sftp_storage[source]
host[source]
port[source]
user[source]
auth_method[source]
password[source]
private_key[source]
key_passphrase[source]
remote_directory[source]
class Meta[source]

Meta options for the BackupOptions model.

verbose_name = 'Backup Option'[source]
__str__()[source]

Return a string representation of the backup options.

Return type:

str

save(*args, **kwargs)[source]

Ensure only one instance exists (singleton pattern).

Parameters:
  • args (Any)

  • kwargs (Any)

Return type:

None

clean()[source]

Prevent the creation of more than one instance.

Return type:

None

class management.models.KeyStorageConfig(*args, **kwargs)[source]

Bases: django.db.models.Model

Configuration model for cryptographic material storage.

class StorageType(*args, **kwds)[source]

Bases: django.db.models.TextChoices

Types of cryptographic storage.

SOFTWARE[source]
SOFTHSM[source]
PHYSICAL_HSM[source]
storage_type[source]
hsm_config[source]
last_updated[source]
class Meta[source]

Meta options for the KeyStorageConfig model.

verbose_name[source]
verbose_name_plural[source]
__str__()[source]

Return a string representation of the storage configuration.

Return type:

str

classmethod get_config()[source]

Get the crypto storage configuration (singleton).

Returns:

The configuration instance

Return type:

KeyStorageConfig

Raises:

cls.DoesNotExist – If no configuration exists

classmethod get_or_create_default()[source]

Get the configuration or create a default one.

Returns:

The configuration instance

Return type:

KeyStorageConfig

class management.models.PKCS11Token(*args, **kwargs)[source]

Bases: django.db.models.Model, trustpoint.logger.LoggerMixin

Model representing a PKCS#11 token (e.g., a SoftHSM slot/token pair).

Stores metadata required to authenticate and interact with the token, including slot number, user and security officer PINs, and the path to the PKCS#11 module library.

KEK_ENCRYPTION_KEY_LABEL = 'trustpoint-kek'[source]
DEK_CACHE_LABEL = 'trustpoint-dek-chache'[source]
WRAPPED_DEK_LENGTH = 40[source]
ARGON2_TIME_COST = 3[source]
ARGON2_MEMORY_COST = 65536[source]
ARGON2_PARALLELISM = 1[source]
ARGON2_HASH_LENGTH = 32[source]
label[source]
slot[source]
module_path[source]
encrypted_dek[source]
bek_encrypted_dek[source]
kek[source]
created_at[source]
class Meta[source]

Meta options for the PKCS11Token model.

verbose_name[source]
verbose_name_plural[source]
__str__()[source]

Returns a human-readable representation of the token.

Returns:

A string in the format “<label> (Slot <slot>)”.

Return type:

str

save(*args, **kwargs)[source]

Ensure only one instance exists (singleton pattern).

Parameters:
  • args (Any)

  • kwargs (Any)

Return type:

None

classmethod load()[source]

Returns the single instance, creating it if necessary.

Return type:

PKCS11Token

clean()[source]

Ensure only one PKCS11Token instance exists.

Raises:

ValidationError

If more than one PKCS11Token instance is attempted to be created.

Return type:

None

generate_kek(key_length=256)[source]

Generate the KEK (key encryption key) in the PKCS#11 token.

Parameters:

key_length (int) – AES key length in bits (default: 256)

Returns:

True if key was generated successfully, False otherwise

Return type:

bool

Raises:

RuntimeError – If key generation fails

load_kek()[source]

Load and verify the KEK (key encryption key) exists on the PKCS#11 token.

This method checks if the KEK actually exists on the physical HSM, not just in the database. It attempts to load the key from the HSM.

Returns:

True if KEK exists on HSM, False otherwise

Return type:

bool

generate_and_wrap_dek(dek_size=32)[source]

Generate a new DEK and wrap it using the HSM AES key.

Parameters:

dek_size (int) – Size of the DEK in bytes (default: 32 for AES-256)

Returns:

The wrapped DEK data

Return type:

bytes

Raises:

RuntimeError – If DEK generation or wrapping fails

wrap_dek(dek_bytes)[source]

Wrap a DEK using the HSM AES key.

Parameters:

dek_bytes (bytes) – The plain DEK to wrap

Returns:

The wrapped DEK data

Return type:

bytes

Raises:

RuntimeError – If wrapping fails

_pad_to_block_size(data, block_size)[source]

Pad data to block size using PKCS#7 padding.

Parameters:
  • data (bytes) – Data to pad

  • block_size (int) – Block size for padding

Returns:

Padded data

Return type:

bytes

_unpad_from_block_size(data)[source]

Remove PKCS#7 padding from data.

Parameters:

data (bytes) – Padded data

Returns:

Unpadded data

Return type:

bytes

Raises:

ValueError – If padding is invalid

get_dek()[source]

Get the Data Encryption Key (DEK), unwrapping it if necessary.

Returns:

The 32-byte DEK

Return type:

bytes

Raises:

RuntimeError – If DEK cannot be retrieved or unwrapped

_raise_no_dek()[source]

Raise an error if no wrapped DEK is available.

Raises:

RuntimeError – If no wrapped DEK is available for unwrapping.

Return type:

None

_raise_dek_no_value()[source]

Raise an error if the unwrapped DEK has no value.

Raises:

RuntimeError – If the unwrapped DEK has no VALUE attribute.

Return type:

None

_raise_invalid_dek_length(length)[source]

Raise an error for invalid DEK length.

Parameters:

length (int) – The length of the DEK.

Raises:

RuntimeError – If the DEK length is invalid.

Return type:

None

_get_wrapped_data()[source]

Get the wrapped DEK data.

Returns:

The wrapped DEK data.

Return type:

bytes

_unwrap_dek()[source]

Unwrap the DEK using the HSM AES key.

If a legacy wrapped DEK is detected, it will be automatically migrated to the new format.

Returns:

The unwrapped DEK

Return type:

bytes

Raises:

RuntimeError – If unwrapping fails or DEK is not available

_log_unexpected_wrapped_length(wrapped_data)[source]

Log a warning if the wrapped DEK length is unexpected.

Parameters:

wrapped_data (bytes) – The wrapped DEK data.

Return type:

None

_open_session_and_get_wrap_key()[source]

Open a PKCS#11 session and retrieve the AES wrapping key for this token.

Return type:

tuple[pkcs11.Session, pkcs11.Key]

_raise_type_error(msg)[source]

Raise a TypeError with the given message.

Parameters:

msg (str) – The error message.

Raises:

TypeError – Always raised with the provided message.

Return type:

NoReturn

_unwrap_with_key(wrap_key, wrapped_data)[source]

Unwrap the DEK using the provided wrapping key.

Handles both new format (8 bytes IV + 32 bytes encrypted DEK) and legacy format (16 bytes IV + 48 bytes padded encrypted DEK).

Parameters:
  • wrap_key (pkcs11.Key) – The wrapping key.

  • wrapped_data (bytes) – The wrapped DEK data.

Returns:

The unwrapped DEK.

Return type:

bytes

_validate_dek_bytes(dek_bytes)[source]

Validate the unwrapped DEK bytes.

Parameters:

dek_bytes (bytes)

Return type:

None

_handle_no_such_key(e)[source]

Handle the case where the wrapping key is not found.

Parameters:

e (Exception) – The exception raised.

Raises:

RuntimeError – If the wrapping key is not found.

Return type:

None

_handle_unwrap_exception(e, wrapped_data)[source]

Handle exceptions that occur during DEK unwrapping.

Parameters:
  • e (Exception) – The exception raised.

  • wrapped_data (bytes) – The wrapped DEK data.

Raises:
  • RuntimeError – If the wrapped DEK data is invalid.

  • RuntimeError – If the unwrapping mechanism is not supported.

  • RuntimeError – If the DEK unwrapping fails for any other reason.

Return type:

None

_cleanup_session(session)[source]

Cleanup the session from memory.

Parameters:

session (pkcs11.Session) – The session object.

Return type:

None

get_dek_cache()[source]

Get the cached DEK without triggering unwrapping.

This method provides direct access to the cached DEK value without performing any PKCS#11 operations. Returns None if the cache is empty.

Returns:

The cached DEK bytes if available, None otherwise.

Return type:

bytes | None

clear_dek_cache()[source]

Clear the cached DEK from memory.

Return type:

None

get_pin()[source]

Get the user PIN for this PKCS#11 token.

PIN retrieval priority: 1. HSM_PIN_FILE environment variable (Docker secrets) 2. HSM_PIN environment variable

Returns:

The user PIN for token authentication.

Return type:

str

Raises:

ImproperlyConfigured – If no PIN is available.

set_backup_password(password, dek_size=32)[source]

Set a backup password and encrypt the current DEK with BEK derived from it using Argon2.

Parameters:
  • password (str) – The backup password to use for BEK derivation

  • dek_size (int) – Size of the DEK in bytes (default: 32 for AES-256)

Raises:
  • RuntimeError – If DEK encryption with BEK fails

  • ValueError – If no DEK is available to encrypt or invalid parameters

Return type:

None

get_dek_with_backup_password(password)[source]

Retrieve the DEK using the backup password.

Parameters:

password (str) – The backup password used for BEK derivation

Returns:

The decrypted DEK

Return type:

bytes

Raises:
  • RuntimeError – If DEK decryption fails

  • ValueError – If no backup encryption is available

verify_backup_password(password)[source]

Verify if the provided backup password is correct.

Parameters:

password (str) – The backup password to verify

Returns:

True if password is correct, False otherwise

Return type:

bool

remove_backup_encryption()[source]

Remove backup encryption (BEK-encrypted DEK).

This only removes the backup encryption, the primary KEK-encrypted DEK remains.

Return type:

None

has_backup_encryption()[source]

Check if backup encryption is configured.

Returns:

True if backup encryption is available, False otherwise

Return type:

bool

_raise_value_error(message)[source]

Raise a ValueError with the given message.

Parameters:

message (str)

Return type:

None

_derive_bek_from_password(password)[source]

Derive a BEK (Backup Encryption Key) from a password using Argon2.

Uses deterministic salt based on token label to ensure the same password always produces the same key for the same token.

Parameters:

password (str) – The password to derive the key from

Returns:

The 32-byte derived BEK

Return type:

bytes

Raises:

ValueError – If password is invalid

_encrypt_dek_with_bek(dek_bytes, bek)[source]

Encrypt DEK using BEK with AES-GCM.

Parameters:
  • dek_bytes (bytes) – The DEK to encrypt

  • bek (bytes) – The BEK to use for encryption

Returns:

IV (12 bytes) + encrypted_data + tag (16 bytes)

Return type:

bytes

Raises:

ValueError – If encryption fails

_decrypt_dek_with_bek(encrypted_data, bek)[source]

Decrypt DEK using BEK with AES-GCM.

Parameters:
  • encrypted_data (bytes | memoryview) – The encrypted DEK (IV + ciphertext + tag)

  • bek (bytes) – The BEK to use for decryption

Returns:

The decrypted DEK

Return type:

bytes

Raises:

ValueError – If decryption fails

class management.models.LoggingConfig(*args, **kwargs)[source]

Bases: django.db.models.Model

Logging Configuration model.

class LogLevelChoices(*args, **kwds)[source]

Bases: django.db.models.TextChoices

Types of log levels.

DEBUG[source]
INFO[source]
WARNING[source]
ERROR[source]
CRITICAL[source]
log_level[source]
last_updated[source]
__str__()[source]

Output as string.

Return type:

str