Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
cluster-security.md5.51 kB
# Cluster Security **Configure authentication and security for NornicDB clusters.** ## Overview NornicDB clusters use the same authentication system for both client connections and inter-node communication: - **Bolt Protocol Authentication** - Standard Neo4j-compatible auth (port 7687) - **JWT Bearer Tokens** - Recommended for cluster inter-node auth - **Service Accounts** - Non-human identities for automation - **RBAC Integration** - Full role-based access control ## Supported Auth Schemes | Scheme | Principal | Description | |--------|-----------|-------------| | `basic` | username | Username/password authentication | | `basic` | (empty) | JWT token in credentials field | | `bearer` | (ignored) | JWT token in credentials field | | `none` | - | Anonymous (if enabled, grants viewer role) | ## Authentication Methods ### Basic Authentication Username/password authentication via Bolt protocol: ```go // Go driver, _ := neo4j.NewDriverWithContext( "bolt://localhost:7687", neo4j.BasicAuth("admin", "password", ""), ) ``` ```python # Python driver = GraphDatabase.driver( "bolt://localhost:7687", auth=("admin", "password") ) ``` ```typescript // JavaScript/TypeScript const driver = neo4j.driver( 'bolt://localhost:7687', neo4j.auth.basic('admin', 'password') ); ``` ### JWT Bearer Tokens (Recommended for Clusters) For cluster nodes, JWT tokens provide stateless, scalable authentication: #### Step 1: Generate a Shared JWT Secret ```bash # Generate a 48-byte (384-bit) secret (min 32 bytes required) openssl rand -base64 48 # Example: K7xB2mN9pQr4sT6uV8wY0zA3bC5dE7fG9hI1jK3lM5nO7pQ9rS1tU3vW5xY7zA== ``` **⚠️ Important**: This secret must be identical on ALL cluster nodes. #### Step 2: Configure All Nodes ```bash # .env file for ALL cluster nodes NORNICDB_JWT_SECRET=K7xB2mN9pQr4sT6uV8wY0zA3bC5dE7fG9hI1jK3lM5nO7pQ9rS1tU3vW5xY7zA== NORNICDB_BOLT_REQUIRE_AUTH=true ``` #### Step 3: Generate Cluster Tokens Via API: ```bash curl -X POST http://localhost:7474/api/v1/auth/cluster-token \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"node_id": "node-2", "role": "admin"}' ``` Via Go code: ```go // Token never expires (default) token, _ := authenticator.GenerateClusterToken("node-2", auth.RoleAdmin) // Token with custom expiry token7d, _ := authenticator.GenerateClusterTokenWithExpiry( "node-2", auth.RoleAdmin, 7*24*time.Hour) ``` #### Step 4: Connect Using JWT ```go // Go - Empty username signals JWT authentication driver, _ := neo4j.NewDriverWithContext( "bolt://node1.cluster.local:7687", neo4j.BasicAuth("", token, ""), // Empty username = JWT ) ``` ```python # Python driver = GraphDatabase.driver( "bolt://node1.cluster.local:7687", auth=("", token) # Empty username = JWT ) ``` ```typescript // JavaScript/TypeScript const driver = neo4j.driver( 'bolt://node1.cluster.local:7687', neo4j.auth.basic('', token) // Empty username = JWT ); ``` ## Cluster Node Authentication ### Service Account Setup Create service accounts for cluster nodes: ```bash # Via HTTP API (port 7474 for HTTP, 7687 for Bolt) curl -X POST http://localhost:7474/api/v1/service-accounts \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "cluster-node-1", "secret": "secure-generated-password", "role": "admin" }' ``` Via Go code: ```go // Create service account for cluster node authenticator.CreateUser("cluster-node-1", "secure-password", []auth.Role{auth.RoleAdmin}) ``` ### Docker Compose with Auth ```yaml version: '3.8' services: nornicdb-node1: image: nornicdb:latest environment: NORNICDB_JWT_SECRET: ${SHARED_JWT_SECRET} NORNICDB_BOLT_REQUIRE_AUTH: "true" NORNICDB_BOLT_ALLOW_ANONYMOUS: "false" secrets: - jwt-secret secrets: jwt-secret: external: true ``` ## Permissions | Query Type | Required Permission | |------------|---------------------| | `MATCH ... RETURN` | `read` | | `CREATE`, `MERGE`, `SET` | `write` | | `DELETE` | `delete` | | `CREATE INDEX` | `schema` | ## Security Best Practices ### 1. Use Strong Secrets ```bash # Generate secure secrets openssl rand -base64 32 # Service account openssl rand -base64 48 # JWT secret ``` ### 2. Network Isolation ```yaml # Isolate cluster network networks: cluster-internal: internal: true # No external access ``` ### 3. Secret Rotation Rotate secrets quarterly: ```go func RotateServiceAccountSecret(auth *Authenticator, accountID string) (string, error) { newSecret := generateSecureSecret() err := auth.UpdateServiceAccountSecret(accountID, newSecret) return newSecret, err } ``` ## Troubleshooting ### Authentication Failures ```bash # Check service account exists (HTTP API port 7474) curl -X GET http://localhost:7474/api/v1/service-accounts/cluster-node-1 \ -H "Authorization: Bearer $ADMIN_TOKEN" ``` ### Permission Denied ```bash # Check/update account role curl -X PATCH http://localhost:7474/api/v1/service-accounts/cluster-node-1 \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"role": "admin"}' ``` ### Debug Logging ```bash export NORNICDB_LOG_LEVEL=debug export NORNICDB_AUTH_DEBUG=true ``` ## See Also - **[Clustering Guide](../user-guides/clustering.md)** - Full clustering setup - **[RBAC](../compliance/rbac.md)** - Authentication details - **[Scaling](scaling.md)** - Performance scaling

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server