Securing a deployment
Use this guide to secure an Exofind deployment by bootstrapping an initial administrative key and creating scoped keys for your services. Exofind nodes check credentials by default.
Prerequisites
Section titled “Prerequisites”Before you begin, make sure that you have:
- An Exofind deployment with nodes running in
keysmode (the default). - A tool such as OpenSSL to generate random strings.
- Network access to an Exofind node.
Bootstrapping the initial key
Section titled “Bootstrapping the initial key”To create the first administrative key, provide a root key to one node:
-
Generate a root key secret:
Terminal window openssl rand -base64 32 # keep this somewhere a person can reach itStore this value securely. The root key has full permissions, is not stored anywhere, and ensures that a deployment always has an entry point.
-
Set the root key on one node using the
EXOFIND_AUTH_ROOT_KEYenvironment variable:Terminal window EXOFIND_AUTH_ROOT_KEY=<that value> ...Prefer setting a hashed key so the plaintext value does not appear in an environment variable:
Terminal window EXOFIND_AUTH_ROOT_KEY=sha256:$(printf %s "<that value>" | shasum -a 256 | cut -d' ' -f1) -
Create the administrative key that manages authentication from then on:
POST /v1alpha1/admin/keysAuthorization: Bearer <root key>Content-Type: application/json{"description": "deployment pipeline","grants": [{ "role": "admin", "indexes": ["*"] }]}The response returns the credential once. Store it in your continuous integration (CI) secrets store; you cannot retrieve it again.
Creating scoped keys for services
Section titled “Creating scoped keys for services”Three identities cover almost every deployment. Because they have different lifecycles, create separate keys for each component instead of sharing one key:
-
Create an administrative key for definition management. Components that apply definitions, such as CI or deploy jobs, require the
adminrole over the indexes they manage:{ "description": "ci", "grants": [{ "role": "admin", "indexes": ["*"] }] }Definitions live in version control, so assign this key to a pipeline rather than an individual.
-
Create a writer key for loading documents. Components that load documents require the
writerrole:{ "description": "product feed", "grants": [{ "role": "writer", "indexes": ["products"] }] }A writer cannot change definitions, preventing a runaway loader from reshaping a schema.
-
Create a reader key for search queries. Components that serve searches, such as your application backend, require the
readerrole scoped to the indexes they query:{ "description": "web backend", "grants": [{ "role": "reader", "indexes": ["products", "articles"] }] }This key has the widest deployment surface and the least privilege.
Scope every key with index patterns. A pattern is a name or a prefix followed by *. For example, use a prefix pattern for per-tenant scoping:
{ "grants": [{ "role": "writer", "indexes": ["tenant-42-*"] }] }Name indexes exactly where possible. A key granted products accesses the index and no generations of it, following the index across rollouts without being able to address or list the generations it moves between. Add products@* only to keys that perform rollouts. For more details, see patterns and generations.
Confirming the configuration
Section titled “Confirming the configuration”To confirm your deployment security setup:
- Verify that your components can authenticate and perform their allowed actions with their assigned keys.
- Once a stored key holds
keys.write, verify that additional nodes start without a root key configured. A node running inkeysmode refuses to start only when it cannot find a root key or a stored key withkeys.write.
Rotating a credential
Section titled “Rotating a credential”To replace the credential of a key while keeping everything the key allows, rotate it:
POST /v1alpha1/admin/keys/{id}/actions/rotateThe response carries the new credential. The key ID, description, grants, and expiry are all kept, so nothing that records the key ID has to change. Update the service that uses the key with the new credential.
The previous credential keeps working on other nodes until their next storage read, within EXOFIND_AUTH_REFRESH_INTERVAL (10s by default). Rotate on a schedule, and after a credential has been exposed.
Replacing what a key allows
Section titled “Replacing what a key allows”What a key allows cannot be changed. To grant a service something else:
-
Create the new key with the required grants.
-
Update the service that uses the key and confirm that it works.
-
Revoke the old key:
DELETE /v1alpha1/admin/keys/{id}
This order ensures that both keys work momentarily during the transition, preventing downtime.
Revocation takes effect immediately on the node that served the request, and on every other node within its EXOFIND_AUTH_REFRESH_INTERVAL. A key leaked into a public repository stops working in seconds.
A node refuses to revoke two keys: the last key granted keys.write when the node has no root key, and the key named by EXOFIND_AUTH_ANONYMOUS_KEY. Create a replacement, or point the configuration elsewhere, and send the request again. For both, see keys that cannot be revoked.
Managing keys does not require reaching a specific node, so both procedures work while no candidate is up to take writes.
To make short-lived credentials expire automatically, set expiresAt when creating the key. Use this for temporary access, such as for a contractor or a one-off migration.
Searching from a browser
Section titled “Searching from a browser”Put your own backend in front of search requests. A key reaches every index its patterns cover and cannot be narrowed per end user, so a page that holds one hands every visitor that reach - see Trust model.
The exception is a page that you permit anyone to search in full, as described in a demo node.
Disabling credential checking
Section titled “Disabling credential checking”Setting EXOFIND_AUTH_MODE=none answers every request as though it were allowed everything. Dev mode runs this way. In any environment reachable by more than your own laptop, this setting allows anyone who can reach the port to delete every index. For both modes, see Modes.
Related
Section titled “Related”- Authentication - Keys, permissions, roles, and the keys API.
- Trust model - What a key reaches, and why it cannot be narrowed per end user.
- Running a public demo node - Answering searches with no credentials on purpose.
- Configuration - The authentication settings and the bootstrap key.
- Generating an API client - Giving a generated client its key.
- Deploying on Kubernetes - Holding keys in a cluster.
Exofind is built by Level Four AB and is available under the Apache License 2.0.