mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-09 15:38:03 -05:00
fix: fips + hsm mode, key requirements
This commit is contained in:
@@ -146,7 +146,8 @@ describe("Service token secret ops", async () => {
|
||||
let folderId = "";
|
||||
beforeAll(async () => {
|
||||
initLogger();
|
||||
await initEnvConfig(testSuperAdminDAL, logger);
|
||||
|
||||
await initEnvConfig(testHsmService, testKmsRootConfigDAL, testSuperAdminDAL, logger);
|
||||
|
||||
serviceToken = await createServiceToken(
|
||||
[{ secretPath: "/**", environment: seedData1.environment.slug }],
|
||||
|
||||
@@ -158,7 +158,7 @@ describe("Secret V3 Router", async () => {
|
||||
let folderId = "";
|
||||
beforeAll(async () => {
|
||||
initLogger();
|
||||
await initEnvConfig(testSuperAdminDAL, logger);
|
||||
await initEnvConfig(testHsmService, testKmsRootConfigDAL, testSuperAdminDAL, logger);
|
||||
|
||||
const projectKeyRes = await testServer.inject({
|
||||
method: "GET",
|
||||
|
||||
@@ -6,7 +6,7 @@ import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import path from "path";
|
||||
|
||||
import { seedData1 } from "@app/db/seed-data";
|
||||
import { getDatabaseCredentials, initEnvConfig } from "@app/lib/config/env";
|
||||
import { getDatabaseCredentials, getHsmConfig, initEnvConfig } from "@app/lib/config/env";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { main } from "@app/server/app";
|
||||
import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
@@ -20,6 +20,8 @@ import { initializeHsmModule } from "@app/ee/services/hsm/hsm-fns";
|
||||
import { buildRedisFromConfig } from "@app/lib/config/redis";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
import { bootstrapCheck } from "@app/server/boot-strap-check";
|
||||
import { hsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
|
||||
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
||||
export default {
|
||||
@@ -28,6 +30,7 @@ export default {
|
||||
async setup() {
|
||||
const logger = initLogger();
|
||||
const databaseCredentials = getDatabaseCredentials(logger);
|
||||
const hsmConfig = getHsmConfig(logger);
|
||||
|
||||
const db = initDbConnection({
|
||||
dbConnectionUri: databaseCredentials.dbConnectionUri,
|
||||
@@ -35,7 +38,19 @@ export default {
|
||||
});
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(db);
|
||||
const envCfg = await initEnvConfig(superAdminDAL, logger);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(db);
|
||||
|
||||
const hsmModule = initializeHsmModule(hsmConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig: hsmConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
|
||||
const envCfg = await initEnvConfig(hsmService, kmsRootConfigDAL, superAdminDAL, logger);
|
||||
|
||||
const redis = buildRedisFromConfig(envCfg);
|
||||
await redis.flushdb("SYNC");
|
||||
@@ -68,16 +83,14 @@ export default {
|
||||
|
||||
await queue.initialize();
|
||||
|
||||
const hsmModule = initializeHsmModule(envCfg);
|
||||
hsmModule.initialize();
|
||||
|
||||
const server = await main({
|
||||
db,
|
||||
smtp,
|
||||
logger,
|
||||
queue,
|
||||
keyStore,
|
||||
hsmModule: hsmModule.getModule(),
|
||||
hsmService,
|
||||
kmsRootConfigDAL,
|
||||
superAdminDAL,
|
||||
redis,
|
||||
envConfig: envCfg
|
||||
@@ -92,6 +105,10 @@ export default {
|
||||
// @ts-expect-error type
|
||||
globalThis.testSuperAdminDAL = superAdminDAL;
|
||||
// @ts-expect-error type
|
||||
globalThis.testKmsRootConfigDAL = kmsRootConfigDAL;
|
||||
// @ts-expect-error type
|
||||
globalThis.testHsmService = hsmService;
|
||||
// @ts-expect-error type
|
||||
globalThis.jwtAuthToken = crypto.jwt().sign(
|
||||
{
|
||||
authTokenType: AuthTokenType.ACCESS_TOKEN,
|
||||
|
||||
4
backend/src/@types/fastify-zod.d.ts
vendored
4
backend/src/@types/fastify-zod.d.ts
vendored
@@ -1,7 +1,9 @@
|
||||
import { FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
|
||||
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { CustomLogger } from "@app/lib/logger/logger";
|
||||
import { ZodTypeProvider } from "@app/server/plugins/fastify-zod";
|
||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
declare global {
|
||||
@@ -16,5 +18,7 @@ declare global {
|
||||
// used only for testing
|
||||
const testServer: FastifyZodProvider;
|
||||
const testSuperAdminDAL: TSuperAdminDALFactory;
|
||||
const testKmsRootConfigDAL: TKmsRootConfigDALFactory;
|
||||
const testHsmService: THsmServiceFactory;
|
||||
const jwtAuthToken: string;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ import { Knex } from "knex";
|
||||
import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
@@ -25,10 +26,12 @@ export async function up(knex: Knex): Promise<void> {
|
||||
if (hasUrl) t.string("url").nullable().alter();
|
||||
});
|
||||
}
|
||||
|
||||
initLogger();
|
||||
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
@@ -4,13 +4,14 @@ import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
@@ -30,8 +31,12 @@ export async function up(knex: Knex): Promise<void> {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
@@ -4,13 +4,14 @@ import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
@@ -24,8 +25,11 @@ export async function up(knex: Knex): Promise<void> {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
@@ -4,13 +4,14 @@ import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName, TOrgBots } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
const reencryptIdentityK8sAuth = async (knex: Knex) => {
|
||||
@@ -55,9 +56,11 @@ const reencryptIdentityK8sAuth = async (knex: Knex) => {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
const orgEncryptionRingBuffer =
|
||||
|
||||
@@ -4,13 +4,14 @@ import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName, TOrgBots } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
const reencryptIdentityOidcAuth = async (knex: Knex) => {
|
||||
@@ -35,8 +36,11 @@ const reencryptIdentityOidcAuth = async (knex: Knex) => {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
@@ -4,16 +4,18 @@ import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
const reencryptSamlConfig = async (knex: Knex) => {
|
||||
const reencryptSamlConfig = async (knex: Knex, kmsService: TKmsServiceFactory) => {
|
||||
const hasEncryptedEntrypointColumn = await knex.schema.hasColumn(TableName.SamlConfig, "encryptedSamlEntryPoint");
|
||||
const hasEncryptedIssuerColumn = await knex.schema.hasColumn(TableName.SamlConfig, "encryptedSamlIssuer");
|
||||
const hasEncryptedCertificateColumn = await knex.schema.hasColumn(TableName.SamlConfig, "encryptedSamlCertificate");
|
||||
@@ -28,10 +30,6 @@ const reencryptSamlConfig = async (knex: Knex) => {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
const orgEncryptionRingBuffer =
|
||||
createCircularCache<Awaited<ReturnType<(typeof kmsService)["createCipherPairWithDataKey"]>>>(25);
|
||||
|
||||
@@ -159,7 +157,7 @@ const reencryptSamlConfig = async (knex: Knex) => {
|
||||
}
|
||||
};
|
||||
|
||||
const reencryptLdapConfig = async (knex: Knex) => {
|
||||
const reencryptLdapConfig = async (knex: Knex, kmsService: TKmsServiceFactory) => {
|
||||
const hasEncryptedLdapBindDNColum = await knex.schema.hasColumn(TableName.LdapConfig, "encryptedLdapBindDN");
|
||||
const hasEncryptedLdapBindPassColumn = await knex.schema.hasColumn(TableName.LdapConfig, "encryptedLdapBindPass");
|
||||
const hasEncryptedCertificateColumn = await knex.schema.hasColumn(TableName.LdapConfig, "encryptedLdapCaCertificate");
|
||||
@@ -194,10 +192,6 @@ const reencryptLdapConfig = async (knex: Knex) => {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
const orgEncryptionRingBuffer =
|
||||
createCircularCache<Awaited<ReturnType<(typeof kmsService)["createCipherPairWithDataKey"]>>>(25);
|
||||
|
||||
@@ -323,7 +317,7 @@ const reencryptLdapConfig = async (knex: Knex) => {
|
||||
}
|
||||
};
|
||||
|
||||
const reencryptOidcConfig = async (knex: Knex) => {
|
||||
const reencryptOidcConfig = async (knex: Knex, kmsService: TKmsServiceFactory) => {
|
||||
const hasEncryptedOidcClientIdColumn = await knex.schema.hasColumn(TableName.OidcConfig, "encryptedOidcClientId");
|
||||
const hasEncryptedOidcClientSecretColumn = await knex.schema.hasColumn(
|
||||
TableName.OidcConfig,
|
||||
@@ -354,10 +348,6 @@ const reencryptOidcConfig = async (knex: Knex) => {
|
||||
}
|
||||
|
||||
initLogger();
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
const orgEncryptionRingBuffer =
|
||||
createCircularCache<Awaited<ReturnType<(typeof kmsService)["createCipherPairWithDataKey"]>>>(25);
|
||||
|
||||
@@ -462,9 +452,18 @@ const reencryptOidcConfig = async (knex: Knex) => {
|
||||
};
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
await reencryptSamlConfig(knex);
|
||||
await reencryptLdapConfig(knex);
|
||||
await reencryptOidcConfig(knex);
|
||||
initLogger();
|
||||
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
await reencryptSamlConfig(knex, kmsService);
|
||||
await reencryptLdapConfig(knex, kmsService);
|
||||
await reencryptOidcConfig(knex, kmsService);
|
||||
}
|
||||
|
||||
const dropSamlConfigColumns = async (knex: Knex) => {
|
||||
|
||||
@@ -3,12 +3,13 @@ import { Knex } from "knex";
|
||||
import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { initLogger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
// Note(daniel): We aren't dropping tables or columns in this migrations so we can easily rollback if needed.
|
||||
// In the future we need to drop the projectGatewayId on the dynamic secrets table, and drop the project_gateways table entirely.
|
||||
@@ -40,8 +41,10 @@ export async function up(knex: Knex): Promise<void> {
|
||||
);
|
||||
|
||||
initLogger();
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
|
||||
@@ -2,19 +2,23 @@ import { Knex } from "knex";
|
||||
|
||||
import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { selectAllTableCols } from "@app/lib/knex";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
export async function up(knex: Knex) {
|
||||
const existingSuperAdminsWithGithubConnection = await knex(TableName.SuperAdmin)
|
||||
.select(selectAllTableCols(TableName.SuperAdmin))
|
||||
.whereNotNull(`${TableName.SuperAdmin}.encryptedGitHubAppConnectionClientId`);
|
||||
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@ import { Knex } from "knex";
|
||||
|
||||
import { inMemoryKeyStore } from "@app/keystore/memory";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { SecretKeyEncoding, TableName } from "../schemas";
|
||||
import { getMigrationEnvConfig } from "./utils/env-config";
|
||||
import { getMigrationEnvConfig, getMigrationHsmConfig } from "./utils/env-config";
|
||||
import { createCircularCache } from "./utils/ring-buffer";
|
||||
import { getMigrationEncryptionServices } from "./utils/services";
|
||||
import { getMigrationEncryptionServices, getMigrationHsmService } from "./utils/services";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
@@ -25,8 +26,10 @@ export async function up(knex: Knex): Promise<void> {
|
||||
});
|
||||
|
||||
if (!hasEncryptedCredentials) {
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
@@ -131,8 +134,11 @@ export async function down(knex: Knex): Promise<void> {
|
||||
const hasEncryptedCredentials = await knex.schema.hasColumn(TableName.AuditLogStream, "encryptedCredentials");
|
||||
|
||||
if (hasEncryptedCredentials) {
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig: getMigrationHsmConfig() });
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const envConfig = await getMigrationEnvConfig(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
const keyStore = inMemoryKeyStore();
|
||||
|
||||
const { kmsService } = await getMigrationEncryptionServices({ envConfig, keyStore, db: knex });
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { zpStr } from "@app/lib/zod";
|
||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
const envSchema = z
|
||||
@@ -42,7 +44,27 @@ const envSchema = z
|
||||
|
||||
export type TMigrationEnvConfig = z.infer<typeof envSchema>;
|
||||
|
||||
export const getMigrationEnvConfig = async (superAdminDAL: TSuperAdminDALFactory) => {
|
||||
export const getMigrationHsmConfig = () => {
|
||||
const parsedEnv = envSchema.safeParse(process.env);
|
||||
if (!parsedEnv.success) {
|
||||
console.error("Invalid environment variables. Check the error below");
|
||||
console.error(parsedEnv.error.issues);
|
||||
process.exit(-1);
|
||||
}
|
||||
return {
|
||||
isHsmConfigured: parsedEnv.data.isHsmConfigured,
|
||||
HSM_PIN: parsedEnv.data.HSM_PIN,
|
||||
HSM_SLOT: parsedEnv.data.HSM_SLOT,
|
||||
HSM_LIB_PATH: parsedEnv.data.HSM_LIB_PATH,
|
||||
HSM_KEY_LABEL: parsedEnv.data.HSM_KEY_LABEL
|
||||
};
|
||||
};
|
||||
|
||||
export const getMigrationEnvConfig = async (
|
||||
superAdminDAL: TSuperAdminDALFactory,
|
||||
hsmService: THsmServiceFactory,
|
||||
kmsRootConfigDAL: TKmsRootConfigDALFactory
|
||||
) => {
|
||||
const parsedEnv = envSchema.safeParse(process.env);
|
||||
if (!parsedEnv.success) {
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -58,7 +80,7 @@ export const getMigrationEnvConfig = async (superAdminDAL: TSuperAdminDALFactory
|
||||
|
||||
let envCfg = Object.freeze(parsedEnv.data);
|
||||
|
||||
const fipsEnabled = await crypto.initialize(superAdminDAL, envCfg);
|
||||
const fipsEnabled = await crypto.initialize(superAdminDAL, hsmService, kmsRootConfigDAL, envCfg);
|
||||
|
||||
// Fix for 128-bit entropy encryption key expansion issue:
|
||||
// In FIPS it is not ideal to expand a 128-bit key into 256-bit. We solved this issue in the past by creating the ROOT_ENCRYPTION_KEY.
|
||||
|
||||
@@ -29,6 +29,24 @@ type TDependencies = {
|
||||
keyStore: TKeyStoreFactory;
|
||||
};
|
||||
|
||||
type THsmServiceDependencies = {
|
||||
envConfig: Pick<TMigrationEnvConfig, "HSM_PIN" | "HSM_SLOT" | "HSM_LIB_PATH" | "HSM_KEY_LABEL" | "isHsmConfigured">;
|
||||
};
|
||||
|
||||
export const getMigrationHsmService = async ({ envConfig }: THsmServiceDependencies) => {
|
||||
const hsmModule = initializeHsmModule(envConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
|
||||
return { hsmService };
|
||||
};
|
||||
|
||||
export const getMigrationEncryptionServices = async ({ envConfig, db, keyStore }: TDependencies) => {
|
||||
// ----- DAL dependencies -----
|
||||
const orgDAL = orgDALFactory(db);
|
||||
@@ -67,15 +85,7 @@ export const getMigrationEncryptionServices = async ({ envConfig, db, keyStore }
|
||||
|
||||
// ----- HSM startup -----
|
||||
|
||||
const hsmModule = initializeHsmModule(envConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
const { hsmService } = await getMigrationHsmService({ envConfig });
|
||||
|
||||
const hsmStatus = await isHsmActiveAndEnabled({
|
||||
hsmService,
|
||||
@@ -113,5 +123,5 @@ export const getMigrationEncryptionServices = async ({ envConfig, db, keyStore }
|
||||
|
||||
await kmsService.startService(hsmStatus);
|
||||
|
||||
return { kmsService };
|
||||
return { kmsService, hsmService };
|
||||
};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { initEnvConfig } from "@app/lib/config/env";
|
||||
import { initializeHsmModule } from "@app/ee/services/hsm/hsm-fns";
|
||||
import { hsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { getHsmConfig, initEnvConfig } from "@app/lib/config/env";
|
||||
import { initLogger, logger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { AuthMethod } from "../../services/auth/auth-type";
|
||||
@@ -17,7 +20,21 @@ export async function seed(knex: Knex): Promise<void> {
|
||||
initLogger();
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
await initEnvConfig(superAdminDAL, logger);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
|
||||
const hsmConfig = getHsmConfig(logger);
|
||||
|
||||
const hsmModule = initializeHsmModule(hsmConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig: hsmConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
|
||||
await initEnvConfig(hsmService, kmsRootConfigDAL, superAdminDAL, logger);
|
||||
|
||||
await knex(TableName.SuperAdmin).insert([
|
||||
// eslint-disable-next-line
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { initEnvConfig } from "@app/lib/config/env";
|
||||
import { initializeHsmModule } from "@app/ee/services/hsm/hsm-fns";
|
||||
import { hsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { getHsmConfig, initEnvConfig } from "@app/lib/config/env";
|
||||
import { crypto, SymmetricKeySize } from "@app/lib/crypto/cryptography";
|
||||
import { generateUserSrpKeys } from "@app/lib/crypto/srp";
|
||||
import { initLogger, logger } from "@app/lib/logger";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { AuthMethod } from "@app/services/auth/auth-type";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { membershipRoleDALFactory } from "@app/services/membership/membership-role-dal";
|
||||
import { membershipUserDALFactory } from "@app/services/membership-user/membership-user-dal";
|
||||
import { assignWorkspaceKeysToMembers, createProjectKey } from "@app/services/project/project-fns";
|
||||
@@ -192,7 +195,21 @@ export async function seed(knex: Knex): Promise<void> {
|
||||
initLogger();
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
await initEnvConfig(superAdminDAL, logger);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
|
||||
const hsmConfig = getHsmConfig(logger);
|
||||
|
||||
const hsmModule = initializeHsmModule(hsmConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig: hsmConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
|
||||
await initEnvConfig(hsmService, kmsRootConfigDAL, superAdminDAL, logger);
|
||||
|
||||
const [project] = await knex(TableName.Project)
|
||||
.insert({
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { initEnvConfig } from "@app/lib/config/env";
|
||||
import { initializeHsmModule } from "@app/ee/services/hsm/hsm-fns";
|
||||
import { hsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { getHsmConfig, initEnvConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { initLogger, logger } from "@app/lib/logger";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
import { AccessScope, IdentityAuthMethod, OrgMembershipRole, ProjectMembershipRole, TableName } from "../schemas";
|
||||
@@ -15,7 +18,20 @@ export async function seed(knex: Knex): Promise<void> {
|
||||
initLogger();
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(knex);
|
||||
await initEnvConfig(superAdminDAL, logger);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(knex);
|
||||
const hsmConfig = getHsmConfig(logger);
|
||||
|
||||
const hsmModule = initializeHsmModule(hsmConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig: hsmConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
|
||||
await initEnvConfig(hsmService, kmsRootConfigDAL, superAdminDAL, logger);
|
||||
|
||||
// Inserts seed entries
|
||||
await knex(TableName.Identity).insert([
|
||||
|
||||
@@ -73,7 +73,7 @@ export const isHsmActiveAndEnabled = async ({
|
||||
}: {
|
||||
hsmService: Pick<THsmServiceFactory, "isActive">;
|
||||
kmsRootConfigDAL: Pick<TKmsRootConfigDALFactory, "findById">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "onPremFeatures">;
|
||||
licenseService?: Pick<TLicenseServiceFactory, "onPremFeatures">;
|
||||
}) => {
|
||||
const isHsmConfigured = await hsmService.isActive();
|
||||
|
||||
@@ -83,7 +83,11 @@ export const isHsmActiveAndEnabled = async ({
|
||||
const rootKmsConfig = await kmsRootConfigDAL.findById(KMS_ROOT_CONFIG_UUID).catch(() => null);
|
||||
|
||||
rootKmsConfigEncryptionStrategy = (rootKmsConfig?.encryptionStrategy || null) as RootKeyEncryptionStrategy | null;
|
||||
if (rootKmsConfigEncryptionStrategy === RootKeyEncryptionStrategy.HSM && !licenseService.onPremFeatures.hsm) {
|
||||
if (
|
||||
rootKmsConfigEncryptionStrategy === RootKeyEncryptionStrategy.HSM &&
|
||||
licenseService &&
|
||||
!licenseService.onPremFeatures.hsm
|
||||
) {
|
||||
throw new BadRequestError({
|
||||
message: "Your license does not include HSM integration. Please upgrade to the Enterprise plan to use HSM."
|
||||
});
|
||||
|
||||
@@ -25,6 +25,8 @@ export const hsmServiceFactory = ({ hsmModule: { isInitialized, pkcs11 }, envCon
|
||||
const AES_KEY_SIZE = 256;
|
||||
const HMAC_KEY_SIZE = 256;
|
||||
|
||||
let pkcs11TestPassed = false;
|
||||
|
||||
const $withSession = async <T>(callbackWithSession: SessionCallback<T>): Promise<T> => {
|
||||
const RETRY_INTERVAL = 200; // 200ms between attempts
|
||||
const MAX_TIMEOUT = 90_000; // 90 seconds maximum total time
|
||||
@@ -363,7 +365,9 @@ export const hsmServiceFactory = ({ hsmModule: { isInitialized, pkcs11 }, envCon
|
||||
return false;
|
||||
}
|
||||
|
||||
let pkcs11TestPassed = false;
|
||||
if (pkcs11TestPassed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
pkcs11TestPassed = await $withSession($testPkcs11Module);
|
||||
@@ -371,7 +375,7 @@ export const hsmServiceFactory = ({ hsmModule: { isInitialized, pkcs11 }, envCon
|
||||
logger.error(err, "HSM: Error testing PKCS#11 module");
|
||||
}
|
||||
|
||||
return envConfig.isHsmConfigured && isInitialized && pkcs11TestPassed;
|
||||
return pkcs11TestPassed;
|
||||
};
|
||||
|
||||
const startService = async () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { QueueWorkerProfile } from "@app/lib/types";
|
||||
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
@@ -8,6 +9,7 @@ import { BadRequestError } from "../errors";
|
||||
import { removeTrailingSlash } from "../fn";
|
||||
import { CustomLogger } from "../logger/logger";
|
||||
import { zpStr } from "../zod";
|
||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
|
||||
export const GITLAB_URL = "https://gitlab.com";
|
||||
|
||||
@@ -448,7 +450,12 @@ export const getConfig = () => envCfg;
|
||||
export const getOriginalConfig = () => originalEnvConfig;
|
||||
|
||||
// cannot import singleton logger directly as it needs config to load various transport
|
||||
export const initEnvConfig = async (superAdminDAL?: TSuperAdminDALFactory, logger?: CustomLogger) => {
|
||||
export const initEnvConfig = async (
|
||||
hsmService: THsmServiceFactory,
|
||||
kmsRootConfigDAL: TKmsRootConfigDALFactory,
|
||||
superAdminDAL?: TSuperAdminDALFactory,
|
||||
logger?: CustomLogger
|
||||
) => {
|
||||
const parsedEnv = envSchema.safeParse(process.env);
|
||||
if (!parsedEnv.success) {
|
||||
(logger ?? console).error("Invalid environment variables. Check the error below");
|
||||
@@ -464,7 +471,7 @@ export const initEnvConfig = async (superAdminDAL?: TSuperAdminDALFactory, logge
|
||||
}
|
||||
|
||||
if (superAdminDAL) {
|
||||
const fipsEnabled = await crypto.initialize(superAdminDAL);
|
||||
const fipsEnabled = await crypto.initialize(superAdminDAL, hsmService, kmsRootConfigDAL);
|
||||
|
||||
if (fipsEnabled) {
|
||||
const newEnvCfg = {
|
||||
@@ -527,6 +534,22 @@ export const getDatabaseCredentials = (logger?: CustomLogger) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const getHsmConfig = (logger?: CustomLogger) => {
|
||||
const parsedEnv = envSchema.safeParse(process.env);
|
||||
if (!parsedEnv.success) {
|
||||
(logger ?? console).error("Invalid environment variables. Check the error below");
|
||||
(logger ?? console).error(parsedEnv.error.issues);
|
||||
process.exit(-1);
|
||||
}
|
||||
return {
|
||||
isHsmConfigured: parsedEnv.data.isHsmConfigured,
|
||||
HSM_PIN: parsedEnv.data.HSM_PIN,
|
||||
HSM_SLOT: parsedEnv.data.HSM_SLOT,
|
||||
HSM_LIB_PATH: parsedEnv.data.HSM_LIB_PATH,
|
||||
HSM_KEY_LABEL: parsedEnv.data.HSM_KEY_LABEL
|
||||
};
|
||||
};
|
||||
|
||||
// A list of environment variables that can be overwritten
|
||||
export const overwriteSchema: {
|
||||
[key: string]: {
|
||||
|
||||
@@ -9,7 +9,11 @@ import nacl from "tweetnacl";
|
||||
import naclUtils from "tweetnacl-util";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { isHsmActiveAndEnabled } from "@app/ee/services/hsm/hsm-fns";
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { RootKeyEncryptionStrategy } from "@app/services/kms/kms-types";
|
||||
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
import { ADMIN_CONFIG_DB_UUID } from "@app/services/super-admin/super-admin-service";
|
||||
|
||||
@@ -106,7 +110,12 @@ const cryptographyFactory = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const $setFipsModeEnabled = (enabled: boolean, envCfg?: Pick<TEnvConfig, "ENCRYPTION_KEY">) => {
|
||||
const $setFipsModeEnabled = async (
|
||||
enabled: boolean,
|
||||
hsmService: THsmServiceFactory,
|
||||
kmsRootConfigDAL: TKmsRootConfigDALFactory,
|
||||
envCfg?: Pick<TEnvConfig, "ENCRYPTION_KEY">
|
||||
) => {
|
||||
// If FIPS is enabled, we need to validate that the ENCRYPTION_KEY is in a base64 format, and is a 256-bit key.
|
||||
if (enabled) {
|
||||
crypto.setFips(true);
|
||||
@@ -131,24 +140,42 @@ const cryptographyFactory = () => {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new CryptographyError({
|
||||
message:
|
||||
"FIPS mode is enabled, but the ENCRYPTION_KEY environment variable is not set.\nYou can generate a 256-bit key using the following command: `openssl rand -base64 32`"
|
||||
const hsmStatus = await isHsmActiveAndEnabled({
|
||||
hsmService,
|
||||
kmsRootConfigDAL
|
||||
});
|
||||
|
||||
// if the encryption strategy is software - user needs to provide an encryption key
|
||||
// if the encryption strategy is null AND the hsm is not configured - user needs to provide an encryption key
|
||||
const needsEncryptionKey =
|
||||
hsmStatus.rootKmsConfigEncryptionStrategy === RootKeyEncryptionStrategy.Software ||
|
||||
(hsmStatus.rootKmsConfigEncryptionStrategy === null && !hsmStatus.isHsmConfigured);
|
||||
|
||||
if (needsEncryptionKey) {
|
||||
throw new CryptographyError({
|
||||
message:
|
||||
"FIPS mode is enabled, but the ENCRYPTION_KEY environment variable is not set.\nYou can generate a 256-bit key using the following command: `openssl rand -base64 32`"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
$fipsEnabled = enabled;
|
||||
$isInitialized = true;
|
||||
};
|
||||
|
||||
const initialize = async (superAdminDAL: TSuperAdminDALFactory, envCfg?: Pick<TEnvConfig, "ENCRYPTION_KEY">) => {
|
||||
const initialize = async (
|
||||
superAdminDAL: TSuperAdminDALFactory,
|
||||
hsmService: THsmServiceFactory,
|
||||
kmsRootConfigDAL: TKmsRootConfigDALFactory,
|
||||
envCfg?: Pick<TEnvConfig, "ENCRYPTION_KEY">
|
||||
) => {
|
||||
if ($isInitialized) {
|
||||
return isFipsModeEnabled();
|
||||
}
|
||||
|
||||
if (process.env.FIPS_ENABLED !== "true") {
|
||||
logger.info("Cryptography module initialized in normal operation mode.");
|
||||
$setFipsModeEnabled(false, envCfg);
|
||||
await $setFipsModeEnabled(false, hsmService, kmsRootConfigDAL, envCfg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -158,11 +185,11 @@ const cryptographyFactory = () => {
|
||||
if (serverCfg) {
|
||||
if (serverCfg.fipsEnabled) {
|
||||
logger.info("[FIPS]: Instance is configured for FIPS mode of operation. Continuing startup with FIPS enabled.");
|
||||
$setFipsModeEnabled(true, envCfg);
|
||||
await $setFipsModeEnabled(true, hsmService, kmsRootConfigDAL, envCfg);
|
||||
return true;
|
||||
}
|
||||
logger.info("[FIPS]: Instance age predates FIPS mode inception date. Continuing without FIPS.");
|
||||
$setFipsModeEnabled(false, envCfg);
|
||||
await $setFipsModeEnabled(false, hsmService, kmsRootConfigDAL, envCfg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -171,7 +198,7 @@ const cryptographyFactory = () => {
|
||||
// TODO(daniel): check if it's an enterprise deployment
|
||||
|
||||
// if there is no server cfg, and FIPS_MODE is `true`, its a fresh FIPS deployment. We need to set the fipsEnabled to true.
|
||||
$setFipsModeEnabled(true, envCfg);
|
||||
await $setFipsModeEnabled(true, hsmService, kmsRootConfigDAL, envCfg);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
@@ -9,14 +9,16 @@ import { keyValueStoreDALFactory } from "@app/keystore/key-value-store-dal";
|
||||
|
||||
import { runMigrations } from "./auto-start-migrations";
|
||||
import { initAuditLogDbConnection, initDbConnection } from "./db";
|
||||
import { hsmServiceFactory } from "./ee/services/hsm/hsm-service";
|
||||
import { keyStoreFactory } from "./keystore/keystore";
|
||||
import { formatSmtpConfig, getDatabaseCredentials, initEnvConfig } from "./lib/config/env";
|
||||
import { formatSmtpConfig, getDatabaseCredentials, getHsmConfig, initEnvConfig } from "./lib/config/env";
|
||||
import { buildRedisFromConfig } from "./lib/config/redis";
|
||||
import { removeTemporaryBaseDirectory } from "./lib/files";
|
||||
import { initLogger } from "./lib/logger";
|
||||
import { queueServiceFactory } from "./queue";
|
||||
import { main } from "./server/app";
|
||||
import { bootstrapCheck } from "./server/boot-strap-check";
|
||||
import { kmsRootConfigDALFactory } from "./services/kms/kms-root-config-dal";
|
||||
import { smtpServiceFactory } from "./services/smtp/smtp-service";
|
||||
import { superAdminDALFactory } from "./services/super-admin/super-admin-dal";
|
||||
|
||||
@@ -26,6 +28,18 @@ const run = async () => {
|
||||
const logger = initLogger();
|
||||
await removeTemporaryBaseDirectory();
|
||||
|
||||
const hsmConfig = getHsmConfig(logger);
|
||||
|
||||
const hsmModule = initializeHsmModule(hsmConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule: hsmModule.getModule(),
|
||||
envConfig: hsmConfig
|
||||
});
|
||||
|
||||
await hsmService.startService();
|
||||
|
||||
const databaseCredentials = getDatabaseCredentials(logger);
|
||||
|
||||
const db = initDbConnection({
|
||||
@@ -35,7 +49,8 @@ const run = async () => {
|
||||
});
|
||||
|
||||
const superAdminDAL = superAdminDALFactory(db);
|
||||
const envConfig = await initEnvConfig(superAdminDAL, logger);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(db);
|
||||
const envConfig = await initEnvConfig(hsmService, kmsRootConfigDAL, superAdminDAL, logger);
|
||||
|
||||
const auditLogDb = envConfig.AUDIT_LOGS_DB_CONNECTION_URI
|
||||
? initAuditLogDbConnection({
|
||||
@@ -59,14 +74,12 @@ const run = async () => {
|
||||
const keyStore = keyStoreFactory(envConfig, keyValueStoreDAL);
|
||||
const redis = buildRedisFromConfig(envConfig);
|
||||
|
||||
const hsmModule = initializeHsmModule(envConfig);
|
||||
hsmModule.initialize();
|
||||
|
||||
const server = await main({
|
||||
db,
|
||||
auditLogDb,
|
||||
superAdminDAL,
|
||||
hsmModule: hsmModule.getModule(),
|
||||
kmsRootConfigDAL,
|
||||
hsmService,
|
||||
smtp,
|
||||
logger,
|
||||
queue,
|
||||
|
||||
@@ -15,12 +15,13 @@ import fastify from "fastify";
|
||||
import { Cluster, Redis } from "ioredis";
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { HsmModule } from "@app/ee/services/hsm/hsm-types";
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig, IS_PACKAGED, TEnvConfig } from "@app/lib/config/env";
|
||||
import { CustomLogger } from "@app/lib/logger/logger";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { TQueueServiceFactory } from "@app/queue";
|
||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
|
||||
@@ -42,16 +43,16 @@ type TMain = {
|
||||
logger?: CustomLogger;
|
||||
queue: TQueueServiceFactory;
|
||||
keyStore: TKeyStoreFactory;
|
||||
hsmModule: HsmModule;
|
||||
redis: Redis | Cluster;
|
||||
envConfig: TEnvConfig;
|
||||
superAdminDAL: TSuperAdminDALFactory;
|
||||
hsmService: THsmServiceFactory;
|
||||
kmsRootConfigDAL: TKmsRootConfigDALFactory;
|
||||
};
|
||||
|
||||
// Run the server!
|
||||
export const main = async ({
|
||||
db,
|
||||
hsmModule,
|
||||
auditLogDb,
|
||||
smtp,
|
||||
logger,
|
||||
@@ -59,7 +60,9 @@ export const main = async ({
|
||||
keyStore,
|
||||
redis,
|
||||
envConfig,
|
||||
superAdminDAL
|
||||
superAdminDAL,
|
||||
hsmService,
|
||||
kmsRootConfigDAL
|
||||
}: TMain) => {
|
||||
const appCfg = getConfig();
|
||||
|
||||
@@ -148,9 +151,10 @@ export const main = async ({
|
||||
db,
|
||||
auditLogDb,
|
||||
keyStore,
|
||||
hsmModule,
|
||||
hsmService,
|
||||
envConfig,
|
||||
superAdminDAL
|
||||
superAdminDAL,
|
||||
kmsRootConfigDAL
|
||||
});
|
||||
|
||||
await server.register(registerServeUI, {
|
||||
|
||||
@@ -47,8 +47,7 @@ import { groupDALFactory } from "@app/ee/services/group/group-dal";
|
||||
import { groupServiceFactory } from "@app/ee/services/group/group-service";
|
||||
import { userGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
||||
import { isHsmActiveAndEnabled } from "@app/ee/services/hsm/hsm-fns";
|
||||
import { hsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { HsmModule } from "@app/ee/services/hsm/hsm-types";
|
||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||
import { identityAuthTemplateDALFactory } from "@app/ee/services/identity-auth-template/identity-auth-template-dal";
|
||||
import { identityAuthTemplateServiceFactory } from "@app/ee/services/identity-auth-template/identity-auth-template-service";
|
||||
import { kmipClientCertificateDALFactory } from "@app/ee/services/kmip/kmip-client-certificate-dal";
|
||||
@@ -237,7 +236,7 @@ import { integrationAuthDALFactory } from "@app/services/integration-auth/integr
|
||||
import { integrationAuthServiceFactory } from "@app/services/integration-auth/integration-auth-service";
|
||||
import { internalKmsDALFactory } from "@app/services/kms/internal-kms-dal";
|
||||
import { kmskeyDALFactory } from "@app/services/kms/kms-key-dal";
|
||||
import { kmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||
import { kmsServiceFactory } from "@app/services/kms/kms-service";
|
||||
import { RootKeyEncryptionStrategy } from "@app/services/kms/kms-types";
|
||||
import { membershipDALFactory } from "@app/services/membership/membership-dal";
|
||||
@@ -365,20 +364,22 @@ export const registerRoutes = async (
|
||||
auditLogDb,
|
||||
superAdminDAL,
|
||||
db,
|
||||
hsmModule,
|
||||
smtp: smtpService,
|
||||
queue: queueService,
|
||||
keyStore,
|
||||
envConfig
|
||||
envConfig,
|
||||
hsmService,
|
||||
kmsRootConfigDAL
|
||||
}: {
|
||||
auditLogDb?: Knex;
|
||||
superAdminDAL: TSuperAdminDALFactory;
|
||||
db: Knex;
|
||||
hsmModule: HsmModule;
|
||||
smtp: TSmtpService;
|
||||
queue: TQueueServiceFactory;
|
||||
keyStore: TKeyStoreFactory;
|
||||
envConfig: TEnvConfig;
|
||||
hsmService: THsmServiceFactory;
|
||||
kmsRootConfigDAL: TKmsRootConfigDALFactory;
|
||||
}
|
||||
) => {
|
||||
const appCfg = getConfig();
|
||||
@@ -509,7 +510,6 @@ export const registerRoutes = async (
|
||||
const kmsDAL = kmskeyDALFactory(db);
|
||||
const internalKmsDAL = internalKmsDALFactory(db);
|
||||
const externalKmsDAL = externalKmsDALFactory(db);
|
||||
const kmsRootConfigDAL = kmsRootConfigDALFactory(db);
|
||||
|
||||
const slackIntegrationDAL = slackIntegrationDALFactory(db);
|
||||
const projectSlackConfigDAL = projectSlackConfigDALFactory(db);
|
||||
@@ -625,11 +625,6 @@ export const registerRoutes = async (
|
||||
permissionService
|
||||
});
|
||||
|
||||
const hsmService = hsmServiceFactory({
|
||||
hsmModule,
|
||||
envConfig
|
||||
});
|
||||
|
||||
const kmsService = kmsServiceFactory({
|
||||
kmsRootConfigDAL,
|
||||
keyStore,
|
||||
|
||||
Reference in New Issue
Block a user