Skip to content

Add secrets engines abstraction #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 74 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ This array contains an element named ``keys``, whose value is an array of the se

[
"keys": [
"hello"
"hello",
"world"
]
]
Fetching a secret
Expand Down Expand Up @@ -149,6 +150,78 @@ Fetching a secret

$data = $response->getData(); // Raw array with secret's content.

// ...
Secrets Engines overlays
==================
Each secret engine (such as Key/Value [versions 1/2], Cubbyhole, Transit, etc.) comes with a different APIs.
Overlays provide a way to use secret engine without worrying about underlaying path structure, in a more object-oriented way.

To use one, simply create new instance while specifying authenticated Vault client and path at which it is located:

.. code-block:: php

<?php

use Vault\AuthenticationStrategies\TokenAuthenticationStrategy;
use Vault\Client;
use Vault\SecretsEngines\KeyValueVersion2SecretsEngine;
use Laminas\Diactoros\RequestFactory;
use Laminas\Diactoros\StreamFactory;
use Laminas\Diactoros\Uri;

// Creating the client
$client = new Client(
new Uri('http://127.0.0.1:8200'),
new \AlexTartan\GuzzlePsr18Adapter\Client(),
new RequestFactory(),
new StreamFactory()
); // Using alextartan/guzzle-psr18-adapter and laminas/laminas-diactoros

// Authenticating using token auth backend.
// Request exception could appear here.
$authenticated = $client
->setAuthenticationStrategy(new TokenAuthenticationStrategy('463763ae-0c3b-ff77-e137-af668941465c'))
->authenticate();

if (!$authenticated) {
// Throw an exception or handle authentication failure.
}

// Create an instance of KV2 secret engine overlay, mounted at path "secret" using authenticated client
$kv2 = new KeyValueVersion2SecretsEngine($client, 'secret');

List secret keys
----------------

.. code-block:: php

// Request exception could appear here.
/** @var \Vault\ResponseModels\KeyValueVersion2\ListResponse $response */
$response = $kv2->list(''); // Corresponds to calling $client->keys('/secret/metadata/')
$keys = $response->getKeys(); // Raw array of secret's keys

Notice, that secret engine overlay knows structure of Vault response, so it can parse and objectify it.
It means you don't have to look for "keys" index in raw data array as before. On success, $keys would be equal to:

.. code-block:: php

[
"hello",
"world"
]

Fetching a secret
----------------

.. code-block:: php

// Request exception could appear here.
/** @var \Vault\ResponseModels\KeyValueVersion2\ReadResponse $response */
$response = $kv2->read('database'); // Corresponds to calling $client->read('secret/data/database');

$data = $response->getData(); // Raw array with secret's content.
$metadata = $response->getMetadata(); // Object containing KV2 secret version metadata

// ...

