Metadata-Version: 2.4
Name: helvetisafe-vault-k8s
Version: 0.1.1
Summary: Kubernetes integration for Helvetisafe secret management — sidecar agent, Secret sync, and init-container injection
Author: Helvetisafe contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/TheM0f/aegis
Project-URL: Documentation, https://github.com/TheM0f/aegis/tree/main/clients/kubernetes/README.md
Project-URL: Repository, https://github.com/TheM0f/aegis
Project-URL: Issue Tracker, https://github.com/TheM0f/aegis/issues
Project-URL: Changelog, https://github.com/TheM0f/aegis/releases
Keywords: secrets,vault,kubernetes,k8s,sidecar,zero-knowledge,helvetisafe
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: helvetisafe-client>=0.1.0
Provides-Extra: kubernetes
Requires-Dist: kubernetes>=28.0.0; extra == "kubernetes"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: build>=1.0.0; extra == "dev"
Requires-Dist: twine>=5.0.0; extra == "dev"
Dynamic: license-file

# helvetisafe-vault-k8s

Python package for consuming [Helvetisafe](https://vault.helvetisafe.ch) secrets in any environment — locally, in CI, or inside a Kubernetes workload. Built on the Helvetisafe Python client and its zero-knowledge encryption model.

Three CLI modes are available:

| Mode | Command | Description |
|------|---------|-------------|
| **Serve** | `helvetisafe-vault-k8s serve` | HTTP agent that exposes decrypted secrets on `127.0.0.1` |
| **Inject** | `helvetisafe-vault-k8s inject` | Write secrets to a `.env` file once at startup |
| **Sync** | `helvetisafe-vault-k8s sync` | Sync secrets into a Kubernetes `Secret` object |

> Kubernetes deployment manifests and examples are maintained separately in the [aegis](https://github.com/helvetisafe/aegis) repository under `clients/kubernetes/`.

## Status

✅ v0.1.0 — available

---

## Installation

```bash
pip install helvetisafe-vault-k8s
```

The `sync` mode requires the `kubernetes` extra:

```bash
pip install "helvetisafe-vault-k8s[kubernetes]"
```

**Requirements:** Python 3.8+ · `helvetisafe-client >= 0.1.0` (auto-installed) · `kubernetes >= 28.0.0` (optional, `sync` only)

---

## Configuration

All settings are read from environment variables.

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `HELVETISAFE_BASE_URL` | ✅ | — | Base URL of the Helvetisafe instance, e.g. `https://vault.helvetisafe.ch` |
| `HELVETISAFE_CLIENT_ID` | ✅ | — | OAuth 2.0 client ID |
| `HELVETISAFE_CLIENT_SECRET` | ✅ | — | OAuth 2.0 client secret |
| `HELVETISAFE_PASSWORD` | one of three | — | Service account password |
| `HELVETISAFE_PRIVATE_KEY_PATH` | one of three | — | Path to a PEM private key file |
| `HELVETISAFE_PRIVATE_KEY_PEM` | one of three | — | PEM private key as a string |
| `HELVETISAFE_AGENT_PORT` | | `8080` | Port the serve agent listens on |
| `HELVETISAFE_AGENT_HOST` | | `127.0.0.1` | Host the serve agent binds to |
| `HELVETISAFE_K8S_NAMESPACE` | | `default` | Kubernetes namespace (sync mode) |
| `HELVETISAFE_K8S_SECRET_NAME` | | — | Kubernetes Secret name (sync mode) |
| `HELVETISAFE_SECRET_KEYS` | | — | Comma-separated keys to fetch; empty means all |

Exactly **one** of `HELVETISAFE_PASSWORD`, `HELVETISAFE_PRIVATE_KEY_PATH`, or `HELVETISAFE_PRIVATE_KEY_PEM` must be set.

---

## Modes

### Serve

Starts a lightweight HTTP server bound to `127.0.0.1` (loopback only). Any process on the same host can fetch decrypted secrets without implementing any cryptographic logic.

```bash
helvetisafe-vault-k8s serve [--port PORT] [--host HOST]
```

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/health` | Returns `{"status": "ok"}` |
| `GET` | `/secrets` | Lists all secret key names |
| `GET` | `/secret/{key}` | Returns the decrypted value of a secret |

```python
import requests
value = requests.get("http://localhost:8080/secret/database_password").json()["value"]
```

### Inject

Fetches secrets once and writes them to a shell-compatible `.env` file.

```bash
helvetisafe-vault-k8s inject --output /path/to/secrets.env
```

Output format:

```
KEY_NAME="plaintext-value"
ANOTHER_KEY="another-value"
```

Backslashes, double quotes, and newlines in values are escaped automatically.

### Sync

Fetches secrets and creates or updates a Kubernetes `Secret` object.

```bash
helvetisafe-vault-k8s sync [--output /path/to/secrets.env]
```

Requires the `kubernetes` extra and a service account with `get`, `create`, and `update` permissions on `secrets` in the target namespace.

---

## Architecture

```
Client process
├── Your application
│       └─► GET http://127.0.0.1:8080/secret/db_password   (serve mode)
│
└── helvetisafe-vault-k8s
        ├─► POST https://vault.helvetisafe.ch/oauth/token
        │       ← access_token
        ├─► GET  /api/v1/credentials/org-key
        │       ← encrypted Org Key (RSA-OAEP)
        │   RSA decrypt → Org Key  (in memory only)
        └─► GET  /api/v1/secrets/db_password
                ← AES-256-GCM ciphertext
            AES decrypt → plaintext
```

Plaintext values never leave the process memory. The Helvetisafe server only ever stores and transmits ciphertext.

---

## Project Structure

```
helvetisafe-vault-k8s/
├── pyproject.toml
├── src/
│   └── helvetisafe_k8s/
│       ├── agent.py     # Serve mode HTTP server
│       ├── cli.py       # CLI entry point
│       ├── config.py    # Environment-variable config loader
│       └── sync.py      # Inject / sync utilities
└── tests/
    ├── test_agent.py
    ├── test_config.py
    └── test_sync.py
```

---

## Running Tests

```bash
pip install -e ".[dev]"
pytest tests/ -v
```

---

## Contributing

Contributions are welcome. Please open an issue or pull request in this repository.

## License

MIT
