mcp-framework/docs/secrets.md

212 lines
4.9 KiB
Markdown
Raw Normal View History

# Secrets
Le package `secretstore` supporte plusieurs politiques de backend :
- `auto` : comportement par défaut, utilise un backend keyring disponible et peut retomber sur l'environnement si `LookupEnv` est fourni
- `kwallet-only` : impose KWallet et retourne une erreur explicite si KWallet n'est pas disponible
- `keyring-any` : impose l'utilisation d'un backend keyring disponible
- `env-only` : lecture seule depuis les variables d'environnement
- `bitwarden-cli` : utilise le CLI Bitwarden (`bw`) comme backend de vault
Backends keyring typiques :
- macOS : Keychain
- Linux : Secret Service ou KWallet selon l'environnement
- Windows : Credential Manager
Ouverture recommandée depuis la policy du manifeste runtime (`mcp.toml` résolu près de l'exécutable) :
```go
store, err := secretstore.OpenFromManifest(secretstore.OpenFromManifestOptions{
ServiceName: "my-mcp",
LookupEnv: os.LookupEnv,
})
if err != nil {
return err
}
```
Exemple bas niveau :
```go
store, err := secretstore.Open(secretstore.Options{
ServiceName: "my-mcp",
BackendPolicy: secretstore.BackendAuto,
})
if err != nil {
return err
}
if err := store.SetSecret("api-token", "My MCP API token", token); err != nil {
return err
}
token, err = store.GetSecret("api-token")
switch {
case err == nil:
// secret found
case errors.Is(err, secretstore.ErrNotFound):
// first run
default:
return err
}
```
Pour imposer KWallet sur Linux :
```go
store, err := secretstore.Open(secretstore.Options{
ServiceName: "email-mcp",
BackendPolicy: secretstore.BackendKWalletOnly,
})
```
Pour imposer Bitwarden via son CLI :
```go
store, err := secretstore.Open(secretstore.Options{
ServiceName: "email-mcp",
BackendPolicy: secretstore.BackendBitwardenCLI,
// Optionnel si `bw` n'est pas dans le PATH :
// BitwardenCommand: "/usr/local/bin/bw",
})
```
Pour vérifier explicitement que Bitwarden est prêt (login + unlock + `BW_SESSION`) :
```go
if err := secretstore.EnsureBitwardenReady(secretstore.Options{
BitwardenCommand: "bw",
LookupEnv: os.LookupEnv,
}); err != nil {
switch {
case errors.Is(err, secretstore.ErrBWNotLoggedIn):
// guider vers `bw login`
case errors.Is(err, secretstore.ErrBWLocked):
// guider vers `bw unlock --raw` puis export BW_SESSION
default:
// indisponibilité CLI/réseau
}
return err
}
```
Pour stocker un secret structuré en JSON :
```go
type Credentials struct {
Host string `json:"host"`
Username string `json:"username"`
Password string `json:"password"`
}
err = secretstore.SetJSON(store, "imap-credentials", "IMAP credentials", Credentials{
Host: "imap.example.com",
Username: "alice",
Password: token,
})
if err != nil {
return err
}
creds, err := secretstore.GetJSON[Credentials](store, "imap-credentials")
if err != nil {
return err
}
_ = creds
```
Pour écrire puis confirmer immédiatement une relecture :
```go
if err := secretstore.SetSecretVerified(store, "api-token", "My MCP API token", token); err != nil {
return err
}
```
Pour connaître le backend effectif utilisé :
```go
effective := secretstore.EffectiveBackendPolicy(store)
fmt.Println("backend effectif:", effective) // bitwarden-cli, env-only, keyring-any...
```
Pour obtenir en un seul appel une description runtime (source manifeste, policy déclarée/effective, disponibilité) :
```go
desc, err := secretstore.DescribeRuntime(secretstore.DescribeRuntimeOptions{
ServiceName: "my-mcp",
LookupEnv: os.LookupEnv,
})
if err != nil {
return err
}
fmt.Println(secretstore.FormatBackendStatus(desc))
// declared=... effective=... display=... ready=... source=...
```
Pour un préflight réutilisable dans `setup`, `config show` et `config test` :
```go
report, err := secretstore.PreflightFromManifest(secretstore.PreflightOptions{
ServiceName: "my-mcp",
LookupEnv: os.LookupEnv,
})
if err != nil {
return err
}
fmt.Println(report.Status) // ready | fail
fmt.Println(report.Summary) // message court
fmt.Println(report.Remediation) // action recommandée
```
## Debug Bitwarden en 60 secondes
1. Vérifier l'état de session :
```bash
bw status
```
2. Déverrouiller le vault et exporter `BW_SESSION` :
- Bash/Zsh :
```bash
export BW_SESSION="$(bw unlock --raw)"
```
- Fish :
```fish
set -x BW_SESSION (bw unlock --raw)
```
- PowerShell :
```powershell
$env:BW_SESSION = (bw unlock --raw)
```
3. Vérifier lecture/écriture rapide :
```go
if err := store.SetSecret("debug-token", "Debug token", "ok"); err != nil {
return err
}
_, err := store.GetSecret("debug-token")
return err
```
4. Interpréter les erreurs typées :
- `secretstore.ErrBWNotLoggedIn` : `bw login` requis.
- `secretstore.ErrBWLocked` : vault verrouillé ou `BW_SESSION` absent.
- `secretstore.ErrBWUnavailable` : CLI/réseau indisponible.
- `secretstore.ErrBackendUnavailable` : policy non satisfiable dans le contexte courant.
En mode `env-only`, `GetSecret("API_TOKEN")` lit la variable d'environnement `API_TOKEN`.
Les opérations d'écriture et de suppression retournent `secretstore.ErrReadOnly`.