Indices and tables
Expand Down
15 changes: 8 additions & 7 deletions src/BaseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
*/
abstract class BaseClient implements LoggerAwareInterface
{
public const VERSION_1 = 'v1';

use LoggerAwareTrait;

public const VERSION_1 = 'v1';

/**
* @var string
Expand All @@ -40,7 +40,7 @@ abstract class BaseClient implements LoggerAwareInterface
protected $token;

/**
* @var Namespace
* @var string
*/
protected $namespace;

Expand Down Expand Up @@ -116,9 +116,10 @@ public function head(string $path): Response
*/
public function send(string $method, string $path, string $body = ''): ResponseInterface
{
$method = strtoupper($method);
$headers = [
'User-Agent' => 'VaultPHP/1.0.0',
'Content-Type' => 'application/json',
'Content-Type' => ($method === 'PATCH' ? 'application/merge-patch+json' : 'application/json'),
];

if ($this->token) {
Expand All @@ -134,7 +135,7 @@ public function send(string $method, string $path, string $body = ''): ResponseI
$this->baseUri = $this->baseUri->withQuery($query);
}

$request = $this->requestFactory->createRequest(strtoupper($method), $this->baseUri->withPath($path));
$request = $this->requestFactory->createRequest($method, $this->baseUri->withPath($path));

foreach ($headers as $name => $value) {
$request = $request->withHeader($name, $value);
Expand Down Expand Up @@ -309,15 +310,15 @@ public function setToken(Token $token)
}

/**
* @return Namespace
* @return string
*/
public function getNamespace(): string
{
return $this->namespace;
}

/**
* @param String $namespace
* @param string $namespace
*
* @return $this
*/
Expand Down
17 changes: 14 additions & 3 deletions src/BaseObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

namespace Vault;

use RuntimeException;
use Vault\Exceptions\RuntimeException;
use Vault\Helpers\ArrayHelper;
use Vault\Helpers\ModelHelper;

/**
* Class Object
* Class BaseObject
*
* @package Vault
*/
class BaseObject
class BaseObject implements \JsonSerializable
{
/**
* Object constructor.
Expand Down Expand Up @@ -193,4 +194,14 @@ public function getFields(): array

return $result;
}

/**
* @return array
*
* @throws RuntimeException
*/
public function jsonSerialize(): array
{
return ModelHelper::snakelize($this->toArray(), false);
}
}
27 changes: 27 additions & 0 deletions src/Builders/KeyValueVersion1/ListResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Vault\Builders\KeyValueVersion1;

use Vault\Helpers\ModelHelper;
use Vault\ResponseModels\KeyValueVersion1\ListResponse;
use Vault\ResponseModels\Response;

/**
* Class ListResponseBuilder
*
* @package Vault\Builder\KeyValueVersion1
*/
class ListResponseBuilder
{
/**
* @param Response $response
*
* @return ListResponse
*/
public static function build(Response $response): ListResponse
{
$data = $response->getData();

return new ListResponse(ModelHelper::camelize($data, false));
}
}
27 changes: 27 additions & 0 deletions src/Builders/KeyValueVersion2/ListResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Vault\Builders\KeyValueVersion2;

use Vault\Helpers\ModelHelper;
use Vault\ResponseModels\KeyValueVersion2\ListResponse;
use Vault\ResponseModels\Response;

/**
* Class ListResponseBuilder
*
* @package Vault\Builder\KeyValueVersion2
*/
class ListResponseBuilder
{
/**
* @param Response $response
*
* @return ListResponse
*/
public static function build(Response $response): ListResponse
{
$data = $response->getData();

return new ListResponse(ModelHelper::camelize($data, false));
}
}
27 changes: 27 additions & 0 deletions src/Builders/KeyValueVersion2/ReadConfigurationResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Vault\Builders\KeyValueVersion2;

use Vault\Helpers\ModelHelper;
use Vault\Models\KeyValueVersion2\Configuration;
use Vault\ResponseModels\Response;

/**
* Class ReadConfigurationResponseBuilder
*
* @package Vault\Builder\KeyValueVersion2
*/
class ReadConfigurationResponseBuilder
{
/**
* @param Response $response
*
* @return Configuration
*/
public static function build(Response $response): Configuration
{
$data = $response->getData();

return new Configuration(ModelHelper::camelize($data, false));
}
}
36 changes: 36 additions & 0 deletions src/Builders/KeyValueVersion2/ReadMetadataResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Vault\Builders\KeyValueVersion2;

use Vault\Helpers\ModelHelper;
use Vault\ResponseModels\KeyValueVersion2\ReadMetadataResponse;
use Vault\ResponseModels\KeyValueVersion2\VersionMetadata;
use Vault\ResponseModels\Response;

/**
* Class ReadMetadataResponseBuilder
*
* @package Vault\Builder\KeyValueVersion2
*/
class ReadMetadataResponseBuilder
{
/**
* @param Response $response
*
* @return ReadMetadataResponse
*/
public static function build(Response $response): ReadMetadataResponse
{
$data = $response->getData();

$versions = [];
foreach ($data['versions'] as $versionNumber => $versionData) {
$versionData['custom_metadata'] = $data['custom_metadata'] ?? null;
$versionData['version'] = $versionNumber;
$versions[$versionNumber] = new VersionMetadata(ModelHelper::camelize($versionData, false));
}
$data['versions'] = $versions;

return new ReadMetadataResponse(ModelHelper::camelize($data, false));
}
}
30 changes: 30 additions & 0 deletions src/Builders/KeyValueVersion2/ReadResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Vault\Builders\KeyValueVersion2;

use Vault\Helpers\ModelHelper;
use Vault\ResponseModels\KeyValueVersion2\ReadResponse;
use Vault\ResponseModels\KeyValueVersion2\VersionMetadata;
use Vault\ResponseModels\Response;

/**
* Class ReadResponseBuilder
*
* @package Vault\Builder\KeyValueVersion2
*/
class ReadResponseBuilder
{
/**
* @param Response $response
*
* @return ReadResponse
*/
public static function build(Response $response): ReadResponse
{
$data = $response->getData();

$data['metadata'] = new VersionMetadata(ModelHelper::camelize($data['metadata'], false));

return new ReadResponse($data);
}
}
30 changes: 30 additions & 0 deletions src/Builders/KeyValueVersion2/ReadSubkeysResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Vault\Builders\KeyValueVersion2;

use Vault\Helpers\ModelHelper;
use Vault\ResponseModels\KeyValueVersion2\ReadSubkeysResponse;
use Vault\ResponseModels\KeyValueVersion2\VersionMetadata;
use Vault\ResponseModels\Response;

/**
* Class ReadSubkeysResponseBuilder
*
* @package Vault\Builder\KeyValueVersion2
*/
class ReadSubkeysResponseBuilder
{
/**
* @param Response $response
*
* @return ReadSubkeysResponse
*/
public static function build(Response $response): ReadSubkeysResponse
{
$data = $response->getData();

$data['metadata'] = new VersionMetadata(ModelHelper::camelize($data['metadata'], false));

return new ReadSubkeysResponse($data);
}
}
27 changes: 27 additions & 0 deletions src/Builders/KeyValueVersion2/VersionMetadataResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Vault\Builders\KeyValueVersion2;

use Vault\Helpers\ModelHelper;
use Vault\ResponseModels\KeyValueVersion2\VersionMetadata;
use Vault\ResponseModels\Response;

/**
* Class VersionMetadataResponseBuilder
*
* @package Vault\Builder\KeyValueVersion2
*/
class VersionMetadataResponseBuilder
{
/**
* @param Response $response
*
* @return VersionMetadata
*/
public static function build(Response $response): VersionMetadata
{
$data = $response->getData();

return new VersionMetadata(ModelHelper::camelize($data, false));
}
}
Loading