secret-adapters

Secret Management Adapters (密鑰管理適配器)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "secret-adapters" with this command: npx skills add rytass/utils/rytass-utils-secret-adapters

Secret Management Adapters (密鑰管理適配器)

Overview

@rytass/secret 系列套件提供統一的密鑰管理介面,目前支援 HashiCorp Vault 作為後端儲存。

套件清單

套件 說明 用途

@rytass/secret

基礎介面 定義 SecretManager 抽象類別

@rytass/secret-adapter-vault

Vault 適配器 HashiCorp Vault 完整實現

@rytass/secret-adapter-vault-nestjs

NestJS 模組 Vault 的 NestJS 依賴注入整合

SecretManager 抽象類別

import { SecretManager } from '@rytass/secret';

// 所有 Secret Adapter 都繼承此抽象類別 abstract class SecretManager { constructor(project: string); get project(): string; // 取得初始化時的 path abstract get<T>(key: string): Promise<T> | T; abstract set<T>(key: string, value: T): Promise<void> | void; abstract delete(key: string): Promise<void> | void; }

Quick Start

安裝

直接使用 Vault

npm install @rytass/secret-adapter-vault

NestJS 專案

npm install @rytass/secret-adapter-vault-nestjs

基本使用(離線模式)

import { VaultSecret } from '@rytass/secret-adapter-vault';

const vault = new VaultSecret('apps/myapp/config', { host: 'https://vault.company.com', online: false, // 離線模式(預設) auth: { account: 'myapp-service', password: 'secure-password', }, onReady: () => { // 同步操作,無需 await const dbPassword = vault.get<string>('DATABASE_PASSWORD');

// 修改本地快取(不立即同步到 Vault)
vault.set('API_KEY', 'new-value');
vault.delete('OLD_CONFIG');

// 或者立即同步到 Vault(syncToOnline = true)
vault.set('ANOTHER_KEY', 'value', true);  // 立即同步
vault.delete('TEMP_KEY', true);           // 立即同步

// 批次同步變更到 Vault
vault.sync();  // 如果版本不符會拋錯
vault.sync(true);  // force = true,強制覆蓋

}, });

NestJS 整合

// app.module.ts import { VaultModule } from '@rytass/secret-adapter-vault-nestjs';

