# 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 Tu peux activer les traces d'appels Bitwarden avec le flag CLI global `--debug` (via `bootstrap`) ou en exportant `MCP_FRAMEWORK_BITWARDEN_DEBUG=1`. Les commandes `bw` exécutées seront affichées (avec redaction des payloads sensibles). 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`.