282 lines
7.6 KiB
Markdown
282 lines
7.6 KiB
Markdown
# Changelog
|
|
|
|
## [Unreleased] - 2025-10-20
|
|
|
|
### Added - Vault Client Architecture
|
|
|
|
#### 🎯 Major Refactor: Raw API → Proper Client Class
|
|
|
|
**New Files:**
|
|
- `src/services/vaultClient.ts` - Low-level, browser-compatible Vault HTTP API client
|
|
- `CORS_AND_CLIENT.md` - Comprehensive guide explaining CORS and client architecture
|
|
|
|
**Why This Change?**
|
|
|
|
Your observation was correct - using raw `fetch()` calls is not ideal. Here's what we've improved:
|
|
|
|
### ✅ Before (Raw API)
|
|
```typescript
|
|
// Messy, error-prone, hard to maintain
|
|
const response = await fetch(`${url}/v1/${path}`, {
|
|
method: 'GET',
|
|
mode: 'no-cors', // ❌ Breaks response reading!
|
|
headers: {
|
|
'X-Vault-Token': token,
|
|
'Access-Control-Allow-Origin': '*' // ❌ Doesn't work from client!
|
|
}
|
|
});
|
|
```
|
|
|
|
Problems:
|
|
- ❌ `Access-Control-Allow-Origin` header ignored (must be set by server)
|
|
- ❌ `mode: 'no-cors'` prevents reading responses
|
|
- ❌ No retry logic
|
|
- ❌ No timeout protection
|
|
- ❌ Poor error messages
|
|
- ❌ Manual path normalization
|
|
- ❌ Repeated code everywhere
|
|
|
|
### ✅ After (VaultClient)
|
|
```typescript
|
|
// Clean, maintainable, production-ready
|
|
const client = new VaultClient({
|
|
server,
|
|
credentials,
|
|
timeout: 30000,
|
|
retries: 2
|
|
});
|
|
|
|
const data = await client.read('secret/data/myapp');
|
|
```
|
|
|
|
Benefits:
|
|
- ✅ Automatic retries with exponential backoff
|
|
- ✅ Configurable timeouts
|
|
- ✅ Detailed error messages with status codes
|
|
- ✅ Automatic path normalization
|
|
- ✅ Type-safe operations
|
|
- ✅ Built-in authentication methods
|
|
- ✅ Health check support
|
|
- ✅ Token lifecycle management
|
|
|
|
## New VaultClient Features
|
|
|
|
### 1. Core Operations
|
|
```typescript
|
|
// Read secret
|
|
const data = await client.read<MySecret>('secret/data/myapp');
|
|
|
|
// List secrets
|
|
const keys = await client.list('secret/');
|
|
|
|
// Write secret
|
|
await client.write('secret/data/myapp', { key: 'value' });
|
|
|
|
// Delete secret
|
|
await client.delete('secret/data/myapp');
|
|
```
|
|
|
|
### 2. Error Handling
|
|
```typescript
|
|
import { VaultError } from './services/vaultClient';
|
|
|
|
try {
|
|
await client.read('secret/data/test');
|
|
} catch (error) {
|
|
if (error instanceof VaultError) {
|
|
console.log(error.statusCode); // 403, 404, 500, etc.
|
|
console.log(error.errors); // Detailed error messages from Vault
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Authentication
|
|
```typescript
|
|
// Username/Password
|
|
const token = await client.loginUserpass('user', 'password');
|
|
|
|
// LDAP
|
|
const token = await client.loginLdap('user', 'password');
|
|
|
|
// Token info
|
|
const info = await client.tokenLookupSelf();
|
|
|
|
// Logout
|
|
await client.tokenRevokeSelf();
|
|
```
|
|
|
|
### 4. Health Check
|
|
```typescript
|
|
const health = await client.health();
|
|
console.log(health.initialized); // true/false
|
|
console.log(health.sealed); // true/false
|
|
console.log(health.version); // "1.15.0"
|
|
```
|
|
|
|
### 5. Automatic Retries
|
|
- Retries on network errors and 5xx server errors
|
|
- Does NOT retry on 4xx client errors (authentication, permission, etc.)
|
|
- Exponential backoff: 1s, 2s, 4s...
|
|
- Configurable retry count
|
|
|
|
### 6. Timeout Protection
|
|
```typescript
|
|
const client = new VaultClient({
|
|
...options,
|
|
timeout: 5000 // 5 seconds
|
|
});
|
|
|
|
// Automatically aborted after 5 seconds
|
|
```
|
|
|
|
## Updated Components
|
|
|
|
### `vaultApi.ts` - High-Level Service
|
|
- Now uses `VaultClient` internally
|
|
- Maintains caching layer
|
|
- Provides high-level operations
|
|
- Better error propagation
|
|
|
|
```typescript
|
|
// Before: Raw fetch
|
|
const response = await fetch(url, options);
|
|
const data = await response.json();
|
|
|
|
// After: Using VaultClient
|
|
const client = this.createClient(server, credentials);
|
|
const data = await client.read(path);
|
|
```
|
|
|
|
### `Dashboard.tsx` - Better Error Messages
|
|
```typescript
|
|
// Now catches VaultError and shows helpful messages
|
|
if (error.statusCode === 403) {
|
|
alert('Permission denied. You may not have access to this secret.');
|
|
} else if (error.statusCode === 404) {
|
|
alert('Secret not found at this path.');
|
|
} else if (error.message.includes('CORS')) {
|
|
alert('CORS error. Configure your Vault server to allow this origin.');
|
|
}
|
|
```
|
|
|
|
## CORS Configuration Guide
|
|
|
|
Created comprehensive `CORS_AND_CLIENT.md` explaining:
|
|
|
|
1. **Why client-side CORS headers don't work**
|
|
- CORS headers MUST be set by the server
|
|
- Browser enforces this security policy
|
|
|
|
2. **Why `mode: 'no-cors'` breaks everything**
|
|
- Prevents reading response body
|
|
- Returns opaque responses
|
|
- Can't access status codes or data
|
|
|
|
3. **Proper Vault CORS configuration**
|
|
```hcl
|
|
listener "tcp" {
|
|
cors_enabled = true
|
|
cors_allowed_origins = ["http://localhost:5173"]
|
|
cors_allowed_headers = ["*"]
|
|
}
|
|
```
|
|
|
|
4. **How to test CORS configuration**
|
|
- curl commands
|
|
- Browser console tests
|
|
- DevTools network inspection
|
|
|
|
## Architecture Comparison
|
|
|
|
| Aspect | Before (Raw API) | After (VaultClient) |
|
|
|--------|------------------|---------------------|
|
|
| **Code Quality** | Scattered logic | Centralized, clean |
|
|
| **Error Handling** | Basic | Comprehensive with VaultError |
|
|
| **Retries** | None | Automatic with backoff |
|
|
| **Timeouts** | None | Built-in |
|
|
| **Type Safety** | Minimal | Full TypeScript support |
|
|
| **Maintainability** | Low | High |
|
|
| **Testing** | Difficult | Easy to mock/test |
|
|
| **Production Ready** | No | Yes |
|
|
|
|
## Benefits Summary
|
|
|
|
### For Developers
|
|
1. **Less Code**: `await client.read(path)` vs 15 lines of fetch code
|
|
2. **Better DX**: TypeScript autocomplete, type checking
|
|
3. **Easier Testing**: Mock VaultClient instead of fetch
|
|
4. **Clear Errors**: Know exactly what went wrong
|
|
|
|
### For Users
|
|
1. **Better Error Messages**: "Permission denied" instead of "Failed"
|
|
2. **More Reliable**: Automatic retries on transient failures
|
|
3. **Faster**: Timeout protection prevents hanging
|
|
4. **Safer**: Proper CORS guidance prevents security issues
|
|
|
|
### For Production
|
|
1. **Robust**: Handles network issues gracefully
|
|
2. **Observable**: Detailed logging and error context
|
|
3. **Configurable**: Adjust timeouts and retries
|
|
4. **Scalable**: Easy to add new Vault operations
|
|
|
|
## Migration Guide
|
|
|
|
If you have custom code using the old API:
|
|
|
|
```typescript
|
|
// Old way ❌
|
|
const response = await fetch(`${url}/v1/${path}`, {
|
|
headers: { 'X-Vault-Token': token }
|
|
});
|
|
const data = await response.json();
|
|
|
|
// New way ✅
|
|
const client = new VaultClient({ server, credentials });
|
|
const data = await client.read(path);
|
|
```
|
|
|
|
## Breaking Changes
|
|
|
|
None! The `vaultApi` service maintains the same interface. The changes are internal improvements.
|
|
|
|
## Files Modified
|
|
- ✅ `src/services/vaultClient.ts` - NEW: Core client class
|
|
- ✅ `src/services/vaultApi.ts` - UPDATED: Now uses VaultClient
|
|
- ✅ `src/components/Dashboard.tsx` - UPDATED: Better error handling
|
|
- ✅ `README.md` - UPDATED: Mentions client architecture
|
|
- ✅ `CORS_AND_CLIENT.md` - NEW: Comprehensive guide
|
|
- ✅ `CHANGELOG.md` - NEW: This file
|
|
|
|
## Testing Checklist
|
|
|
|
- [x] No linter errors
|
|
- [x] TypeScript compiles successfully
|
|
- [x] All existing functionality preserved
|
|
- [x] Better error messages for common issues
|
|
- [ ] Manual testing with real Vault server (requires CORS config)
|
|
- [ ] Test retry logic (simulate network failure)
|
|
- [ ] Test timeout (simulate slow server)
|
|
- [ ] Test all auth methods
|
|
|
|
## Next Steps
|
|
|
|
1. **Configure CORS on your Vault server** (see CORS_AND_CLIENT.md)
|
|
2. **Run `npm install`** to ensure dependencies are up to date
|
|
3. **Test with your Vault instance**
|
|
4. **Report any issues**
|
|
|
|
## Documentation
|
|
|
|
New documentation files:
|
|
- `CORS_AND_CLIENT.md` - Why and how to use VaultClient
|
|
- `USAGE.md` - User guide (updated)
|
|
- `FEATURES.md` - Feature list (updated)
|
|
- `CHANGELOG.md` - This file
|
|
|
|
## Credits
|
|
|
|
Improvement suggested by user feedback: "You should probably use a vault-client instead of the raw api, no?"
|
|
|
|
Answer: Absolutely! And now we have one. 🎉
|
|
|