August 7, 2022·4 min read·engineeringrqliteauthorizationnetworking

rqlite checks credentials across forwarded requests

rqlite 7.6.1 applies credential checks to intra-cluster query and execute requests. It also rejects unspecified advertised addresses before a node starts with unusable contact information.

A request can arrive at one database node and execute on another. Authorization needs to survive that transition. rqlite 7.6.1, released on August 7, corrects credential checking for intra-cluster communication. The tagged changelog identifies the repair alongside validation of advertised network addresses.

These changes concern the boundaries between nodes. One governs whether a forwarded operation has the required authority. The other governs whether a node has supplied an address peers can use. I value rqlite's compact distributed design, and these boundaries deserve explicit handling even when the cluster is small. A trusted-looking network path does not itself describe which database operation a caller may perform.

The receiving service checks the command

The cluster service in 7.6.1 accepts commands carrying optional credentials. Its credential-store interface provides AA, described as authenticating a username and password and checking a permission. The receiving service invokes that operation for the command it is about to execute.

For an execute command, the service first requires a non-NULL execute request. It then checks the execute permission before invoking the database. Failure produces an unauthorized error in the command response. Query commands follow the corresponding structure with the query permission.

This locates the decision at the point where the remote operation reaches the database service. The receiving node does not simply assume that another node's connection represents sufficient authorization for every payload. It checks the identity and requested capability through its configured credential store.

If no credential store is configured, the check returns true. The implementation therefore preserves the distinction between a deployment with authentication enabled and one that intentionally has no such checks. The release does not create credentials automatically or turn an unconfigured deployment into an authenticated one.

HTTP credentials accompany the forwarded operation

The HTTP service implementation extracts Basic authentication values when forwarding ordinary execute and query requests. It constructs cluster credentials from the username and password and passes them to the cluster client with the request. The remote service can then evaluate the same caller identity at the execution boundary.

The HTTP layer also translates a remote unauthorized error into HTTP 401. Its messages distinguish remote execute authorization from remote query authorization. That gives a caller a result reflecting the rejected operation, rather than treating a reachable cluster connection as proof that the database command succeeded.

This is a concrete example of preserving security context through an internal request. The first node's API and the second node's execution service are different interfaces. Carrying the credentials connects the caller's identity across them, while the receiver's permission check connects that identity to the command type.

The check is operation-specific. A credential with query permission is not automatically an execute credential. A distributed forwarding mechanism must retain that distinction even when both requests share the same transport and serialization machinery. The source shows separate authorization checks before either database method runs.

Missing credentials have a defined path

The cluster service initializes empty username and password values when a command has no credentials. If credentials are present, it reads their values before calling the store's authentication-and-authorization method. This makes absence part of the decision rather than silently substituting an unrestricted identity.

The resulting behavior depends on the configured credential policy. The receiving service supplies the values and required permission to that policy. It does not invent a successful user identity merely because the command arrived over the inter-node connection.

That separation is useful when diagnosing a request that works locally but fails when forwarded. The route can affect which node performs the check, so nodes need compatible configuration for the intended operation. The implementation supplies a remote unauthorized response rather than hiding the second check behind a generic execution failure.

Binding and advertising have different meanings

The same release rejects invalid advertised Raft and HTTP addresses at startup. Its configuration validation code splits host and port, parses numeric hosts, and rejects unspecified IP addresses. An error identifies the advertised address and the relevant configuration options.

An unspecified address can be meaningful as a local listener configuration. It does not identify a particular endpoint that another machine should contact. Confusing a bind address with an advertised address can leave a process listening successfully while publish unusable contact information to its peers.

The validation has a precise scope. It checks whether an explicitly numeric advertised host is unspecified. It does not prove that every accepted hostname resolves correctly or that every accepted address is reachable across the deployment's network. The startup check catches a known invalid category without replacing network operation with a claim of universal routability.

Rejecting that category early gives the operator a configuration failure at launch. The alternative is a node whose process appears started but whose peers receive contact information that cannot serve its intended purpose. The difference improves the relationship between startup success and a minimally coherent advertised identity.

These checks also preserve hostname-based configuration. The validator does not resolve every name and replace it with a startup-time IP. That is consistent with retaining names as network identifiers, while rejecting numeric values that explicitly mean an unspecified local address. Validation and name resolution retain separate roles in the configuration path.

Both repairs make internal boundaries explicit

The credential change and the advertised-address check address different failure modes. A valid address does not authorize an operation. A valid credential does not make an unusable address reachable. Each requirement belongs to the part of the inter-node path that can evaluate it.

I consider the authorization repair particularly important because forwarding is part of the normal service design. A client should not acquire a different effective permission merely because one node delegates execution to another. Version 7.6.1 carries the caller's credentials through that delegation and checks the required capability before the receiving service invokes the database.