Merge pull request #4868 from Infisical/chore/unify-license-key

[ENG-4019] chore: unify license key env variables
This commit is contained in:
Piyush Gupta
2025-11-20 23:03:00 +05:30
committed by GitHub
8 changed files with 100 additions and 21 deletions
@@ -39,3 +39,9 @@ export const getDefaultOnPremFeatures = () => {
};
export const setupLicenseRequestWithStore = () => {};
export const getLicenseKeyConfig = () => {
return {
isValid: false
};
};
+45 -2
View File
@@ -1,13 +1,56 @@
import axios, { AxiosError } from "axios";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { getConfig } from "@app/lib/config/env";
import { getConfig, TEnvConfig } from "@app/lib/config/env";
import { request } from "@app/lib/config/request";
import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger";
import { UserAliasType } from "@app/services/user-alias/user-alias-types";
import { TFeatureSet } from "./license-types";
import { LicenseType, TFeatureSet, TLicenseKeyConfig, TOfflineLicenseContents } from "./license-types";
export const isOfflineLicenseKey = (licenseKey: string): boolean => {
try {
const contents = JSON.parse(Buffer.from(licenseKey, "base64").toString("utf8")) as TOfflineLicenseContents;
return "signature" in contents && "license" in contents;
} catch (error) {
return false;
}
};
export const getLicenseKeyConfig = (
config?: Pick<TEnvConfig, "LICENSE_KEY" | "LICENSE_KEY_OFFLINE">
): TLicenseKeyConfig => {
const cfg = config || getConfig();
if (!cfg) {
return { isValid: false };
}
const licenseKey = cfg.LICENSE_KEY;
if (licenseKey) {
if (isOfflineLicenseKey(licenseKey)) {
return { isValid: true, licenseKey, type: LicenseType.Offline };
}
return { isValid: true, licenseKey, type: LicenseType.Online };
}
const offlineLicenseKey = cfg.LICENSE_KEY_OFFLINE;
// backwards compatibility
if (offlineLicenseKey) {
if (isOfflineLicenseKey(offlineLicenseKey)) {
return { isValid: true, licenseKey: offlineLicenseKey, type: LicenseType.Offline };
}
return { isValid: false };
}
return { isValid: false };
};
export const getDefaultOnPremFeatures = (): TFeatureSet => ({
_id: null,
@@ -22,9 +22,10 @@ import { OrgPermissionBillingActions, OrgPermissionSubjects } from "../permissio
import { TPermissionServiceFactory } from "../permission/permission-service-types";
import { BillingPlanRows, BillingPlanTableHead } from "./licence-enums";
import { TLicenseDALFactory } from "./license-dal";
import { getDefaultOnPremFeatures, setupLicenseRequestWithStore } from "./license-fns";
import { getDefaultOnPremFeatures, getLicenseKeyConfig, setupLicenseRequestWithStore } from "./license-fns";
import {
InstanceType,
LicenseType,
TAddOrgPmtMethodDTO,
TAddOrgTaxIdDTO,
TCreateOrgPortalSession,
@@ -77,6 +78,7 @@ export const licenseServiceFactory = ({
let instanceType = InstanceType.OnPrem;
let onPremFeatures: TFeatureSet = getDefaultOnPremFeatures();
let selfHostedLicense: TOfflineLicense | null = null;
const licenseKeyConfig = getLicenseKeyConfig(envConfig);
const licenseServerCloudApi = setupLicenseRequestWithStore(
envConfig.LICENSE_SERVER_URL || "",
@@ -85,10 +87,13 @@ export const licenseServiceFactory = ({
envConfig.INTERNAL_REGION
);
const onlineLicenseKey =
licenseKeyConfig.isValid && licenseKeyConfig.type === LicenseType.Online ? licenseKeyConfig.licenseKey : "";
const licenseServerOnPremApi = setupLicenseRequestWithStore(
envConfig.LICENSE_SERVER_URL || "",
LICENSE_SERVER_ON_PREM_LOGIN,
envConfig.LICENSE_KEY || "",
onlineLicenseKey,
envConfig.INTERNAL_REGION
);
@@ -131,7 +136,7 @@ export const licenseServiceFactory = ({
return;
}
if (envConfig.LICENSE_KEY) {
if (licenseKeyConfig.isValid && licenseKeyConfig.type === LicenseType.Online) {
const token = await licenseServerOnPremApi.refreshLicense();
if (token) {
await syncLicenseKeyOnPremFeatures(true);
@@ -142,10 +147,10 @@ export const licenseServiceFactory = ({
return;
}
if (envConfig.LICENSE_KEY_OFFLINE) {
if (licenseKeyConfig.isValid && licenseKeyConfig.type === LicenseType.Offline) {
let isValidOfflineLicense = true;
const contents: TOfflineLicenseContents = JSON.parse(
Buffer.from(envConfig.LICENSE_KEY_OFFLINE, "base64").toString("utf8")
Buffer.from(licenseKeyConfig.licenseKey, "base64").toString("utf8")
);
const isVerified = await verifyOfflineLicense(JSON.stringify(contents.license), contents.signature);
@@ -184,7 +189,7 @@ export const licenseServiceFactory = ({
};
const initializeBackgroundSync = async () => {
if (envConfig.LICENSE_KEY) {
if (licenseKeyConfig?.isValid && licenseKeyConfig?.type === LicenseType.Online) {
logger.info("Setting up background sync process for refresh onPremFeatures");
const job = new CronJob("*/10 * * * *", syncLicenseKeyOnPremFeatures);
job.start();
@@ -136,3 +136,18 @@ export type TDelOrgTaxIdDTO = TOrgPermission & { taxId: string };
export type TOrgInvoiceDTO = TOrgPermission;
export type TOrgLicensesDTO = TOrgPermission;
export enum LicenseType {
Offline = "offline",
Online = "online"
}
export type TLicenseKeyConfig =
| {
isValid: false;
}
| {
isValid: true;
licenseKey: string;
type: LicenseType;
};
+1 -1
View File
@@ -2431,6 +2431,7 @@ export const registerRoutes = async (
}
}
await kmsService.startService(hsmStatus);
await telemetryQueue.startTelemetryCheck();
await telemetryQueue.startAggregatedEventsJob();
await dailyResourceCleanUp.init();
@@ -2443,7 +2444,6 @@ export const registerRoutes = async (
await pkiSubscriberQueue.startDailyAutoRenewalJob();
await pkiAlertV2Queue.init();
await certificateV3Queue.init();
await kmsService.startService(hsmStatus);
await microsoftTeamsService.start();
await dynamicSecretQueueService.init();
await eventBusService.init();
+6 -1
View File
@@ -9,6 +9,8 @@ import {
SuperAdminSchema,
UsersSchema
} from "@app/db/schemas";
import { getLicenseKeyConfig } from "@app/ee/services/license/license-fns";
import { LicenseType } from "@app/ee/services/license/license-types";
import { getConfig, overridableKeys } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto/cryptography";
import { BadRequestError } from "@app/lib/errors";
@@ -65,6 +67,9 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
const config = await getServerCfg();
const serverEnvs = getConfig();
const licenseKeyConfig = getLicenseKeyConfig();
const hasOfflineLicense = licenseKeyConfig.isValid && licenseKeyConfig.type === LicenseType.Offline;
return {
config: {
...config,
@@ -73,7 +78,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
isSecretScanningDisabled: serverEnvs.DISABLE_SECRET_SCANNING,
kubernetesAutoFetchServiceAccountToken: serverEnvs.KUBERNETES_AUTO_FETCH_SERVICE_ACCOUNT_TOKEN,
paramsFolderSecretDetectionEnabled: serverEnvs.PARAMS_FOLDER_SECRET_DETECTION_ENABLED,
isOfflineUsageReportsEnabled: !!serverEnvs.LICENSE_KEY_OFFLINE
isOfflineUsageReportsEnabled: hasOfflineLicense
}
};
}
@@ -1,7 +1,8 @@
import crypto from "crypto";
import { getLicenseKeyConfig } from "@app/ee/services/license/license-fns";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { getConfig } from "@app/lib/config/env";
import { LicenseType } from "@app/ee/services/license/license-types";
import { BadRequestError } from "@app/lib/errors";
import { TOfflineUsageReportDALFactory } from "./offline-usage-report-dal";
@@ -30,10 +31,13 @@ export const offlineUsageReportServiceFactory = ({
};
const generateUsageReportCSV = async () => {
const cfg = getConfig();
if (!cfg.LICENSE_KEY_OFFLINE) {
const licenseKeyConfig = getLicenseKeyConfig();
const hasOfflineLicense = licenseKeyConfig.isValid && licenseKeyConfig.type === LicenseType.Offline;
if (!hasOfflineLicense) {
throw new BadRequestError({
message: "Offline usage reports are not enabled. LICENSE_KEY_OFFLINE must be configured."
message:
"Offline usage reports are not enabled. Usage reports are only available for self-hosted offline instances"
});
}