mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 15:40:47 +00:00
feat: fips inside support (checkpoint)
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
import { TApiKeys } from "@app/db/schemas/api-keys";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
|
||||
import { TUserDALFactory } from "../user/user-dal";
|
||||
@@ -27,7 +24,7 @@ export const apiKeyServiceFactory = ({ apiKeyDAL, userDAL }: TApiKeyServiceFacto
|
||||
const createApiKey = async (userId: string, name: string, expiresIn: number) => {
|
||||
const appCfg = getConfig();
|
||||
const secret = crypto.randomBytes(16).toString("hex");
|
||||
const secretHash = await bcrypt.hash(secret, appCfg.SALT_ROUNDS);
|
||||
const secretHash = await crypto.hashing().createHash(secret, appCfg.SALT_ROUNDS);
|
||||
const expiresAt = new Date();
|
||||
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
|
||||
|
||||
@@ -59,7 +56,7 @@ export const apiKeyServiceFactory = ({ apiKeyDAL, userDAL }: TApiKeyServiceFacto
|
||||
throw new UnauthorizedError();
|
||||
}
|
||||
|
||||
const isMatch = await bcrypt.compare(TOKEN_SECRET, apiKey.secretHash);
|
||||
const isMatch = await crypto.hashing().compareHash(TOKEN_SECRET, apiKey.secretHash);
|
||||
if (!isMatch) throw new UnauthorizedError();
|
||||
await apiKeyDAL.updateById(apiKey.id, { lastUsed: new Date() });
|
||||
const user = await userDAL.findById(apiKey.userId);
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from "@app/ee/services/app-connections/oci";
|
||||
import { getOracleDBConnectionListItem, OracleDBConnectionMethod } from "@app/ee/services/app-connections/oracledb";
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { generateHash } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { APP_CONNECTION_NAME_MAP, APP_CONNECTION_PLAN_MAP } from "@app/services/app-connection/app-connection-maps";
|
||||
import {
|
||||
@@ -290,7 +290,7 @@ export const decryptAppConnection = async (
|
||||
orgId: appConnection.orgId,
|
||||
kmsService
|
||||
}),
|
||||
credentialsHash: generateHash(appConnection.encryptedCredentials)
|
||||
credentialsHash: crypto.rawCrypto.createHash("sha256").update(appConnection.encryptedCredentials).digest("hex")
|
||||
} as TAppConnection;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ValidateOracleDBConnectionCredentialsSchema } from "@app/ee/services/ap
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { OrgPermissionAppConnectionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { generateHash } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { DatabaseErrorCode } from "@app/lib/error-codes";
|
||||
import { BadRequestError, DatabaseError, NotFoundError } from "@app/lib/errors";
|
||||
import { DiscriminativePick, OrgServiceActor } from "@app/lib/types";
|
||||
@@ -272,7 +272,7 @@ export const appConnectionServiceFactory = ({
|
||||
|
||||
return {
|
||||
...connection,
|
||||
credentialsHash: generateHash(connection.encryptedCredentials),
|
||||
credentialsHash: crypto.rawCrypto.createHash("sha256").update(connection.encryptedCredentials).digest("hex"),
|
||||
credentials: validatedCredentials
|
||||
} as TAppConnection;
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts";
|
||||
import AWS from "aws-sdk";
|
||||
import { AxiosError } from "axios";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, InternalServerError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { AppConnection, AWSRegion } from "@app/services/app-connection/app-connection-enums";
|
||||
@@ -46,7 +46,7 @@ export const getAwsConnectionConfig = async (appConnection: TAwsConnectionConfig
|
||||
|
||||
const command = new AssumeRoleCommand({
|
||||
RoleArn: credentials.roleArn,
|
||||
RoleSessionName: `infisical-app-connection-${randomUUID()}`,
|
||||
RoleSessionName: `infisical-app-connection-${crypto.rawCrypto.randomUUID()}`,
|
||||
DurationSeconds: 900, // 15 mins
|
||||
ExternalId: orgId
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TAuthTokens, TAuthTokenSessions } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
|
||||
|
||||
@@ -81,7 +79,7 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, orgMembershipDAL }: TAu
|
||||
const createTokenForUser = async ({ type, userId, orgId }: TCreateTokenForUserDTO) => {
|
||||
const { token, ...tkCfg } = getTokenConfig(type);
|
||||
const appCfg = getConfig();
|
||||
const tokenHash = await bcrypt.hash(token, appCfg.SALT_ROUNDS);
|
||||
const tokenHash = await crypto.hashing().createHash(token, appCfg.SALT_ROUNDS);
|
||||
await tokenDAL.transaction(async (tx) => {
|
||||
await tokenDAL.delete({ userId, type, orgId: orgId || null }, tx);
|
||||
const newToken = await tokenDAL.create(
|
||||
@@ -115,7 +113,7 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, orgMembershipDAL }: TAu
|
||||
throw new Error("Token expired. Please try again");
|
||||
}
|
||||
|
||||
const isValidToken = await bcrypt.compare(code, token.tokenHash);
|
||||
const isValidToken = await crypto.hashing().compareHash(code, token.tokenHash);
|
||||
if (!isValidToken) {
|
||||
if (token?.triesLeft) {
|
||||
if (token.triesLeft === 1) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { Knex } from "knex";
|
||||
|
||||
@@ -8,7 +7,7 @@ import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { getMinExpiresIn, removeTrailingSlash } from "@app/lib/fn";
|
||||
@@ -336,8 +335,11 @@ export const authLoginServiceFactory = ({
|
||||
);
|
||||
return "";
|
||||
});
|
||||
const hashedPassword = await bcrypt.hash(password, cfg.BCRYPT_SALT_ROUND);
|
||||
const { iv, tag, ciphertext, encoding } = infisicalSymmetricEncypt(privateKey);
|
||||
|
||||
const hashedPassword = await crypto.hashing().createHash(password, cfg.SALT_ROUNDS);
|
||||
|
||||
const { iv, tag, ciphertext, encoding } = crypto.encryption().encryptWithRootEncryptionKey(privateKey);
|
||||
|
||||
await userDAL.updateUserEncryptionByUserId(userEnc.userId, {
|
||||
serverPrivateKey: null,
|
||||
clientPublicKey: null,
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { generateUserSrpKeys } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -95,7 +94,7 @@ export const authPaswordServiceFactory = ({
|
||||
if (!isValidClientProof) throw new Error("Failed to authenticate. Try again?");
|
||||
|
||||
const appCfg = getConfig();
|
||||
const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND);
|
||||
const hashedPassword = await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS);
|
||||
await userDAL.updateUserEncryptionByUserId(userId, {
|
||||
encryptionVersion: 2,
|
||||
protectedKey,
|
||||
@@ -208,13 +207,13 @@ export const authPaswordServiceFactory = ({
|
||||
throw new BadRequestError({ message: "Current password is required." });
|
||||
}
|
||||
|
||||
const isValid = await bcrypt.compare(oldPassword, user.hashedPassword);
|
||||
const isValid = await crypto.hashing().compareHash(oldPassword, user.hashedPassword);
|
||||
if (!isValid) {
|
||||
throw new BadRequestError({ message: "Incorrect current password." });
|
||||
}
|
||||
}
|
||||
|
||||
const newHashedPassword = await bcrypt.hash(newPassword, cfg.BCRYPT_SALT_ROUND);
|
||||
const newHashedPassword = await crypto.hashing().createHash(newPassword, cfg.SALT_ROUNDS);
|
||||
|
||||
// we need to get the original private key first for v2
|
||||
let privateKey: string;
|
||||
@@ -225,7 +224,7 @@ export const authPaswordServiceFactory = ({
|
||||
user.serverEncryptedPrivateKeyEncoding &&
|
||||
user.encryptionVersion === UserEncryption.V2
|
||||
) {
|
||||
privateKey = infisicalSymmetricDecrypt({
|
||||
privateKey = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
iv: user.serverEncryptedPrivateKeyIV,
|
||||
tag: user.serverEncryptedPrivateKeyTag,
|
||||
ciphertext: user.serverEncryptedPrivateKey,
|
||||
@@ -243,7 +242,7 @@ export const authPaswordServiceFactory = ({
|
||||
privateKey
|
||||
});
|
||||
|
||||
const { tag, iv, ciphertext, encoding } = infisicalSymmetricEncypt(privateKey);
|
||||
const { tag, iv, ciphertext, encoding } = crypto.encryption().encryptWithRootEncryptionKey(privateKey);
|
||||
|
||||
await userDAL.updateUserEncryptionByUserId(userId, {
|
||||
hashedPassword: newHashedPassword,
|
||||
@@ -285,7 +284,7 @@ export const authPaswordServiceFactory = ({
|
||||
}: TResetPasswordViaBackupKeyDTO) => {
|
||||
const cfg = getConfig();
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, cfg.BCRYPT_SALT_ROUND);
|
||||
const hashedPassword = await crypto.hashing().createHash(password, cfg.SALT_ROUNDS);
|
||||
|
||||
await userDAL.updateUserEncryptionByUserId(userId, {
|
||||
encryptionVersion: 2,
|
||||
@@ -461,7 +460,7 @@ export const authPaswordServiceFactory = ({
|
||||
|
||||
const cfg = getConfig();
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, cfg.BCRYPT_SALT_ROUND);
|
||||
const hashedPassword = await crypto.hashing().createHash(password, cfg.SALT_ROUNDS);
|
||||
|
||||
await userDAL.updateUserEncryptionByUserId(
|
||||
actor.id,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
import { OrgMembershipStatus, SecretKeyEncoding, TableName } from "@app/db/schemas";
|
||||
@@ -7,7 +6,7 @@ import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-grou
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { generateUserSrpKeys, getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { getMinExpiresIn } from "@app/lib/fn";
|
||||
@@ -193,7 +192,7 @@ export const authSignupServiceFactory = ({
|
||||
validateSignUpAuthorization(authorization, user.id);
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND);
|
||||
const hashedPassword = await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS);
|
||||
const privateKey = await getUserPrivateKey(password, {
|
||||
salt,
|
||||
protectedKey,
|
||||
@@ -204,7 +203,7 @@ export const authSignupServiceFactory = ({
|
||||
tag: encryptedPrivateKeyTag,
|
||||
encryptionVersion: UserEncryption.V2
|
||||
});
|
||||
const { tag, encoding, ciphertext, iv } = infisicalSymmetricEncypt(privateKey);
|
||||
const { tag, encoding, ciphertext, iv } = crypto.encryption().encryptWithRootEncryptionKey(privateKey);
|
||||
const updateduser = await authDAL.transaction(async (tx) => {
|
||||
const us = await userDAL.updateById(user.id, { firstName, lastName, isAccepted: true }, tx);
|
||||
if (!us) throw new Error("User not found");
|
||||
@@ -225,7 +224,7 @@ export const authSignupServiceFactory = ({
|
||||
systemGeneratedUserEncryptionKey.serverEncryptedPrivateKeyEncoding
|
||||
) {
|
||||
// get server generated password
|
||||
const serverGeneratedPassword = infisicalSymmetricDecrypt({
|
||||
const serverGeneratedPassword = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
iv: systemGeneratedUserEncryptionKey.serverEncryptedPrivateKeyIV,
|
||||
tag: systemGeneratedUserEncryptionKey.serverEncryptedPrivateKeyTag,
|
||||
ciphertext: systemGeneratedUserEncryptionKey.serverEncryptedPrivateKey,
|
||||
@@ -436,7 +435,7 @@ export const authSignupServiceFactory = ({
|
||||
});
|
||||
|
||||
const appCfg = getConfig();
|
||||
const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND);
|
||||
const hashedPassword = await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS);
|
||||
const privateKey = await getUserPrivateKey(password, {
|
||||
salt,
|
||||
protectedKey,
|
||||
@@ -447,7 +446,7 @@ export const authSignupServiceFactory = ({
|
||||
tag: encryptedPrivateKeyTag,
|
||||
encryptionVersion: 2
|
||||
});
|
||||
const { tag, encoding, ciphertext, iv } = infisicalSymmetricEncypt(privateKey);
|
||||
const { tag, encoding, ciphertext, iv } = crypto.encryption().encryptWithRootEncryptionKey(privateKey);
|
||||
const updateduser = await authDAL.transaction(async (tx) => {
|
||||
const us = await userDAL.updateById(user.id, { firstName, lastName, isAccepted: true }, tx);
|
||||
if (!us) throw new Error("User not found");
|
||||
@@ -464,7 +463,7 @@ export const authSignupServiceFactory = ({
|
||||
systemGeneratedUserEncryptionKey.serverEncryptedPrivateKeyEncoding
|
||||
) {
|
||||
// get server generated password
|
||||
const serverGeneratedPassword = infisicalSymmetricDecrypt({
|
||||
const serverGeneratedPassword = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
iv: systemGeneratedUserEncryptionKey.serverEncryptedPrivateKeyIV,
|
||||
tag: systemGeneratedUserEncryptionKey.serverEncryptedPrivateKeyTag,
|
||||
ciphertext: systemGeneratedUserEncryptionKey.serverEncryptedPrivateKey,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ChangeResourceRecordSetsCommand, Route53Client } from "@aws-sdk/client-route-53";
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import acme from "acme-client";
|
||||
import { KeyObject } from "crypto";
|
||||
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { OrgServiceActor } from "@app/lib/types";
|
||||
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
|
||||
@@ -404,8 +404,9 @@ export const AcmeCertificateAuthorityFns = ({
|
||||
});
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(CertKeyAlgorithm.RSA_2048);
|
||||
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const skLeafObj = KeyObject.from(leafKeys.privateKey);
|
||||
|
||||
const leafKeys = await crypto.rawCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const skLeafObj = crypto.rawCrypto.KeyObject.from(leafKeys.privateKey);
|
||||
const skLeaf = skLeafObj.export({ format: "pem", type: "pkcs8" }) as string;
|
||||
|
||||
const [, certificateCsr] = await acme.crypto.createCsr(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import crypto from "crypto";
|
||||
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
||||
|
||||
@@ -133,8 +133,8 @@ export const getCaCredentials = async ({
|
||||
});
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||
const skObj = crypto.createPrivateKey({ key: decryptedPrivateKey, format: "der", type: "pkcs8" });
|
||||
const caPrivateKey = await crypto.subtle.importKey(
|
||||
const skObj = crypto.rawCrypto.createPrivateKey({ key: decryptedPrivateKey, format: "der", type: "pkcs8" });
|
||||
const caPrivateKey = await crypto.rawCrypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
skObj.export({ format: "der", type: "pkcs8" }),
|
||||
alg,
|
||||
@@ -142,10 +142,14 @@ export const getCaCredentials = async ({
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const pkObj = crypto.createPublicKey(skObj);
|
||||
const caPublicKey = await crypto.subtle.importKey("spki", pkObj.export({ format: "der", type: "spki" }), alg, true, [
|
||||
"verify"
|
||||
]);
|
||||
const pkObj = crypto.rawCrypto.createPublicKey(skObj);
|
||||
const caPublicKey = await crypto.rawCrypto.subtle.importKey(
|
||||
"spki",
|
||||
pkObj.export({ format: "der", type: "spki" }),
|
||||
alg,
|
||||
true,
|
||||
["verify"]
|
||||
);
|
||||
|
||||
return {
|
||||
caSecret,
|
||||
@@ -277,10 +281,14 @@ export const rebuildCaCrl = async ({
|
||||
cipherTextBlob: caSecret.encryptedPrivateKey
|
||||
});
|
||||
|
||||
const skObj = crypto.createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
||||
const sk = await crypto.subtle.importKey("pkcs8", skObj.export({ format: "der", type: "pkcs8" }), alg, true, [
|
||||
"sign"
|
||||
]);
|
||||
const skObj = crypto.rawCrypto.createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
||||
const sk = await crypto.rawCrypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
skObj.export({ format: "der", type: "pkcs8" }),
|
||||
alg,
|
||||
true,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const revokedCerts = await certificateDAL.find({
|
||||
caId: ca.id,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import crypto from "crypto";
|
||||
|
||||
import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { daysToMillisecond, secondsToMillis } from "@app/lib/dates";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -198,10 +198,14 @@ export const certificateAuthorityQueueFactory = ({
|
||||
cipherTextBlob: caSecret.encryptedPrivateKey
|
||||
});
|
||||
|
||||
const skObj = crypto.createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
||||
const sk = await crypto.subtle.importKey("pkcs8", skObj.export({ format: "der", type: "pkcs8" }), alg, true, [
|
||||
"sign"
|
||||
]);
|
||||
const skObj = crypto.rawCrypto.createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
||||
const sk = await crypto.rawCrypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
skObj.export({ format: "der", type: "pkcs8" }),
|
||||
alg,
|
||||
true,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const revokedCerts = await certificateDAL.find({
|
||||
caId: ca.id,
|
||||
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
/* eslint-disable no-bitwise */
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import { KeyObject } from "crypto";
|
||||
import RE2 from "re2";
|
||||
import { z } from "zod";
|
||||
|
||||
import { TCertificateTemplates, TPkiSubscribers } from "@app/db/schemas";
|
||||
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { isFQDN } from "@app/lib/validator/validate-url";
|
||||
@@ -99,7 +99,7 @@ export const InternalCertificateAuthorityFns = ({
|
||||
}
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const leafKeys = await crypto.rawCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
|
||||
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
||||
name: `CN=${subscriber.commonName}`,
|
||||
@@ -184,7 +184,7 @@ export const InternalCertificateAuthorityFns = ({
|
||||
extensions
|
||||
});
|
||||
|
||||
const skLeafObj = KeyObject.from(leafKeys.privateKey);
|
||||
const skLeafObj = crypto.rawCrypto.KeyObject.from(leafKeys.privateKey);
|
||||
const skLeaf = skLeafObj.export({ format: "pem", type: "pkcs8" }) as string;
|
||||
|
||||
const kmsEncryptor = await kmsService.encryptWithKmsKey({
|
||||
@@ -331,7 +331,7 @@ export const InternalCertificateAuthorityFns = ({
|
||||
});
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const leafKeys = await crypto.rawCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
|
||||
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
||||
name: `CN=${commonName}`,
|
||||
@@ -450,7 +450,7 @@ export const InternalCertificateAuthorityFns = ({
|
||||
extensions
|
||||
});
|
||||
|
||||
const skLeafObj = KeyObject.from(leafKeys.privateKey);
|
||||
const skLeafObj = crypto.rawCrypto.KeyObject.from(leafKeys.privateKey);
|
||||
const skLeaf = skLeafObj.export({ format: "pem", type: "pkcs8" }) as string;
|
||||
|
||||
const kmsEncryptor = await kmsService.encryptWithKmsKey({
|
||||
|
||||
+7
-7
@@ -2,7 +2,6 @@
|
||||
import { ForbiddenError, subject } from "@casl/ability";
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import crypto, { KeyObject } from "crypto";
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
@@ -21,6 +20,7 @@ import {
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { extractX509CertFromChain } from "@app/lib/certificates/extract-certificate";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
@@ -189,7 +189,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
||||
});
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(keyAlgorithm);
|
||||
const keys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const keys = await crypto.rawCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
|
||||
const newCa = await certificateAuthorityDAL.transaction(async (tx) => {
|
||||
const notBeforeDate = notBefore ? new Date(notBefore) : new Date();
|
||||
@@ -243,8 +243,8 @@ export const internalCertificateAuthorityServiceFactory = ({
|
||||
kmsId: certificateManagerKmsId
|
||||
});
|
||||
|
||||
// // https://nodejs.org/api/crypto.html#static-method-keyobjectfromkey
|
||||
const skObj = KeyObject.from(keys.privateKey);
|
||||
// https://nodejs.org/api/crypto.html#static-method-keyobjectfromkey
|
||||
const skObj = crypto.rawCrypto.KeyObject.from(keys.privateKey);
|
||||
|
||||
const { cipherTextBlob: encryptedPrivateKey } = await kmsEncryptor({
|
||||
plainText: skObj.export({
|
||||
@@ -1129,7 +1129,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
||||
kmsService
|
||||
});
|
||||
|
||||
const isCaAndCertPublicKeySame = Buffer.from(await crypto.subtle.exportKey("spki", caPublicKey)).equals(
|
||||
const isCaAndCertPublicKeySame = Buffer.from(await crypto.rawCrypto.subtle.exportKey("spki", caPublicKey)).equals(
|
||||
Buffer.from(certObj.publicKey.rawData)
|
||||
);
|
||||
|
||||
@@ -1293,7 +1293,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
||||
}
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
const leafKeys = await crypto.rawCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||
|
||||
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
||||
name: `CN=${commonName}`,
|
||||
@@ -1440,7 +1440,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
||||
extensions
|
||||
});
|
||||
|
||||
const skLeafObj = KeyObject.from(leafKeys.privateKey);
|
||||
const skLeafObj = crypto.rawCrypto.KeyObject.from(leafKeys.privateKey);
|
||||
const skLeaf = skLeafObj.export({ format: "pem", type: "pkcs8" }) as string;
|
||||
|
||||
const kmsEncryptor = await kmsService.encryptWithKmsKey({
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ForbiddenError, subject } from "@casl/ability";
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
import { ActionProjectType, TCertificateTemplateEstConfigsUpdate } from "@app/db/schemas";
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { extractX509CertFromChain } from "@app/lib/certificates/extract-certificate";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { isCertChainValid } from "../certificate/certificate-fns";
|
||||
@@ -313,7 +313,7 @@ export const certificateTemplateServiceFactory = ({
|
||||
encryptedCaChain = cipherTextBlob;
|
||||
}
|
||||
|
||||
const hashedPassphrase = await bcrypt.hash(passphrase, appCfg.SALT_ROUNDS);
|
||||
const hashedPassphrase = await crypto.hashing().createHash(passphrase, appCfg.SALT_ROUNDS);
|
||||
const estConfig = await certificateTemplateEstConfigDAL.create({
|
||||
certificateTemplateId,
|
||||
hashedPassphrase,
|
||||
@@ -410,7 +410,7 @@ export const certificateTemplateServiceFactory = ({
|
||||
}
|
||||
|
||||
if (passphrase) {
|
||||
const hashedPassphrase = await bcrypt.hash(passphrase, appCfg.SALT_ROUNDS);
|
||||
const hashedPassphrase = await crypto.hashing().createHash(passphrase, appCfg.SALT_ROUNDS);
|
||||
updatedData.hashedPassphrase = hashedPassphrase;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import RE2 from "re2";
|
||||
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { getProjectKmsCertificateKeyId } from "../project/project-fns";
|
||||
@@ -87,10 +86,10 @@ export const getCertificateCredentials = async ({
|
||||
});
|
||||
|
||||
try {
|
||||
const skObj = crypto.createPrivateKey({ key: decryptedPrivateKey, format: "pem", type: "pkcs8" });
|
||||
const skObj = crypto.rawCrypto.createPrivateKey({ key: decryptedPrivateKey, format: "pem", type: "pkcs8" });
|
||||
const certPrivateKey = skObj.export({ format: "pem", type: "pkcs8" }).toString();
|
||||
|
||||
const pkObj = crypto.createPublicKey(skObj);
|
||||
const pkObj = crypto.rawCrypto.createPublicKey(skObj);
|
||||
const certPublicKey = pkObj.export({ format: "pem", type: "spki" }).toString();
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import * as x509 from "@peculiar/x509";
|
||||
import { createPrivateKey, createPublicKey, sign, verify } from "crypto";
|
||||
|
||||
import { ActionProjectType, ProjectType } from "@app/db/schemas";
|
||||
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
ProjectPermissionCertificateActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { TCertificateBodyDALFactory } from "@app/services/certificate/certificate-body-dal";
|
||||
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||
@@ -391,16 +391,16 @@ export const certificateServiceFactory = ({
|
||||
// Verify private key matches the certificate
|
||||
let privateKey;
|
||||
try {
|
||||
privateKey = createPrivateKey(privateKeyPem);
|
||||
privateKey = crypto.rawCrypto.createPrivateKey(privateKeyPem);
|
||||
} catch (err) {
|
||||
throw new BadRequestError({ message: "Invalid private key format" });
|
||||
}
|
||||
|
||||
try {
|
||||
const message = Buffer.from(Buffer.alloc(32));
|
||||
const publicKey = createPublicKey(certificatePem);
|
||||
const signature = sign(null, message, privateKey);
|
||||
const isValid = verify(null, message, publicKey, signature);
|
||||
const publicKey = crypto.rawCrypto.createPublicKey(certificatePem);
|
||||
const signature = crypto.rawCrypto.sign(null, message, privateKey);
|
||||
const isValid = crypto.rawCrypto.verify(null, message, publicKey, signature);
|
||||
|
||||
if (!isValid) {
|
||||
throw new BadRequestError({ message: "Private key does not match certificate" });
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { randomUUID } from "crypto";
|
||||
import sjcl from "sjcl";
|
||||
import tweetnacl from "tweetnacl";
|
||||
import tweetnaclUtil from "tweetnacl-util";
|
||||
|
||||
import { SecretType, TSecretFolders } from "@app/db/schemas";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { chunkArray } from "@app/lib/fn";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -228,7 +228,7 @@ export const parseEnvKeyDataFn = async (decryptedJson: string): Promise<Infisica
|
||||
}
|
||||
|
||||
infisicalImportData.secrets.push({
|
||||
id: randomUUID(),
|
||||
id: crypto.rawCrypto.randomUUID(),
|
||||
name: secretName,
|
||||
environmentId: matchingAppEnv.id,
|
||||
value: resolvedSecret.val || "",
|
||||
@@ -261,7 +261,7 @@ export const parseEnvKeyDataFn = async (decryptedJson: string): Promise<Infisica
|
||||
}
|
||||
|
||||
infisicalImportData.secrets.push({
|
||||
id: randomUUID(),
|
||||
id: crypto.rawCrypto.randomUUID(),
|
||||
name: secretName,
|
||||
environmentId: matchingAppEnv.id,
|
||||
value: secretData.val || "",
|
||||
@@ -348,7 +348,7 @@ export const parseEnvKeyDataFn = async (decryptedJson: string): Promise<Infisica
|
||||
}
|
||||
|
||||
infisicalImportData.secrets.push({
|
||||
id: randomUUID(),
|
||||
id: crypto.rawCrypto.randomUUID(),
|
||||
name: secret,
|
||||
environmentId: matchingEnv.id,
|
||||
value: resolvedSecret.val || "",
|
||||
@@ -380,7 +380,7 @@ export const parseEnvKeyDataFn = async (decryptedJson: string): Promise<Infisica
|
||||
}
|
||||
|
||||
infisicalImportData.secrets.push({
|
||||
id: randomUUID(),
|
||||
id: crypto.rawCrypto.randomUUID(),
|
||||
name: secret,
|
||||
environmentId: matchingEnv.id,
|
||||
value: selectedSecret.val || "",
|
||||
@@ -461,7 +461,7 @@ export const parseEnvKeyDataFn = async (decryptedJson: string): Promise<Infisica
|
||||
}
|
||||
|
||||
infisicalImportData.secrets.push({
|
||||
id: randomUUID(),
|
||||
id: crypto.rawCrypto.randomUUID(),
|
||||
name: secretName,
|
||||
environmentId: subEnv ? subEnv.parentEnvironmentId : env,
|
||||
value: resolvedSecret.val || "",
|
||||
@@ -487,7 +487,7 @@ export const parseEnvKeyDataFn = async (decryptedJson: string): Promise<Infisica
|
||||
const folderId = targetIdToFolderIdsMap.get(subEnv?.id || "") || subEnv?.id;
|
||||
|
||||
infisicalImportData.secrets.push({
|
||||
id: randomUUID(),
|
||||
id: crypto.rawCrypto.randomUUID(),
|
||||
name: secretName,
|
||||
environmentId: subEnv ? subEnv.parentEnvironmentId : env,
|
||||
value: secretData.val || "",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
||||
|
||||
@@ -98,7 +98,7 @@ export const externalMigrationQueueFactory = ({
|
||||
template: SmtpTemplates.ExternalImportStarted
|
||||
});
|
||||
|
||||
const decrypted = infisicalSymmetricDecrypt({
|
||||
const decrypted = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
ciphertext: data.ciphertext,
|
||||
iv: data.iv,
|
||||
keyEncoding: data.encoding,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { OrgMembershipRole } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { ForbiddenRequestError } from "@app/lib/errors";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
|
||||
|
||||
import { TUserDALFactory } from "../user/user-dal";
|
||||
import { decryptEnvKeyDataFn, parseEnvKeyDataFn } from "./external-migration-fns";
|
||||
@@ -29,6 +29,10 @@ export const externalMigrationServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorAuthMethod
|
||||
}: TImportEnvKeyDataCreate) => {
|
||||
if (crypto.isFipsModeEnabled()) {
|
||||
throw new BadRequestError({ message: "EnvKey migration is not supported when running in FIPS mode." });
|
||||
}
|
||||
|
||||
const { membership } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -52,7 +56,7 @@ export const externalMigrationServiceFactory = ({
|
||||
actorAuthMethod
|
||||
});
|
||||
|
||||
const encrypted = infisicalSymmetricEncypt(stringifiedJson);
|
||||
const encrypted = crypto.encryption().encryptWithRootEncryptionKey(stringifiedJson);
|
||||
|
||||
await externalMigrationQueue.startImport({
|
||||
actorEmail: user.email!,
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
} from "@app/ee/services/permission/permission-fns";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { ProjectPermissionGroupActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
import { ms } from "@app/lib/ms";
|
||||
@@ -214,14 +213,14 @@ export const groupProjectServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const botPrivateKey = infisicalSymmetricDecrypt({
|
||||
const botPrivateKey = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
keyEncoding: bot.keyEncoding as SecretKeyEncoding,
|
||||
iv: bot.iv,
|
||||
tag: bot.tag,
|
||||
ciphertext: bot.encryptedPrivateKey
|
||||
});
|
||||
|
||||
const plaintextProjectKey = decryptAsymmetric({
|
||||
const plaintextProjectKey = crypto.encryption().asymmetric().decrypt({
|
||||
ciphertext: ghostUserLatestKey.encryptedKey,
|
||||
nonce: ghostUserLatestKey.nonce,
|
||||
publicKey: ghostUserLatestKey.sender.publicKey,
|
||||
@@ -229,7 +228,10 @@ export const groupProjectServiceFactory = ({
|
||||
});
|
||||
|
||||
const projectKeyData = groupMembers.map(({ user: { publicKey, id } }) => {
|
||||
const { ciphertext: encryptedKey, nonce } = encryptAsymmetric(plaintextProjectKey, publicKey, botPrivateKey);
|
||||
const { ciphertext: encryptedKey, nonce } = crypto
|
||||
.encryption()
|
||||
.asymmetric()
|
||||
.encrypt(plaintextProjectKey, publicKey, botPrivateKey);
|
||||
|
||||
return {
|
||||
encryptedKey,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
@@ -13,6 +11,7 @@ import {
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { extractX509CertFromChain } from "@app/lib/certificates/extract-certificate";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
@@ -87,8 +86,8 @@ export const identityTlsCertAuthServiceFactory = ({
|
||||
throw new BadRequestError({ message: "Missing client certificate" });
|
||||
}
|
||||
|
||||
const clientCertificateX509 = new crypto.X509Certificate(leafCertificate);
|
||||
const caCertificateX509 = new crypto.X509Certificate(caCertificate);
|
||||
const clientCertificateX509 = new crypto.rawCrypto.X509Certificate(leafCertificate);
|
||||
const caCertificateX509 = new crypto.rawCrypto.X509Certificate(caCertificate);
|
||||
|
||||
const isValidCertificate = clientCertificateX509.verify(caCertificateX509.publicKey);
|
||||
if (!isValidCertificate)
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
import { IdentityAuthMethod } from "@app/db/schemas";
|
||||
@@ -13,6 +10,7 @@ import {
|
||||
} from "@app/ee/services/permission/permission-fns";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr, TIp } from "@app/lib/ip";
|
||||
|
||||
@@ -76,7 +74,8 @@ export const identityUaServiceFactory = ({
|
||||
|
||||
let validClientSecretInfo: (typeof clientSecrtInfo)[0] | null = null;
|
||||
for await (const info of clientSecrtInfo) {
|
||||
const isMatch = await bcrypt.compare(clientSecret, info.clientSecretHash);
|
||||
const isMatch = await crypto.hashing().compareHash(clientSecret, info.clientSecretHash);
|
||||
|
||||
if (isMatch) {
|
||||
validClientSecretInfo = info;
|
||||
break;
|
||||
@@ -250,7 +249,7 @@ export const identityUaServiceFactory = ({
|
||||
const doc = await identityUaDAL.create(
|
||||
{
|
||||
identityId: identityMembershipOrg.identityId,
|
||||
clientId: crypto.randomUUID(),
|
||||
clientId: crypto.rawCrypto.randomUUID(),
|
||||
clientSecretTrustedIps: JSON.stringify(reformattedClientSecretTrustedIps),
|
||||
accessTokenMaxTTL,
|
||||
accessTokenTTL,
|
||||
@@ -494,7 +493,7 @@ export const identityUaServiceFactory = ({
|
||||
|
||||
const appCfg = getConfig();
|
||||
const clientSecret = crypto.randomBytes(32).toString("hex");
|
||||
const clientSecretHash = await bcrypt.hash(clientSecret, appCfg.SALT_ROUNDS);
|
||||
const clientSecretHash = await crypto.hashing().createHash(clientSecret, appCfg.SALT_ROUNDS);
|
||||
|
||||
const identityUaAuth = await identityUaDAL.findOne({ identityId: identityMembershipOrg.identityId });
|
||||
if (!identityUaAuth) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
|
||||
@@ -15,7 +15,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { decryptSymmetric128BitHexKeyUTF8, encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, InternalServerError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -228,13 +228,22 @@ export const integrationAuthServiceFactory = ({
|
||||
} else {
|
||||
if (!botKey) throw new NotFoundError({ message: `Project bot key for project with ID '${projectId}' not found` });
|
||||
if (tokenExchange.refreshToken) {
|
||||
const refreshEncToken = encryptSymmetric128BitHexKeyUTF8(tokenExchange.refreshToken, botKey);
|
||||
const refreshEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenExchange.refreshToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
updateDoc.refreshIV = refreshEncToken.iv;
|
||||
updateDoc.refreshTag = refreshEncToken.tag;
|
||||
updateDoc.refreshCiphertext = refreshEncToken.ciphertext;
|
||||
}
|
||||
if (tokenExchange.accessToken) {
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(tokenExchange.accessToken, botKey);
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenExchange.accessToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.accessIV = accessEncToken.iv;
|
||||
updateDoc.accessTag = accessEncToken.tag;
|
||||
updateDoc.accessCiphertext = accessEncToken.ciphertext;
|
||||
@@ -357,11 +366,19 @@ export const integrationAuthServiceFactory = ({
|
||||
url,
|
||||
updateDoc.metadata as Record<string, string>
|
||||
);
|
||||
const refreshEncToken = encryptSymmetric128BitHexKeyUTF8(tokenDetails.refreshToken, botKey);
|
||||
const refreshEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenDetails.refreshToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.refreshIV = refreshEncToken.iv;
|
||||
updateDoc.refreshTag = refreshEncToken.tag;
|
||||
updateDoc.refreshCiphertext = refreshEncToken.ciphertext;
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(tokenDetails.accessToken, botKey);
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenDetails.accessToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.accessIV = accessEncToken.iv;
|
||||
updateDoc.accessTag = accessEncToken.tag;
|
||||
updateDoc.accessCiphertext = accessEncToken.ciphertext;
|
||||
@@ -371,19 +388,31 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
if (!refreshToken && (accessId || accessToken || awsAssumeIamRoleArn)) {
|
||||
if (accessToken) {
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(accessToken, botKey);
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: accessToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.accessIV = accessEncToken.iv;
|
||||
updateDoc.accessTag = accessEncToken.tag;
|
||||
updateDoc.accessCiphertext = accessEncToken.ciphertext;
|
||||
}
|
||||
if (accessId) {
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(accessId, botKey);
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: accessId,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.accessIdIV = accessEncToken.iv;
|
||||
updateDoc.accessIdTag = accessEncToken.tag;
|
||||
updateDoc.accessIdCiphertext = accessEncToken.ciphertext;
|
||||
}
|
||||
if (awsAssumeIamRoleArn) {
|
||||
const awsAssumeIamRoleArnEnc = encryptSymmetric128BitHexKeyUTF8(awsAssumeIamRoleArn, botKey);
|
||||
const awsAssumeIamRoleArnEnc = crypto.encryption().encryptSymmetric({
|
||||
plaintext: awsAssumeIamRoleArn,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.awsAssumeIamRoleArnCipherText = awsAssumeIamRoleArnEnc.ciphertext;
|
||||
updateDoc.awsAssumeIamRoleArnIV = awsAssumeIamRoleArnEnc.iv;
|
||||
updateDoc.awsAssumeIamRoleArnTag = awsAssumeIamRoleArnEnc.tag;
|
||||
@@ -499,11 +528,21 @@ export const integrationAuthServiceFactory = ({
|
||||
url,
|
||||
updateDoc.metadata as Record<string, string>
|
||||
);
|
||||
const refreshEncToken = encryptSymmetric128BitHexKeyUTF8(tokenDetails.refreshToken, botKey);
|
||||
const refreshEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenDetails.refreshToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.refreshIV = refreshEncToken.iv;
|
||||
updateDoc.refreshTag = refreshEncToken.tag;
|
||||
updateDoc.refreshCiphertext = refreshEncToken.ciphertext;
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(tokenDetails.accessToken, botKey);
|
||||
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenDetails.accessToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
updateDoc.accessIV = accessEncToken.iv;
|
||||
updateDoc.accessTag = accessEncToken.tag;
|
||||
updateDoc.accessCiphertext = accessEncToken.ciphertext;
|
||||
@@ -513,19 +552,32 @@ export const integrationAuthServiceFactory = ({
|
||||
|
||||
if (!refreshToken && (accessId || accessToken || awsAssumeIamRoleArn)) {
|
||||
if (accessToken) {
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(accessToken, botKey);
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: accessToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.accessIV = accessEncToken.iv;
|
||||
updateDoc.accessTag = accessEncToken.tag;
|
||||
updateDoc.accessCiphertext = accessEncToken.ciphertext;
|
||||
}
|
||||
if (accessId) {
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(accessId, botKey);
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: accessId,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
updateDoc.accessIdIV = accessEncToken.iv;
|
||||
updateDoc.accessIdTag = accessEncToken.tag;
|
||||
updateDoc.accessIdCiphertext = accessEncToken.ciphertext;
|
||||
}
|
||||
if (awsAssumeIamRoleArn) {
|
||||
const awsAssumeIamRoleArnEnc = encryptSymmetric128BitHexKeyUTF8(awsAssumeIamRoleArn, botKey);
|
||||
const awsAssumeIamRoleArnEnc = crypto.encryption().encryptSymmetric({
|
||||
plaintext: awsAssumeIamRoleArn,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
updateDoc.awsAssumeIamRoleArnCipherText = awsAssumeIamRoleArnEnc.ciphertext;
|
||||
updateDoc.awsAssumeIamRoleArnIV = awsAssumeIamRoleArnEnc.iv;
|
||||
updateDoc.awsAssumeIamRoleArnTag = awsAssumeIamRoleArnEnc.tag;
|
||||
@@ -608,20 +660,22 @@ export const integrationAuthServiceFactory = ({
|
||||
} else {
|
||||
if (!botKey) throw new NotFoundError({ message: "Project bot key not found" });
|
||||
if (integrationAuth.accessTag && integrationAuth.accessIV && integrationAuth.accessCiphertext) {
|
||||
accessToken = decryptSymmetric128BitHexKeyUTF8({
|
||||
accessToken = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: integrationAuth.accessCiphertext,
|
||||
iv: integrationAuth.accessIV,
|
||||
tag: integrationAuth.accessTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
}
|
||||
|
||||
if (integrationAuth.refreshCiphertext && integrationAuth.refreshIV && integrationAuth.refreshTag) {
|
||||
const refreshToken = decryptSymmetric128BitHexKeyUTF8({
|
||||
const refreshToken = crypto.encryption().decryptSymmetric({
|
||||
key: botKey,
|
||||
ciphertext: integrationAuth.refreshCiphertext,
|
||||
iv: integrationAuth.refreshIV,
|
||||
tag: integrationAuth.refreshTag
|
||||
tag: integrationAuth.refreshTag,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
if (integrationAuth.accessExpiresAt && integrationAuth.accessExpiresAt < new Date()) {
|
||||
@@ -632,8 +686,18 @@ export const integrationAuthServiceFactory = ({
|
||||
integrationAuth?.url,
|
||||
integrationAuth.metadata as Record<string, string>
|
||||
);
|
||||
const refreshEncToken = encryptSymmetric128BitHexKeyUTF8(tokenDetails.refreshToken, botKey);
|
||||
const accessEncToken = encryptSymmetric128BitHexKeyUTF8(tokenDetails.accessToken, botKey);
|
||||
|
||||
const refreshEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenDetails.refreshToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
const accessEncToken = crypto.encryption().encryptSymmetric({
|
||||
plaintext: tokenDetails.accessToken,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
accessToken = tokenDetails.accessToken;
|
||||
await integrationAuthDAL.updateById(integrationAuth.id, {
|
||||
refreshIV: refreshEncToken.iv,
|
||||
@@ -649,11 +713,12 @@ export const integrationAuthServiceFactory = ({
|
||||
if (!accessToken) throw new BadRequestError({ message: "Missing access token" });
|
||||
|
||||
if (integrationAuth.accessIdTag && integrationAuth.accessIdIV && integrationAuth.accessIdCiphertext) {
|
||||
accessId = decryptSymmetric128BitHexKeyUTF8({
|
||||
accessId = crypto.encryption().decryptSymmetric({
|
||||
key: botKey,
|
||||
ciphertext: integrationAuth.accessIdCiphertext,
|
||||
iv: integrationAuth.accessIdIV,
|
||||
tag: integrationAuth.accessIdTag
|
||||
tag: integrationAuth.accessIdTag,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Octokit } from "@octokit/rest";
|
||||
|
||||
import { TIntegrationAuths, TIntegrations } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
|
||||
@@ -109,12 +109,14 @@ const getIntegrationSecretsV1 = async (
|
||||
|
||||
// process secrets in current folder
|
||||
const secrets = await secretDAL.findByFolderId(dto.folderId);
|
||||
|
||||
secrets.forEach((secret) => {
|
||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key: dto.key
|
||||
key: dto.key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
content[secretKey] = true;
|
||||
|
||||
@@ -23,7 +23,6 @@ import { createAppAuth } from "@octokit/auth-app";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import AWS, { AWSError } from "aws-sdk";
|
||||
import { AxiosError } from "axios";
|
||||
import { randomUUID } from "crypto";
|
||||
import https from "https";
|
||||
import sodium from "libsodium-wrappers";
|
||||
import isEqual from "lodash.isequal";
|
||||
@@ -33,6 +32,7 @@ import { z } from "zod";
|
||||
import { SecretType, TIntegrationAuths, TIntegrations } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, InternalServerError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { TCreateManySecretsRawFn, TUpdateManySecretsRawFn } from "@app/services/secret/secret-types";
|
||||
@@ -806,7 +806,7 @@ const syncSecretsAWSParameterStore = async ({
|
||||
});
|
||||
const command = new AssumeRoleCommand({
|
||||
RoleArn: awsAssumeRoleArn,
|
||||
RoleSessionName: `infisical-parameter-store-${randomUUID()}`,
|
||||
RoleSessionName: `infisical-parameter-store-${crypto.rawCrypto.randomUUID()}`,
|
||||
DurationSeconds: 900, // 15mins
|
||||
ExternalId: projectId
|
||||
});
|
||||
@@ -1126,7 +1126,7 @@ const syncSecretsAWSSecretManager = async ({
|
||||
});
|
||||
const command = new AssumeRoleCommand({
|
||||
RoleArn: awsAssumeRoleArn,
|
||||
RoleSessionName: `infisical-sm-${randomUUID()}`,
|
||||
RoleSessionName: `infisical-sm-${crypto.rawCrypto.randomUUID()}`,
|
||||
DurationSeconds: 900, // 15mins
|
||||
ExternalId: projectId
|
||||
});
|
||||
|
||||
@@ -14,9 +14,8 @@ import {
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { KeyStorePrefixes, PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { TEnvConfig } from "@app/lib/config/env";
|
||||
import { randomSecureBytes } from "@app/lib/crypto";
|
||||
import { symmetricCipherService, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
|
||||
import { generateHash } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { AsymmetricKeyAlgorithm, signingService } from "@app/lib/crypto/sign";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -101,7 +100,7 @@ export const kmsServiceFactory = ({
|
||||
|
||||
let kmsKeyMaterial: Buffer | null = null;
|
||||
if (keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT) {
|
||||
kmsKeyMaterial = randomSecureBytes(
|
||||
kmsKeyMaterial = crypto.randomBytes(
|
||||
getByteLengthForSymmetricEncryptionAlgorithm(encryptionAlgorithm as SymmetricKeyAlgorithm)
|
||||
);
|
||||
} else if (keyUsage === KmsKeyUsage.SIGN_VERIFY) {
|
||||
@@ -618,7 +617,7 @@ export const kmsServiceFactory = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const dataKey = randomSecureBytes();
|
||||
const dataKey = crypto.randomBytes(32);
|
||||
const kmsEncryptor = await encryptWithKmsKey(
|
||||
{
|
||||
kmsId: kmsKeyId
|
||||
@@ -761,7 +760,7 @@ export const kmsServiceFactory = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const dataKey = randomSecureBytes();
|
||||
const dataKey = crypto.randomBytes(32);
|
||||
const kmsEncryptor = await encryptWithKmsKey(
|
||||
{
|
||||
kmsId: kmsKeyId
|
||||
@@ -994,7 +993,7 @@ export const kmsServiceFactory = ({
|
||||
"base64"
|
||||
)}`;
|
||||
|
||||
const verificationHash = generateHash(secretManagerBackup);
|
||||
const verificationHash = crypto.rawCrypto.createHash("sha256").update(secretManagerBackup).digest("hex");
|
||||
secretManagerBackup = `${secretManagerBackup}.${verificationHash}`;
|
||||
|
||||
return {
|
||||
@@ -1011,7 +1010,12 @@ export const kmsServiceFactory = ({
|
||||
}
|
||||
|
||||
const [, backupProjectId, , backupKmsKeyId, backupBase64EncryptedDataKey, backupHash] = backup.split(".");
|
||||
const computedHash = generateHash(backup.substring(0, backup.lastIndexOf(".")));
|
||||
|
||||
const computedHash = crypto.rawCrypto
|
||||
.createHash("sha256")
|
||||
.update(backup.substring(0, backup.lastIndexOf(".")))
|
||||
.digest("hex");
|
||||
|
||||
if (computedHash !== backupHash) {
|
||||
throw new BadRequestError({
|
||||
message: "Invalid backup"
|
||||
@@ -1075,7 +1079,7 @@ export const kmsServiceFactory = ({
|
||||
if (existingRootConfig) return existingRootConfig;
|
||||
|
||||
logger.info("KMS: Generating new ROOT Key");
|
||||
const newRootKey = randomSecureBytes(32);
|
||||
const newRootKey = crypto.randomBytes(32);
|
||||
const encryptedRootKey = await $encryptRootKey(newRootKey, RootKeyEncryptionStrategy.Software).catch((err) => {
|
||||
logger.error({ hsmEnabled: hsmService.isActive() }, "KMS: Failed to encrypt ROOT Key");
|
||||
throw err;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability";
|
||||
import { ProjectMembershipRole, ProjectVersion, SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { OrgPermissionAdminConsoleAction, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
@@ -144,7 +144,7 @@ export const orgAdminServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const botPrivateKey = infisicalSymmetricDecrypt({
|
||||
const botPrivateKey = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
keyEncoding: bot.keyEncoding as SecretKeyEncoding,
|
||||
iv: bot.iv,
|
||||
tag: bot.tag,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import crypto from "crypto";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { Knex } from "knex";
|
||||
|
||||
@@ -34,8 +33,7 @@ import { ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/ee/se
|
||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||
import { TSamlConfigDALFactory } from "@app/ee/services/saml-config/saml-config-dal";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { generateAsymmetricKeyPair } from "@app/lib/crypto";
|
||||
import { generateSymmetricKey, infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { generateUserSrpKeys } from "@app/lib/crypto/srp";
|
||||
import {
|
||||
BadRequestError,
|
||||
@@ -251,6 +249,7 @@ export const orgServiceFactory = ({
|
||||
|
||||
const addGhostUser = async (orgId: string, tx?: Knex) => {
|
||||
const email = `sudo-${alphaNumericNanoId(16)}-${orgId}@infisical.com`; // We add a nanoid because the email is unique. And we have to create a new ghost user each time, so we can have access to the private key.
|
||||
|
||||
const password = crypto.randomBytes(128).toString("hex");
|
||||
|
||||
const user = await userDAL.create(
|
||||
@@ -492,22 +491,22 @@ export const orgServiceFactory = ({
|
||||
orgName: string;
|
||||
userEmail?: string | null;
|
||||
}) => {
|
||||
const { privateKey, publicKey } = generateAsymmetricKeyPair();
|
||||
const key = generateSymmetricKey();
|
||||
const { privateKey, publicKey } = crypto.encryption().asymmetric().generateKeyPair();
|
||||
const key = crypto.randomBytes(32).toString("base64");
|
||||
const {
|
||||
ciphertext: encryptedPrivateKey,
|
||||
iv: privateKeyIV,
|
||||
tag: privateKeyTag,
|
||||
encoding: privateKeyKeyEncoding,
|
||||
algorithm: privateKeyAlgorithm
|
||||
} = infisicalSymmetricEncypt(privateKey);
|
||||
} = crypto.encryption().encryptWithRootEncryptionKey(privateKey);
|
||||
const {
|
||||
ciphertext: encryptedSymmetricKey,
|
||||
iv: symmetricKeyIV,
|
||||
tag: symmetricKeyTag,
|
||||
encoding: symmetricKeyKeyEncoding,
|
||||
algorithm: symmetricKeyAlgorithm
|
||||
} = infisicalSymmetricEncypt(key);
|
||||
} = crypto.encryption().encryptWithRootEncryptionKey(key);
|
||||
|
||||
const customerId = await licenseService.generateOrgCustomerId(orgName, userEmail);
|
||||
const organization = await orgDAL.transaction(async (tx) => {
|
||||
@@ -825,6 +824,7 @@ export const orgServiceFactory = ({
|
||||
const mailsForOrgInvitation: { email: string; userId: string; firstName: string; lastName: string }[] = [];
|
||||
const mailsForProjectInvitation: { email: string[]; projectName: string }[] = [];
|
||||
const newProjectMemberships: TProjectMemberships[] = [];
|
||||
|
||||
await orgDAL.transaction(async (tx) => {
|
||||
const users: Pick<TUsers, "id" | "firstName" | "lastName" | "email" | "username">[] = [];
|
||||
|
||||
@@ -864,7 +864,9 @@ export const orgServiceFactory = ({
|
||||
// Then when user sign in (as login is not possible as isAccepted is false) we rencrypt the private key with the user password
|
||||
if (!inviteeUser || (inviteeUser && !inviteeUser?.isAccepted && !existingEncrytionKey)) {
|
||||
const serverGeneratedPassword = crypto.randomBytes(32).toString("hex");
|
||||
const { tag, encoding, ciphertext, iv } = infisicalSymmetricEncypt(serverGeneratedPassword);
|
||||
const { tag, encoding, ciphertext, iv } = crypto
|
||||
.encryption()
|
||||
.encryptWithRootEncryptionKey(serverGeneratedPassword);
|
||||
const encKeys = await generateUserSrpKeys(inviteeEmail, serverGeneratedPassword);
|
||||
await userDAL.createUserEncryption(
|
||||
{
|
||||
@@ -1091,9 +1093,9 @@ export const orgServiceFactory = ({
|
||||
tx
|
||||
);
|
||||
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = infisicalSymmetricEncypt(
|
||||
newGhostUser.keys.plainPrivateKey
|
||||
);
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = crypto
|
||||
.encryption()
|
||||
.encryptWithRootEncryptionKey(newGhostUser.keys.plainPrivateKey);
|
||||
if (autoGeneratedBot) {
|
||||
await projectBotDAL.updateById(
|
||||
autoGeneratedBot.id,
|
||||
@@ -1131,7 +1133,7 @@ export const orgServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const botPrivateKey = infisicalSymmetricDecrypt({
|
||||
const botPrivateKey = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
keyEncoding: bot.keyEncoding as SecretKeyEncoding,
|
||||
iv: bot.iv,
|
||||
tag: bot.tag,
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
import { SecretKeyEncoding } from "@app/db/schemas";
|
||||
import {
|
||||
decryptAsymmetric,
|
||||
encryptAsymmetric,
|
||||
generateAsymmetricKeyPair,
|
||||
infisicalSymmetricDecrypt,
|
||||
infisicalSymmetricEncypt
|
||||
} from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TGetPrivateKeyDTO } from "./project-bot-types";
|
||||
|
||||
export const getBotPrivateKey = ({ bot }: TGetPrivateKeyDTO) =>
|
||||
infisicalSymmetricDecrypt({
|
||||
export const getBotPrivateKey = ({ bot }: TGetPrivateKeyDTO) => {
|
||||
return crypto.encryption().decryptWithRootEncryptionKey({
|
||||
keyEncoding: bot.keyEncoding as SecretKeyEncoding,
|
||||
iv: bot.iv,
|
||||
tag: bot.tag,
|
||||
ciphertext: bot.encryptedPrivateKey
|
||||
});
|
||||
};
|
||||
|
||||
export const getBotKeyFnFactory = (
|
||||
projectBotDAL: TProjectBotDALFactory,
|
||||
@@ -51,22 +46,27 @@ export const getBotKeyFnFactory = (
|
||||
projectV1Keys.serverEncryptedPrivateKeyTag &&
|
||||
projectV1Keys.serverEncryptedPrivateKeyEncoding
|
||||
) {
|
||||
userPrivateKey = infisicalSymmetricDecrypt({
|
||||
userPrivateKey = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
iv: projectV1Keys.serverEncryptedPrivateKeyIV,
|
||||
tag: projectV1Keys.serverEncryptedPrivateKeyTag,
|
||||
ciphertext: projectV1Keys.serverEncryptedPrivateKey,
|
||||
keyEncoding: projectV1Keys.serverEncryptedPrivateKeyEncoding as SecretKeyEncoding
|
||||
});
|
||||
}
|
||||
const workspaceKey = decryptAsymmetric({
|
||||
const workspaceKey = crypto.encryption().asymmetric().decrypt({
|
||||
ciphertext: projectV1Keys.projectEncryptedKey,
|
||||
nonce: projectV1Keys.projectKeyNonce,
|
||||
publicKey: projectV1Keys.senderPublicKey,
|
||||
privateKey: userPrivateKey
|
||||
});
|
||||
const botKey = generateAsymmetricKeyPair();
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = infisicalSymmetricEncypt(botKey.privateKey);
|
||||
const encryptedWorkspaceKey = encryptAsymmetric(workspaceKey, botKey.publicKey, userPrivateKey);
|
||||
const botKey = crypto.encryption().asymmetric().generateKeyPair();
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = crypto
|
||||
.encryption()
|
||||
.encryptWithRootEncryptionKey(botKey.privateKey);
|
||||
const encryptedWorkspaceKey = crypto
|
||||
.encryption()
|
||||
.asymmetric()
|
||||
.encrypt(workspaceKey, botKey.publicKey, userPrivateKey);
|
||||
|
||||
let botId;
|
||||
if (!bot) {
|
||||
@@ -105,7 +105,7 @@ export const getBotKeyFnFactory = (
|
||||
}
|
||||
|
||||
const botPrivateKey = getBotPrivateKey({ bot });
|
||||
const botKey = decryptAsymmetric({
|
||||
const botKey = crypto.encryption().asymmetric().decrypt({
|
||||
ciphertext: bot.encryptedProjectKey,
|
||||
privateKey: botPrivateKey,
|
||||
nonce: bot.encryptedProjectKeyNonce,
|
||||
|
||||
@@ -3,8 +3,7 @@ import { ForbiddenError } from "@casl/ability";
|
||||
import { ActionProjectType, ProjectVersion } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { generateAsymmetricKeyPair } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
@@ -55,9 +54,12 @@ export const projectBotServiceFactory = ({
|
||||
const doc = await projectBotDAL.findOne({ projectId }, tx);
|
||||
if (doc) return doc;
|
||||
|
||||
const keys = privateKey && publicKey ? { privateKey, publicKey } : generateAsymmetricKeyPair();
|
||||
const keys =
|
||||
privateKey && publicKey ? { privateKey, publicKey } : crypto.encryption().asymmetric().generateKeyPair();
|
||||
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = infisicalSymmetricEncypt(keys.privateKey);
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = crypto
|
||||
.encryption()
|
||||
.encryptWithRootEncryptionKey(keys.privateKey);
|
||||
|
||||
const project = await projectDAL.findById(projectId, tx);
|
||||
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
import { TSecretSharing } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { SecretSharingAccessType } from "@app/lib/types";
|
||||
@@ -136,7 +133,7 @@ export const secretSharingServiceFactory = ({
|
||||
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
||||
|
||||
const id = crypto.randomBytes(32).toString("hex");
|
||||
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
||||
const hashedPassword = password ? await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS) : null;
|
||||
|
||||
const newSharedSecret = await secretSharingDAL.create({
|
||||
identifier: id,
|
||||
@@ -386,8 +383,10 @@ export const secretSharingServiceFactory = ({
|
||||
const encryptWithRoot = kmsService.encryptWithRootKey();
|
||||
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
||||
|
||||
const appCfg = getConfig();
|
||||
|
||||
const id = crypto.randomBytes(32).toString("hex");
|
||||
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
||||
const hashedPassword = password ? await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS) : null;
|
||||
|
||||
const newSharedSecret = await secretSharingDAL.create({
|
||||
identifier: id,
|
||||
@@ -529,7 +528,7 @@ export const secretSharingServiceFactory = ({
|
||||
const hasProvidedPassword = Boolean(password);
|
||||
if (isPasswordProtected) {
|
||||
if (hasProvidedPassword) {
|
||||
const isMatch = await bcrypt.compare(password as string, sharedSecret.password as string);
|
||||
const isMatch = await crypto.hashing().compareHash(password as string, sharedSecret.password as string);
|
||||
if (!isMatch) throw new UnauthorizedError({ message: "Invalid credentials" });
|
||||
} else {
|
||||
return { isPasswordProtected };
|
||||
|
||||
@@ -16,11 +16,8 @@ import { hasSecretReadValueOrDescribePermission } from "@app/ee/services/permiss
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { ProjectPermissionSecretActions } from "@app/ee/services/permission/project-permission";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import {
|
||||
buildSecretBlindIndexFromName,
|
||||
decryptSymmetric128BitHexKeyUTF8,
|
||||
encryptSymmetric128BitHexKeyUTF8
|
||||
} from "@app/lib/crypto";
|
||||
import { buildSecretBlindIndexFromName } from "@app/lib/crypto";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { daysToMillisecond, secondsToMillis } from "@app/lib/dates";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy, unique } from "@app/lib/fn";
|
||||
@@ -239,17 +236,19 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
|
||||
const secrets = await secretDAL.findByFolderId(folder.id);
|
||||
|
||||
const decryptedSec = secrets.reduce<Record<string, string>>((prev, secret) => {
|
||||
const decryptedSecretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const decryptedSecretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key: secretEncKey
|
||||
key: secretEncKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const decryptedSecretValue = decryptSymmetric128BitHexKeyUTF8({
|
||||
const decryptedSecretValue = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretValueCiphertext,
|
||||
iv: secret.secretValueIV,
|
||||
tag: secret.secretValueTag,
|
||||
key: secretEncKey
|
||||
key: secretEncKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
@@ -366,30 +365,33 @@ export const decryptSecretRaw = (
|
||||
},
|
||||
key: string
|
||||
) => {
|
||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key
|
||||
key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
const secretValue = !secret.secretValueHidden
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretValueCiphertext,
|
||||
iv: secret.secretValueIV,
|
||||
tag: secret.secretValueTag,
|
||||
key
|
||||
key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: INFISICAL_SECRET_VALUE_HIDDEN_MASK;
|
||||
|
||||
let secretComment = "";
|
||||
|
||||
if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) {
|
||||
secretComment = decryptSymmetric128BitHexKeyUTF8({
|
||||
secretComment = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretCommentCiphertext,
|
||||
iv: secret.secretCommentIV,
|
||||
tag: secret.secretCommentTag,
|
||||
key
|
||||
key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
}
|
||||
|
||||
@@ -877,11 +879,24 @@ export const createManySecretsRawFnFactory = ({
|
||||
message: `Project bot not found for project with ID '${projectId}'. Please upgrade your project.`,
|
||||
name: "bot_not_found_error"
|
||||
});
|
||||
|
||||
const inputSecrets = secrets.map((secret) => {
|
||||
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(secret.secretName, botKey);
|
||||
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secret.secretValue || "", botKey);
|
||||
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secret.secretName,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secret.secretValue || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretReferences = getAllNestedSecretReferences(secret.secretValue || "");
|
||||
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secret.secretComment || "", botKey);
|
||||
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secret.secretComment || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
return {
|
||||
type: secret.type,
|
||||
@@ -1065,10 +1080,22 @@ export const updateManySecretsRawFnFactory = ({
|
||||
throw new BadRequestError({ message: "New secret name cannot be empty" });
|
||||
}
|
||||
|
||||
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(secret.secretName, botKey);
|
||||
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secret.secretValue || "", botKey);
|
||||
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secret.secretName,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secret.secretValue || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretReferences = getAllNestedSecretReferences(secret.secretValue || "");
|
||||
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secret.secretComment || "", botKey);
|
||||
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secret.secretComment || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
return {
|
||||
type: secret.type,
|
||||
@@ -1151,28 +1178,31 @@ export const decryptSecretWithBot = (
|
||||
>,
|
||||
key: string
|
||||
) => {
|
||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key
|
||||
key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
const secretValue = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretValue = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretValueCiphertext,
|
||||
iv: secret.secretValueIV,
|
||||
tag: secret.secretValueTag,
|
||||
key
|
||||
key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
let secretComment = "";
|
||||
|
||||
if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) {
|
||||
secretComment = decryptSymmetric128BitHexKeyUTF8({
|
||||
secretComment = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretCommentCiphertext,
|
||||
iv: secret.secretCommentIV,
|
||||
tag: secret.secretCommentTag,
|
||||
key
|
||||
key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ import { TSnapshotDALFactory } from "@app/ee/services/secret-snapshot/snapshot-d
|
||||
import { TSnapshotSecretV2DALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-v2-dal";
|
||||
import { KeyStorePrefixes, KeyStoreTtls, TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { daysToMillisecond, secondsToMillis } from "@app/lib/dates";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { getTimeDifferenceInSeconds, groupBy, isSamePath, unique } from "@app/lib/fn";
|
||||
@@ -504,18 +503,20 @@ export const secretQueueFactory = ({
|
||||
const secrets = await secretDAL.findByFolderId(dto.folderId);
|
||||
await Promise.allSettled(
|
||||
secrets.map(async (secret) => {
|
||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key: dto.key
|
||||
key: dto.key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
const secretValue = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretValue = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretValueCiphertext,
|
||||
iv: secret.secretValueIV,
|
||||
tag: secret.secretValueTag,
|
||||
key: dto.key
|
||||
key: dto.key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const expandedSecretValue = await expandSecretReferences({
|
||||
environment: dto.environment,
|
||||
@@ -527,11 +528,12 @@ export const secretQueueFactory = ({
|
||||
content[secretKey] = { value: expandedSecretValue || "" };
|
||||
|
||||
if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) {
|
||||
const commentValue = decryptSymmetric128BitHexKeyUTF8({
|
||||
const commentValue = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretCommentCiphertext,
|
||||
iv: secret.secretCommentIV,
|
||||
tag: secret.secretCommentTag,
|
||||
key: dto.key
|
||||
key: dto.key,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
content[secretKey].comment = commentValue;
|
||||
}
|
||||
@@ -952,11 +954,12 @@ export const secretQueueFactory = ({
|
||||
integrationAuth.awsAssumeIamRoleArnIV &&
|
||||
integrationAuth.awsAssumeIamRoleArnCipherText
|
||||
) {
|
||||
awsAssumeRoleArn = decryptSymmetric128BitHexKeyUTF8({
|
||||
awsAssumeRoleArn = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: integrationAuth.awsAssumeIamRoleArnCipherText,
|
||||
iv: integrationAuth.awsAssumeIamRoleArnIV,
|
||||
tag: integrationAuth.awsAssumeIamRoleArnTag,
|
||||
key: botKey as string
|
||||
key: botKey as string,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1236,7 +1239,9 @@ export const secretQueueFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = infisicalSymmetricEncypt(ghostUser.keys.plainPrivateKey);
|
||||
const { iv, tag, ciphertext, encoding, algorithm } = crypto
|
||||
.encryption()
|
||||
.encryptWithRootEncryptionKey(ghostUser.keys.plainPrivateKey);
|
||||
await projectBotDAL.updateById(
|
||||
bot.id,
|
||||
{
|
||||
@@ -1267,27 +1272,31 @@ export const secretQueueFactory = ({
|
||||
secretId: string;
|
||||
references: { environment: string; secretPath: string; secretKey: string }[];
|
||||
}[] = [];
|
||||
|
||||
await secretV2BridgeDAL.batchInsert(
|
||||
projectV1Secrets.map((el) => {
|
||||
const key = decryptSymmetric128BitHexKeyUTF8({
|
||||
const key = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretKeyCiphertext,
|
||||
iv: el.secretKeyIV,
|
||||
tag: el.secretKeyTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const value = decryptSymmetric128BitHexKeyUTF8({
|
||||
const value = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretValueCiphertext,
|
||||
iv: el.secretValueIV,
|
||||
tag: el.secretValueTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const comment =
|
||||
el.secretCommentCiphertext && el.secretCommentTag && el.secretCommentIV
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretCommentCiphertext,
|
||||
iv: el.secretCommentIV,
|
||||
tag: el.secretCommentTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: "";
|
||||
const encryptedValue = secretManagerEncryptor({ plainText: Buffer.from(value) }).cipherTextBlob;
|
||||
@@ -1325,6 +1334,7 @@ export const secretQueueFactory = ({
|
||||
const projectV3SecretVersionsGroupById: Record<string, TSecretVersionsV2> = {};
|
||||
const projectV3SecretVersionTags: { secret_versions_v2Id: string; secret_tagsId: string }[] = [];
|
||||
const projectV3SnapshotSecrets: Omit<TSecretSnapshotSecretsV2, "id">[] = [];
|
||||
|
||||
snapshots.forEach(({ secretVersions = [], ...snapshot }) => {
|
||||
secretVersions.forEach((el) => {
|
||||
projectV3SnapshotSecrets.push({
|
||||
@@ -1336,25 +1346,28 @@ export const secretQueueFactory = ({
|
||||
});
|
||||
if (projectV3SecretVersionsGroupById[el.id]) return;
|
||||
|
||||
const key = decryptSymmetric128BitHexKeyUTF8({
|
||||
const key = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretKeyCiphertext,
|
||||
iv: el.secretKeyIV,
|
||||
tag: el.secretKeyTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const value = decryptSymmetric128BitHexKeyUTF8({
|
||||
const value = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretValueCiphertext,
|
||||
iv: el.secretValueIV,
|
||||
tag: el.secretValueTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const comment =
|
||||
el.secretCommentCiphertext && el.secretCommentTag && el.secretCommentIV
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretCommentCiphertext,
|
||||
iv: el.secretCommentIV,
|
||||
tag: el.secretCommentTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: "";
|
||||
const encryptedValue = secretManagerEncryptor({ plainText: Buffer.from(value) }).cipherTextBlob;
|
||||
@@ -1395,25 +1408,28 @@ export const secretQueueFactory = ({
|
||||
);
|
||||
Object.values(latestSecretVersionByFolder).forEach((el) => {
|
||||
if (projectV3SecretVersionsGroupById[el.id]) return;
|
||||
const key = decryptSymmetric128BitHexKeyUTF8({
|
||||
const key = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretKeyCiphertext,
|
||||
iv: el.secretKeyIV,
|
||||
tag: el.secretKeyTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const value = decryptSymmetric128BitHexKeyUTF8({
|
||||
const value = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretValueCiphertext,
|
||||
iv: el.secretValueIV,
|
||||
tag: el.secretValueTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const comment =
|
||||
el.secretCommentCiphertext && el.secretCommentTag && el.secretCommentIV
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.secretCommentCiphertext,
|
||||
iv: el.secretCommentIV,
|
||||
tag: el.secretCommentTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: "";
|
||||
const encryptedValue = secretManagerEncryptor({ plainText: Buffer.from(value) }).cipherTextBlob;
|
||||
@@ -1475,42 +1491,47 @@ export const secretQueueFactory = ({
|
||||
* */
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const projectV1IntegrationAuths = await integrationAuthDAL.find({ projectId }, { tx });
|
||||
|
||||
await integrationAuthDAL.upsert(
|
||||
projectV1IntegrationAuths.map((el) => {
|
||||
const accessToken =
|
||||
el.accessIV && el.accessTag && el.accessCiphertext
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.accessCiphertext,
|
||||
iv: el.accessIV,
|
||||
tag: el.accessTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: undefined;
|
||||
const accessId =
|
||||
el.accessIdIV && el.accessIdTag && el.accessIdCiphertext
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.accessIdCiphertext,
|
||||
iv: el.accessIdIV,
|
||||
tag: el.accessIdTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: undefined;
|
||||
const refreshToken =
|
||||
el.refreshIV && el.refreshTag && el.refreshCiphertext
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.refreshCiphertext,
|
||||
iv: el.refreshIV,
|
||||
tag: el.refreshTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: undefined;
|
||||
const awsAssumeRoleArn =
|
||||
el.awsAssumeIamRoleArnCipherText && el.awsAssumeIamRoleArnIV && el.awsAssumeIamRoleArnTag
|
||||
? decryptSymmetric128BitHexKeyUTF8({
|
||||
? crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.awsAssumeIamRoleArnCipherText,
|
||||
iv: el.awsAssumeIamRoleArnIV,
|
||||
tag: el.awsAssumeIamRoleArnTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
: undefined;
|
||||
|
||||
|
||||
@@ -29,11 +29,8 @@ import { TSecretApprovalRequestSecretDALFactory } from "@app/ee/services/secret-
|
||||
import { TSecretApprovalRequestServiceFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-service";
|
||||
import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import {
|
||||
buildSecretBlindIndexFromName,
|
||||
decryptSymmetric128BitHexKeyUTF8,
|
||||
encryptSymmetric128BitHexKeyUTF8
|
||||
} from "@app/lib/crypto";
|
||||
import { buildSecretBlindIndexFromName, SymmetricKeySize } from "@app/lib/crypto";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy, pick } from "@app/lib/fn";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -162,11 +159,12 @@ export const secretServiceFactory = ({
|
||||
return (el: { ciphertext?: string; iv: string; tag: string }) =>
|
||||
projectBot?.botKey
|
||||
? getAllNestedSecretReferences(
|
||||
decryptSymmetric128BitHexKeyUTF8({
|
||||
crypto.encryption().decryptSymmetric({
|
||||
ciphertext: el.ciphertext || "",
|
||||
iv: el.iv,
|
||||
tag: el.tag,
|
||||
key: projectBot.botKey
|
||||
key: projectBot.botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
)
|
||||
: undefined;
|
||||
@@ -1705,9 +1703,22 @@ export const secretServiceFactory = ({
|
||||
message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`,
|
||||
name: "bot_not_found_error"
|
||||
});
|
||||
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(secretName, botKey);
|
||||
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secretValue || "", botKey);
|
||||
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secretComment || "", botKey);
|
||||
|
||||
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretName,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretValue || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretComment || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
if (policy) {
|
||||
const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
|
||||
policy,
|
||||
@@ -1873,9 +1884,22 @@ export const secretServiceFactory = ({
|
||||
name: "bot_not_found_error"
|
||||
});
|
||||
|
||||
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secretValue || "", botKey);
|
||||
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secretComment || "", botKey);
|
||||
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(newSecretName || secretName, botKey);
|
||||
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretValue || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretComment || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: newSecretName || secretName,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
if (policy) {
|
||||
const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
|
||||
@@ -2119,11 +2143,24 @@ export const secretServiceFactory = ({
|
||||
message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`,
|
||||
name: "bot_not_found_error"
|
||||
});
|
||||
|
||||
const sanitizedSecrets = inputSecrets.map(
|
||||
({ secretComment, secretKey, metadata, tagIds, secretValue, skipMultilineEncoding }) => {
|
||||
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(secretKey, botKey);
|
||||
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secretValue || "", botKey);
|
||||
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secretComment || "", botKey);
|
||||
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretKey,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretValue || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretComment || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
return {
|
||||
secretName: secretKey,
|
||||
skipMultilineEncoding,
|
||||
@@ -2263,6 +2300,7 @@ export const secretServiceFactory = ({
|
||||
message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`,
|
||||
name: "bot_not_found_error"
|
||||
});
|
||||
|
||||
const sanitizedSecrets = inputSecrets.map(
|
||||
({
|
||||
secretComment,
|
||||
@@ -2274,9 +2312,21 @@ export const secretServiceFactory = ({
|
||||
secretReminderNote,
|
||||
secretReminderRepeatDays
|
||||
}) => {
|
||||
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(newSecretName || secretKey, botKey);
|
||||
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secretValue || "", botKey);
|
||||
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secretComment || "", botKey);
|
||||
const secretKeyEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: newSecretName || secretKey,
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretValueEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretValue || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
const secretCommentEncrypted = crypto.encryption().encryptSymmetric({
|
||||
plaintext: secretComment || "",
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
return {
|
||||
secretName: secretKey,
|
||||
newSecretName,
|
||||
@@ -2486,12 +2536,14 @@ export const secretServiceFactory = ({
|
||||
limit,
|
||||
sort: [["createdAt", "desc"]]
|
||||
});
|
||||
|
||||
return secretVersions.map((el) => {
|
||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
const secretValueHidden = !hasSecretReadValueOrDescribePermission(
|
||||
@@ -2811,11 +2863,12 @@ export const secretServiceFactory = ({
|
||||
secrets.map(({ id, secretValueCiphertext, secretValueIV, secretValueTag }) => ({
|
||||
secretId: id,
|
||||
references: getAllNestedSecretReferences(
|
||||
decryptSymmetric128BitHexKeyUTF8({
|
||||
crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secretValueCiphertext,
|
||||
iv: secretValueIV,
|
||||
tag: secretValueTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
)
|
||||
})),
|
||||
@@ -2916,11 +2969,12 @@ export const secretServiceFactory = ({
|
||||
const destinationActions = [ProjectPermissionSecretActions.Create, ProjectPermissionSecretActions.Edit] as const;
|
||||
|
||||
const decryptedSourceSecrets = sourceSecrets.map((secret) => {
|
||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||
const secretKey = crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
});
|
||||
|
||||
for (const destinationAction of destinationActions) {
|
||||
@@ -2956,11 +3010,12 @@ export const secretServiceFactory = ({
|
||||
return {
|
||||
...secret,
|
||||
secretKey,
|
||||
secretValue: decryptSymmetric128BitHexKeyUTF8({
|
||||
secretValue: crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretValueCiphertext,
|
||||
iv: secret.secretValueIV,
|
||||
tag: secret.secretValueTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
};
|
||||
});
|
||||
@@ -2981,17 +3036,19 @@ export const secretServiceFactory = ({
|
||||
const decryptedDestinationSecrets = destinationSecretsFromDB.map((secret) => {
|
||||
return {
|
||||
...secret,
|
||||
secretKey: decryptSymmetric128BitHexKeyUTF8({
|
||||
secretKey: crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretKeyCiphertext,
|
||||
iv: secret.secretKeyIV,
|
||||
tag: secret.secretKeyTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
}),
|
||||
secretValue: decryptSymmetric128BitHexKeyUTF8({
|
||||
secretValue: crypto.encryption().decryptSymmetric({
|
||||
ciphertext: secret.secretValueCiphertext,
|
||||
iv: secret.secretValueIV,
|
||||
tag: secret.secretValueTag,
|
||||
key: botKey
|
||||
key: botKey,
|
||||
keySize: SymmetricKeySize.Bits128
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import { ForbiddenError, subject } from "@casl/ability";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
import { ActionProjectType } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
@@ -11,6 +8,7 @@ import {
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
|
||||
@@ -89,7 +87,7 @@ export const serviceTokenServiceFactory = ({
|
||||
throw new NotFoundError({ message: `One or more selected environments not found` });
|
||||
|
||||
const secret = crypto.randomBytes(16).toString("hex");
|
||||
const secretHash = await bcrypt.hash(secret, appCfg.SALT_ROUNDS);
|
||||
const secretHash = await crypto.hashing().createHash(secret, appCfg.SALT_ROUNDS);
|
||||
let expiresAt: Date | null = null;
|
||||
if (expiresIn) {
|
||||
expiresAt = new Date();
|
||||
@@ -182,7 +180,7 @@ export const serviceTokenServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Service token has expired" });
|
||||
}
|
||||
|
||||
const isMatch = await bcrypt.compare(tokenSecret, serviceToken.secretHash);
|
||||
const isMatch = await crypto.hashing().compareHash(tokenSecret, serviceToken.secretHash);
|
||||
if (!isMatch) throw new UnauthorizedError({ message: "Invalid service token" });
|
||||
await accessTokenQueue.updateServiceTokenStatus(serviceToken.id);
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import { CronJob } from "cron";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
@@ -6,7 +5,7 @@ import { IdentityAuthMethod, OrgMembershipRole, TSuperAdmin, TSuperAdminUpdate }
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
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 { generateUserSrpKeys, getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -157,6 +156,7 @@ export const superAdminServiceFactory = ({
|
||||
const newCfg = await serverCfgDAL.create({
|
||||
// @ts-expect-error id is kept as fixed for idempotence and to avoid race condition
|
||||
id: ADMIN_CONFIG_DB_UUID,
|
||||
fipsEnabled: crypto.isFipsModeEnabled(),
|
||||
initialized: false,
|
||||
allowSignUp: true,
|
||||
defaultAuthOrgId: null
|
||||
@@ -435,8 +435,10 @@ export const superAdminServiceFactory = ({
|
||||
iv: encryptedPrivateKeyIV,
|
||||
tag: encryptedPrivateKeyTag
|
||||
});
|
||||
const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND);
|
||||
const { iv, tag, ciphertext, encoding } = infisicalSymmetricEncypt(privateKey);
|
||||
|
||||
const hashedPassword = await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS);
|
||||
|
||||
const { iv, tag, ciphertext, encoding } = crypto.encryption().encryptWithRootEncryptionKey(privateKey);
|
||||
const userInfo = await userDAL.transaction(async (tx) => {
|
||||
const newUser = await userDAL.create(
|
||||
{
|
||||
@@ -522,7 +524,7 @@ export const superAdminServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
const { tag, encoding, ciphertext, iv } = infisicalSymmetricEncypt(password);
|
||||
const { tag, encoding, ciphertext, iv } = crypto.encryption().encryptWithRootEncryptionKey(password);
|
||||
const encKeys = await generateUserSrpKeys(sanitizedEmail, password);
|
||||
|
||||
const userEnc = await userDAL.createUserEncryption(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { createHash, randomUUID } from "crypto";
|
||||
import { PostHog } from "posthog-node";
|
||||
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
@@ -6,6 +5,7 @@ import { InstanceType } from "@app/ee/services/license/license-types";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { logger } from "@app/lib/logger";
|
||||
|
||||
import { PostHogEventTypes, TPostHogEvent, TSecretModifiedEvent } from "./telemetry-types";
|
||||
@@ -42,7 +42,7 @@ export type TTelemetryServiceFactoryDep = {
|
||||
|
||||
const getBucketForDistinctId = (distinctId: string): string => {
|
||||
// Use SHA-256 hash for consistent distribution
|
||||
const hash = createHash("sha256").update(distinctId).digest("hex");
|
||||
const hash = crypto.rawCrypto.createHash("sha256").update(distinctId).digest("hex");
|
||||
|
||||
// Take first 8 characters and convert to number for better distribution
|
||||
const hashNumber = parseInt(hash.substring(0, 8), 16);
|
||||
@@ -53,7 +53,7 @@ const getBucketForDistinctId = (distinctId: string): string => {
|
||||
|
||||
export const createTelemetryEventKey = (event: string, distinctId: string): string => {
|
||||
const bucketId = getBucketForDistinctId(distinctId);
|
||||
return `telemetry-event-${event}-${bucketId}-${distinctId}-${randomUUID()}`;
|
||||
return `telemetry-event-${event}-${bucketId}-${distinctId}-${crypto.rawCrypto.randomUUID()}`;
|
||||
};
|
||||
|
||||
export const telemetryServiceFactory = ({ keyStore, licenseService }: TTelemetryServiceFactoryDep) => {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import crypto from "node:crypto";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
|
||||
export const generateRecoveryCode = () => String(crypto.randomInt(10 ** 7, 10 ** 8 - 1));
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability";
|
||||
import { SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
@@ -217,7 +217,8 @@ export const userServiceFactory = ({
|
||||
if (!user?.serverEncryptedPrivateKey || !user.serverEncryptedPrivateKeyIV || !user.serverEncryptedPrivateKeyTag) {
|
||||
throw new NotFoundError({ message: `Private key for user with ID '${userId}' not found` });
|
||||
}
|
||||
const privateKey = infisicalSymmetricDecrypt({
|
||||
|
||||
const privateKey = crypto.encryption().decryptWithRootEncryptionKey({
|
||||
ciphertext: user.serverEncryptedPrivateKey,
|
||||
tag: user.serverEncryptedPrivateKeyTag,
|
||||
iv: user.serverEncryptedPrivateKeyIV,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
import { AxiosError } from "axios";
|
||||
import picomatch from "picomatch";
|
||||
|
||||
import { TWebhooks } from "@app/db/schemas";
|
||||
import { EventType, TAuditLogServiceFactory, WebhookTriggeredEvent } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
@@ -41,9 +40,8 @@ export const triggerWebhookRequest = async (
|
||||
const headers: Record<string, string> = {};
|
||||
const payload = { ...data, timestamp: Date.now() };
|
||||
const { secretKey, url } = decryptWebhookDetails(webhook, decryptor);
|
||||
|
||||
if (secretKey) {
|
||||
const webhookSign = crypto.createHmac("sha256", secretKey).update(JSON.stringify(payload)).digest("hex");
|
||||
const webhookSign = crypto.rawCrypto.createHmac("sha256", secretKey).update(JSON.stringify(payload)).digest("hex");
|
||||
headers["x-infisical-signature"] = `t=${payload.timestamp};${webhookSign}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user