Clients & Libraries
PHP
A single-file client with no Composer dependencies. Requires PHP 8.0 or newer with the curl and json extensions.
Install
The Composer package is afterdark/secretserver with PSR-4 namespace SecretServer\. Until a published release exists, add the checkout as a Composer path repository:
git clone https://github.com/afterdarksys/secretserver-clients.git # in your project composer config repositories.secretserver path /path/to/secretserver-clients/php composer require afterdark/secretserver:@dev
bash scripts/install-php.sh runs composer install --no-dev --optimize-autoloader in the library directory and prints these commands.
Authenticate
<?php
require __DIR__ . '/vendor/autoload.php';
use SecretServer\SecretServerClient;
// $apiKey falls back to SS_API_KEY, $apiUrl to SS_API_URL.
$ss = new SecretServerClient();
$ss = new SecretServerClient(
apiKey: getenv('SS_API_KEY') ?: null,
apiUrl: 'https://api.secretserver.io',
timeout: 10,
caFile: '/etc/ssl/private-ca.pem', // optional private CA
);The constructor throws AuthException with no key, and SecretServerException for verifySsl: false, a missing CA file or a non-https URL.
Read a secret
// Value only: "name", "container/key" or "container/key/N" (N = 1..12)
$password = $ss->secret('db-password');
$previous = $ss->secret('production/db-password/2');
// Full record. A read by name includes the ETag under ETAG_KEY ('_etag').
$record = $ss->getSecret('db-password');
$etag = $record[SecretServerClient::ETAG_KEY];Write a secret
Create
$ss->createSecret('db-password', 's3cr3t', [
'description' => 'Primary database',
'container_id' => '3f0c...uuid',
]);Update
A null value keeps the stored value. A key absent from $opts keeps that field; a key present with null clears it. The call is refused unless the client opted in (partialUpdates: true, setPartialUpdates(true) or SS_PARTIAL_UPDATES=1) or $ifMatch is an ETag from the server.
$record = $ss->getSecret('db-password');
$ss->updateSecret('db-password', 'new-value', [], $record[SecretServerClient::ETAG_KEY]);
// metadata only: clear the description, keep the value
$ss->updateSecret('db-password', null, ['description' => null], $record[SecretServerClient::ETAG_KEY]);Delete
$ss->deleteSecret('db-password');List secrets
foreach ($ss->listSecrets() as $s) {
echo $s['name'], "\n";
}Error handling
| Exception | When |
|---|---|
AuthException | HTTP 401, or no API key |
PermissionException | HTTP 403 |
NotFoundException | HTTP 404 |
ConflictException | HTTP 409. getETag() returns the current ETag |
SecretServerException | Base class; other HTTP errors, connection failure, invalid responses |
All exceptions live in the SecretServer namespace and extend RuntimeException.
use SecretServer\ConflictException;
use SecretServer\NotFoundException;
use SecretServer\SecretServerException;
try {
$value = $ss->secret('production/db-password');
} catch (NotFoundException $e) {
$value = null;
} catch (SecretServerException $e) {
error_log('secretserver request failed: ' . $e->getMessage());
throw $e;
}Complete example
example.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use SecretServer\ConflictException;
use SecretServer\NotFoundException;
use SecretServer\SecretServerClient;
use SecretServer\SecretServerException;
$ss = new SecretServerClient(); // SS_API_KEY / SS_API_URL
$name = 'example-api-token';
try {
try {
$record = $ss->getSecret($name);
} catch (NotFoundException $e) {
$ss->createSecret($name, 'first-value', ['description' => 'created by example']);
$record = $ss->getSecret($name);
}
try {
$ss->updateSecret($name, 'second-value', [], $record[SecretServerClient::ETAG_KEY]);
} catch (ConflictException $e) {
fwrite(STDERR, 'changed by someone else; current ETag ' . $e->getETag() . "\n");
exit(1);
}
printf("%d secrets visible to this key\n", count($ss->listSecrets()));
} catch (SecretServerException $e) {
fwrite(STDERR, 'error: ' . $e->getMessage() . "\n");
exit(2);
}More operations
- Any REST route:
$ss->request('GET', '/containers'). - Named variables:
assignVariable,render,resolveDocument(JSON objects come back asstdClass, arrays as PHP arrays). - Extended credentials:
$ss->credentials('wifi-credentials')returns an object withlist/get/create/update/delete. - Certificates:
enrollCertificateand related methods; TOTP and YubiKey helpers.