.. include:: /Includes.rst.txt .. _developer-api: === API === This chapter documents the public API of the nr-vault extension. .. _api-vault-service: VaultService ============ The main service for interacting with the vault. .. php:namespace:: Netresearch\NrVault\Service .. php:interface:: VaultServiceInterface Main interface for vault operations. .. php:method:: store(string $identifier, string $secret, array $options = []): void Store a secret in the vault. :param string $identifier: Unique identifier for the secret. :param string $secret: The secret value to store. :param array $options: Optional configuration (owner, groups, context, expiresAt, metadata). .. php:method:: retrieve(string $identifier) Retrieve a secret from the vault. :param string $identifier: The secret identifier. :returns: The decrypted secret value or null if not found. :returntype: string|null :throws AccessDeniedException: If user lacks read permission. :throws SecretExpiredException: If the secret has expired. .. php:method:: exists(string $identifier): bool Check if a secret exists. :param string $identifier: The secret identifier. :returns: True if the secret exists. .. php:method:: delete(string $identifier, string $reason = ''): void Delete a secret from the vault. :param string $identifier: The secret identifier. :param string $reason: Optional reason for deletion (logged). :throws SecretNotFoundException: If secret doesn't exist. :throws AccessDeniedException: If user lacks delete permission. .. php:method:: rotate(string $identifier, string $newSecret, string $reason = ''): void Rotate a secret with a new value. :param string $identifier: The secret identifier. :param string $newSecret: The new secret value. :param string $reason: Optional reason for rotation (logged). .. php:method:: list(string $pattern = null): array List accessible secrets. :param string|null $pattern: Optional pattern to filter identifiers. :returns: Array of secret metadata. .. php:method:: getMetadata(string $identifier): array Get metadata for a secret without retrieving its value. :param string $identifier: The secret identifier. :returns: Array with identifier, description, owner, groups, version, etc. .. php:method:: http(): VaultHttpClientInterface Get an HTTP client that can inject secrets into requests. :returns: A PSR-18 compatible vault-aware HTTP client. .. _api-usage-examples: Usage examples -------------- .. _api-example-storing: Storing a secret ~~~~~~~~~~~~~~~~ .. code-block:: php :caption: Store a secret with VaultService use Netresearch\NrVault\Service\VaultServiceInterface; class MyService { public function __construct( private readonly VaultServiceInterface $vault, ) {} public function storeApiKey(string $apiKey): void { $this->vault->store( 'my_extension_api_key', $apiKey, [ 'description' => 'API key for external service', 'groups' => [1, 2], // Admin, Editor groups 'context' => 'payment', 'expiresAt' => time() + 86400 * 90, // 90 days ] ); } } .. _api-example-retrieving: Retrieving a secret ~~~~~~~~~~~~~~~~~~~ .. code-block:: php :caption: Retrieve a secret value public function getApiKey(): ?string { return $this->vault->retrieve('my_extension_api_key'); } .. _api-http-client: Vault HTTP client ----------------- The vault provides a PSR-18 compatible HTTP client that can inject secrets into requests without exposing them to your code. Configure authentication with :php:`withAuthentication()`, then use standard :php:`sendRequest()`. .. _api-http-direct-injection: Direct injection (recommended) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: php :caption: Inject VaultHttpClientInterface use GuzzleHttp\Psr7\Request; use Netresearch\NrVault\Http\SecretPlacement; use Netresearch\NrVault\Http\VaultHttpClientInterface; final class ExternalApiService { public function __construct( private readonly VaultHttpClientInterface $httpClient, ) {} public function fetchData(): array { // Configure authentication, then use standard PSR-18 $client = $this->httpClient->withAuthentication( 'api_token', SecretPlacement::Bearer, ); $request = new Request('GET', 'https://api.example.com/data'); $response = $client->sendRequest($request); return json_decode($response->getBody()->getContents(), true); } } .. _api-http-via-service: Via VaultService ~~~~~~~~~~~~~~~~ .. code-block:: php :caption: HTTP client via VaultService use GuzzleHttp\Psr7\Request; use Netresearch\NrVault\Http\SecretPlacement; $client = $this->vaultService->http() ->withAuthentication('stripe_api_key', SecretPlacement::Bearer); $request = new Request( 'POST', 'https://api.stripe.com/v1/charges', ['Content-Type' => 'application/json'], json_encode($payload), ); $response = $client->sendRequest($request); .. php:interface:: VaultHttpClientInterface PSR-18 compatible HTTP client with vault-based authentication. Extends :php:`Psr\Http\Client\ClientInterface`. .. php:method:: withAuthentication(string $secretIdentifier, SecretPlacement $placement = SecretPlacement::Bearer, array $options = []): static Create a new client instance configured with authentication. Returns an immutable instance - the original is unchanged. :param string $secretIdentifier: Vault identifier for the secret. :param SecretPlacement $placement: How to inject the secret. :param array $options: Additional options (headerName, queryParam, usernameSecret, reason). :returns: New client instance with authentication configured. .. php:method:: withOAuth(OAuthConfig $config, string $reason = 'OAuth2 API call'): static Create a new client instance configured with OAuth 2.0 authentication. :param OAuthConfig $config: OAuth configuration. :param string $reason: Audit log reason. :returns: New client instance with OAuth configured. .. php:method:: withReason(string $reason): static Create a new client instance with a custom audit reason. :param string $reason: Audit log reason for requests. :returns: New client instance with reason configured. .. php:method:: sendRequest(RequestInterface $request): ResponseInterface Send an HTTP request (PSR-18 method). :param RequestInterface $request: PSR-7 request. :returns: PSR-7 response. :throws ClientExceptionInterface: If request fails. .. _api-http-auth-options: Authentication options ~~~~~~~~~~~~~~~~~~~~~~ The :php:`withAuthentication()` method accepts these options: headerName Custom header name (for :php:`SecretPlacement::Header`, default: ``X-API-Key``). queryParam Query parameter name (for :php:`SecretPlacement::QueryParam`, default: ``api_key``). bodyField Body field name (for :php:`SecretPlacement::BodyField`, default: ``api_key``). usernameSecret Separate username secret identifier (for :php:`SecretPlacement::BasicAuth`). reason Reason for access (logged in audit). .. _api-secret-placement: SecretPlacement enum ~~~~~~~~~~~~~~~~~~~~ placement Authentication placement using :php:`SecretPlacement` enum: - :php:`SecretPlacement::Bearer` - Bearer token in Authorization header. - :php:`SecretPlacement::BasicAuth` - HTTP Basic Authentication. - :php:`SecretPlacement::Header` - Custom header value. - :php:`SecretPlacement::QueryParam` - Query parameter. - :php:`SecretPlacement::BodyField` - Field in request body. - :php:`SecretPlacement::OAuth2` - OAuth 2.0 with automatic token refresh. - :php:`SecretPlacement::ApiKey` - X-API-Key header (shorthand). .. _api-http-auth-examples: .. code-block:: php :caption: Authentication examples use GuzzleHttp\Psr7\Request; use Netresearch\NrVault\Http\SecretPlacement; // Bearer authentication $client = $this->vault->http() ->withAuthentication('stripe_api_key', SecretPlacement::Bearer); $response = $client->sendRequest( new Request('POST', 'https://api.stripe.com/v1/charges', [], $body) ); // Custom header $client = $this->vault->http() ->withAuthentication('api_token', SecretPlacement::Header, [ 'headerName' => 'X-API-Key', ]); $response = $client->sendRequest( new Request('GET', 'https://api.example.com/data') ); // Basic authentication with separate credentials $client = $this->vault->http() ->withAuthentication('service_password', SecretPlacement::BasicAuth, [ 'usernameSecret' => 'service_username', 'reason' => 'Fetching secure data', ]); $response = $client->sendRequest( new Request('GET', 'https://api.example.com/secure') ); // Query parameter $client = $this->vault->http() ->withAuthentication('api_key', SecretPlacement::QueryParam, [ 'queryParam' => 'key', ]); $response = $client->sendRequest( new Request('GET', 'https://maps.example.com/geocode') ); .. _api-events: PSR-14 events ------------- The vault dispatches events during secret operations. .. php:class:: SecretCreatedEvent Dispatched when a new secret is created. - :php:`getIdentifier()`: The secret identifier. - :php:`getSecret()`: The Secret entity. - :php:`getActorUid()`: User ID who created it. .. php:class:: SecretAccessedEvent Dispatched when a secret is read. - :php:`getIdentifier()`: The secret identifier. - :php:`getActorUid()`: User ID who accessed it. - :php:`getContext()`: The secret's context. .. php:class:: SecretRotatedEvent Dispatched when a secret is rotated. - :php:`getIdentifier()`: The secret identifier. - :php:`getNewVersion()`: The new version number. - :php:`getActorUid()`: User ID who rotated it. - :php:`getReason()`: The rotation reason. .. php:class:: SecretDeletedEvent Dispatched when a secret is deleted. - :php:`getIdentifier()`: The secret identifier. - :php:`getActorUid()`: User ID who deleted it. - :php:`getReason()`: The deletion reason. .. php:class:: SecretUpdatedEvent Dispatched when a secret value is updated (without rotation). - :php:`getIdentifier()`: The secret identifier. - :php:`getNewVersion()`: The new version number. - :php:`getActorUid()`: User ID who updated it. .. php:class:: MasterKeyRotatedEvent Dispatched after master key rotation completes. - :php:`getSecretsReEncrypted()`: Number of secrets re-encrypted. - :php:`getActorUid()`: User ID who performed the rotation. - :php:`getRotatedAt()`: DateTimeImmutable of when rotation completed.