mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-07 23:30:07 +09:00
db: store all credentials in one SHA-256-hashed table
API keys, pre-auth keys and OAuth clients/tokens share one table and verify path. Secrets carry 256 bits of crypto/rand entropy, so a SHA-256 digest needs no stretching; bcrypt/argon2id rows rehash on use until 0.32.
This commit is contained in:
committed by
Kristoffer Dalby
parent
e90500e3a9
commit
393dd3e2d9
+20
-51
@@ -38,67 +38,35 @@ CREATE UNIQUE INDEX idx_provider_identifier ON users(provider_identifier) WHERE
|
||||
CREATE UNIQUE INDEX idx_name_provider_identifier ON users(name, provider_identifier);
|
||||
CREATE UNIQUE INDEX idx_name_no_provider_identifier ON users(name) WHERE provider_identifier IS NULL;
|
||||
|
||||
CREATE TABLE pre_auth_keys(
|
||||
-- Unified store for every authenticatable secret (API keys, pre-auth keys,
|
||||
-- OAuth clients and access tokens), discriminated by kind. Only a hash of the
|
||||
-- secret is stored (SHA-256; legacy bcrypt/Argon2id until next use); identifier
|
||||
-- is the public lookup value, unique within a kind. Per-kind columns are sparse
|
||||
-- by design.
|
||||
CREATE TABLE credentials(
|
||||
id integer PRIMARY KEY AUTOINCREMENT,
|
||||
key text,
|
||||
prefix text,
|
||||
kind text NOT NULL CHECK(kind IN ('api','authkey','oauth_client','oauth_token')),
|
||||
identifier text,
|
||||
hash blob,
|
||||
user_id integer,
|
||||
description text,
|
||||
scopes text,
|
||||
tags text,
|
||||
reusable numeric,
|
||||
ephemeral numeric DEFAULT false,
|
||||
used numeric DEFAULT false,
|
||||
tags text,
|
||||
last_seen datetime,
|
||||
client_id text,
|
||||
created_at datetime,
|
||||
expiration datetime,
|
||||
revoked datetime,
|
||||
|
||||
created_at datetime,
|
||||
|
||||
CONSTRAINT fk_pre_auth_keys_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL
|
||||
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
||||
CONSTRAINT chk_credentials_hash_format CHECK(hash IS NULL OR substr(CAST(hash AS TEXT), 1, 1) = '$')
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_pre_auth_keys_prefix ON pre_auth_keys(prefix) WHERE prefix IS NOT NULL AND prefix != '';
|
||||
|
||||
CREATE TABLE api_keys(
|
||||
id integer PRIMARY KEY AUTOINCREMENT,
|
||||
prefix text,
|
||||
hash blob,
|
||||
user_id integer,
|
||||
expiration datetime,
|
||||
last_seen datetime,
|
||||
|
||||
created_at datetime
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_api_keys_prefix ON api_keys(prefix);
|
||||
|
||||
-- OAuth 2.0 client-credentials clients for the v2 API. client_id is public and
|
||||
-- embedded in the secret (hskey-client-<client_id>-<secret>); only the bcrypt
|
||||
-- hash of the secret is stored. Mirrors the api_keys security model.
|
||||
CREATE TABLE oauth_clients(
|
||||
id integer PRIMARY KEY AUTOINCREMENT,
|
||||
client_id text,
|
||||
secret_hash blob,
|
||||
scopes text,
|
||||
tags text,
|
||||
description text,
|
||||
user_id integer,
|
||||
created_at datetime,
|
||||
revoked datetime
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_oauth_clients_client_id ON oauth_clients(client_id);
|
||||
|
||||
-- Short-lived bearer access tokens minted by an oauth_client. Stored as a bcrypt
|
||||
-- hash of the secret, looked up by prefix.
|
||||
CREATE TABLE oauth_access_tokens(
|
||||
id integer PRIMARY KEY AUTOINCREMENT,
|
||||
prefix text,
|
||||
hash blob,
|
||||
client_id text,
|
||||
scopes text,
|
||||
tags text,
|
||||
expiration datetime,
|
||||
created_at datetime
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_oauth_access_tokens_prefix ON oauth_access_tokens(prefix);
|
||||
CREATE UNIQUE INDEX idx_credentials_identifier ON credentials(kind, identifier);
|
||||
CREATE INDEX idx_credentials_user_id ON credentials(user_id);
|
||||
|
||||
CREATE TABLE nodes(
|
||||
id integer PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -127,8 +95,9 @@ CREATE TABLE nodes(
|
||||
deleted_at datetime,
|
||||
|
||||
CONSTRAINT fk_nodes_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_nodes_auth_key FOREIGN KEY(auth_key_id) REFERENCES pre_auth_keys(id)
|
||||
CONSTRAINT fk_nodes_auth_key FOREIGN KEY(auth_key_id) REFERENCES credentials(id)
|
||||
);
|
||||
CREATE INDEX idx_nodes_auth_key_id ON nodes(auth_key_id);
|
||||
|
||||
CREATE TABLE policies(
|
||||
id integer PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
Reference in New Issue
Block a user