Speichern und rufen Sie sensible Anmeldeinformationen sicher mit den nativen Credential-Storage-APIs des Betriebssystems ab.
import { secrets } from "bun";
let githubToken: string | null = await secrets.get({
service: "my-cli-tool",
name: "github-token",
});
if (!githubToken) {
githubToken = prompt("Bitte geben Sie Ihr GitHub-Token ein");
await secrets.set({
service: "my-cli-tool",
name: "github-token",
value: githubToken,
});
console.log("GitHub-Token gespeichert");
}
const response = await fetch("https://api.github.com/user", {
headers: { Authorization: `token ${githubToken}` },
});
console.log(`Angemeldet als ${(await response.json()).login}`);Übersicht
Bun.secrets bietet eine plattformübergreifende API zur Verwaltung sensibler Anmeldeinformationen, die CLI-Tools und Entwicklungsanwendungen typischerweise in Klartextdateien wie ~/.npmrc, ~/.aws/credentials oder .env-Dateien speichern. Es verwendet:
- macOS: Keychain Services
- Linux: libsecret (GNOME Keyring, KWallet, etc.)
- Windows: Windows Credential Manager
Alle Vorgänge sind asynchron und nicht-blockierend und laufen auf Buns Threadpool.
NOTE
In Zukunft könnten wir eine zusätzliche `provider`-Option hinzufügen, um dies besser für Produktions-Deployment-Secrets zu machen, aber heute ist diese API hauptsächlich für lokale Entwicklungstools nützlich.API
Bun.secrets.get(options)
Ruft eine gespeicherte Anmeldeinformation ab.
import { secrets } from "bun";
const password = await Bun.secrets.get({
service: "my-app",
name: "alice@example.com",
});
// Gibt zurück: string | null
// Oder wenn Sie es ohne ein Objekt bevorzugen
const password = await Bun.secrets.get("my-app", "alice@example.com");Parameter:
options.service(string, erforderlich) - Der Dienst- oder Anwendungsnameoptions.name(string, erforderlich) - Der Benutzername oder Kontokenner
Rückgabewert:
Promise<string | null>- Das gespeicherte Passwort odernull, wenn nicht gefunden
Bun.secrets.set(options, value)
Speichert oder aktualisiert eine Anmeldeinformation.
import { secrets } from "bun";
await secrets.set({
service: "my-app",
name: "alice@example.com",
value: "super-secret-password",
});Parameter:
options.service(string, erforderlich) - Der Dienst- oder Anwendungsnameoptions.name(string, erforderlich) - Der Benutzername oder Kontokennervalue(string, erforderlich) - Das zu speichernde Passwort oder Secret
Hinweise:
- Wenn bereits eine Anmeldeinformation für die angegebene service/name-Kombination existiert, wird sie ersetzt
- Der gespeicherte Wert wird vom Betriebssystem verschlüsselt
Bun.secrets.delete(options)
Löscht eine gespeicherte Anmeldeinformation.
const deleted = await Bun.secrets.delete({
service: "my-app",
name: "alice@example.com",
value: "super-secret-password",
});
// Gibt zurück: booleanParameter:
options.service(string, erforderlich) - Der Dienst- oder Anwendungsnameoptions.name(string, erforderlich) - Der Benutzername oder Kontokenner
Rückgabewert:
Promise<boolean>-true, wenn eine Anmeldeinformation gelöscht wurde,false, wenn nicht gefunden
Beispiele
Speichern von CLI-Tool-Anmeldeinformationen
// GitHub-CLI-Token speichern (anstatt ~/.config/gh/hosts.yml)
await Bun.secrets.set({
service: "my-app.com",
name: "github-token",
value: "ghp_xxxxxxxxxxxxxxxxxxxx",
});
// Oder wenn Sie es ohne ein Objekt bevorzugen
await Bun.secrets.set("my-app.com", "github-token", "ghp_xxxxxxxxxxxxxxxxxxxx");
// npm-Registry-Token speichern (anstatt ~/.npmrc)
await Bun.secrets.set({
service: "npm-registry",
name: "https://registry.npmjs.org",
value: "npm_xxxxxxxxxxxxxxxxxxxx",
});
// Für API-Aufrufe abrufen
const token = await Bun.secrets.get({
service: "gh-cli",
name: "github.com",
});
if (token) {
const response = await fetch("https://api.github.com/name", {
headers: {
Authorization: `token ${token}`,
},
});
}Migration von Klartext-Konfigurationsdateien
// Anstatt in ~/.aws/credentials zu speichern
await Bun.secrets.set({
service: "aws-cli",
name: "AWS_SECRET_ACCESS_KEY",
value: process.env.AWS_SECRET_ACCESS_KEY,
});
// Anstatt .env-Dateien mit sensiblen Daten
await Bun.secrets.set({
service: "my-app",
name: "api-key",
value: "sk_live_xxxxxxxxxxxxxxxxxxxx",
});
// Zur Laufzeit laden
const apiKey =
(await Bun.secrets.get({
service: "my-app",
name: "api-key",
})) || process.env.API_KEY; // Fallback für CI/ProduktionFehlerbehandlung
try {
await Bun.secrets.set({
service: "my-app",
name: "alice",
value: "password123",
});
} catch (error) {
console.error("Speichern der Anmeldeinformation fehlgeschlagen:", error.message);
}
// Überprüfen, ob eine Anmeldeinformation existiert
const password = await Bun.secrets.get({
service: "my-app",
name: "alice",
});
if (password === null) {
console.log("Keine Anmeldeinformation gefunden");
}Aktualisieren von Anmeldeinformationen
// Initiales Passwort
await Bun.secrets.set({
service: "email-server",
name: "admin@example.com",
value: "old-password",
});
// Auf neues Passwort aktualisieren
await Bun.secrets.set({
service: "email-server",
name: "admin@example.com",
value: "new-password",
});
// Das alte Passwort wird ersetztPlattformverhalten
macOS (Keychain)
- Anmeldeinformationen werden im Login-Keychain des Benutzers gespeichert
- Der Keychain kann beim ersten Gebrauch nach Zugriffsberechtigung fragen
- Anmeldeinformationen bleiben über Systemneustarts erhalten
- Zugänglich für den Benutzer, der sie gespeichert hat
Linux (libsecret)
- Erfordert einen Secret-Service-Daemon (GNOME Keyring, KWallet, etc.)
- Anmeldeinformationen werden in der Standard-Sammlung gespeichert
- Kann zur Entsperrung auffordern, wenn der Keyring gesperrt ist
- Der Secret-Service muss laufen
Windows (Credential Manager)
- Anmeldeinformationen werden im Windows Credential Manager gespeichert
- Sichtbar in Systemsteuerung → Credential Manager → Windows-Anmeldeinformationen
- Bleiben mit
CRED_PERSIST_ENTERPRISE-Flag erhalten, sodass sie pro Benutzer begrenzt sind - Verschlüsselt mit Windows Data Protection API
Sicherheitshinweise
- Verschlüsselung: Anmeldeinformationen werden vom Credential Manager des Betriebssystems verschlüsselt
- Zugriffskontrolle: Nur der Benutzer, der die Anmeldeinformation gespeichert hat, kann sie abrufen
- Kein Klartext: Passwörter werden niemals im Klartext gespeichert
- Speichersicherheit: Bun löscht den Passwort-Speicher nach der Verwendung
- Prozessisolierung: Anmeldeinformationen sind pro Benutzerkonto isoliert
Einschränkungen
- Maximale Passwortlänge variiert je nach Plattform (typischerweise 2048-4096 Bytes)
- Dienst- und Benutzernamen sollten angemessene Längen haben (< 256 Zeichen)
- Einige Sonderzeichen müssen je nach Plattform möglicherweise escaped werden
- Erfordert entsprechende Systemdienste:
- Linux: Secret-Service-Daemon muss laufen
- macOS: Keychain Access muss verfügbar sein
- Windows: Credential Manager-Dienst muss aktiviert sein
Vergleich mit Umgebungsvariablen
Im Gegensatz zu Umgebungsvariablen Bun.secrets:
- ✅ Verschlüsselt Anmeldeinformationen im Ruhezustand (dank des Betriebssystems)
- ✅ Vermeidet das Offenlegen von Secrets in Prozess-Speicher-Dumps (Speicher wird gelöscht, nachdem er nicht mehr benötigt wird)
- ✅ Übersteht Anwendungsneustarts
- ✅ Kann ohne Neustart der Anwendung aktualisiert werden
- ✅ Bietet Zugriffskontrolle auf Benutzerebene
- ❌ Erfordert OS-Credential-Service
- ❌ Nicht sehr nützlich für Deployment-Secrets (verwenden Sie Umgebungsvariablen in der Produktion)
Best Practices
Verwenden Sie beschreibende Dienstnamen: Passen Sie den Tool- oder Anwendungsnamen an Wenn Sie ein CLI für externe Verwendung erstellen, sollten Sie wahrscheinlich einen UTI (Uniform Type Identifier) für den Dienstnamen verwenden.
javascript// Gut - entspricht dem tatsächlichen Tool { service: "com.docker.hub", name: "username" } { service: "com.vercel.cli", name: "team-name" } // Vermeiden - zu generisch { service: "api", name: "key" }Nur Anmeldeinformationen: Speichern Sie keine Anwendungskonfiguration in dieser API Diese API ist langsam, Sie müssen wahrscheinlich immer noch eine Konfigurationsdatei für einige Dinge verwenden.
Verwendung für lokale Entwicklungstools:
- ✅ CLI-Tools (gh, npm, docker, kubectl)
- ✅ Lokale Entwicklungsserver
- ✅ Persönliche API-Schlüssel zum Testen
- ❌ Produktionsserver (verwenden Sie ordnungsgemäßes Secret-Management)
TypeScript
namespace Bun {
interface SecretsOptions {
service: string;
name: string;
}
interface Secrets {
get(options: SecretsOptions): Promise<string | null>;
set(options: SecretsOptions, value: string): Promise<void>;
delete(options: SecretsOptions): Promise<boolean>;
}
const secrets: Secrets;
}