- kaya backend with OIDC sessions, API tokens, Postgres/Tortoise models - AES-256-GCM private key storage and full certificate/CSR/CRL domain logic - Sycamore/WASM SPA for vaults, keys, requests, certificates, CRLs and templates - imports/exports, XCA .xdb migration, Docker Compose stack and tests
288 lines
14 KiB
Python
288 lines
14 KiB
Python
from tortoise import BaseDBAsyncClient
|
|
|
|
RUN_IN_TRANSACTION = True
|
|
|
|
|
|
async def upgrade(db: BaseDBAsyncClient) -> str:
|
|
return """
|
|
CREATE TABLE IF NOT EXISTS "api_token" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"user_sub" VARCHAR(255) NOT NULL,
|
|
"name" VARCHAR(100) NOT NULL,
|
|
"token_prefix" VARCHAR(16) NOT NULL,
|
|
"token_hash" VARCHAR(64) NOT NULL UNIQUE,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"last_used_at" TIMESTAMPTZ,
|
|
"expires_at" DATE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_api_token_user_su_7c5de7" ON "api_token" ("user_sub");
|
|
COMMENT ON TABLE "api_token" IS 'Personal access token for programmatic API access.';
|
|
CREATE TABLE IF NOT EXISTS "app_user" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"sub" VARCHAR(255) NOT NULL UNIQUE,
|
|
"display_name" VARCHAR(200) NOT NULL,
|
|
"name" VARCHAR(255),
|
|
"family_name" VARCHAR(255),
|
|
"given_name" VARCHAR(255),
|
|
"middle_name" VARCHAR(255),
|
|
"nickname" VARCHAR(255),
|
|
"preferred_username" VARCHAR(255),
|
|
"profile" VARCHAR(2048),
|
|
"picture" VARCHAR(2048),
|
|
"website" VARCHAR(2048),
|
|
"gender" VARCHAR(100),
|
|
"birthdate" VARCHAR(32),
|
|
"zoneinfo" VARCHAR(100),
|
|
"locale" VARCHAR(100),
|
|
"updated_at" BIGINT,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"last_seen_at" TIMESTAMPTZ NOT NULL
|
|
);
|
|
COMMENT ON TABLE "app_user" IS 'One OIDC identity that has logged in at least once.';
|
|
CREATE TABLE IF NOT EXISTS "vault" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"owner_sub" VARCHAR(255) NOT NULL,
|
|
"name" VARCHAR(200) NOT NULL,
|
|
"description" TEXT NOT NULL,
|
|
"settings" JSONB NOT NULL,
|
|
"version" INT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_vault_owner_s_cdc1f8" ON "vault" ("owner_sub");
|
|
COMMENT ON TABLE "vault" IS 'One private XCA database owned by an OIDC user.';
|
|
CREATE TABLE IF NOT EXISTS "key" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"name" VARCHAR(200) NOT NULL,
|
|
"comment" TEXT NOT NULL,
|
|
"source" VARCHAR(20) NOT NULL,
|
|
"key_type" VARCHAR(20) NOT NULL,
|
|
"key_size" INT,
|
|
"curve" VARCHAR(100),
|
|
"public_der" BYTEA NOT NULL,
|
|
"public_key_sha256" VARCHAR(64) NOT NULL,
|
|
"private_der" BYTEA,
|
|
"private_nonce" BYTEA,
|
|
"has_private" BOOL NOT NULL,
|
|
"version" INT NOT NULL,
|
|
"search_text" TEXT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE,
|
|
CONSTRAINT "uid_key_vault_i_e0ffb5" UNIQUE ("vault_id", "public_key_sha256")
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_key_public__eba47e" ON "key" ("public_key_sha256");
|
|
CREATE INDEX IF NOT EXISTS "idx_key_vault_i_a6f27f" ON "key" ("vault_id", "name");
|
|
CREATE INDEX IF NOT EXISTS "idx_key_vault_i_c2e997" ON "key" ("vault_id", "key_type");
|
|
COMMENT ON TABLE "key" IS 'A public or private key item.';
|
|
CREATE TABLE IF NOT EXISTS "request" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"name" VARCHAR(200) NOT NULL,
|
|
"comment" TEXT NOT NULL,
|
|
"source" VARCHAR(20) NOT NULL,
|
|
"subject_der" BYTEA NOT NULL,
|
|
"req_der" BYTEA NOT NULL,
|
|
"public_key_der" BYTEA NOT NULL,
|
|
"request_sha256" VARCHAR(64) NOT NULL,
|
|
"signed" BOOL NOT NULL,
|
|
"signed_at" TIMESTAMPTZ,
|
|
"attributes" JSONB NOT NULL,
|
|
"version" INT NOT NULL,
|
|
"search_text" TEXT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"key_id" UUID REFERENCES "key" ("id") ON DELETE SET NULL,
|
|
"vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE,
|
|
CONSTRAINT "uid_request_vault_i_b661f4" UNIQUE ("vault_id", "request_sha256")
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_request_request_fad061" ON "request" ("request_sha256");
|
|
CREATE INDEX IF NOT EXISTS "idx_request_vault_i_346e22" ON "request" ("vault_id", "name");
|
|
CREATE INDEX IF NOT EXISTS "idx_request_vault_i_2cd9ef" ON "request" ("vault_id", "signed");
|
|
COMMENT ON TABLE "request" IS 'A PKCS#10 certificate signing request item.';
|
|
CREATE TABLE IF NOT EXISTS "certificate" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"name" VARCHAR(200) NOT NULL,
|
|
"comment" TEXT NOT NULL,
|
|
"source" VARCHAR(20) NOT NULL,
|
|
"serial_hex" VARCHAR(128) NOT NULL,
|
|
"subject_der" BYTEA NOT NULL,
|
|
"issuer_der" BYTEA NOT NULL,
|
|
"subject_hash" VARCHAR(64) NOT NULL,
|
|
"issuer_hash" VARCHAR(64) NOT NULL,
|
|
"not_before" TIMESTAMPTZ NOT NULL,
|
|
"not_after" TIMESTAMPTZ NOT NULL,
|
|
"is_ca" BOOL NOT NULL,
|
|
"path_length" INT,
|
|
"cert_der" BYTEA NOT NULL,
|
|
"public_key_der" BYTEA NOT NULL,
|
|
"signature_algorithm" VARCHAR(100) NOT NULL,
|
|
"fingerprint_md5" VARCHAR(32) NOT NULL,
|
|
"fingerprint_sha1" VARCHAR(40) NOT NULL,
|
|
"fingerprint_sha256" VARCHAR(64) NOT NULL,
|
|
"version" INT NOT NULL,
|
|
"search_text" TEXT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"issuer_id" UUID REFERENCES "certificate" ("id") ON DELETE SET NULL,
|
|
"key_id" UUID REFERENCES "key" ("id") ON DELETE SET NULL,
|
|
"request_id" UUID REFERENCES "request" ("id") ON DELETE SET NULL,
|
|
"vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE,
|
|
CONSTRAINT "uid_certificate_vault_i_842384" UNIQUE ("vault_id", "fingerprint_sha256")
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_serial__787fd1" ON "certificate" ("serial_hex");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_subject_ed411b" ON "certificate" ("subject_hash");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_issuer__b8daa0" ON "certificate" ("issuer_hash");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_is_ca_906cf3" ON "certificate" ("is_ca");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_fingerp_12be2c" ON "certificate" ("fingerprint_sha256");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_vault_i_18b9a0" ON "certificate" ("vault_id", "name");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_vault_i_dfb18f" ON "certificate" ("vault_id", "issuer_id");
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_vault_i_eded8f" ON "certificate" ("vault_id", "not_after");
|
|
COMMENT ON TABLE "certificate" IS 'An X.509 certificate item.';
|
|
CREATE TABLE IF NOT EXISTS "certificate_revocation" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"serial_hex" VARCHAR(128) NOT NULL,
|
|
"revoked_at" TIMESTAMPTZ NOT NULL,
|
|
"invalidity_date" TIMESTAMPTZ,
|
|
"reason" VARCHAR(50) NOT NULL,
|
|
"crl_number" INT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"ca_id" UUID NOT NULL REFERENCES "certificate" ("id") ON DELETE CASCADE,
|
|
CONSTRAINT "uid_certificate_ca_id_1c9aa5" UNIQUE ("ca_id", "serial_hex")
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_certificate_serial__8fa20f" ON "certificate_revocation" ("serial_hex");
|
|
COMMENT ON TABLE "certificate_revocation" IS 'A serial revoked by a CA (XCA stores revocations on the CA).';
|
|
CREATE TABLE IF NOT EXISTS "crl" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"name" VARCHAR(200) NOT NULL,
|
|
"comment" TEXT NOT NULL,
|
|
"source" VARCHAR(20) NOT NULL,
|
|
"crl_der" BYTEA NOT NULL,
|
|
"crl_hash" VARCHAR(64) NOT NULL,
|
|
"crl_number" INT,
|
|
"last_update" TIMESTAMPTZ NOT NULL,
|
|
"next_update" TIMESTAMPTZ,
|
|
"revoked_count" INT NOT NULL,
|
|
"signature_algorithm" VARCHAR(100) NOT NULL,
|
|
"search_text" TEXT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"issuer_id" UUID REFERENCES "certificate" ("id") ON DELETE SET NULL,
|
|
"vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE,
|
|
CONSTRAINT "uid_crl_vault_i_e5461a" UNIQUE ("vault_id", "crl_hash")
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_crl_crl_has_c44d61" ON "crl" ("crl_hash");
|
|
CREATE INDEX IF NOT EXISTS "idx_crl_vault_i_6af15c" ON "crl" ("vault_id", "name");
|
|
CREATE INDEX IF NOT EXISTS "idx_crl_vault_i_576344" ON "crl" ("vault_id", "issuer_id");
|
|
COMMENT ON TABLE "crl" IS 'A certificate revocation list item.';
|
|
CREATE TABLE IF NOT EXISTS "template" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"name" VARCHAR(200) NOT NULL,
|
|
"comment" TEXT NOT NULL,
|
|
"source" VARCHAR(20) NOT NULL,
|
|
"subject" JSONB NOT NULL,
|
|
"settings" JSONB NOT NULL,
|
|
"version" INT NOT NULL,
|
|
"search_text" TEXT NOT NULL,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "idx_template_vault_i_18d8f5" ON "template" ("vault_id", "name");
|
|
COMMENT ON TABLE "template" IS 'An XCA-style template: subject + extension/validity defaults.';
|
|
CREATE TABLE IF NOT EXISTS "authority" (
|
|
"id" UUID NOT NULL PRIMARY KEY,
|
|
"crl_expire" TIMESTAMPTZ,
|
|
"crl_number" INT NOT NULL,
|
|
"crl_days" INT NOT NULL,
|
|
"tls_auth_key" BYTEA,
|
|
"tls_auth_key_nonce" BYTEA,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"template_id" UUID REFERENCES "template" ("id") ON DELETE SET NULL,
|
|
"certificate_id" UUID NOT NULL UNIQUE REFERENCES "certificate" ("id") ON DELETE CASCADE
|
|
);
|
|
COMMENT ON TABLE "authority" IS 'CA-specific properties, one row per CA certificate.';
|
|
CREATE TABLE IF NOT EXISTS "aerich" (
|
|
"id" SERIAL NOT NULL PRIMARY KEY,
|
|
"version" VARCHAR(255) NOT NULL,
|
|
"app" VARCHAR(100) NOT NULL,
|
|
"content" JSONB NOT NULL
|
|
);"""
|
|
|
|
|
|
async def downgrade(db: BaseDBAsyncClient) -> str:
|
|
return """
|
|
"""
|
|
|
|
|
|
MODELS_STATE = (
|
|
"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"
|
|
)
|