Skip to content

Speichern und rufen Sie sensible Anmeldeinformationen sicher mit den nativen Credential-Storage-APIs des Betriebssystems ab.

typescript
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.

typescript
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 Anwendungsname
  • options.name (string, erforderlich) - Der Benutzername oder Kontokenner

Rückgabewert:

  • Promise<string | null> - Das gespeicherte Passwort oder null, wenn nicht gefunden

Bun.secrets.set(options, value)

Speichert oder aktualisiert eine Anmeldeinformation.

typescript
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 Anwendungsname
  • options.name (string, erforderlich) - Der Benutzername oder Kontokenner
  • value (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.

typescript
const deleted = await Bun.secrets.delete({
  service: "my-app",
  name: "alice@example.com",
  value: "super-secret-password",
});
// Gibt zurück: boolean

Parameter:

  • options.service (string, erforderlich) - Der Dienst- oder Anwendungsname
  • options.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

javascript
// 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

javascript
// 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/Produktion

Fehlerbehandlung

javascript
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

javascript
// 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 ersetzt

Plattformverhalten

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

  1. Verschlüsselung: Anmeldeinformationen werden vom Credential Manager des Betriebssystems verschlüsselt
  2. Zugriffskontrolle: Nur der Benutzer, der die Anmeldeinformation gespeichert hat, kann sie abrufen
  3. Kein Klartext: Passwörter werden niemals im Klartext gespeichert
  4. Speichersicherheit: Bun löscht den Passwort-Speicher nach der Verwendung
  5. 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

  1. 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" }
  2. 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.

  3. 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

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;
}

Bun von www.bunjs.com.cn bearbeitet