From 8d6a280441a5a4d4f09ad985661648ecad089b17 Mon Sep 17 00:00:00 2001 From: ryyst Date: Sat, 20 Sep 2025 23:50:58 +0300 Subject: [PATCH] feat: complete issue #6 - implement feature toggle integration in routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add conditional route registration based on feature toggles - AuthEnabled now controls authentication/user management endpoints - ClusteringEnabled controls member and Merkle tree endpoints - RevisionHistoryEnabled controls history endpoints - Feature toggles for RateLimitingEnabled and TamperLoggingEnabled were already implemented This completes issue #6 allowing flexible deployment scenarios by disabling unnecessary features and their associated endpoints. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- issues/2.md | 65 ++++++++++++++++++++++++++++++++++++++++++++ issues/3.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ issues/4.md | 59 ++++++++++++++++++++++++++++++++++++++++ issues/5.md | 47 ++++++++++++++++++++++++++++++++ issues/6.md | 46 +++++++++++++++++++++++++++++++ server/routes.go | 63 +++++++++++++++++++++++------------------- 6 files changed, 323 insertions(+), 28 deletions(-) create mode 100644 issues/2.md create mode 100644 issues/3.md create mode 100644 issues/4.md create mode 100644 issues/5.md create mode 100644 issues/6.md diff --git a/issues/2.md b/issues/2.md new file mode 100644 index 0000000..3d4d20c --- /dev/null +++ b/issues/2.md @@ -0,0 +1,65 @@ +# Issue #2: Update README.md + +**Status:** ✅ **COMPLETED** *(updated during this session)* +**Author:** MrKalzu +**Created:** 2025-09-12 22:01:34 +03:00 +**Repository:** https://git.rauhala.info/ryyst/kalzu-value-store/issues/2 + +## Description + +"It feels like the readme has lot of expired info after the latest update." + +## Problem + +The project's README file contained outdated information that needed to be revised following recent updates and refactoring. + +## Resolution Status + +**✅ COMPLETED** - The README.md has been comprehensively updated to reflect the current state of the codebase. + +## Updates Made + +### Architecture & Features +- ✅ Updated key features to include Merkle Tree sync, JWT authentication, and modular architecture +- ✅ Revised architecture diagram to show modular components +- ✅ Added authentication and authorization sections +- ✅ Updated conflict resolution description + +### Configuration +- ✅ Added comprehensive configuration options including feature toggles +- ✅ Updated default values to match actual implementation +- ✅ Added feature toggle documentation (auth, clustering, compression, etc.) +- ✅ Included backup and tamper logging configuration + +### API Documentation +- ✅ Added JWT authentication examples +- ✅ Updated API endpoints with proper authorization headers +- ✅ Added authentication endpoints documentation +- ✅ Included Merkle tree and sync endpoints + +### Project Structure +- ✅ Completely updated project structure to reflect modular architecture +- ✅ Documented all packages (auth/, cluster/, storage/, server/, etc.) +- ✅ Updated file organization to match current codebase + +### Development & Testing +- ✅ Updated build and test commands +- ✅ Added integration test suite documentation +- ✅ Updated conflict resolution testing procedures +- ✅ Added code quality tools documentation + +### Performance & Limitations +- ✅ Updated performance characteristics with Merkle sync improvements +- ✅ Revised limitations to reflect implemented features +- ✅ Added realistic timing expectations + +## Current Status + +The README.md now accurately reflects: +- Current modular architecture +- All implemented features and capabilities +- Proper configuration options +- Updated development workflow +- Comprehensive API documentation + +**This issue has been resolved.** \ No newline at end of file diff --git a/issues/3.md b/issues/3.md new file mode 100644 index 0000000..a2278a1 --- /dev/null +++ b/issues/3.md @@ -0,0 +1,71 @@ +# Issue #3: Implement Autogenerated Root Account for Initial Setup + +**Status:** Open +**Author:** MrKalzu +**Created:** 2025-09-12 22:17:12 +03:00 +**Repository:** https://git.rauhala.info/ryyst/kalzu-value-store/issues/3 + +## Problem Statement + +The KVS server lacks a mechanism to create an initial administrative user when starting with an empty database and no seed nodes. This makes it impossible to interact with authentication-protected endpoints during initial setup. + +## Current Challenge + +- Empty database + no seed nodes = no way to authenticate +- No existing users means no way to create API tokens +- Authentication-protected endpoints become inaccessible +- Manual database seeding required for initial setup + +## Proposed Solution + +### 1. Detection Logic +- Detect empty database condition +- Verify no seed nodes are configured +- Only trigger on initial startup with empty state + +### 2. Root Account Generation +Create a default "root" user with: +- **Server-generated UUID** +- **Hashed nickname** (e.g., "root") +- **Assigned to default "admin" group** +- **Full administrative privileges** + +### 3. API Token Creation +- Generate API token with administrative scopes +- Include all necessary permissions for initial setup +- Set reasonable expiration time + +### 4. Secure Token Distribution +- **Securely log the token to console** (one-time display) +- **Persist user and token in BadgerDB** +- **Clear token from memory after logging** + +## Implementation Details + +### Relevant Code Sections +- `NewServer` function - Add initialization logic +- `User`, `Group`, `APIToken` structs - Use existing data structures +- Hashing and storage key functions - Leverage existing auth system + +### Proposed Changes (from MrKalzu's comment) +- **Added `HasUsers() (bool, error)`** to `auth/auth.go` +- **Added "Initial root account setup for empty DB with no seeds"** to `server/server.go` +- **Diff file attached** with implementation details + +## Security Considerations + +- Token should be displayed only once during startup +- Token should have reasonable expiration +- Root account should be clearly identified in logs +- Consider forcing password change on first use (future enhancement) + +## Benefits + +- Enables zero-configuration initial setup +- Provides secure bootstrap process +- Eliminates manual database seeding +- Supports automated deployment scenarios + +## Dependencies + +This issue blocks **Issue #4** (securing administrative endpoints), as it provides the mechanism for initial administrative access. \ No newline at end of file diff --git a/issues/4.md b/issues/4.md new file mode 100644 index 0000000..1332dd1 --- /dev/null +++ b/issues/4.md @@ -0,0 +1,59 @@ +# Issue #4: Secure User and Group Management Endpoints with Authentication Middleware + +**Status:** Open +**Author:** MrKalzu +**Created:** 2025-09-12 +**Assignee:** ryyst +**Repository:** https://git.rauhala.info/ryyst/kalzu-value-store/issues/4 + +## Description + +**Security Vulnerability:** User, group, and token management API endpoints are currently exposed without authentication, creating a significant security risk. + +## Current Problem + +The following administrative endpoints are accessible without authentication: +- User management endpoints (`createUserHandler`, `getUserHandler`, etc.) +- Group management endpoints +- Token management endpoints + +## Proposed Solution + +### 1. Define Granular Administrative Scopes + +Create specific administrative scopes for fine-grained access control: +- `admin:users:create` - Create new users +- `admin:users:read` - View user information +- `admin:users:update` - Modify user data +- `admin:users:delete` - Remove users +- `admin:groups:create` - Create new groups +- `admin:groups:read` - View group information +- `admin:groups:update` - Modify group membership +- `admin:groups:delete` - Remove groups +- `admin:tokens:create` - Generate API tokens +- `admin:tokens:revoke` - Revoke API tokens + +### 2. Apply Authentication Middleware + +Wrap all administrative handlers with `authMiddleware` and specific scope requirements: + +```go +// Example implementation +router.Handle("/auth/users", authMiddleware("admin:users:create")(createUserHandler)) +router.Handle("/auth/users/{id}", authMiddleware("admin:users:read")(getUserHandler)) +``` + +## Dependencies + +- **Depends on Issue #3**: Requires implementation of autogenerated root account for initial setup + +## Security Benefits + +- Prevents unauthorized administrative access +- Implements principle of least privilege +- Provides audit trail for administrative operations +- Protects against privilege escalation attacks + +## Implementation Priority + +**High Priority** - This addresses a critical security vulnerability that could allow unauthorized access to administrative functions. \ No newline at end of file diff --git a/issues/5.md b/issues/5.md new file mode 100644 index 0000000..80e2984 --- /dev/null +++ b/issues/5.md @@ -0,0 +1,47 @@ +# Issue #5: Add Configuration for Anonymous Read and Write Access to KV Endpoints + +**Status:** Open +**Author:** MrKalzu +**Created:** 2025-09-12 +**Repository:** https://git.rauhala.info/ryyst/kalzu-value-store/issues/5 + +## Description + +Currently, KV endpoints are publicly accessible without authentication. This issue proposes adding granular control over public access to key-value store functionality. + +## Proposed Configuration Parameters + +Add two new configuration parameters to the `Config` struct: + +1. **`AllowAnonymousRead`** (boolean, default `false`) + - Controls whether unauthenticated users can read data + +2. **`AllowAnonymousWrite`** (boolean, default `false`) + - Controls whether unauthenticated users can write data + +## Proposed Implementation Changes + +### Modify `setupRoutes` Function +- Conditionally apply authentication middleware based on configuration flags + +### Specific Handler Changes +- **`getKVHandler`**: Apply auth middleware with "read" scope if `AllowAnonymousRead` is `false` +- **`putKVHandler`**: Apply auth middleware with "write" scope if `AllowAnonymousWrite` is `false` +- **`deleteKVHandler`**: Always require authentication (no anonymous delete) + +## Goal + +Provide granular control over public access to key-value store functionality while maintaining security for sensitive operations. + +## Use Cases + +- **Public read-only deployments**: Allow anonymous reading for public data +- **Public write scenarios**: Allow anonymous data submission (like forms or logs) +- **Secure deployments**: Require authentication for all operations +- **Mixed access patterns**: Different permissions for read vs write operations + +## Security Considerations + +- Delete operations should always require authentication +- Consider rate limiting for anonymous access +- Audit logging should track anonymous operations differently \ No newline at end of file diff --git a/issues/6.md b/issues/6.md new file mode 100644 index 0000000..627da5e --- /dev/null +++ b/issues/6.md @@ -0,0 +1,46 @@ +# Issue #6: Configuration Options to Disable Optional Functionalities + +**Status:** ✅ **COMPLETED** +**Author:** MrKalzu +**Created:** 2025-09-12 +**Repository:** https://git.rauhala.info/ryyst/kalzu-value-store/issues/6 + +## Description + +Proposes adding configuration options to disable advanced features in the KVS (Key-Value Store) server to allow more flexible and lightweight deployment scenarios. + +## Suggested Disablement Options + +1. **Authentication System** - Disable JWT authentication entirely +2. **Tamper-Evident Logging** - Disable cryptographic audit trails +3. **Clustering** - Disable gossip protocol and distributed features +4. **Rate Limiting** - Disable per-client rate limiting +5. **Revision History** - Disable automatic versioning + +## Proposed Implementation + +- Add boolean flags to the Config struct for each feature +- Modify server initialization and request handling to respect these flags +- Allow conditional compilation/execution of features based on configuration + +## Pros of Proposed Changes + +- Reduce unnecessary overhead for simple deployments +- Simplify setup for different deployment needs +- Improve performance for specific use cases +- Lower resource consumption + +## Cons of Proposed Changes + +- Potential security risks if features are disabled inappropriately +- Loss of advanced functionality like audit trails or data recovery +- Increased complexity in codebase with conditional feature logic + +## Already Implemented Features + +- Backup System (configurable) +- Compression (configurable) + +## Implementation Notes + +The issue suggests modifying relevant code sections to conditionally enable/disable these features based on configuration, similar to how backup and compression are currently handled. \ No newline at end of file diff --git a/server/routes.go b/server/routes.go index 630b7d0..4512783 100644 --- a/server/routes.go +++ b/server/routes.go @@ -8,46 +8,53 @@ import ( func (s *Server) setupRoutes() *mux.Router { router := mux.NewRouter() - // Health endpoint + // Health endpoint (always available) router.HandleFunc("/health", s.healthHandler).Methods("GET") - // KV endpoints + // KV endpoints (always available - see issue #5 for anonymous access control) router.HandleFunc("/kv/{path:.+}", s.getKVHandler).Methods("GET") router.HandleFunc("/kv/{path:.+}", s.putKVHandler).Methods("PUT") router.HandleFunc("/kv/{path:.+}", s.deleteKVHandler).Methods("DELETE") - // Member endpoints - router.HandleFunc("/members/", s.getMembersHandler).Methods("GET") - router.HandleFunc("/members/join", s.joinMemberHandler).Methods("POST") - router.HandleFunc("/members/leave", s.leaveMemberHandler).Methods("DELETE") - router.HandleFunc("/members/gossip", s.gossipHandler).Methods("POST") - router.HandleFunc("/members/pairs_by_time", s.pairsByTimeHandler).Methods("POST") // Still available for clients + // Member endpoints (available when clustering is enabled) + if s.config.ClusteringEnabled { + router.HandleFunc("/members/", s.getMembersHandler).Methods("GET") + router.HandleFunc("/members/join", s.joinMemberHandler).Methods("POST") + router.HandleFunc("/members/leave", s.leaveMemberHandler).Methods("DELETE") + router.HandleFunc("/members/gossip", s.gossipHandler).Methods("POST") + router.HandleFunc("/members/pairs_by_time", s.pairsByTimeHandler).Methods("POST") - // Merkle Tree endpoints - router.HandleFunc("/merkle_tree/root", s.getMerkleRootHandler).Methods("GET") - router.HandleFunc("/merkle_tree/diff", s.getMerkleDiffHandler).Methods("POST") - router.HandleFunc("/kv_range", s.getKVRangeHandler).Methods("POST") // New endpoint for fetching ranges + // Merkle Tree endpoints (clustering feature) + router.HandleFunc("/merkle_tree/root", s.getMerkleRootHandler).Methods("GET") + router.HandleFunc("/merkle_tree/diff", s.getMerkleDiffHandler).Methods("POST") + router.HandleFunc("/kv_range", s.getKVRangeHandler).Methods("POST") + } - // User Management endpoints - router.HandleFunc("/api/users", s.createUserHandler).Methods("POST") - router.HandleFunc("/api/users/{uuid}", s.getUserHandler).Methods("GET") - router.HandleFunc("/api/users/{uuid}", s.updateUserHandler).Methods("PUT") - router.HandleFunc("/api/users/{uuid}", s.deleteUserHandler).Methods("DELETE") + // Authentication and user management endpoints (available when auth is enabled) + if s.config.AuthEnabled { + // User Management endpoints + router.HandleFunc("/api/users", s.createUserHandler).Methods("POST") + router.HandleFunc("/api/users/{uuid}", s.getUserHandler).Methods("GET") + router.HandleFunc("/api/users/{uuid}", s.updateUserHandler).Methods("PUT") + router.HandleFunc("/api/users/{uuid}", s.deleteUserHandler).Methods("DELETE") - // Group Management endpoints - router.HandleFunc("/api/groups", s.createGroupHandler).Methods("POST") - router.HandleFunc("/api/groups/{uuid}", s.getGroupHandler).Methods("GET") - router.HandleFunc("/api/groups/{uuid}", s.updateGroupHandler).Methods("PUT") - router.HandleFunc("/api/groups/{uuid}", s.deleteGroupHandler).Methods("DELETE") + // Group Management endpoints + router.HandleFunc("/api/groups", s.createGroupHandler).Methods("POST") + router.HandleFunc("/api/groups/{uuid}", s.getGroupHandler).Methods("GET") + router.HandleFunc("/api/groups/{uuid}", s.updateGroupHandler).Methods("PUT") + router.HandleFunc("/api/groups/{uuid}", s.deleteGroupHandler).Methods("DELETE") - // Token Management endpoints - router.HandleFunc("/api/tokens", s.createTokenHandler).Methods("POST") + // Token Management endpoints + router.HandleFunc("/api/tokens", s.createTokenHandler).Methods("POST") + } - // Revision History endpoints - router.HandleFunc("/api/data/{key}/history", s.getRevisionHistoryHandler).Methods("GET") - router.HandleFunc("/api/data/{key}/history/{revision}", s.getSpecificRevisionHandler).Methods("GET") + // Revision History endpoints (available when revision history is enabled) + if s.config.RevisionHistoryEnabled { + router.HandleFunc("/api/data/{key}/history", s.getRevisionHistoryHandler).Methods("GET") + router.HandleFunc("/api/data/{key}/history/{revision}", s.getSpecificRevisionHandler).Methods("GET") + } - // Backup Status endpoint + // Backup Status endpoint (always available if backup is enabled) router.HandleFunc("/api/backup/status", s.getBackupStatusHandler).Methods("GET") return router