rqlite adds bcrypt passwords to its authentication file
rqlite 4.3.0 accepts bcrypt hashes in its existing credential format. The release retains plaintext compatibility, node-local permissions and a separate need for transport encryption.
A database service can authenticate every request and still keep its passwords in plaintext on disk. Authentication and credential storage solve different problems. rqlite 4.3.0 changes the second part by allowing bcrypt hashes in the same configuration field that already held a password.
The 18 March 2018 release describes security improvements, and the versioned changelog identifies hashed-password support as the change. The implementation preserves the existing JSON credential format and accepts both hashed and plaintext entries.
I like rqlite's small operational requirements. Reusing its credential file fits that approach, but the security properties depend on the verification code as well as the format. In this release, an administrator should understand the compatibility path before treating a stored hash as harmless to disclose.
A credential still combines identity and permissions
The security documentation shipped with 4.3.0 describes HTTP Basic authentication configured through a JSON file. Each entry supplies a username, password and list of permissions. A node receives that file through its authentication option.
The permission vocabulary distinguishes data access from management operations. A user can have query access and status access without receiving execute permission or the ability to remove members. Other permissions cover backup, loading database dumps and joining a cluster.
That distinction remains after the password-storage change. A successful password check establishes which configured user made a request. The requested endpoint still needs the relevant permission. Storing a stronger password representation does not broaden or narrow that user's authorized operations.
The credential store keeps passwords and permissions in separate maps keyed by username. Loading an entry records its password string and builds the set of permission names associated with it. The representation of the password does not change the layout of the permission configuration.
This means a deployment can change a user's stored password representation without redesigning its access model. Existing consumers continue to send credentials through the same authentication mechanism. The server changes how it checks the supplied password against its configuration.
The verification path retains literal comparison
The credential store implementation first looks up the username. An absent user fails the check. For a present user, the supplied password passes if it equals the configured string or if bcrypt verification succeeds.
The second branch calls bcrypt.CompareHashAndPassword. That lets the configuration hold a bcrypt hash while the client supplies the original password. There is no separate JSON property declaring an algorithm, and there is no separate hash field for an administrator to populate.
The first branch preserves compatibility with plaintext passwords. Existing entries still work because their configured string compares equal to the password a client sends. That makes an incremental configuration change possible, with different users using different representations in the same file.
There is also a consequence directly visible in this version's code. Literal equality remains sufficient even when the configured string is a hash. The implementation does not first classify the stored value and then restrict it to a single verification method. The configuration file therefore remains authentication-sensitive, including entries that use bcrypt.
That is an inference from the released comparison expression, not a claim about a separate advisory. It limits what this release alone establishes about protection after configuration disclosure. Hash support should not become a reason to put the credential file somewhere less restricted.
The tests cover mixed representations
The credential-store tests at the release tag load a configuration containing a hashed entry alongside a plaintext entry. They then test requests using the original passwords and reject wrong passwords for both users.
This confirms that mixed operation is intentional. A deployment does not have to convert every entry before the file becomes loadable. It also confirms that a client uses the password represented by the hash in the ordinary authentication path.
The tests separate request parsing from credential verification through a small object that supplies Basic authentication values. That makes the stored-format behavior inspectable without an HTTP server. The relevant contract is whether a username and password pair passes the credential store, independent of how the network transports the pair.
An application integrating this store still has to apply permission checks after identifying the user. The implementation's permission methods explicitly do not perform password verification. A function that answers whether a username has a permission cannot substitute for authenticating the request that supplied the name.
Configuration is local to each node
The security guide states that an authentication file controls the node receiving it. The cluster does not acquire a single shared authentication configuration merely because data replication uses Raft. Each API endpoint needs the intended file.
That distinction affects a client moving among nodes. A credential accepted by one node can fail on another whose configuration differs. A permission intended to be uniform across the cluster needs to be provisioned uniformly, separately from the SQL data managed by the database.
The node-local model also keeps authentication changes outside the database's replicated statements. An operator needs to know which process loaded which file, and which permissions that file grants. This is part of operating the HTTP service, even when the database itself has a small persistent directory.
Hashing does not encrypt the connection
The same guide documents HTTPS for the API and encryption for communication among nodes. Those controls operate at different boundaries from stored-password verification. A hash in the server's file does not encrypt a password supplied by a client.
The API port and the intra-cluster port also have different audiences. The guide recommends limiting the Raft port to cluster nodes and restricting API reachability where possible. A user-facing authentication feature is not a reason to expose the cluster transport to every client.
I regard 4.3.0 as a useful addition to the existing authentication model, with an important compatibility detail to retain in the documentation. Bcrypt verification works within the established file format, permissions remain separate, and each node has its own configuration. The released literal-comparison path means that protecting that file remains necessary even after its password entries have been converted to hashes.