Skip to content

Commit 42de637

Browse files
committed
Add Vault component for secret storage
1 parent a1cdab5 commit 42de637

16 files changed

Lines changed: 452 additions & 1 deletion

File tree

ROADMAP.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,35 @@ This roadmap outlines planned libraries and updates for the Sons of PHP monorepo
121121
- Release notes highlight Symfony 7 support.
122122
- Implementation meets the Global DoD.
123123

124+
### Epic: Introduce Vault Component
125+
**Description:** Provide secure secret storage with pluggable backends.
126+
127+
- [ ] Add filesystem storage adapter.
128+
- **Acceptance Criteria**
129+
- All Global DoR items are satisfied before implementation begins.
130+
- Filesystem adapter encrypts and retrieves secrets reliably.
131+
- Implementation meets the Global DoD.
132+
- [ ] Add database storage adapter.
133+
- **Acceptance Criteria**
134+
- All Global DoR items are satisfied before implementation begins.
135+
- Database adapter persists encrypted secrets.
136+
- Implementation meets the Global DoD.
137+
- [ ] Add Redis storage adapter.
138+
- **Acceptance Criteria**
139+
- All Global DoR items are satisfied before implementation begins.
140+
- Redis adapter stores encrypted secrets and respects expirations.
141+
- Implementation meets the Global DoD.
142+
- [ ] Support key rotation and secret versioning.
143+
- **Acceptance Criteria**
144+
- All Global DoR items are satisfied before implementation begins.
145+
- Secrets can be rotated without loss using new keys.
146+
- Implementation meets the Global DoD.
147+
- [ ] Provide CLI tools for managing secrets.
148+
- **Acceptance Criteria**
149+
- All Global DoR items are satisfied before implementation begins.
150+
- CLI allows setting, retrieving, and rotating secrets.
151+
- Implementation meets the Global DoD.
152+
124153
## Suggestions
125154

126155
- Automate dependency updates with a scheduled tool (e.g., Renovate or Dependabot).

composer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"sonsofphp/pager-implementation": "0.3.x-dev",
6161
"sonsofphp/registry-implementation": "0.3.x-dev",
6262
"sonsofphp/state-machine-implementation": "0.3.x-dev",
63+
"sonsofphp/vault-implementation": "0.3.x-dev",
6364
"sonsofphp/version-implementation": "0.3.x-dev"
6465
},
6566
"require": {
@@ -136,6 +137,7 @@
136137
"sonsofphp/registry-contract": "self.version",
137138
"sonsofphp/state-machine": "self.version",
138139
"sonsofphp/state-machine-contract": "self.version",
140+
"sonsofphp/vault": "self.version",
139141
"sonsofphp/version": "self.version",
140142
"sonsofphp/version-contract": "self.version"
141143
},
@@ -172,7 +174,8 @@
172174
"src/SonsOfPHP/Bridge/Doctrine/DBAL/Pager/Tests",
173175
"src/SonsOfPHP/Bridge/Doctrine/ORM/Pager/Tests",
174176
"src/SonsOfPHP/Component/Version/Tests",
175-
"src/SonsOfPHP/Component/Registry/Tests"
177+
"src/SonsOfPHP/Component/Registry/Tests",
178+
"src/SonsOfPHP/Component/Vault/Tests"
176179
],
177180
"psr-4": {
178181
"SonsOfPHP\\Bard\\": "src/SonsOfPHP/Bard/src",
@@ -206,6 +209,7 @@
206209
"SonsOfPHP\\Component\\Pager\\": "src/SonsOfPHP/Component/Pager",
207210
"SonsOfPHP\\Component\\Registry\\": "src/SonsOfPHP/Component/Registry",
208211
"SonsOfPHP\\Component\\StateMachine\\": "src/SonsOfPHP/Component/StateMachine",
212+
"SonsOfPHP\\Component\\Vault\\": "src/SonsOfPHP/Component/Vault",
209213
"SonsOfPHP\\Component\\Version\\": "src/SonsOfPHP/Component/Version",
210214
"SonsOfPHP\\Contract\\Common\\": "src/SonsOfPHP/Contract/Common",
211215
"SonsOfPHP\\Contract\\Cookie\\": "src/SonsOfPHP/Contract/Cookie",

docs/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
* [Adapters](components/pager/adapters.md)
7575
* [Registry](components/registry.md)
7676
* [State Machine](components/state-machine.md)
77+
* [Vault](components/vault.md)
7778
* [Version](components/version.md)
7879

7980
## 💁 Contributing

docs/components/vault.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Vault
2+
3+
The Vault component securely stores secrets using pluggable storage backends and encryption.
4+
5+
## Basic Usage
6+
7+
```php
8+
use SonsOfPHP\Component\Vault\Cipher\OpenSSLCipher;
9+
use SonsOfPHP\Component\Vault\Storage\InMemoryStorage;
10+
use SonsOfPHP\Component\Vault\Vault;
11+
12+
$vault = new Vault(new InMemoryStorage(), new OpenSSLCipher(), 'encryption-key');
13+
$vault->set('db_password', 'secret');
14+
$secret = $vault->get('db_password');
15+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Agents Guide for Package: src/SonsOfPHP/Component/Vault
2+
3+
## Scope
4+
5+
- Source: `src/SonsOfPHP/Component/Vault`
6+
- Tests: `src/SonsOfPHP/Component/Vault/Tests`
7+
- Do not edit: any `vendor/` directories
8+
9+
## Workflows
10+
11+
- Install once at repo root: `make install`
12+
- Test this package only: `PHPUNIT_OPTIONS='src/SonsOfPHP/Component/Vault/Tests' make test`
13+
- Style and static analysis: `make php-cs-fixer` and `make psalm`
14+
- Upgrade code (may modify files): `make upgrade-code`
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SonsOfPHP\Component\Vault\Cipher;
6+
7+
/**
8+
* Defines methods for encrypting and decrypting secrets.
9+
*/
10+
interface CipherInterface
11+
{
12+
/**
13+
* Encrypts plaintext using the provided key.
14+
*/
15+
public function encrypt(string $plaintext, string $key): string;
16+
17+
/**
18+
* Decrypts ciphertext using the provided key.
19+
*/
20+
public function decrypt(string $ciphertext, string $key): string;
21+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SonsOfPHP\Component\Vault\Cipher;
6+
7+
use RuntimeException;
8+
9+
/**
10+
* Encrypts and decrypts secrets using OpenSSL.
11+
*/
12+
class OpenSSLCipher implements CipherInterface
13+
{
14+
public function __construct(private readonly string $cipherMethod = 'aes-256-ctr')
15+
{
16+
}
17+
18+
public function encrypt(string $plaintext, string $key): string
19+
{
20+
$ivLength = openssl_cipher_iv_length($this->cipherMethod);
21+
$iv = random_bytes($ivLength);
22+
$encrypted = openssl_encrypt($plaintext, $this->cipherMethod, $key, OPENSSL_RAW_DATA, $iv);
23+
if (false === $encrypted) {
24+
throw new RuntimeException('Unable to encrypt secret.');
25+
}
26+
27+
return base64_encode($iv . $encrypted);
28+
}
29+
30+
public function decrypt(string $ciphertext, string $key): string
31+
{
32+
$data = base64_decode($ciphertext, true);
33+
$ivLength = openssl_cipher_iv_length($this->cipherMethod);
34+
$iv = substr($data, 0, $ivLength);
35+
$payload = substr($data, $ivLength);
36+
$decrypted = openssl_decrypt($payload, $this->cipherMethod, $key, OPENSSL_RAW_DATA, $iv);
37+
if (false === $decrypted) {
38+
throw new RuntimeException('Unable to decrypt secret.');
39+
}
40+
41+
return $decrypted;
42+
}
43+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright 2022 to Present Joshua Estes
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7+
of the Software, and to permit persons to whom the Software is furnished to do
8+
so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Sons of PHP - Vault
2+
===================
3+
4+
## Learn More
5+
6+
* [Documentation][docs]
7+
* [Contributing][contributing]
8+
* [Report Issues][issues] and [Submit Pull Requests][pull-requests] in the [Mother Repository][mother-repo]
9+
* Get Help & Support using [Discussions][discussions]
10+
11+
[discussions]: https://github.com/orgs/SonsOfPHP/discussions
12+
[mother-repo]: https://github.com/SonsOfPHP/sonsofphp
13+
[contributing]: https://docs.sonsofphp.com/contributing/
14+
[docs]: https://docs.sonsofphp.com/components/vault/
15+
[issues]: https://github.com/SonsOfPHP/sonsofphp/issues?q=is%3Aopen+is%3Aissue+label%3AVault
16+
[pull-requests]: https://github.com/SonsOfPHP/sonsofphp/pulls?q=is%3Aopen+is%3Apr+label%3AVault
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Vault Component Roadmap
2+
3+
## Upcoming Features
4+
5+
### Add filesystem storage adapter
6+
- [ ] Implementation uses encrypted files to persist secrets.
7+
- **Acceptance Criteria**
8+
- All Global DoR items are satisfied before implementation begins.
9+
- Filesystem adapter securely reads and writes secrets.
10+
- Implementation meets the Global DoD.
11+
12+
### Add database storage adapter
13+
- [ ] Store secrets in a relational database using PDO.
14+
- **Acceptance Criteria**
15+
- All Global DoR items are satisfied before implementation begins.
16+
- Secrets are encrypted before storage.
17+
- Implementation meets the Global DoD.
18+
19+
### Add Redis storage adapter
20+
- [ ] Store secrets in Redis for fast access.
21+
- **Acceptance Criteria**
22+
- All Global DoR items are satisfied before implementation begins.
23+
- Redis adapter encrypts secrets and handles expirations.
24+
- Implementation meets the Global DoD.
25+
26+
### Support key rotation and secret versioning
27+
- [ ] Provide APIs to rotate encryption keys and maintain secret history.
28+
- **Acceptance Criteria**
29+
- All Global DoR items are satisfied before implementation begins.
30+
- Secrets can be re-encrypted with new keys without loss.
31+
- Implementation meets the Global DoD.
32+
33+
### Provide CLI tools for managing secrets
34+
- [ ] Expose commands to set, get, and rotate secrets.
35+
- **Acceptance Criteria**
36+
- All Global DoR items are satisfied before implementation begins.
37+
- CLI allows basic secret management tasks.
38+
- Implementation meets the Global DoD.

0 commit comments

Comments
 (0)