feat: fips inside support (checkpoint)

This commit is contained in:
Daniel Hougaard
2025-07-06 15:44:07 +04:00
parent 83f0a500bd
commit 9aa3c14bf2
121 changed files with 1766 additions and 1277 deletions
+10 -14
View File
@@ -1,10 +1,8 @@
import crypto from "crypto";
import { ProjectVersion, TProjects } from "@app/db/schemas";
import { createSshCaHelper } from "@app/ee/services/ssh/ssh-certificate-authority-fns";
import { SshCaKeySource } from "@app/ee/services/ssh/ssh-certificate-authority-types";
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
import { crypto } from "@app/lib/crypto/cryptography";
import { NotFoundError } from "@app/lib/errors";
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { TProjectDALFactory } from "@app/services/project/project-dal";
@@ -12,7 +10,7 @@ import { TProjectDALFactory } from "@app/services/project/project-dal";
import { AddUserToWsDTO, TBootstrapSshProjectDTO } from "./project-types";
export const assignWorkspaceKeysToMembers = ({ members, decryptKey, userPrivateKey }: AddUserToWsDTO) => {
const plaintextProjectKey = decryptAsymmetric({
const plaintextProjectKey = crypto.encryption().asymmetric().decrypt({
ciphertext: decryptKey.encryptedKey,
nonce: decryptKey.nonce,
publicKey: decryptKey.sender.publicKey,
@@ -20,11 +18,10 @@ export const assignWorkspaceKeysToMembers = ({ members, decryptKey, userPrivateK
});
const newWsMembers = members.map(({ orgMembershipId, userPublicKey }) => {
const { ciphertext: inviteeCipherText, nonce: inviteeNonce } = encryptAsymmetric(
plaintextProjectKey,
userPublicKey,
userPrivateKey
);
const { ciphertext: inviteeCipherText, nonce: inviteeNonce } = crypto
.encryption()
.asymmetric()
.encrypt(plaintextProjectKey, userPublicKey, userPrivateKey);
return {
orgMembershipId,
@@ -47,11 +44,10 @@ export const createProjectKey = ({ publicKey, privateKey, plainProjectKey }: TCr
const randomBytes = plainProjectKey || crypto.randomBytes(16).toString("hex");
// 4. Encrypt the project key with the users key pair.
const { ciphertext: encryptedProjectKey, nonce: encryptedProjectKeyIv } = encryptAsymmetric(
randomBytes,
publicKey,
privateKey
);
const { ciphertext: encryptedProjectKey, nonce: encryptedProjectKeyIv } = crypto
.encryption()
.asymmetric()
.encrypt(randomBytes, publicKey, privateKey);
return { key: encryptedProjectKey, iv: encryptedProjectKeyIv };
};
+74 -42
View File
@@ -21,14 +21,10 @@ import {
decryptIntegrationAuths,
decryptSecretApprovals,
decryptSecrets,
decryptSecretVersions
decryptSecretVersions,
SymmetricKeySize
} from "@app/lib/crypto";
import {
decryptAsymmetric,
encryptSymmetric128BitHexKeyUTF8,
infisicalSymmetricDecrypt,
infisicalSymmetricEncypt
} from "@app/lib/crypto/encryption";
import { crypto } from "@app/lib/crypto/cryptography";
import { logger } from "@app/lib/logger";
import { QueueJobs, QueueName, TQueueJobTypes, TQueueServiceFactory } from "@app/queue";
@@ -118,17 +114,14 @@ export const projectQueueFactory = ({
await projectDAL.setProjectUpgradeStatus(data.projectId, ProjectUpgradeStatus.InProgress); // Set the status to in progress. This is important to prevent multiple upgrades at the same time.
// eslint-disable-next-line no-promise-executor-return
// await new Promise((resolve) => setTimeout(resolve, 50_000));
const userPrivateKey = infisicalSymmetricDecrypt({
const userPrivateKey = crypto.encryption().decryptWithRootEncryptionKey({
keyEncoding: data.encryptedPrivateKey.keyEncoding,
ciphertext: data.encryptedPrivateKey.encryptedKey,
iv: data.encryptedPrivateKey.encryptedKeyIv,
tag: data.encryptedPrivateKey.encryptedKeyTag
});
const decryptedPlainProjectKey = decryptAsymmetric({
const decryptedPlainProjectKey = crypto.encryption().asymmetric().decrypt({
ciphertext: oldProjectKey.encryptedKey,
nonce: oldProjectKey.nonce,
publicKey: oldProjectKey.sender.publicKey,
@@ -321,7 +314,9 @@ export const projectQueueFactory = ({
await projectKeyDAL.insertMany(newProjectMembers, tx);
// Encrypt the bot private key (which is the same as the ghost user)
const { iv, tag, ciphertext, encoding, algorithm } = infisicalSymmetricEncypt(ghostUser.keys.plainPrivateKey);
const { iv, tag, ciphertext, encoding, algorithm } = crypto
.encryption()
.encryptWithRootEncryptionKey(ghostUser.keys.plainPrivateKey);
// 5. Create a bot for the project
const newBot = await projectBotDAL.create(
@@ -342,14 +337,14 @@ export const projectQueueFactory = ({
tx
);
const botPrivateKey = infisicalSymmetricDecrypt({
const botPrivateKey = crypto.encryption().decryptWithRootEncryptionKey({
keyEncoding: newBot.keyEncoding as SecretKeyEncoding,
iv: newBot.iv,
tag: newBot.tag,
ciphertext: newBot.encryptedPrivateKey
});
const botKey = decryptAsymmetric({
const botKey = crypto.encryption().asymmetric().decrypt({
ciphertext: newBot.encryptedProjectKey!,
privateKey: botPrivateKey,
nonce: newBot.encryptedProjectKeyNonce!,
@@ -361,12 +356,23 @@ export const projectQueueFactory = ({
const updatedSecretApprovals: TSecretApprovalRequestsSecrets[] = [];
const updatedIntegrationAuths: TIntegrationAuths[] = [];
for (const rawSecret of decryptedSecrets) {
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(rawSecret.decrypted.secretKey, botKey);
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(rawSecret.decrypted.secretValue || "", botKey);
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(
rawSecret.decrypted.secretComment || "",
botKey
);
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecret.decrypted.secretKey,
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecret.decrypted.secretValue || "",
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecret.decrypted.secretComment || "",
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const payload: TSecrets = {
...rawSecret.original,
@@ -393,15 +399,23 @@ export const projectQueueFactory = ({
}
for (const rawSecretVersion of decryptedSecretVersions) {
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(rawSecretVersion.decrypted.secretKey, botKey);
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(
rawSecretVersion.decrypted.secretValue || "",
botKey
);
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(
rawSecretVersion.decrypted.secretComment || "",
botKey
);
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecretVersion.decrypted.secretKey,
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecretVersion.decrypted.secretValue || "",
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecretVersion.decrypted.secretComment || "",
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const payload: TSecretVersions = {
...rawSecretVersion.original,
@@ -428,15 +442,21 @@ export const projectQueueFactory = ({
}
for (const rawSecretApproval of decryptedApprovalSecrets) {
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(rawSecretApproval.decrypted.secretKey, botKey);
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(
rawSecretApproval.decrypted.secretValue || "",
botKey
);
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(
rawSecretApproval.decrypted.secretComment || "",
botKey
);
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecretApproval.decrypted.secretKey,
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecretApproval.decrypted.secretValue || "",
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
plaintext: rawSecretApproval.decrypted.secretComment || "",
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const payload: TSecretApprovalRequestsSecrets = {
...rawSecretApproval.original,
@@ -463,9 +483,21 @@ export const projectQueueFactory = ({
}
for (const integrationAuth of decryptedIntegrationAuths) {
const access = encryptSymmetric128BitHexKeyUTF8(integrationAuth.decrypted.access, botKey);
const accessId = encryptSymmetric128BitHexKeyUTF8(integrationAuth.decrypted.accessId, botKey);
const refresh = encryptSymmetric128BitHexKeyUTF8(integrationAuth.decrypted.refresh, botKey);
const access = crypto.encryption().encryptSymmetric({
plaintext: integrationAuth.decrypted.access,
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const accessId = crypto.encryption().encryptSymmetric({
plaintext: integrationAuth.decrypted.accessId,
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const refresh = crypto.encryption().encryptSymmetric({
plaintext: integrationAuth.decrypted.refresh,
key: botKey,
keySize: SymmetricKeySize.Bits128
});
const payload: TIntegrationAuths = {
...integrationAuth.original,
@@ -34,7 +34,7 @@ import { TSshHostDALFactory } from "@app/ee/services/ssh-host/ssh-host-dal";
import { TSshHostGroupDALFactory } from "@app/ee/services/ssh-host-group/ssh-host-group-dal";
import { PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore";
import { getConfig } from "@app/lib/config/env";
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
import { crypto } from "@app/lib/crypto/cryptography";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { alphaNumericNanoId } from "@app/lib/nanoid";
@@ -392,7 +392,9 @@ export const projectServiceFactory = ({
tx
);
const { iv, tag, ciphertext, encoding, algorithm } = infisicalSymmetricEncypt(ghostUser.keys.plainPrivateKey);
const { iv, tag, ciphertext, encoding, algorithm } = crypto
.encryption()
.encryptWithRootEncryptionKey(ghostUser.keys.plainPrivateKey);
// 5. Create & a bot for the project
await projectBotDAL.create(
@@ -853,7 +855,7 @@ export const projectServiceFactory = ({
});
}
const encryptedPrivateKey = infisicalSymmetricEncypt(userPrivateKey);
const encryptedPrivateKey = crypto.encryption().encryptWithRootEncryptionKey(userPrivateKey);
await projectQueue.upgradeProject({
projectId,