src/auth/spec.md
--auth mode)This document provides the specifications for implementing authentication and authorization functionality in Manticore Search. The system includes support for managing users and their credentials, as well as finely-grained permissions defined at the level of individual actions and targets. It ensures compatibility with end-user clients via the MySQL and HTTP protocols, while providing a robust, encrypted binary protocol for secure inter-daemon communication.
MySQL Protocol
mysql_native_password authentication mechanism only.mysql_native_password explicitly.HTTP Protocol
Authorization: Basic <base64(user:password)>).Authorization: Bearer <token>.Binary Protocol (for Inter-Daemon Communication)
searchd --auth) for secure initial administrator setup.password_sha1 for mysql_native_passwordpassword_sha256 for Basic HTTP authenticationbearer_sha256 for HTTP Bearer Tokendata_dir. The configuration must explicitly specify the auth setting.Authentication data is split into two parts:
Structure:
{
"users": [
{
"username": "admin",
"salt": "<unique_salt>",
"hashes": {
"password_sha1_no_salt": "<sha1(password)>",
"password_sha256": "<sha256(salt + password)>",
"bearer_sha256": "<sha256(salt + sha256(token))>"
}
},
{
"username": "readonly",
"salt": "<unique_salt>",
"hashes": {
"password_sha1_no_salt": "<sha1(password)>",
"password_sha256": "<sha256(salt + password)>",
"bearer_sha256": "<sha256(salt + sha256(token))>"
}
},
{
"username": "custom_user",
"salt": "<unique_salt>",
"hashes": {
"password_sha1_no_salt": "<sha1(password)>",
"password_sha256": "<sha256(salt + password)>",
"bearer_sha256": "<sha256(salt + sha256(token))>"
}
}
],
"permissions": [
{
"username": "admin",
"action": "read",
"target": "*",
"allow": true,
"budget": { "queries_per_minute": 1000 }
},
{
"username": "readonly",
"action": "read",
"target": "*",
"allow": true,
"budget": { "queries_per_day": 10000 }
},
{
"username": "custom_user",
"action": "read",
"target": "table/mytable",
"allow": true,
"budget": { "queries_per_minute": 500 }
}
]
}
The budget examples above are stored reference metadata only. They are not enforced as quotas or rate limits in this version.
In RT Mode, authentication data should be stored in system tables with salts and hashes for enhanced security.
Users Table ("system.auth_users"):
Example schema:
CREATE TABLE system.auth_users (
username string,
salt string,
hashes json
);
Permissions Table ("system.auth_permissions"):
Example schema:
CREATE TABLE system.auth_permissions (
username string,
action string,
target string,
allow bool,
budget json
);
Example "system.auth_users" content:
| username | salt | hashes |
|-------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| admin | <unique_salt> | {"password_sha1_no_salt": "<sha1(password)>", "password_sha256": "<sha256(salt + password)>", "bearer_sha256": "<sha256(salt + sha256(token))>"} |
| readonly | <unique_salt> | {"password_sha1_no_salt": "<sha1(password)>", "password_sha256": "<sha256(salt + password)>", "bearer_sha256": "<sha256(salt + sha256(token))>"} |
| custom_user | <unique_salt> | {"password_sha1_no_salt": "<sha1(password)>", "password_sha256": "<sha256(salt + password)>", "bearer_sha256": "<sha256(salt + sha256(token))>"} |
Example "system.auth_permissions" content:
| username | action | target | allow | budget |
|-------------|--------|--------------------|-------|-----------------------------------------|
| admin | read | * | true | {"queries_per_minute":1000} |
| admin | write | * | true | null |
| admin | schema | * | true | null |
| readonly | read | * | true | {"queries_per_day":10000} |
| readonly | write | * | false | null |
| readonly | schema | * | false | null |
| custom_user | read | table/mytable | true | {"queries_per_minute":500} |
| custom_user | write | table/mytable | true | null |
| custom_user | write | table/anothertable | false | null |
Follows the requirements of the mysql/mariadb clients, e.g. https://dev.mysql.com/doc/refman/8.4/en/native-pluggable-authentication.html
password_sha1_no_salt hash in the auth file/table.mysql_native_password authentication mechanism only.mysql_native_password explicitly.Here's the diagram of how it works:
sequenceDiagram
participant Client
participant Server
Server->>Client: Generate random nonce (public_seed) and send to Client
Client->>Client: Compute hash_stage1 = SHA1(password)
Client->>Client: Compute hash_stage2 = SHA1(hash_stage1)
Client->>Client: Compute scramble = XOR(hash_stage1, SHA1(public_seed + hash_stage2))
Client->>Server: Send scramble
Server->>Server: Retrieve stored hash_stage2 (SHA1(SHA1(password)))
Server->>Server: Compute SHA1(public_seed + stored hash_stage2)
Server->>Server: Compute hash_stage1 = XOR(scramble, SHA1(public_seed + stored hash_stage2))
Server->>Server: Compute candidate_hash2 = SHA1(hash_stage1)
Server->>Server: Compare candidate_hash2 with stored hash_stage2
alt Authentication Successful
Server->>Client: Authentication successful
else Authentication Failed
Server->>Client: Authentication failed
end
Authentication supports the following mechanisms:
Basic Auth:
The client provides a username and password in the Authorization header, encoded in Base64.
The server validates the password by comparing its SHA256 (with salt) hash against password_sha256 in the hashes JSON object.
Example:
Request:
GET /search HTTP/1.1
Host: example.com
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
In this example:
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
admin:passwordadmin is the username, and password is the plaintext password.sha256(salt + password) and compares it to the password_sha256 value stored in the hashes column for the admin user.Validation:
hashes JSON for the admin user:
{
"password_sha256": "<sha256(salt + password)>",
"bearer_sha256": "<sha256(salt + sha256(token))>"
}
sha256(salt + password) and ensures it matches the stored password_sha256. If they match, the user is authenticated.Bearer Token:
The client provides a token in the Authorization header using the Bearer scheme.
The server validates the token by hashing it and comparing it to the stored bearer_sha256.
Token Generation:
TOKEN SQL command or the POST /token HTTP endpoint:Authorization header.Storage:
bearer_sha256 = sha256(salt + token)
Request:
GET /search HTTP/1.1
Host: example.com
Authorization: Bearer a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
In this example:
Authorization: Bearer a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2a1b2c3...) is the user's token, obtained earlier using the TOKEN SQL command or the POST /token HTTP endpoint.Validation:
bearer_sha256. If a match is found, the request is considered authorized.The HTTP Authorization header name and the Basic and Bearer scheme names are matched case-insensitively. Usernames are exact-case: app_user and App_User are different users.
Communication via the Manticore binary protocol utilizes a robust, encrypted, and authenticated transport layer designed to ensure confidentiality, integrity, and protection against replay attacks, even when SSL/TLS is not used.
The protocol implements a custom cryptographic scheme known as Mini-TLS, built upon AES-256-GCM (Authenticated Encryption with Associated Data).
For detailed technical specifications, refer to the Specification: Secure Binary Protocol for Daemon Communication.
The binary packets sent over the wire include an unencrypted header (containing command and length) followed by the cryptographic blob:
[Nonce (12 bytes)][Tag (16 bytes)][Ciphertext (variable length)]
If decryption fails (due to wrong key, tampering detected by the GCM tag, or a detected nonce replay attack), the message is rejected. The server replies with a status code indicating an authentication or integrity failure (e.g., STATUS_AUTH_ERROR or similar internal status codes).
In replication clusters, a common cause of decryption/authentication failure is inconsistent auth data for the same username across nodes (for example, the user was created independently on different nodes, producing different key material). This must be treated as an auth-data consistency problem, not as a username/permission resolution problem.
Due to the built-in security features, this protocol is suitable for inter-daemon communication over both trusted and untrusted networks. It replaces the need for an external TLS layer while maintaining equivalent security guarantees for the message payload.
Permissions are defined as individual records. Each record specifies:
username: The user to whom the permission applies.action: One of the defined actions (read, write, schema, admin, replication).target: The object the action applies to (e.g., a table name). * can be used as a wildcard to apply to all targets.allow: A boolean indicating if the action is permitted (true) or denied (false).budget: An optional JSON object stored as reference metadata for possible future resource-limit controls (e.g., queries_per_minute, queries_per_day, cpu_time_per_hour, etc.).If multiple records apply to the same user/action/target, a record with allow = false will deny that action. If allow = true, the action is permitted unless a matching deny exists. Budget data is stored and displayed, but it does not affect authorization enforcement in this version.
The actions read, write, schema, replication and admin map to specific SQL commands, HTTP endpoints and internal commands. Any command or endpoint not listed defaults to being denied unless explicitly granted.
read:
SQL commands that do not modify data or schema:
HTTP endpoints that retrieve data without modification:
write:
SQL commands that modify data or session-level state:
HTTP endpoints that modify data:
schema:
SQL commands that modify schema, global state, or provide insights into the system:
Global variable changes considered schema:
HTTP endpoints that modify schema:
replication:
admin:
SQL commands that manage users and permissions:
HTTP endpoints that manage authentication and authorization:
/sql, /cli, or /cli_json endpoints.POST /token
Authorization header (e.g., Basic Auth).{}).{"token": "<new_token>"}.Notes
admin action are restricted to managing users and permissions. For other actions, such as read, write, or schema, explicit grants are required.system.auth_users and system.auth_permissions are restricted to daemon-internal auth handlers. Users should inspect and manage authentication data through SHOW USERS, SHOW PERMISSIONS, SHOW TOKEN, CREATE USER, DROP USER, GRANT, REVOKE, SET PASSWORD, TOKEN, and RELOAD AUTH. Even users with the admin privilege should not be able to access these tables directly to prevent credential exposure or storage corruption.Matching rules:
restricted_table) or wildcard-based (for example, logs_* or *).Explicit deny takes precedence:
allow = false, the action is denied.Examples:
Rule 1: User readonly is allowed to read on *.
Rule 2: User readonly is denied read on sensitive_table.
Result: Access to sensitive_table is denied, but access to other tables is allowed.
Rule 1: User auditor is denied read on logs_*.
Rule 2: User auditor is allowed read on logs_public.
Result: Access to logs_public is denied because the wildcard deny matches.
Allow applies only when no matching deny exists:
allow = true, the action is allowed.Example:
reporter is allowed to read on reports_*.reporter is allowed to read on reports_public.reports_public is allowed.Default deny:
When a user attempts an action, evaluate permissions in the following order:
Collect All Matching Rules: Identify all rules that apply to the user's action and target, including exact and wildcard target rules.
Apply Matching Denies First:
allow = false, deny the action.Apply Matching Allows:
allow = true, allow the action.Default Deny:
To help administrators understand the system, we should document the rule resolution strategy clearly. Examples and edge cases, such as the following should be included:
allow and deny.--auth mode)To ensure a secure-by-default configuration, Manticore Search provides a command-line bootstrap procedure for creating the initial administrator user. This process must be run after the daemon has been started for the first time.
How it works:
sequenceDiagram
participant User
participant Daemon as Manticore Daemon (Running)
participant Bootstrap as searchd --auth (Client Mode)
User->>Daemon: Starts daemon normally (e.g., `searchd -c manticore.conf`)
Note over Daemon: Daemon is running and creates an empty `auth.json` if needed.
User->>Bootstrap: Runs `searchd -c manticore.conf --auth`
Bootstrap->>User: prompts for "Enter a new administrator login:"
User-->>Bootstrap: Enters login
Bootstrap->>User: prompts for "Enter password:" (twice)
User-->>Bootstrap: Enters password securely
Bootstrap->>Bootstrap: Generates salt and hashes
Bootstrap->>Bootstrap: Writes new admin user and full permissions to `auth.json`
Note over Bootstrap: Fails if `auth.json` is not empty.
Bootstrap->>Daemon: Sends IPC command to trigger `RELOAD AUTH`
Daemon->>Daemon: Receives IPC command and reloads auth data from `auth.json`
Daemon-->>Bootstrap: Sends IPC reply with success/failure status
Bootstrap->>User: Prints "authentication settings successfully created and reloaded"
Process Flow:
searchd process normally. If authentication is enabled, it will run but will not have any users defined.searchd binary with the --auth flag (e.g., sudo -u manticore searchd -c /etc/manticoresearch/manticore.conf --auth).auth.json file (or populates it if it was empty). This process will fail if the file already contains user or permission data, preventing accidental overwrites.RELOAD AUTH command.This one-time procedure is the only supported method for creating the first user, ensuring the system is immediately secured.
For SQL-level semantics of RELOAD AUTH, see SQL Commands for Authentication and Authorization, command Reload Authentication Data.
--auth-non-interactive)For automation (CI/CD, containers, init jobs), searchd also supports non-interactive bootstrap mode:
searchd -c /etc/manticoresearch/manticore.conf --auth-non-interactive
In this mode, credentials are read from standard input as 3 lines:
Example:
printf 'admin\nStrongPass#2026\nStrongPass#2026\n' | searchd -c /etc/manticoresearch/manticore.conf --auth-non-interactive
Recommended for container builds: use Docker BuildKit secrets instead of inline literals.
# syntax=docker/dockerfile:1.7
RUN --mount=type=secret,id=auth_user \
--mount=type=secret,id=auth_pass \
sh -euc '\
searchd -c /etc/manticoresearch/manticore.conf; \
timeout 20 sh -c "until grep -q '\''accepting connections'\'' /var/log/manticore/searchd.log; do sleep 1; done"; \
{ \
cat /run/secrets/auth_user; echo; \
cat /run/secrets/auth_pass; echo; \
cat /run/secrets/auth_pass; echo; \
} | searchd -c /etc/manticoresearch/manticore.conf --auth-non-interactive; \
searchd --stopwait -c /etc/manticoresearch/manticore.conf; \
'
Build command:
DOCKER_BUILDKIT=1 docker build \
--secret id=auth_user,src=./auth_user.txt \
--secret id=auth_pass,src=./auth_pass.txt .
Once the initial administrator is created, all subsequent user and permission management is performed via SQL commands. CREATE USER, DROP USER, GRANT, REVOKE, SHOW USERS, SHOW PERMISSIONS, SHOW TOKEN, SET PASSWORD, and TOKEN are processed natively by the daemon.
This SQL-based approach provides a standardized and powerful interface for all day-to-day administrative tasks, including:
CREATE USER, DROP USER).SET PASSWORD, TOKEN).GRANT, REVOKE).SHOW USERS, SHOW PERMISSIONS).Please refer to the section "SQL Commands for Authentication and Authorization" for a complete list of available commands and their usage.
Create a User Adds a new user with a password.
searchd --auth bootstrap process. This CREATE USER command is intended for creating subsequent, non-admin users.admin permission.CREATE USER '<username>' IDENTIFIED BY '<password>';
token, username, generated_at.user '<username>' already exists.CREATE USER 'readonly' IDENTIFIED BY 'readonlypassword';
Create or update a token Creates a new token for an existing user or updates the current token. The result is the new token.
TOKEN ['<username>'];
admin permission.TOKEN 'readonly';
TOKEN;
Create or update a password Updates the password for an existing user or the current user.
SET PASSWORD '<password>' [FOR '<username>'];
admin permission.SET PASSWORD does not rotate or revoke existing bearer tokens. Use TOKEN or TOKEN '<username>' to rotate bearer access.SET PASSWORD 'abcdef' FOR 'justin';
SET PASSWORD 'abcdef';
Delete a User Deletes a user and their associated permissions.
admin permission.DROP USER '<username>';
<username> does not exist, command fails with user '<username>' not found.DROP USER 'readonly';
Grant a Permission Adds a permission for a specific user.
admin permission.GRANT <action> ON <target> TO '<username>' [WITH ALLOW <0|1> [BUDGET '<json_budget>'] | WITH BUDGET '<json_budget>'];
<action>: READ, WRITE, SCHEMA, REPLICATION, or ADMIN. Users with the ADMIN action can manage users and permissions but require explicit grants for other actions.<target>: The object to which the permission applies. Use either * or '*' for all targets, or specify a table name preceded by the table/ prefix.<action> is ADMIN, <target> must be * (or '*').<username> does not exist, the command fails with user '<username>' not found.<action> is unknown, the command fails with unknown action '<action>'.<action> and <target>, the command fails (budgets do not create a distinct permission key).ALLOW is optional and accepts only 0 or 1:
allow=1.WITH ALLOW 0 creates an explicit deny rule.<json_budget>: Optional JSON reference metadata reserved for future resource-limit controls. It is stored and shown with the permission, but not enforced in this version.GRANT READ ON * TO 'readonly' WITH BUDGET '{"queries_per_day": 10000}';
GRANT READ ON 'restricted_tbl' TO 'readonly' WITH ALLOW 0 BUDGET '{"queries_per_minute": 10}';
GRANT WRITE ON 'mytable' TO 'custom_user';
GRANT ADMIN ON * TO 'security_admin';
Revoke a Permission Removes a specific permission for a user.
admin permission.REVOKE <action> ON <target> FROM '<username>';
<action> is ADMIN, <target> must be * (or '*').<username> does not exist, the command fails with user '<username>' not found.<action> is unknown, the command fails with unknown action '<action>'.user '<username>' does not have '<action>' permission on '<target>'.REVOKE removes the rule; it does not create a deny rule (allow=0).REVOKE READ ON '*' FROM 'readonly';
REVOKE ADMIN ON * FROM 'security_admin';
List All Users Displays all users (admin access required).
SHOW USERS;
+-------------+
| username |
+-------------+
| admin |
| readonly |
| custom_user |
+-------------+
Show Permissions Lists permissions.
SHOW PERMISSIONS;
+-------------+--------+---------------+-------+----------------------------+
| username | action | target | allow | budget |
+-------------+--------+---------------+-------+----------------------------+
| admin | admin | * | true | null |
| readonly | read | * | true | {"queries_per_day": 10000} |
| custom_user | write | table/mytable | true | null |
+-------------+--------+---------------+-------+----------------------------+
custom_user):
+-------------+--------+---------------+-------+--------------------------+
| username | action | target | allow | budget |
+-------------+--------+---------------+-------+--------------------------+
| custom_user | read | table/mytable | true | {"queries_per_day": 500} |
| custom_user | write | table/mytable | true | null |
+-------------+--------+---------------+-------+--------------------------+
Show Permissions for a Specific User Lists permissions for the specified user.
SHOW PERMISSIONS FOR '<username>';
Permission denied.user '<username>' not found.SHOW PERMISSIONS FOR 'custom_user';
SHOW MY PERMISSIONS is not supported.Show Usage Information
SHOW USAGE; displays usage rows for all users.SHOW USAGE FOR '<username>'; displays usage for the target user.SHOW USAGE; shows only the current user’s usage row.SHOW USAGE FOR '<username>'; returns Permission denied.SHOW USAGE;
SHOW USAGE FOR '<username>';
username column is populated.queries_per_min, queries_per_day, and last_login are returned as empty strings until usage counters are implemented.SHOW USAGE FOR '<username>' returns user '<username>' not found.+-------------+-----------------+-----------------+--------------------+
| username | queries_per_min | queries_per_day | last_login |
+-------------+-----------------+-----------------+--------------------+
| admin | | | |
| readonly | | | |
| custom_user | | | |
+-------------+-----------------+-----------------+--------------------+
custom_user):
+-------------+-----------------+-----------------+--------------------+
| username | queries_per_min | queries_per_day | last_login |
+-------------+-----------------+-----------------+--------------------+
| custom_user | | | |
+-------------+-----------------+-----------------+--------------------+
+-------------+-----------------+-----------------+--------------------+
| username | queries_per_min | queries_per_day | last_login |
+-------------+-----------------+-----------------+--------------------+
| custom_user | | | |
+-------------+-----------------+-----------------+--------------------+
SHOW TABLES;
admin:
+-------------+
| table_name |
+-------------+
| 'mytable' |
| 'anothertable' |
| 'thirdtable' |
+-------------+
custom_user:
+-------------+
| table_name |
+-------------+
| 'mytable' |
+-------------+
bearer_sha256) for a specified user or the current user. This is useful for administrative verification.SHOW TOKEN [FOR '<username>' | '<username>'];
SHOW TOKEN: Shows the token hash for the current user.SHOW TOKEN FOR 'some_user': Shows the token hash for the specified user.SHOW TOKEN to see their own token hash.admin permission to run SHOW TOKEN FOR '<username>' to see another user's token hash.+----------+------------------------------------------------------------------+
| Username | Token |
+----------+------------------------------------------------------------------+
| admin | 27f955c72fa08387001c6cb5f83985d7baf002e632e60cdbd0b1985136a366c1 |
+----------+------------------------------------------------------------------+
RELOAD AUTH;
admin permission.auth.json or configured auth file path).RELOAD AUTH is mostly an operational/maintenance command.Notes on ADMIN Action
ADMIN action can only manage users and permissions.ADMIN permissions are global-only and must target *.GRANT ADMIN and REVOKE ADMIN with non-* targets are rejected.READ, WRITE, SCHEMA), explicit grants are required.* and '*' are valid in commands for targets, ensuring flexibility.ADMIN action provides unrestricted access to the SHOW USERS, SHOW PERMISSIONS, and SHOW USAGE commands.auth = 1
auth = 1
auth.json is put to the same directory where we put a binlog by default)
or
auth = /path/to/file
Password quality requirements are controlled by the following configuration options:
auth_password_policy
LOW: applies minimum length and non-empty checks.MEDIUM: applies LOW plus complexity checks (at least one lowercase, one uppercase, one digit, and one non-alphanumeric character).LOW.auth_password_min_length
8.The same password policy must be applied consistently by all password-setting entry points:
searchd --auth bootstrap flow (initial admin password)CREATE USER ... IDENTIFIED BY ...SET PASSWORD ...If validation fails, the command must return a validation error that explains which policy rule failed.
If the system.auth_users and system.auth_permissions tables (RT Mode) or the authentication file (Plain Mode) do not exist, Manticore should create them. If they already exist, Manticore should validate them during startup. If validation fails, Manticore should not start.
system.auth_users and system.auth_permissions with the cluster’s version.searchd log as a backup.CREATE CLUSTER, JOIN CLUSTER, DELETE CLUSTER, and ALTER CLUSTER) leverage a special permission action called replication.(username + matching stored auth material). Username equality alone does not guarantee successful inter-node authentication.Terms:
user field).User resolution rules (initial_cluster_user model):
CREATE CLUSTER:
'<username>' AS user if provided, otherwise session user.JOIN CLUSTER:
'<username>' AS user if provided, otherwise session user.DELETE CLUSTER, ALTER CLUSTER ... ADD, ALTER CLUSTER ... DROP, ALTER CLUSTER ... UPDATE nodes:
ALTER CLUSTER <cluster_name> UPDATE user '<username>':
'<username>' is the new cluster user value.Open delegation model remains in effect:
CREATE CLUSTER / JOIN CLUSTER, or set a new cluster user via ALTER ... UPDATE user.user field) in the internal config (manticore.json).user) is loaded from the internal config and used to initialize replication clusters.CREATE CLUSTER and JOIN CLUSTER are the only statements that may resolve effective replication user from session user when statement user is not specified.replication action). If validation fails, startup of that cluster must fail with an authorization error.JOIN CLUSTER persists cluster metadata immediately.The CREATE CLUSTER command now allows specifying a user who will own and manage the cluster. The specified user must have the replication action, as it is required for performing internal replication operations.
Syntax:
CREATE CLUSTER <cluster_name> ['<username>' AS user]
Validation:
user is specified, that user must have the replication action.user is not specified, the session user must have the replication action.Error Message:
User '<username>' is not permitted to do the "replication" action with the target.
The JOIN CLUSTER command allows a node to join an existing cluster and optionally specifies the user whose credentials will authenticate the operation. This user must also have the replication action.
Syntax:
JOIN CLUSTER <cluster_name> AT '<ip:port>' ['<username>' AS user]
Validation:
CREATE CLUSTER command (effective replication user rules for statement execution).The DELETE CLUSTER command removes the cluster.
Syntax:
DELETE CLUSTER <cluster_name>
Not supported:
DELETE CLUSTER <cluster_name> '<username>' AS userValidation:
The ALTER CLUSTER command supports index membership changes, node-list refresh, and cluster-user reassignment.
Syntax:
ALTER CLUSTER <cluster_name> ADD <table_or_tables>
ALTER CLUSTER <cluster_name> DROP <table_or_tables>
ALTER CLUSTER <cluster_name> UPDATE nodes
ALTER CLUSTER <cluster_name> UPDATE user '<username>'
ALTER CLUSTER ... UPDATE user '<username>' is the only supported form for reassigning a cluster's effective replication user.
Not supported:
ALTER CLUSTER <cluster_name> ADD ... '<username>' AS userALTER CLUSTER <cluster_name> DROP ... '<username>' AS userALTER CLUSTER <cluster_name> UPDATE nodes '<username>' AS userALTER CLUSTER <cluster_name> UPDATE '<username>' AS userValidation:
ADD, DROP, and UPDATE nodes, effective replication user is the persisted cluster user.UPDATE user '<username>', the new assigned user must have the replication action.Error Message:
User '<username>' is not permitted to do the "replication" action with the target.
Manticore Buddy and the Manticore Search daemon communicate via a secure HTTPS channel. Authentication is handled using a standard bearer token model, where Buddy acts as a highly privileged user. The daemon uses a unified process to authenticate all requests it receives.
sequenceDiagram
participant SQLClient as SQL Client
participant ManticoreSearch as Manticore Search
participant Buddy as Manticore Buddy
participant EndUserClient as User's Client
Note over ManticoreSearch: On start, generates and holds BUDDY_TOKEN.
ManticoreSearch->>Buddy: Starts Buddy, passing BUDDY_TOKEN via env var.
alt Delegated Command Path
EndUserClient->>ManticoreSearch: Send request with `Authorization: Bearer <user_token>`
Note over ManticoreSearch: Authenticates user and resolves delegated identity (`user`)
ManticoreSearch->>Buddy: Delegate command with `user`
Buddy->>Buddy: Rewrites/prepares command for daemon
Buddy->>ManticoreSearch: Execute rewritten command with `Authorization: Bearer <BUDDY_TOKEN>` and optional `X-Manticore-User`
ManticoreSearch->>ManticoreSearch: Authenticates Buddy token, authorizes as delegated `user`, executes command
ManticoreSearch-->>Buddy: Return success/error
ManticoreSearch->>EndUserClient: Return final result
end
Token Initialization for Buddy User:
BUDDY_TOKEN along with SSL materials via environment variables: BUDDY_SSL_CERT_CONTENT, and BUDDY_SSL_KEY_CONTENT.Token Usage and Secure Communication:
Authorization header containing the raw token it received at startup:
Authorization: Bearer <BUDDY_TOKEN>
system.auth_users table. The manticore_buddy user must have the required permissions for the operation to succeed.Delegated Command Identity:
user.Authorization: Bearer <BUDDY_TOKEN> (always)X-Manticore-User: <username> only when incoming payload user is non-emptyuser is empty, Buddy must omit X-Manticore-User.Authorization:
X-Manticore-User is present, daemon must authorize the command against that delegated user identity.X-Manticore-User is absent, daemon must treat the request as a non-delegated Buddy request.Security:
BUDDY_TOKEN, BUDDY_SSL_CERT_CONTENT, BUDDY_SSL_KEY_CONTENT) from its own process environment immediately after reading them at startup. As it is impossible to clear child process environment from the parent process with c++ code.All changes and significant events related to authentication and authorization are recorded in a dedicated, human-readable log file. This log is crucial for security auditing, troubleshooting access issues, and monitoring administrative actions.
The authentication log's behavior is controlled by settings in the searchd section of your Manticore configuration file.
1. Log File Location:
The authentication log is automatically created alongside the main searchd log file, with an .auth suffix.
log is set to /var/log/manticore/searchd.log, the authentication log will be located at /var/log/manticore/searchd.log.auth.2. Log Level (auth_log_level):
This setting controls the verbosity of the authentication log.
auth_log_level = <level>infodisabled: No authentication events are logged.error: Logs only critical failures and permission denials.warning: Logs errors plus failed authentication attempts.info: Logs warnings plus all successful administrative changes. This is the recommended level for most production environments.all: Logs info events plus successful user-facing authentication events.trace: Logs all events plus successful internal transport authentication, such as Manticore Buddy and daemon-to-daemon API authentication.Successful authorization allow checks are intentionally not logged at any level. Permission denials are logged, but allow checks can happen for every query and would make the authentication log noisy even in trace mode.
Each line in the authentication log follows a consistent format, providing clear context for every event:
[Timestamp][ThreadID][LEVEL] Log Message
TRACE, ALL, INFO, WARN, ERROR, CRITICAL).The log captures a comprehensive set of events, which can be grouped into the following categories. The log level at which each event is recorded is shown in parentheses.
1. User and Permission Management (INFO)
Tracks all administrative changes to the authentication system, always including which user performed the action and from where.
User creation and deletion.
Bearer token regeneration.
Granting or revoking permissions.
Example: [...][INFO] granted read on 'my_index' to user 'readonly_user' by 'admin' via SphinxQL
2. Security and Access Events Tracks real-time access attempts and the enforcement of permissions.
ALL): Records when a user successfully logs in, including the method (HTTP, MySQL, etc.) and source IP.
Example: [...][ALL] user 'admin' successfully authenticated via HTTP Basic from 127.0.0.1TRACE): Records successful Manticore Buddy and daemon-to-daemon API authentication. Failed internal authentication attempts stay at WARN.WARN): Records any failed login attempt, including the reason (e.g., unknown user, invalid password).
Example: [...][WARN] failed authentication attempt for user 'admin' via HTTP Basic from 192.168.1.50: invalid passwordERROR): Records when an authenticated user is denied access to a resource due to insufficient permissions.
Example: [...][ERROR] user 'readonly_user' from 127.0.0.1 denied write on 'my_index'3. System and Cluster Events Tracks high-level changes to the authentication state.
INFO): Logs when the authentication configuration is successfully reloaded.CRITICAL): A high-priority message is logged when a node joins a cluster and its local authentication data is about to be overwritten.INFO): When joining a cluster, the node's original authentication data is dumped to the log as a JSON backup before being replaced.WARN): Any administrative action that fails (e.g., trying to create a duplicate user) is logged with an error reason.WARN): If internal replication API auth fails because nodes have inconsistent auth material for the same username, a warning is logged (for example, GCM authentication failed (bad tag)), and related cluster operation failures are expected. When authentication is enabled, donor-user fetch failures include a safe client-facing hint to verify the replication user and matching auth data on donor nodes and inspect searchd.log.auth.This section provides guidance for client library developers and users on how to interact with a Manticore Search instance that has authentication enabled.
All standard Manticore Search clients that communicate over the MySQL or HTTP protocols are fully compatible with the authentication system.
HTTP Clients (Official and Third-Party):
Authorization header.Authorization: Basic <base64(user:password)>.Authorization: Bearer <token>.https for all connections to protect credentials.MySQL Clients (Official and Third-Party):
mysql_native_password authentication mechanism.The secure binary protocol described in this specification is designed exclusively for inter-daemon communication (e.g., between a master and agents in a replication cluster). It is not intended for use by general-purpose, third-party client libraries (e.g., from PHP, Python, Java, etc.).
Why can't standard clients use it?
Guidance for Users of Binary Client Libraries: