feat: pki and ssh setup for instance proxy

This commit is contained in:
Sheen Capadngan
2025-08-26 03:02:34 +08:00
parent b3002d784e
commit cc34b92d56
15 changed files with 703 additions and 3 deletions
@@ -0,0 +1,78 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
export async function up(knex: Knex): Promise<void> {
if (!(await knex.schema.hasTable(TableName.InstanceProxyConfig))) {
await knex.schema.createTable(TableName.InstanceProxyConfig, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.timestamps(true, true, true);
// Root CA for proxy PKI
t.binary("encryptedRootProxyPkiCaPrivateKey").notNullable();
t.binary("encryptedRootProxyPkiCaCertificate").notNullable();
// Instance CA for proxy PKI
t.binary("encryptedInstanceProxyPkiCaPrivateKey").notNullable();
t.binary("encryptedInstanceProxyPkiCaCertificate").notNullable();
t.binary("encryptedInstanceProxyPkiCaCertificateChain").notNullable();
// Instance client/server intermediates for proxy PKI
t.binary("encryptedInstanceProxyPkiClientCaPrivateKey").notNullable();
t.binary("encryptedInstanceProxyPkiClientCaCertificate").notNullable();
t.binary("encryptedInstanceProxyPkiClientCaCertificateChain").notNullable();
t.binary("encryptedInstanceProxyPkiServerCaPrivateKey").notNullable();
t.binary("encryptedInstanceProxyPkiServerCaCertificate").notNullable();
t.binary("encryptedInstanceProxyPkiServerCaCertificateChain").notNullable();
// Org Parent CAs for proxy
t.binary("encryptedOrgProxyPkiCaPrivateKey").notNullable();
t.binary("encryptedOrgProxyPkiCaCertificate").notNullable();
t.binary("encryptedOrgProxyPkiCaCertificateChain").notNullable();
// Instance SSH CAs for proxy
t.binary("encryptedInstanceProxySshClientCaPrivateKey").notNullable();
t.binary("encryptedInstanceProxySshClientCaPublicKey").notNullable();
t.binary("encryptedInstanceProxySshServerCaPrivateKey").notNullable();
t.binary("encryptedInstanceProxySshServerCaPublicKey").notNullable();
});
await createOnUpdateTrigger(knex, TableName.InstanceProxyConfig);
}
// Org-level proxy configuration (one-to-one with organization)
if (!(await knex.schema.hasTable(TableName.OrgProxyConfig))) {
await knex.schema.createTable(TableName.OrgProxyConfig, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.timestamps(true, true, true);
t.uuid("orgId").notNullable().unique();
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
// Org-scoped proxy PKI (client + server)
t.binary("encryptedProxyPkiClientCaPrivateKey").notNullable();
t.binary("encryptedProxyPkiClientCaCertificate").notNullable();
t.binary("encryptedProxyPkiClientCaCertificateChain").notNullable();
t.binary("encryptedProxyPkiServerCaPrivateKey").notNullable();
t.binary("encryptedProxyPkiServerCaCertificate").notNullable();
t.binary("encryptedProxyPkiServerCaCertificateChain").notNullable();
// Org-scoped proxy SSH (client + server)
t.binary("encryptedProxySshClientCaPrivateKey").notNullable();
t.binary("encryptedProxySshClientCaPublicKey").notNullable();
t.binary("encryptedProxySshServerCaPrivateKey").notNullable();
t.binary("encryptedProxySshServerCaPublicKey").notNullable();
});
await createOnUpdateTrigger(knex, TableName.OrgProxyConfig);
}
}
export async function down(knex: Knex): Promise<void> {
await dropOnUpdateTrigger(knex, TableName.OrgProxyConfig);
await knex.schema.dropTableIfExists(TableName.OrgProxyConfig);
await dropOnUpdateTrigger(knex, TableName.InstanceProxyConfig);
await knex.schema.dropTableIfExists(TableName.InstanceProxyConfig);
}
+2
View File
@@ -57,6 +57,7 @@ export * from "./identity-token-auths";
export * from "./identity-ua-client-secrets";
export * from "./identity-universal-auths";
export * from "./incident-contacts";
export * from "./instance-proxy-config";
export * from "./integration-auths";
export * from "./integrations";
export * from "./internal-certificate-authorities";
@@ -76,6 +77,7 @@ export * from "./oidc-configs";
export * from "./org-bots";
export * from "./org-gateway-config";
export * from "./org-memberships";
export * from "./org-proxy-config";
export * from "./org-roles";
export * from "./organizations";
export * from "./pki-alerts";
@@ -0,0 +1,38 @@
// Code generated by automation script, DO NOT EDIT.
// Automated by pulling database and generating zod schema
// To update. Just run npm run generate:schema
// Written by akhilmhdh.
import { z } from "zod";
import { zodBuffer } from "@app/lib/zod";
import { TImmutableDBKeys } from "./models";
export const InstanceProxyConfigSchema = z.object({
id: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
encryptedRootProxyPkiCaPrivateKey: zodBuffer,
encryptedRootProxyPkiCaCertificate: zodBuffer,
encryptedInstanceProxyPkiCaPrivateKey: zodBuffer,
encryptedInstanceProxyPkiCaCertificate: zodBuffer,
encryptedInstanceProxyPkiCaCertificateChain: zodBuffer,
encryptedInstanceProxyPkiClientCaPrivateKey: zodBuffer,
encryptedInstanceProxyPkiClientCaCertificate: zodBuffer,
encryptedInstanceProxyPkiClientCaCertificateChain: zodBuffer,
encryptedInstanceProxyPkiServerCaPrivateKey: zodBuffer,
encryptedInstanceProxyPkiServerCaCertificate: zodBuffer,
encryptedInstanceProxyPkiServerCaCertificateChain: zodBuffer,
encryptedOrgProxyPkiCaPrivateKey: zodBuffer,
encryptedOrgProxyPkiCaCertificate: zodBuffer,
encryptedOrgProxyPkiCaCertificateChain: zodBuffer,
encryptedInstanceProxySshClientCaPrivateKey: zodBuffer,
encryptedInstanceProxySshClientCaPublicKey: zodBuffer,
encryptedInstanceProxySshServerCaPrivateKey: zodBuffer,
encryptedInstanceProxySshServerCaPublicKey: zodBuffer
});
export type TInstanceProxyConfig = z.infer<typeof InstanceProxyConfigSchema>;
export type TInstanceProxyConfigInsert = Omit<z.input<typeof InstanceProxyConfigSchema>, TImmutableDBKeys>;
export type TInstanceProxyConfigUpdate = Partial<Omit<z.input<typeof InstanceProxyConfigSchema>, TImmutableDBKeys>>;
+5 -1
View File
@@ -178,7 +178,11 @@ export enum TableName {
SecretScanningConfig = "secret_scanning_configs",
// reminders
Reminder = "reminders",
ReminderRecipient = "reminders_recipients"
ReminderRecipient = "reminders_recipients",
// gateway v2
InstanceProxyConfig = "instance_proxy_config",
OrgProxyConfig = "org_proxy_config"
}
export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt" | "commitId";
@@ -0,0 +1,31 @@
// Code generated by automation script, DO NOT EDIT.
// Automated by pulling database and generating zod schema
// To update. Just run npm run generate:schema
// Written by akhilmhdh.
import { z } from "zod";
import { zodBuffer } from "@app/lib/zod";
import { TImmutableDBKeys } from "./models";
export const OrgProxyConfigSchema = z.object({
id: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
orgId: z.string().uuid(),
encryptedProxyPkiClientCaPrivateKey: zodBuffer,
encryptedProxyPkiClientCaCertificate: zodBuffer,
encryptedProxyPkiClientCaCertificateChain: zodBuffer,
encryptedProxyPkiServerCaPrivateKey: zodBuffer,
encryptedProxyPkiServerCaCertificate: zodBuffer,
encryptedProxyPkiServerCaCertificateChain: zodBuffer,
encryptedProxySshClientCaPrivateKey: zodBuffer,
encryptedProxySshClientCaPublicKey: zodBuffer,
encryptedProxySshServerCaPrivateKey: zodBuffer,
encryptedProxySshServerCaPublicKey: zodBuffer
});
export type TOrgProxyConfig = z.infer<typeof OrgProxyConfigSchema>;
export type TOrgProxyConfigInsert = Omit<z.input<typeof OrgProxyConfigSchema>, TImmutableDBKeys>;
export type TOrgProxyConfigUpdate = Partial<Omit<z.input<typeof OrgProxyConfigSchema>, TImmutableDBKeys>>;