redis: say whether it still holds a consumer's ACL user
The server keeps ACL users in memory only, so a restart forgets every consumer while the provisioner keeps running (hq issue 120). holds() checks ACL GETUSER for the user, enabled, with the mesh's password, so the harness makes a forgotten user again. Needs mesh-sdk 0.1.1.
This commit is contained in:
+22
-1
@@ -8,7 +8,7 @@
|
||||
// order requests were sent, which is what the queue below relies on.
|
||||
|
||||
import { createConnection, type Socket } from "node:net";
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { createHash, randomBytes } from "node:crypto";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
/** A parsed RESP value. Errors are surfaced as rejected commands, not as this type. */
|
||||
@@ -113,6 +113,27 @@ export class RedisClient {
|
||||
await this.command("ACL", "DELUSER", username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether an ACL user exists, is enabled, and accepts exactly this password. Read-only: it asks
|
||||
* `ACL GETUSER`, which answers nil for an unknown user and otherwise a flat list of fields, among
|
||||
* them `flags` and `passwords`, the latter as SHA-256 hex. This server keeps no ACL file, so its
|
||||
* users live in memory and a restart forgets them. This is how the provisioner notices
|
||||
* (novox/hq issue 120).
|
||||
*/
|
||||
async holdsAclUser(username: string, password: string): Promise<boolean> {
|
||||
const reply = await this.command("ACL", "GETUSER", username);
|
||||
if (!Array.isArray(reply)) return false;
|
||||
const field = (name: string): RespValue | undefined => {
|
||||
const i = reply.indexOf(name);
|
||||
return i >= 0 ? reply[i + 1] : undefined;
|
||||
};
|
||||
const flags = field("flags");
|
||||
const passwords = field("passwords");
|
||||
if (!Array.isArray(flags) || !flags.includes("on")) return false;
|
||||
if (!Array.isArray(passwords)) return false;
|
||||
return passwords.includes(createHash("sha256").update(password).digest("hex"));
|
||||
}
|
||||
|
||||
close(): void {
|
||||
if (this.socket) {
|
||||
this.socket.destroy();
|
||||
|
||||
Reference in New Issue
Block a user