mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 11:27:32 +00:00
feat(server): added keystore and made server cfg fetch from keystore to avoid db calls
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
|
|
||||||
|
export const mockKeyStore = (): TKeyStoreFactory => {
|
||||||
|
const store: Record<string, string | number | Buffer> = {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
setItem: async (key, value) => {
|
||||||
|
store[key] = value;
|
||||||
|
return "OK";
|
||||||
|
},
|
||||||
|
getItem: async (key) => {
|
||||||
|
const value = store[key];
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -14,6 +14,7 @@ import { AuthTokenType } from "@app/services/auth/auth-type";
|
|||||||
|
|
||||||
import { mockQueue } from "./mocks/queue";
|
import { mockQueue } from "./mocks/queue";
|
||||||
import { mockSmtpServer } from "./mocks/smtp";
|
import { mockSmtpServer } from "./mocks/smtp";
|
||||||
|
import { mockKeyStore } from "./mocks/keystore";
|
||||||
|
|
||||||
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
||||||
export default {
|
export default {
|
||||||
@@ -41,7 +42,8 @@ export default {
|
|||||||
await db.seed.run();
|
await db.seed.run();
|
||||||
const smtp = mockSmtpServer();
|
const smtp = mockSmtpServer();
|
||||||
const queue = mockQueue();
|
const queue = mockQueue();
|
||||||
const server = await main({ db, smtp, logger, queue });
|
const keyStore = mockKeyStore();
|
||||||
|
const server = await main({ db, smtp, logger, queue, keyStore });
|
||||||
// @ts-expect-error type
|
// @ts-expect-error type
|
||||||
globalThis.testServer = server;
|
globalThis.testServer = server;
|
||||||
// @ts-expect-error type
|
// @ts-expect-error type
|
||||||
|
|||||||
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import Redis from "ioredis";
|
|
||||||
|
|
||||||
export const initRedisConnection = (redisUrl: string) => {
|
|
||||||
const redis = new Redis(redisUrl);
|
|
||||||
return redis;
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Redis } from "ioredis";
|
||||||
|
|
||||||
|
export type TKeyStoreFactory = ReturnType<typeof keyStoreFactory>;
|
||||||
|
|
||||||
|
export const keyStoreFactory = (redisUrl: string) => {
|
||||||
|
const redis = new Redis(redisUrl);
|
||||||
|
|
||||||
|
const setItem = async (key: string, value: string | number | Buffer) => redis.set(key, value);
|
||||||
|
|
||||||
|
const getItem = async (key: string) => redis.get(key);
|
||||||
|
|
||||||
|
return { setItem, getItem };
|
||||||
|
};
|
||||||
+3
-1
@@ -1,6 +1,7 @@
|
|||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
import { initDbConnection } from "./db";
|
import { initDbConnection } from "./db";
|
||||||
|
import { keyStoreFactory } from "./keystore/keystore";
|
||||||
import { formatSmtpConfig, initEnvConfig } from "./lib/config/env";
|
import { formatSmtpConfig, initEnvConfig } from "./lib/config/env";
|
||||||
import { initLogger } from "./lib/logger";
|
import { initLogger } from "./lib/logger";
|
||||||
import { queueServiceFactory } from "./queue";
|
import { queueServiceFactory } from "./queue";
|
||||||
@@ -19,8 +20,9 @@ const run = async () => {
|
|||||||
|
|
||||||
const smtp = smtpServiceFactory(formatSmtpConfig());
|
const smtp = smtpServiceFactory(formatSmtpConfig());
|
||||||
const queue = queueServiceFactory(appCfg.REDIS_URL);
|
const queue = queueServiceFactory(appCfg.REDIS_URL);
|
||||||
|
const keyStore = keyStoreFactory(appCfg.REDIS_URL);
|
||||||
|
|
||||||
const server = await main({ db, smtp, logger, queue });
|
const server = await main({ db, smtp, logger, queue, keyStore });
|
||||||
const bootstrap = await bootstrapCheck({ db });
|
const bootstrap = await bootstrapCheck({ db });
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
process.on("SIGINT", async () => {
|
process.on("SIGINT", async () => {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import fasitfy from "fastify";
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
import { Logger } from "pino";
|
import { Logger } from "pino";
|
||||||
|
|
||||||
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { TQueueServiceFactory } from "@app/queue";
|
import { TQueueServiceFactory } from "@app/queue";
|
||||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
@@ -31,10 +32,11 @@ type TMain = {
|
|||||||
smtp: TSmtpService;
|
smtp: TSmtpService;
|
||||||
logger?: Logger;
|
logger?: Logger;
|
||||||
queue: TQueueServiceFactory;
|
queue: TQueueServiceFactory;
|
||||||
|
keyStore: TKeyStoreFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run the server!
|
// Run the server!
|
||||||
export const main = async ({ db, smtp, logger, queue }: TMain) => {
|
export const main = async ({ db, smtp, logger, queue, keyStore }: TMain) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
const server = fasitfy({
|
const server = fasitfy({
|
||||||
logger: appCfg.NODE_ENV === "test" ? false : logger,
|
logger: appCfg.NODE_ENV === "test" ? false : logger,
|
||||||
@@ -70,7 +72,7 @@ export const main = async ({ db, smtp, logger, queue }: TMain) => {
|
|||||||
}
|
}
|
||||||
await server.register(helmet, { contentSecurityPolicy: false });
|
await server.register(helmet, { contentSecurityPolicy: false });
|
||||||
|
|
||||||
await server.register(registerRoutes, { smtp, queue, db });
|
await server.register(registerRoutes, { smtp, queue, db, keyStore });
|
||||||
|
|
||||||
if (appCfg.isProductionMode) {
|
if (appCfg.isProductionMode) {
|
||||||
await server.register(registerExternalNextjs, {
|
await server.register(registerExternalNextjs, {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { snapshotFolderDALFactory } from "@app/ee/services/secret-snapshot/snaps
|
|||||||
import { snapshotSecretDALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-dal";
|
import { snapshotSecretDALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-dal";
|
||||||
import { trustedIpDALFactory } from "@app/ee/services/trusted-ip/trusted-ip-dal";
|
import { trustedIpDALFactory } from "@app/ee/services/trusted-ip/trusted-ip-dal";
|
||||||
import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service";
|
import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service";
|
||||||
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { TQueueServiceFactory } from "@app/queue";
|
import { TQueueServiceFactory } from "@app/queue";
|
||||||
import { apiKeyDALFactory } from "@app/services/api-key/api-key-dal";
|
import { apiKeyDALFactory } from "@app/services/api-key/api-key-dal";
|
||||||
@@ -112,7 +113,12 @@ import { registerV3Routes } from "./v3";
|
|||||||
|
|
||||||
export const registerRoutes = async (
|
export const registerRoutes = async (
|
||||||
server: FastifyZodProvider,
|
server: FastifyZodProvider,
|
||||||
{ db, smtp: smtpService, queue: queueService }: { db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory }
|
{
|
||||||
|
db,
|
||||||
|
smtp: smtpService,
|
||||||
|
queue: queueService,
|
||||||
|
keyStore
|
||||||
|
}: { db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory; keyStore: TKeyStoreFactory }
|
||||||
) => {
|
) => {
|
||||||
await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" });
|
await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" });
|
||||||
|
|
||||||
@@ -263,7 +269,8 @@ export const registerRoutes = async (
|
|||||||
userDAL,
|
userDAL,
|
||||||
authService: loginService,
|
authService: loginService,
|
||||||
serverCfgDAL: superAdminDAL,
|
serverCfgDAL: superAdminDAL,
|
||||||
orgService
|
orgService,
|
||||||
|
keyStore
|
||||||
});
|
});
|
||||||
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
config: SuperAdminSchema
|
config: SuperAdminSchema.omit({ createdAt: true, updatedAt: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { TSuperAdmin, TSuperAdminUpdate } from "@app/db/schemas";
|
import { TSuperAdmin, TSuperAdminUpdate } from "@app/db/schemas";
|
||||||
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ type TSuperAdminServiceFactoryDep = {
|
|||||||
userDAL: TUserDALFactory;
|
userDAL: TUserDALFactory;
|
||||||
authService: Pick<TAuthLoginFactory, "generateUserTokens">;
|
authService: Pick<TAuthLoginFactory, "generateUserTokens">;
|
||||||
orgService: Pick<TOrgServiceFactory, "createOrganization">;
|
orgService: Pick<TOrgServiceFactory, "createOrganization">;
|
||||||
|
keyStore: Pick<TKeyStoreFactory, "getItem" | "setItem">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TSuperAdminServiceFactory = ReturnType<typeof superAdminServiceFactory>;
|
export type TSuperAdminServiceFactory = ReturnType<typeof superAdminServiceFactory>;
|
||||||
@@ -21,26 +23,44 @@ export type TSuperAdminServiceFactory = ReturnType<typeof superAdminServiceFacto
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
export let getServerCfg: () => Promise<TSuperAdmin>;
|
export let getServerCfg: () => Promise<TSuperAdmin>;
|
||||||
|
|
||||||
|
const ADMIN_CONFIG_KEY = "infisical-admin-cfg";
|
||||||
export const superAdminServiceFactory = ({
|
export const superAdminServiceFactory = ({
|
||||||
serverCfgDAL,
|
serverCfgDAL,
|
||||||
userDAL,
|
userDAL,
|
||||||
authService,
|
authService,
|
||||||
orgService
|
orgService,
|
||||||
|
keyStore
|
||||||
}: TSuperAdminServiceFactoryDep) => {
|
}: TSuperAdminServiceFactoryDep) => {
|
||||||
const initServerCfg = async () => {
|
const initServerCfg = async () => {
|
||||||
// TODO(akhilmhdh): bad pattern time less change this later to me itself
|
// TODO(akhilmhdh): bad pattern time less change this later to me itself
|
||||||
getServerCfg = () => serverCfgDAL.findOne({});
|
getServerCfg = async () => {
|
||||||
|
const config = await keyStore.getItem(ADMIN_CONFIG_KEY);
|
||||||
|
if (!config) {
|
||||||
|
const serverCfg = await serverCfgDAL.findOne({});
|
||||||
|
await keyStore.setItem(ADMIN_CONFIG_KEY, JSON.stringify(serverCfg));
|
||||||
|
return serverCfg;
|
||||||
|
}
|
||||||
|
const keyStoreServerCfg = JSON.parse(config) as TSuperAdmin;
|
||||||
|
return {
|
||||||
|
...keyStoreServerCfg,
|
||||||
|
// this is to allow admin router to work
|
||||||
|
createdAt: new Date(keyStoreServerCfg.createdAt),
|
||||||
|
updatedAt: new Date(keyStoreServerCfg.updatedAt)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const serverCfg = await serverCfgDAL.findOne({});
|
const serverCfg = await getServerCfg();
|
||||||
if (serverCfg) return;
|
if (serverCfg) return;
|
||||||
|
|
||||||
const newCfg = await serverCfgDAL.create({ initialized: false, allowSignUp: true });
|
const newCfg = await serverCfgDAL.create({ initialized: false, allowSignUp: true });
|
||||||
return newCfg;
|
return newCfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateServerCfg = async (data: TSuperAdminUpdate) => {
|
const updateServerCfg = async (data: TSuperAdminUpdate) => {
|
||||||
const serverCfg = await getServerCfg();
|
const serverCfg = await getServerCfg();
|
||||||
const cfg = await serverCfgDAL.updateById(serverCfg.id, data);
|
const updatedServerCfg = await serverCfgDAL.updateById(serverCfg.id, data);
|
||||||
return cfg;
|
await keyStore.setItem(ADMIN_CONFIG_KEY, JSON.stringify(updatedServerCfg));
|
||||||
|
return updatedServerCfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
const adminSignUp = async ({
|
const adminSignUp = async ({
|
||||||
|
|||||||
Reference in New Issue
Block a user