mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 09:35:37 +00:00
improvement: finish address changes
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import { SymmetricEncryption } from "@app/lib/crypto/cipher";
|
||||
|
||||
export const getByteLengthForAlgorithm = (encryptionAlgorithm: SymmetricEncryption) => {
|
||||
switch (encryptionAlgorithm) {
|
||||
case SymmetricEncryption.AES_GCM_128:
|
||||
return 16;
|
||||
case SymmetricEncryption.AES_GCM_256:
|
||||
default:
|
||||
return 32;
|
||||
}
|
||||
};
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { KmsKeysSchema, TableName } from "@app/db/schemas";
|
||||
import { KmsKeysSchema, TableName, TInternalKms, TKmsKeys } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||
import { OrderByDirection } from "@app/lib/types";
|
||||
import { CmekOrderBy, TListCmeksByProjectIdDTO } from "@app/services/cmek/cmek-types";
|
||||
|
||||
export type TKmsKeyDALFactory = ReturnType<typeof kmskeyDALFactory>;
|
||||
|
||||
@@ -71,5 +73,50 @@ export const kmskeyDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
return { ...kmsOrm, findByIdWithAssociatedKms };
|
||||
const findKmsKeysByProjectId = async (
|
||||
{
|
||||
projectId,
|
||||
offset = 0,
|
||||
limit,
|
||||
orderBy = CmekOrderBy.Name,
|
||||
orderDirection = OrderByDirection.ASC,
|
||||
search
|
||||
}: TListCmeksByProjectIdDTO,
|
||||
tx?: Knex
|
||||
) => {
|
||||
try {
|
||||
const query = (tx || db.replicaNode())(TableName.KmsKey)
|
||||
.where("projectId", projectId)
|
||||
.where((qb) => {
|
||||
if (search) {
|
||||
void qb.whereILike("name", `%${search}%`);
|
||||
}
|
||||
})
|
||||
.join(TableName.InternalKms, `${TableName.InternalKms}.kmsKeyId`, `${TableName.KmsKey}.id`)
|
||||
.select<
|
||||
(TKmsKeys &
|
||||
Pick<TInternalKms, "version" | "encryptionAlgorithm"> & {
|
||||
total_count: number;
|
||||
})[]
|
||||
>(
|
||||
selectAllTableCols(TableName.KmsKey),
|
||||
db.raw(`count(*) OVER() as total_count`),
|
||||
db.ref("encryptionAlgorithm").withSchema(TableName.InternalKms),
|
||||
db.ref("version").withSchema(TableName.InternalKms)
|
||||
)
|
||||
.orderBy(orderBy, orderDirection);
|
||||
|
||||
if (limit) {
|
||||
void query.limit(limit).offset(offset);
|
||||
}
|
||||
|
||||
const data = await query;
|
||||
|
||||
return { keys: data, totalCount: Number(data?.[0]?.total_count ?? 0) };
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Find kms keys by project id" });
|
||||
}
|
||||
};
|
||||
|
||||
return { ...kmsOrm, findByIdWithAssociatedKms, findKmsKeysByProjectId };
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import { generateHash } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { getByteLengthForAlgorithm } from "@app/services/kms/kms-fns";
|
||||
|
||||
import { TOrgDALFactory } from "../org/org-dal";
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
@@ -66,22 +67,43 @@ export const kmsServiceFactory = ({
|
||||
}: TKmsServiceFactoryDep) => {
|
||||
let ROOT_ENCRYPTION_KEY = Buffer.alloc(0);
|
||||
|
||||
const $getRootEncryptionKey = (encryptionAlgorithm: SymmetricEncryption) => {
|
||||
switch (encryptionAlgorithm) {
|
||||
case SymmetricEncryption.AES_GCM_128:
|
||||
return ROOT_ENCRYPTION_KEY.subarray(0, 16); // taking first 128bits
|
||||
case SymmetricEncryption.AES_GCM_256:
|
||||
default:
|
||||
return ROOT_ENCRYPTION_KEY;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Generate KMS Key
|
||||
* This function is responsibile for generating the infisical internal KMS for various entities
|
||||
* Like for secret manager, cert manager or for organization
|
||||
*/
|
||||
const generateKmsKey = async ({ orgId, isReserved = true, tx, slug }: TGenerateKMSDTO) => {
|
||||
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
|
||||
const kmsKeyMaterial = randomSecureBytes(32);
|
||||
const encryptedKeyMaterial = cipher.encrypt(kmsKeyMaterial, ROOT_ENCRYPTION_KEY);
|
||||
const sanitizedSlug = slug ? slugify(slug) : slugify(alphaNumericNanoId(8).toLowerCase());
|
||||
const generateKmsKey = async ({
|
||||
orgId,
|
||||
isReserved = true,
|
||||
tx,
|
||||
name,
|
||||
projectId,
|
||||
encryptionAlgorithm = SymmetricEncryption.AES_GCM_256,
|
||||
description
|
||||
}: TGenerateKMSDTO) => {
|
||||
const cipher = symmetricCipherService(encryptionAlgorithm);
|
||||
|
||||
const kmsKeyMaterial = randomSecureBytes(getByteLengthForAlgorithm(encryptionAlgorithm));
|
||||
const encryptedKeyMaterial = cipher.encrypt(kmsKeyMaterial, $getRootEncryptionKey(encryptionAlgorithm));
|
||||
const sanitizedName = name ? slugify(name) : slugify(alphaNumericNanoId(8).toLowerCase());
|
||||
const dbQuery = async (db: Knex) => {
|
||||
const kmsDoc = await kmsDAL.create(
|
||||
{
|
||||
slug: sanitizedSlug,
|
||||
name: sanitizedName,
|
||||
orgId,
|
||||
isReserved
|
||||
isReserved,
|
||||
projectId,
|
||||
description
|
||||
},
|
||||
db
|
||||
);
|
||||
@@ -90,7 +112,7 @@ export const kmsServiceFactory = ({
|
||||
{
|
||||
version: 1,
|
||||
encryptedKey: encryptedKeyMaterial,
|
||||
encryptionAlgorithm: SymmetricEncryption.AES_GCM_256,
|
||||
encryptionAlgorithm,
|
||||
kmsKeyId: kmsDoc.id
|
||||
},
|
||||
db
|
||||
@@ -286,8 +308,13 @@ export const kmsServiceFactory = ({
|
||||
}
|
||||
|
||||
// internal KMS
|
||||
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
|
||||
const kmsKey = cipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
|
||||
const encryptionAlgorithm =
|
||||
(kmsDoc.internalKms?.encryptionAlgorithm as SymmetricEncryption) ?? SymmetricEncryption.AES_GCM_256;
|
||||
const cipher = symmetricCipherService(encryptionAlgorithm);
|
||||
const kmsKey = cipher.decrypt(
|
||||
kmsDoc.internalKms?.encryptedKey as Buffer,
|
||||
$getRootEncryptionKey(encryptionAlgorithm)
|
||||
);
|
||||
|
||||
return ({ cipherTextBlob: versionedCipherTextBlob }: Pick<TDecryptWithKmsDTO, "cipherTextBlob">) => {
|
||||
const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH);
|
||||
@@ -347,10 +374,14 @@ export const kmsServiceFactory = ({
|
||||
}
|
||||
|
||||
// internal KMS
|
||||
// akhilmhdh: as more encryption are added do a check here on kmsDoc.encryptionAlgorithm
|
||||
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
|
||||
const encryptionAlgorithm =
|
||||
(kmsDoc.internalKms?.encryptionAlgorithm as SymmetricEncryption) ?? SymmetricEncryption.AES_GCM_256;
|
||||
const cipher = symmetricCipherService(encryptionAlgorithm);
|
||||
return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
|
||||
const kmsKey = cipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
|
||||
const kmsKey = cipher.decrypt(
|
||||
kmsDoc.internalKms?.encryptedKey as Buffer,
|
||||
$getRootEncryptionKey(encryptionAlgorithm)
|
||||
);
|
||||
const encryptedPlainTextBlob = cipher.encrypt(plainText, kmsKey);
|
||||
|
||||
// Buffer#1 encrypted text + Buffer#2 version number
|
||||
@@ -767,8 +798,8 @@ export const kmsServiceFactory = ({
|
||||
message: "KMS not found"
|
||||
});
|
||||
}
|
||||
const { id, slug, orgId, isExternal } = kms;
|
||||
return { id, slug, orgId, isExternal };
|
||||
const { id, name, orgId, isExternal } = kms;
|
||||
return { id, name, orgId, isExternal };
|
||||
};
|
||||
|
||||
// akhilmhdh: a copy of this is made in migrations/utils/kms
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { SymmetricEncryption } from "@app/lib/crypto/cipher";
|
||||
|
||||
export enum KmsDataKey {
|
||||
Organization,
|
||||
SecretManager
|
||||
@@ -22,8 +24,11 @@ export type TEncryptWithKmsDataKeyDTO =
|
||||
|
||||
export type TGenerateKMSDTO = {
|
||||
orgId: string;
|
||||
projectId?: string;
|
||||
encryptionAlgorithm?: SymmetricEncryption;
|
||||
isReserved?: boolean;
|
||||
slug?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
tx?: Knex;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user