Key management domain (API surface)#
// Structure of documents
└── src/
└── KeyManagement/
└── KeyActivatorException.php
└── KeyActivatorInterface.php
└── KeyGeneratorException.php
└── KeyGeneratorInterface.php
└── KeyPrunePlan.php
└── KeyPruneResult.php
└── KeyPrunerException.php
└── KeyPrunerInterface.php
└── KeyRotationException.php
└── KeyRotationOptions.php
└── KeyRotationPlan.php
└── KeyRotationResult.php
└── KeyRotatorInterface.php
└── KeyUsageTrackerInterface.php
└── Observers/
├── KeyActivatedObserverInterface.php
├── KeyDeletedObserverInterface.php
└── Port/
└── KeyRegistryException.php
└── KeyRegistryInterface.php
└── KeyUsageMapping.php
└── KeyUsageProviderInterface.php
└── MutableKeyRegistryInterface.php
Path: /src/KeyManagement/KeyActivatorException.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Thrown when key activation fails.
*
* This exception is intended to be thrown by the KeyActivator application
* service, so callers do not need to depend on the underlying repository
* exception hierarchy.
*/
final class KeyActivatorException extends \RuntimeException
{
/**
* Creates an exception for a failed encryption key activation.
*
* @param string $keyId
* The key identifier that could not be activated.
* @param \Throwable|null $previous
* (optional) The underlying exception that caused activation to fail.
*
* @return self
* The exception instance.
*/
public static function activationFailed(string $keyId, ?\Throwable $previous = null): self
{
/* ... */
}
}
Path: /src/KeyManagement/KeyActivatorInterface.php#
namespace Drupal\easy_encryption\KeyManagement;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Application service for activating an encryption key.
*
* Activation sets which encryption key ID is considered active for new
* encryption operations on the site.
*/
interface KeyActivatorInterface
{
/**
* Activates an existing encryption key by ID.
*
* Activation MUST be allowed when private key is missing, as long as a public
* key exists (encrypt-only environments).
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
* The encryption key identifier.
*
* @throws \Drupal\easy_encryption\KeyManagement\KeyActivatorException
* Thrown when activation fails.
*/
public function activate(EncryptionKeyId $keyId): void;
}
Path: /src/KeyManagement/KeyGeneratorException.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Thrown when key generation or activation fails.
*/
final class KeyGeneratorException extends \RuntimeException
{
/**
* Creates an exception for a failed encryption key generation.
*
* @param string|null $keyId
* The key identifier, if one was known at the time of failure.
* @param \Throwable|null $previous
* (optional) The underlying exception that caused generation to fail.
*
* @return self
* The exception instance.
*/
public static function generationFailed(?string $keyId = null, ?\Throwable $previous = null): self
{
/* ... */
}
}
Path: /src/KeyManagement/KeyGeneratorInterface.php#
namespace Drupal\easy_encryption\KeyManagement;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Application service for generating and activating encryption keys.
*
* This service returns key identifiers, not key material, to keep the
* application layer decoupled from the underlying cryptographic library.
*/
interface KeyGeneratorInterface
{
/**
* Generates and persists an encryption key.
*
* If no ID is provided, the generator MUST create a new identifier.
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $keyId
* (optional) The encryption key identifier to use.
*
* @return \Drupal\easy_encryption\Encryption\EncryptionKeyId
* The encryption key identifier that was generated.
*
* @throws \Drupal\easy_encryption\KeyManagement\KeyGeneratorException
* Thrown when the encryption key generation fails.
*/
public function generate(?EncryptionKeyId $keyId = null): EncryptionKeyId;
}
Path: /src/KeyManagement/KeyPrunePlan.php#
namespace Drupal\easy_encryption\KeyManagement;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Describes what would be pruned without performing changes.
*
* @immutable
*/
final class KeyPrunePlan
{
/**
* Construct a KeyPrunePlan.
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $activeKeyId
* The active encryption key ID, if any.
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $toDelete
* Encryption key IDs that would be deleted.
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $referenced
* Encryption key IDs referenced, in use.
*/
public function __construct(
public readonly ?EncryptionKeyId $activeKeyId,
public readonly array $toDelete = [],
public readonly array $referenced = [],
) {
/* ... */
}
}
Path: /src/KeyManagement/KeyPruneResult.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Result of pruning unused encryption keys.
*
* @immutable
*/
final class KeyPruneResult
{
/**
* Construct a KeyPruneResult.
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $deleted
* Deleted encryption key IDs.
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $failed
* Encryption key IDs that failed deletion.
*/
public function __construct(
public readonly array $deleted = [],
public readonly array $failed = [],
) {
/* ... */
}
}
Path: /src/KeyManagement/KeyPrunerException.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Thrown when pruning unused encryption keys cannot be planned or started.
*/
final class KeyPrunerException extends \RuntimeException
{
/**
* Creates an exception for failures while building a prune plan.
*
* @param \Throwable|null $previous
* (optional) The underlying exception.
*/
public static function planFailed(?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception for failures that prevent pruning from running at all.
*
* @param \Throwable|null $previous
* (optional) The underlying exception.
*/
public static function pruneFailed(?\Throwable $previous = null): self
{
/* ... */
}
}
Path: /src/KeyManagement/KeyPrunerInterface.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Application service for pruning unused encryption keys.
*/
interface KeyPrunerInterface
{
/**
* Builds a non-mutating plan describing what would be pruned.
*
* @throws \Drupal\easy_encryption\KeyManagement\KeyPrunerException
* Thrown when the plan cannot be computed.
*/
public function planPruning(): KeyPrunePlan;
/**
* Deletes unused encryption keys.
*
* This operation returns partial results: failures are reported in the result
* object rather than aborting the whole run.
*
* @return \Drupal\easy_encryption\KeyManagement\KeyPruneResult
* The prune result.
*
* @throws \Drupal\easy_encryption\KeyManagement\KeyPrunerException
* Thrown when the prune operation cannot start
* (for example, planning fails).
*/
public function pruneUnused(): KeyPruneResult;
}
Path: /src/KeyManagement/KeyRotationException.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Exception is thrown by key rotation workflows.
*/
final class KeyRotationException extends \RuntimeException
{
/**
* Creates an exception for failures while building a rotation plan.
*
* Planning is a non-mutating operation (used for dry-run previews). This
* exception indicates that the system could not compute a plan, typically due
* to storage access errors or unexpected runtime issues.
*
* @param \Throwable|null $previous
* (optional) The underlying exception that caused planning to fail.
*
* @return self
* The exception instance.
*/
public static function planFailed(?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception for failures while rotating the active enc. keys.
*
* This exception indicates that generating or activating a new encryption key
* failed.
*
* @param \Throwable|null $previous
* (optional) The underlying exception that caused rotation to fail.
*
* @return self
* The exception instance.
*/
public static function rotateFailed(?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception when re-encryption cannot be performed.
*
* This is used when the operation is not possible in the current environment,
* for example because the private key is not available and existing encrypted
* values therefore cannot be decrypted for re-encryption.
*
* @param string $reason
* A human-readable explanation of why re-encryption cannot be performed.
* @param \Throwable|null $previous
* (optional) The underlying exception, if any.
*
* @return self
* The exception instance.
*/
public static function reencryptNotPossible(string $reason, ?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception when one or more credentials fail to re-encrypt.
*
* @param int $failedCount
* The number of credentials that failed to re-encrypt.
* @param \Throwable|null $previous
* (optional) The underlying exception, if any.
*
* @return self
* The exception instance.
*/
public static function reencryptFailed(int $failedCount, ?\Throwable $previous = null): self
{
/* ... */
}
}
Path: /src/KeyManagement/KeyRotationOptions.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Options for the rotation operation.
*/
final class KeyRotationOptions
{
public function __construct(
public readonly bool $reencryptKeys = false,
public readonly bool $failOnReencryptErrors = true,
) {
/* ... */
}
}
Path: /src/KeyManagement/KeyRotationPlan.php#
namespace Drupal\easy_encryption\KeyManagement;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Describes what would be re-encrypted without performing changes.
*
* @immutable
*/
final class KeyRotationPlan
{
public function __construct(
public readonly ?EncryptionKeyId $activeKeyId,
public readonly int $total = 0,
public readonly int $toUpdate = 0,
public readonly int $toSkip = 0,
) {
/* ... */
}
}
Path: /src/KeyManagement/KeyRotationResult.php#
namespace Drupal\easy_encryption\KeyManagement;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Result of rotating the active encryption key and optionally re-encrypting.
*
* @immutable
*/
final class KeyRotationResult
{
public function __construct(
public readonly ?EncryptionKeyId $oldActiveKeyId,
public readonly EncryptionKeyId $newActiveKeyId,
public readonly int $updated = 0,
public readonly int $skipped = 0,
public readonly int $failed = 0,
) {
/* ... */
}
}
Path: /src/KeyManagement/KeyRotatorInterface.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Application service for planning and performing encryption key rotation.
*/
interface KeyRotatorInterface
{
/**
* Builds a non-mutating plan describing what would change.
*
* @throws \Drupal\easy_encryption\KeyManagement\KeyRotationException
* If the plan cannot be computed.
*/
public function plan(bool $includeReencryptCounts = true): KeyRotationPlan;
/**
* Rotates the active encryption key and optionally re-encrypts credentials.
*
* @throws \Drupal\easy_encryption\KeyManagement\KeyRotationException
* If rotation fails, or re-encryption fails and failOnReencryptErrors
* is TRUE.
*/
public function rotate(KeyRotationOptions $options): KeyRotationResult;
}
Path: /src/KeyManagement/KeyUsageTrackerInterface.php#
namespace Drupal\easy_encryption\KeyManagement;
/**
* Public API for tracking encryption key usage across the entire system.
*/
interface KeyUsageTrackerInterface
{
/**
* Returns the aggregated mapping of all consumers and their encryption keys.
*
* @return array{result: array<string, \Drupal\easy_encryption\KeyManagement\Port\KeyUsageMapping>, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
* The 'result' is keyed by consumer ID.
* 'cacheability' applies to the entire set.
*/
public function getKeyUsageMapping(): array;
}
Path: /src/KeyManagement/Observers/KeyActivatedObserverInterface.php#
namespace Drupal\easy_encryption\KeyManagement\Observers;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Contract for encryption key activation observers.
*/
interface KeyActivatedObserverInterface
{
/**
* Act when an encryption key gets activated.
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $activeKeyId
* The ID of the activated encryption key.
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $previousKeyId
* The ID of the previously active key if there was any.
*/
public function onKeyActivation(EncryptionKeyId $activeKeyId, ?EncryptionKeyId $previousKeyId): void;
}
Path: /src/KeyManagement/Observers/KeyDeletedObserverInterface.php#
namespace Drupal\easy_encryption\KeyManagement\Observers;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Contract for encryption key deletion observers.
*/
interface KeyDeletedObserverInterface
{
/**
* Act when an encryption key gets deleted.
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
* The ID of the activated encryption key.
*/
public function onKeyDeletion(EncryptionKeyId $keyId): void;
}
Path: /src/KeyManagement/Port/KeyRegistryException.php#
namespace Drupal\easy_encryption\KeyManagement\Port;
/**
* Thrown when the encryption key registry cannot be read or written.
*
* This exception is intended to be thrown by KeyRegistryInterface
* implementations, so callers do not need to depend on underlying storage
* exceptions (config, database, etc.).
*/
final class KeyRegistryException extends \RuntimeException
{
/**
* Creates an exception for failures while reading registry data.
*
* @param \Throwable|null $previous
* (optional) The underlying exception.
*/
public static function readFailed(?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception for failures while registering a key id.
*
* @param string $keyId
* The encryption key identifier that could not be registered.
* @param \Throwable|null $previous
* (optional) The underlying exception.
*/
public static function registerFailed(string $keyId, ?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception for failures while unregistering a key id.
*
* @param string $keyId
* The encryption key identifier that could not be registered.
* @param \Throwable|null $previous
* (optional) The underlying exception.
*/
public static function unregisterFailed(string $keyId, ?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception for failures while setting the active key id.
*
* @param string $keyId
* The encryption key identifier that could not be activated.
* @param \Throwable|null $previous
* (optional) The underlying exception.
*/
public static function setActiveFailed(string $keyId, ?\Throwable $previous = null): self
{
/* ... */
}
/**
* Creates an exception when attempting to set an active key that is unknown.
*
* @param string $keyId
* The encryption key identifier.
*/
public static function unknownKey(string $keyId): self
{
/* ... */
}
}
Path: /src/KeyManagement/Port/KeyRegistryInterface.php#
namespace Drupal\easy_encryption\KeyManagement\Port;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Read-only registry of known encryption keys and the active key.
*/
interface KeyRegistryInterface
{
/**
* Lists encryption key IDs known to this site.
*
* @return array{result: \Drupal\easy_encryption\Encryption\EncryptionKeyId[], cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
* Known key ids plus cacheability metadata.
*
* @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
* When registry storage cannot be read.
*/
public function listKnownKeyIds(): array;
/**
* Returns the active encryption key id, if any.
*
* @return array{result: \Drupal\easy_encryption\Encryption\EncryptionKeyId|null, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
* Active key id plus cacheability metadata.
*
* @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
* When registry storage cannot be read.
*/
public function getActiveKeyId(): array;
/**
* Checks whether a key id is known to the registry.
*
* @return array{result: bool, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
* TRUE if known plus cacheability metadata.
*
* @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
* When registry storage cannot be read.
*/
public function isKnown(EncryptionKeyId $key_id): array;
}
Path: /src/KeyManagement/Port/KeyUsageMapping.php#
namespace Drupal\easy_encryption\KeyManagement\Port;
use Drupal\Core\Cache\CacheBackendInterface as CacheBackendInterface;
use Drupal\Core\Cache\CacheableDependencyInterface as CacheableDependencyInterface;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Represents an encryption key used by a specific consumer with cacheability.
*/
final class KeyUsageMapping implements CacheableDependencyInterface
{
/**
* Constructs a new object.
*
* @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
* The encryption key being used.
* @param \Drupal\Core\Cache\CacheableDependencyInterface|null $cacheability
* Optional cacheability metadata for this specific mapping.
*/
public function __construct(
public readonly EncryptionKeyId $keyId,
private readonly ?CacheableDependencyInterface $cacheability = null,
) {
/* ... */
}
/**
* {@inheritdoc}
*/
public function getCacheContexts(): array
{
/* ... */
}
/**
* {@inheritdoc}
*/
public function getCacheTags(): array
{
/* ... */
}
/**
* {@inheritdoc}
*/
public function getCacheMaxAge(): int
{
/* ... */
}
}
Path: /src/KeyManagement/Port/KeyUsageProviderInterface.php#
namespace Drupal\easy_encryption\KeyManagement\Port;
/**
* Interface for reporters that identify encryption key dependencies.
*/
interface KeyUsageProviderInterface
{
/**
* Returns a mapping of consumers.
*
* @return array{result: array<string, \Drupal\easy_encryption\KeyManagement\Port\KeyUsageMapping>, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
* The 'result' is keyed by consumer ID. 'cacheability' applies to the
* entire set.
*/
public function getKeyUsageMapping(): array;
}
Path: /src/KeyManagement/Port/MutableKeyRegistryInterface.php#
namespace Drupal\easy_encryption\KeyManagement\Port;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;
/**
* Mutable registry of known encryption keys and the active key.
*/
interface MutableKeyRegistryInterface
{
/**
* Registers a key id as known.
*
* Implementations must be idempotent.
*
* @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
* When the registry cannot be written.
*/
public function register(EncryptionKeyId $key_id): void;
/**
* Unregisters a key id from the known list.
*
* @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
* When the registry cannot be written.
*/
public function unregister(EncryptionKeyId $key_id): void;
/**
* Sets the active encryption key id.
*
* Implementations should either:
* - implicitly register the key id if missing, or
* - throw unknownKey() if the key id is not registered.
*
* Pick one policy and keep it consistent. For export/import and for
* predictable behavior, I recommend: throw if unknown.
*
* @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
* When the registry cannot be written or the key is unknown.
*/
public function setActive(EncryptionKeyId $key_id): void;
}
File Statistics
- Size: 20.8 KB
- Lines: 829
File: core/domain/key_management.md