feat(infisical-pg): completed secret rotation with queue service

This commit is contained in:
Akhil Mohan
2024-01-27 12:38:23 +05:30
parent 17e61bfc68
commit 784cdb4201
64 changed files with 3093 additions and 459 deletions
+1
View File
@@ -13,6 +13,7 @@ const zodStrBool = z
const envSchema = z
.object({
PORT: z.coerce.number().default(4000),
REDIS_URL: zpStr(z.string()),
HOST: zpStr(z.string().default("localhost")),
DB_CONNECTION_URI: zpStr(z.string().describe("Postgres database conntection string")),
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
+51
View File
@@ -6,6 +6,8 @@ import naclUtils from "tweetnacl-util";
import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas";
import { getConfig } from "../config/env";
export type TDecryptSymmetricInput = {
ciphertext: string;
iv: string;
@@ -191,3 +193,52 @@ export const createSecretBlindIndex = (rootEncryptionKey?: string, encryptionKey
}
throw new Error("Failed to generate blind index due to encryption key missing");
};
export const infisicalSymmetricEncypt = (data: string) => {
const appCfg = getConfig();
const rootEncryptionKey = appCfg.ROOT_ENCRYPTION_KEY;
const encryptionKey = appCfg.ENCRYPTION_KEY;
if (rootEncryptionKey) {
const { iv, tag, ciphertext } = encryptSymmetric(data, rootEncryptionKey);
return {
iv,
tag,
ciphertext,
algorithm: SecretEncryptionAlgo.AES_256_GCM,
encoding: SecretKeyEncoding.BASE64
};
}
if (encryptionKey) {
const { iv, tag, ciphertext } = encryptSymmetric128BitHexKeyUTF8(data, encryptionKey);
return {
iv,
tag,
ciphertext,
algorithm: SecretEncryptionAlgo.AES_256_GCM,
encoding: SecretKeyEncoding.UTF8
};
}
throw new Error("Missing both encryption keys");
};
export const infisicalSymmetricDecrypt = <T extends any = string>({
keyEncoding,
ciphertext,
tag,
iv
}: Omit<TDecryptSymmetricInput, "key"> & {
keyEncoding: SecretKeyEncoding;
}) => {
const appCfg = getConfig();
const rootEncryptionKey = appCfg.ROOT_ENCRYPTION_KEY;
const encryptionKey = appCfg.ENCRYPTION_KEY;
if (rootEncryptionKey && keyEncoding === SecretKeyEncoding.BASE64) {
const data = decryptSymmetric({ key: rootEncryptionKey, iv, tag, ciphertext });
return data as T;
}
if (encryptionKey && keyEncoding === SecretKeyEncoding.UTF8) {
const data = decryptSymmetric128BitHexKeyUTF8({ key: encryptionKey, iv, tag, ciphertext });
return data as T;
}
throw new Error("Missing both encryption keys");
};
+1
View File
@@ -0,0 +1 @@
export const daysToMillisecond = (days: number) => days * 24 * 60 * 60 * 1000;
+2 -2
View File
@@ -17,7 +17,7 @@ export class UnauthorizedError extends Error {
error: unknown;
constructor({ name, error, message }: { message?: string; name?: string; error?: unknown } = {}) {
super(message ?? "You are not allowed to access this resourve");
super(message ?? "You are not allowed to access this resource");
this.name = name || "UnauthorizedError";
this.error = error;
}
@@ -29,7 +29,7 @@ export class ForbiddenRequestError extends Error {
error: unknown;
constructor({ name, error, message }: { message?: string; name?: string; error?: unknown }) {
super(message ?? "You are not allowed to access this resourve");
super(message ?? "You are not allowed to access this resource");
this.name = name || "ForbideenError";
this.error = error;
}
+1 -1
View File
@@ -48,7 +48,7 @@ export type TChildMapper<T extends {}, U extends string = string, R extends unkn
};
type MappedRecord<T extends TChildMapper<any>> = {
[K in T["label"]]: ReturnType<Extract<T, { label: K }>["mapper"]>[];
[K in T["label"]]: Exclude<ReturnType<Extract<T, { label: K }>["mapper"]>, null | undefined>[];
};
export const sqlNestRelationships = <
+10
View File
@@ -2,3 +2,13 @@ import { Tables } from "knex/types/tables";
export const selectAllTableCols = <Tname extends keyof Tables>(tableName: Tname) =>
`${tableName}.*` as keyof Tables[Tname]["base"];
export const stripUndefinedInWhere = <T extends object>(val: T) => {
const copy = val;
Object.entries(copy).forEach(([key, value]) => {
if (typeof value === "undefined") {
delete copy[key as keyof T];
}
});
return copy;
};