@Module({ imports: [ VaultModule.forRoot({ path: '/secret/data/myapp', fallbackFile: '.env.local', // Vault 不可用時的備用 }), ], }) export class AppModule {}

// config.service.ts @Injectable() export class ConfigService { constructor(private readonly vault: VaultService) {}

// get() 預設泛型為 string,可省略 async getDatabaseUrl(): Promise<string> { return this.vault.get('DATABASE_URL'); // 等同 get<string>() }

// set() 和 delete() 也支援 syncToOnline 參數 async updateConfig(key: string, value: string): Promise<void> { await this.vault.set(key, value); // syncToOnline = false(預設) await this.vault.set(key, value, true); // syncToOnline = true,立即同步 }

async removeConfig(key: string): Promise<void> { await this.vault.delete(key); // syncToOnline = false(預設) await this.vault.delete(key, true); // syncToOnline = true,立即同步 } }

Core Concepts

線上模式 vs 離線模式

特性 線上模式 離線模式(預設)

操作方式 即時連接 Vault 使用本地快取

get() 返回 Promise<T>

T (同步)

set() /delete() 返回 Promise<void>

Promise<void> (syncToOnline 時)或同步操作本地快取

效能 有網路延遲 極快

適用場景 需即時更新 頻繁讀取

Token 管理 自動續期(預設 TTL 約 32 天) 初始化時取得

狀態管理

enum VaultSecretState { INIT = 'INIT', // 初始化中 READY = 'READY', // 可用 TERMINATED = 'TERMINATED', // 已終止 }

// 檢查狀態 if (vault.state === VaultSecretState.READY) { // 可以安全操作 }

事件驅動

enum VaultEvents { INITED = 'INITED', // 初始化開始 READY = 'READY', // Vault 準備就緒 TOKEN_RENEWED = 'TOKEN_RENEWED', // Token 已續期 TERMINATED = 'TERMINATED', // 連線已終止 ERROR = 'ERROR', // 發生錯誤 }

完整型別定義

以下所有型別皆從 @rytass/secret-adapter-vault 導出:

import { VaultSecret, VaultSecretState, VaultEvents, VaultAuthMethods, VaultAuthMethodAccountPassword, VaultSecretOptions, VaultSecretOnlineOptions, VaultSecretOfflineOptions, VaultGetType, VaultSetType, VaultDeleteType, VaultTokenRetrieveSuccessResponse, VaultAPIFailedResponse, VaultTokenRetrieveResponse, VaultGetSecretSuccessResponse, VaultGetSecretResponse, } from '@rytass/secret-adapter-vault';

認證型別:

// 帳號密碼認證 interface VaultAuthMethodAccountPassword { account: string; password: string; }

// 支援的認證方式(目前僅支援帳號密碼) type VaultAuthMethods = VaultAuthMethodAccountPassword;

選項型別:

// 通用選項 interface VaultSecretOptions { host: string; // Vault 伺服器位址 auth: VaultAuthMethods; // 認證方式 online?: boolean; // 是否使用線上模式(預設 false) tokenTTL?: number; // Token TTL(毫秒),預設 2764724(約 32 天) onError?: (error: string) => void; // 錯誤回調 onReady?: () => void; // 準備就緒回調 }

// 線上模式選項(online: true) // 注意:獨立定義,非繼承自 VaultSecretOptions interface VaultSecretOnlineOptions { host: string; auth: VaultAuthMethods; online: true; tokenTTL?: number; onError?: (error: string) => void; onReady?: () => void; }

// 離線模式選項(online: false 或省略) // 注意:獨立定義,非繼承自 VaultSecretOptions interface VaultSecretOfflineOptions { host: string; auth: VaultAuthMethods; online?: false; tokenTTL?: number; onError?: (error: string) => void; onReady?: () => void; }

條件型別(根據模式決定返回值):

// get() 返回型別:線上模式為 Promise<T>,離線模式為 T type VaultGetType<O extends VaultSecretOptions, T> = O extends VaultSecretOnlineOptions ? Promise<T> : T;

// set() 返回型別 type VaultSetType<O extends VaultSecretOptions> = O extends VaultSecretOnlineOptions ? Promise<void> : void;

// delete() 返回型別 type VaultDeleteType<O extends VaultSecretOptions> = O extends VaultSecretOnlineOptions ? Promise<void> : void;

API 回應型別:

// API 失敗回應 interface VaultAPIFailedResponse { errors: string[]; }

// Token 取得成功回應 // 注意:token_type 使用內部 enum VaultTokenType(未導出) type VaultTokenRetrieveSuccessResponse = { auth: { client_token: string; accessor: string; policies: string[]; token_policies: string[]; metadata: Record<string, string> | null; lease_duration: number; renewable: boolean; entity_id: string; token_type: 'service' | 'batch'; // VaultTokenType enum(未導出) orphan: boolean; mfa_requirement: null; num_uses: number; }; } & VaultAPIBaseInfo<null>;

// Token 取得回應(成功或失敗) type VaultTokenRetrieveResponse = VaultTokenRetrieveSuccessResponse | VaultAPIFailedResponse;

// Secret 取得成功回應 type VaultGetSecretSuccessResponse = VaultAPIBaseInfo<{ data: Record<string, unknown>; metadata: { created_time: string; custom_metadata: null; deletion_time: string; destroyed: boolean; version: number; }; }>;

// Secret 取得回應(成功或失敗) type VaultGetSecretResponse = VaultGetSecretSuccessResponse | VaultAPIFailedResponse;

Common Patterns

線上模式使用

const vault = new VaultSecret('apps/myapp/config', { host: 'https://vault.company.com', online: true, auth: { account: 'service-account', password: 'password', }, });

// 需要 await const secret = await vault.get<string>('SECRET_KEY'); await vault.set('NEW_KEY', 'value'); await vault.delete('OLD_KEY');

TypeORM 整合

@Module({ imports: [ VaultModule.forRoot({ path: '/secret/data/database' }), TypeOrmModule.forRootAsync({ imports: [VaultModule], inject: [VaultService], useFactory: async (vault: VaultService) => ({ type: 'postgres', host: await vault.get<string>('DB_HOST'), port: await vault.get<number>('DB_PORT'), username: await vault.get<string>('DB_USERNAME'), password: await vault.get<string>('DB_PASSWORD'), database: await vault.get<string>('DB_NAME'), }), }), ], }) export class DatabaseModule {}

JWT 模組整合

@Module({ imports: [ VaultModule.forRoot({ path: '/secret/data/auth' }), JwtModule.registerAsync({ imports: [VaultModule], inject: [VaultService], useFactory: async (vault: VaultService) => ({ secret: await vault.get<string>('JWT_SECRET'), signOptions: { expiresIn: await vault.get<string>('JWT_EXPIRY') || '1h', }, }), }), ], }) export class AuthModule {}

錯誤處理與備用機制

const vault = new VaultSecret('apps/myapp/config', { host: 'https://vault.company.com', online: false, auth: { account: 'user', password: 'pass' }, onError: (error) => { console.error('Vault error:', error); // 可在此切換到備用配置 }, onReady: () => { console.log('Vault ready'); }, });

定期同步(離線模式)

// 離線模式下定期同步變更 setInterval(async () => { try { // sync() 會檢查版本,如果 Vault 上的版本與快取不符會拋出錯誤 await vault.sync(); console.log('Synced to Vault'); } catch (error) { if (error.message.includes('version is not match')) { // 版本不符時,可選擇強制覆蓋 await vault.sync(true); // force = true console.log('Force synced to Vault'); } else { console.warn('Sync failed:', error); } } }, 300000); // 每 5 分鐘

set() / delete() 的 syncToOnline 參數

// 離線模式下,set() 和 delete() 預設只修改本地快取 vault.set('KEY', 'value'); // syncToOnline = false(預設) vault.delete('KEY'); // syncToOnline = false(預設)

// 如果需要立即同步到 Vault,傳入 syncToOnline = true vault.set('KEY', 'value', true); // 立即同步到 Vault vault.delete('KEY', true); // 立即同步到 Vault

優雅關閉

process.on('SIGTERM', () => { vault.terminate(); process.exit(0); });

NestJS Module Reference

VaultModuleOptions

// NestJS 模組配置選項 interface VaultModuleOptions { path: string; // Vault secret path(預設 '/') fallbackFile?: string; // Vault 不可用時的備用 .env 檔案 }

VaultService 方法簽名

class VaultService { // get() 預設泛型為 string,可省略 async get<T = string>(key: string): Promise<T>;

// set() 支援 syncToOnline 參數 async set<T = string>(key: string, value: T, syncToOnline = false): Promise<void>;

// delete() 支援 syncToOnline 參數 async delete(key: string, syncToOnline = false): Promise<void>; }

Environment Variables (NestJS)

必需(若未設置 VAULT_HOST,會自動切換至備用模式)

VAULT_HOST=https://vault.example.com:8200 VAULT_ACCOUNT=your-username VAULT_PASSWORD=your-password

注意: path 不是透過環境變數設定,而是在 VaultModule.forRoot({ path: '...' }) 中指定。

API Reference

詳細 API 文件請參閱 reference.md。

Troubleshooting

連線失敗

  • 確認 VAULT_HOST 使用 HTTPS

  • 檢查網路連線和防火牆

  • 驗證帳號密碼正確

Token 過期

線上模式會自動續期。如果仍然過期:

  • 檢查 tokenTTL 設定

  • 確認 Vault 伺服器時間同步

  • 查看 Vault Token 政策設定

NestJS 備用模式

當 VAULT_HOST 未設置時或連線失敗時,VaultService 會切換至備用模式:

  • get() 從 ConfigService(環境變數)讀取

  • set() 和 delete() 會拋出錯誤:"Cannot set/delete value when fallback to env file is enabled."

// 備用模式下的行為 try { await vaultService.set('KEY', 'value'); } catch (error) { // Error: Cannot set value when fallback to env file is enabled. console.log('Vault 備用模式不支援寫入操作'); }

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

wms-module

No summary provided by upstream source.

Repository SourceNeeds Review
General

invoice-adapters

No summary provided by upstream source.

Repository SourceNeeds Review
General

wms-react-components

No summary provided by upstream source.

Repository SourceNeeds Review