mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 13:27:46 +00:00
Merge pull request #1968 from Infisical/misc/migrated-custom-rate-limits-to-enterprise
misc: migrated custom rate limits to enterprise
This commit is contained in:
Vendored
+1
-1
@@ -14,6 +14,7 @@ import { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-con
|
|||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
||||||
|
import { TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||||
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
||||||
import { TScimServiceFactory } from "@app/ee/services/scim/scim-service";
|
import { TScimServiceFactory } from "@app/ee/services/scim/scim-service";
|
||||||
import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
||||||
@@ -48,7 +49,6 @@ import { TProjectEnvServiceFactory } from "@app/services/project-env/project-env
|
|||||||
import { TProjectKeyServiceFactory } from "@app/services/project-key/project-key-service";
|
import { TProjectKeyServiceFactory } from "@app/services/project-key/project-key-service";
|
||||||
import { TProjectMembershipServiceFactory } from "@app/services/project-membership/project-membership-service";
|
import { TProjectMembershipServiceFactory } from "@app/services/project-membership/project-membership-service";
|
||||||
import { TProjectRoleServiceFactory } from "@app/services/project-role/project-role-service";
|
import { TProjectRoleServiceFactory } from "@app/services/project-role/project-role-service";
|
||||||
import { TRateLimitServiceFactory } from "@app/services/rate-limit/rate-limit-service";
|
|
||||||
import { TSecretServiceFactory } from "@app/services/secret/secret-service";
|
import { TSecretServiceFactory } from "@app/services/secret/secret-service";
|
||||||
import { TSecretBlindIndexServiceFactory } from "@app/services/secret-blind-index/secret-blind-index-service";
|
import { TSecretBlindIndexServiceFactory } from "@app/services/secret-blind-index/secret-blind-index-service";
|
||||||
import { TSecretFolderServiceFactory } from "@app/services/secret-folder/secret-folder-service";
|
import { TSecretFolderServiceFactory } from "@app/services/secret-folder/secret-folder-service";
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { registerLicenseRouter } from "./license-router";
|
|||||||
import { registerOrgRoleRouter } from "./org-role-router";
|
import { registerOrgRoleRouter } from "./org-role-router";
|
||||||
import { registerProjectRoleRouter } from "./project-role-router";
|
import { registerProjectRoleRouter } from "./project-role-router";
|
||||||
import { registerProjectRouter } from "./project-router";
|
import { registerProjectRouter } from "./project-router";
|
||||||
|
import { registerRateLimitRouter } from "./rate-limit-router";
|
||||||
import { registerSamlRouter } from "./saml-router";
|
import { registerSamlRouter } from "./saml-router";
|
||||||
import { registerScimRouter } from "./scim-router";
|
import { registerScimRouter } from "./scim-router";
|
||||||
import { registerSecretApprovalPolicyRouter } from "./secret-approval-policy-router";
|
import { registerSecretApprovalPolicyRouter } from "./secret-approval-policy-router";
|
||||||
@@ -45,6 +46,7 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
|
|
||||||
await server.register(registerAccessApprovalPolicyRouter, { prefix: "/access-approvals/policies" });
|
await server.register(registerAccessApprovalPolicyRouter, { prefix: "/access-approvals/policies" });
|
||||||
await server.register(registerAccessApprovalRequestRouter, { prefix: "/access-approvals/requests" });
|
await server.register(registerAccessApprovalRequestRouter, { prefix: "/access-approvals/requests" });
|
||||||
|
await server.register(registerRateLimitRouter, { prefix: "/rate-limit" });
|
||||||
|
|
||||||
await server.register(
|
await server.register(
|
||||||
async (dynamicSecretRouter) => {
|
async (dynamicSecretRouter) => {
|
||||||
|
|||||||
@@ -575,6 +575,9 @@ export const licenseServiceFactory = ({
|
|||||||
getInstanceType() {
|
getInstanceType() {
|
||||||
return instanceType;
|
return instanceType;
|
||||||
},
|
},
|
||||||
|
get onPremFeatures() {
|
||||||
|
return onPremFeatures;
|
||||||
|
},
|
||||||
getPlan,
|
getPlan,
|
||||||
updateSubscriptionOrgMemberCount,
|
updateSubscriptionOrgMemberCount,
|
||||||
refreshPlan,
|
refreshPlan,
|
||||||
|
|||||||
+13
-2
@@ -2,6 +2,7 @@ import { CronJob } from "cron";
|
|||||||
|
|
||||||
import { logger } from "@app/lib/logger";
|
import { logger } from "@app/lib/logger";
|
||||||
|
|
||||||
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { TRateLimitDALFactory } from "./rate-limit-dal";
|
import { TRateLimitDALFactory } from "./rate-limit-dal";
|
||||||
import { TRateLimit, TRateLimitUpdateDTO } from "./rate-limit-types";
|
import { TRateLimit, TRateLimitUpdateDTO } from "./rate-limit-types";
|
||||||
|
|
||||||
@@ -24,11 +25,12 @@ export const getRateLimiterConfig = () => {
|
|||||||
|
|
||||||
type TRateLimitServiceFactoryDep = {
|
type TRateLimitServiceFactoryDep = {
|
||||||
rateLimitDAL: TRateLimitDALFactory;
|
rateLimitDAL: TRateLimitDALFactory;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "onPremFeatures">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TRateLimitServiceFactory = ReturnType<typeof rateLimitServiceFactory>;
|
export type TRateLimitServiceFactory = ReturnType<typeof rateLimitServiceFactory>;
|
||||||
|
|
||||||
export const rateLimitServiceFactory = ({ rateLimitDAL }: TRateLimitServiceFactoryDep) => {
|
export const rateLimitServiceFactory = ({ rateLimitDAL, licenseService }: TRateLimitServiceFactoryDep) => {
|
||||||
const DEFAULT_RATE_LIMIT_CONFIG_ID = "00000000-0000-0000-0000-000000000000";
|
const DEFAULT_RATE_LIMIT_CONFIG_ID = "00000000-0000-0000-0000-000000000000";
|
||||||
|
|
||||||
const getRateLimits = async (): Promise<TRateLimit | undefined> => {
|
const getRateLimits = async (): Promise<TRateLimit | undefined> => {
|
||||||
@@ -78,7 +80,16 @@ export const rateLimitServiceFactory = ({ rateLimitDAL }: TRateLimitServiceFacto
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const initializeBackgroundSync = () => {
|
const initializeBackgroundSync = async () => {
|
||||||
|
if (!licenseService.onPremFeatures.customRateLimits) {
|
||||||
|
logger.info("Current license does not support custom rate limit configuration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Setting up background sync process for rate limits");
|
||||||
|
// initial sync upon startup
|
||||||
|
await syncRateLimitConfiguration();
|
||||||
|
|
||||||
// sync rate limits configuration every 10 minutes
|
// sync rate limits configuration every 10 minutes
|
||||||
const job = new CronJob("*/10 * * * *", syncRateLimitConfiguration);
|
const job = new CronJob("*/10 * * * *", syncRateLimitConfiguration);
|
||||||
job.start();
|
job.start();
|
||||||
@@ -17,8 +17,6 @@ import { Logger } from "pino";
|
|||||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { TQueueServiceFactory } from "@app/queue";
|
import { TQueueServiceFactory } from "@app/queue";
|
||||||
import { rateLimitDALFactory } from "@app/services/rate-limit/rate-limit-dal";
|
|
||||||
import { rateLimitServiceFactory } from "@app/services/rate-limit/rate-limit-service";
|
|
||||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
|
|
||||||
import { globalRateLimiterCfg } from "./config/rateLimiter";
|
import { globalRateLimiterCfg } from "./config/rateLimiter";
|
||||||
@@ -71,9 +69,6 @@ export const main = async ({ db, smtp, logger, queue, keyStore }: TMain) => {
|
|||||||
|
|
||||||
// Rate limiters and security headers
|
// Rate limiters and security headers
|
||||||
if (appCfg.isProductionMode) {
|
if (appCfg.isProductionMode) {
|
||||||
const rateLimitDAL = rateLimitDALFactory(db);
|
|
||||||
const rateLimitService = rateLimitServiceFactory({ rateLimitDAL });
|
|
||||||
await rateLimitService.syncRateLimitConfiguration();
|
|
||||||
await server.register<FastifyRateLimitOptions>(ratelimiter, globalRateLimiterCfg());
|
await server.register<FastifyRateLimitOptions>(ratelimiter, globalRateLimiterCfg());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
|
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
|
||||||
import { Redis } from "ioredis";
|
import { Redis } from "ioredis";
|
||||||
|
|
||||||
|
import { getRateLimiterConfig } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { getRateLimiterConfig } from "@app/services/rate-limit/rate-limit-service";
|
|
||||||
|
|
||||||
export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import { permissionDALFactory } from "@app/ee/services/permission/permission-dal
|
|||||||
import { permissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { permissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { projectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
import { projectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||||
import { projectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
import { projectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
||||||
|
import { rateLimitDALFactory } from "@app/ee/services/rate-limit/rate-limit-dal";
|
||||||
|
import { rateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||||
import { samlConfigDALFactory } from "@app/ee/services/saml-config/saml-config-dal";
|
import { samlConfigDALFactory } from "@app/ee/services/saml-config/saml-config-dal";
|
||||||
import { samlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
import { samlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
||||||
import { scimDALFactory } from "@app/ee/services/scim/scim-dal";
|
import { scimDALFactory } from "@app/ee/services/scim/scim-dal";
|
||||||
@@ -122,8 +124,6 @@ import { projectMembershipServiceFactory } from "@app/services/project-membershi
|
|||||||
import { projectUserMembershipRoleDALFactory } from "@app/services/project-membership/project-user-membership-role-dal";
|
import { projectUserMembershipRoleDALFactory } from "@app/services/project-membership/project-user-membership-role-dal";
|
||||||
import { projectRoleDALFactory } from "@app/services/project-role/project-role-dal";
|
import { projectRoleDALFactory } from "@app/services/project-role/project-role-dal";
|
||||||
import { projectRoleServiceFactory } from "@app/services/project-role/project-role-service";
|
import { projectRoleServiceFactory } from "@app/services/project-role/project-role-service";
|
||||||
import { rateLimitDALFactory } from "@app/services/rate-limit/rate-limit-dal";
|
|
||||||
import { rateLimitServiceFactory } from "@app/services/rate-limit/rate-limit-service";
|
|
||||||
import { dailyResourceCleanUpQueueServiceFactory } from "@app/services/resource-cleanup/resource-cleanup-queue";
|
import { dailyResourceCleanUpQueueServiceFactory } from "@app/services/resource-cleanup/resource-cleanup-queue";
|
||||||
import { secretDALFactory } from "@app/services/secret/secret-dal";
|
import { secretDALFactory } from "@app/services/secret/secret-dal";
|
||||||
import { secretQueueFactory } from "@app/services/secret/secret-queue";
|
import { secretQueueFactory } from "@app/services/secret/secret-queue";
|
||||||
@@ -449,7 +449,8 @@ export const registerRoutes = async (
|
|||||||
keyStore
|
keyStore
|
||||||
});
|
});
|
||||||
const rateLimitService = rateLimitServiceFactory({
|
const rateLimitService = rateLimitServiceFactory({
|
||||||
rateLimitDAL
|
rateLimitDAL,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
||||||
|
|
||||||
@@ -910,7 +911,10 @@ export const registerRoutes = async (
|
|||||||
|
|
||||||
const cronJobs: CronJob[] = [];
|
const cronJobs: CronJob[] = [];
|
||||||
if (appCfg.isProductionMode) {
|
if (appCfg.isProductionMode) {
|
||||||
cronJobs.push(rateLimitService.initializeBackgroundSync());
|
const rateLimitSyncJob = await rateLimitService.initializeBackgroundSync();
|
||||||
|
if (rateLimitSyncJob) {
|
||||||
|
cronJobs.push(rateLimitSyncJob);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.decorate<FastifyZodProvider["store"]>("store", {
|
server.decorate<FastifyZodProvider["store"]>("store", {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { registerProjectEnvRouter } from "./project-env-router";
|
|||||||
import { registerProjectKeyRouter } from "./project-key-router";
|
import { registerProjectKeyRouter } from "./project-key-router";
|
||||||
import { registerProjectMembershipRouter } from "./project-membership-router";
|
import { registerProjectMembershipRouter } from "./project-membership-router";
|
||||||
import { registerProjectRouter } from "./project-router";
|
import { registerProjectRouter } from "./project-router";
|
||||||
import { registerRateLimitRouter } from "./rate-limit-router";
|
|
||||||
import { registerSecretFolderRouter } from "./secret-folder-router";
|
import { registerSecretFolderRouter } from "./secret-folder-router";
|
||||||
import { registerSecretImportRouter } from "./secret-import-router";
|
import { registerSecretImportRouter } from "./secret-import-router";
|
||||||
import { registerSecretSharingRouter } from "./secret-sharing-router";
|
import { registerSecretSharingRouter } from "./secret-sharing-router";
|
||||||
@@ -44,7 +43,6 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
|
|||||||
await server.register(registerPasswordRouter, { prefix: "/password" });
|
await server.register(registerPasswordRouter, { prefix: "/password" });
|
||||||
await server.register(registerOrgRouter, { prefix: "/organization" });
|
await server.register(registerOrgRouter, { prefix: "/organization" });
|
||||||
await server.register(registerAdminRouter, { prefix: "/admin" });
|
await server.register(registerAdminRouter, { prefix: "/admin" });
|
||||||
await server.register(registerRateLimitRouter, { prefix: "/rate-limit" });
|
|
||||||
await server.register(registerUserRouter, { prefix: "/user" });
|
await server.register(registerUserRouter, { prefix: "/user" });
|
||||||
await server.register(registerInviteOrgRouter, { prefix: "/invite-org" });
|
await server.register(registerInviteOrgRouter, { prefix: "/invite-org" });
|
||||||
await server.register(registerUserActionRouter, { prefix: "/user-action" });
|
await server.register(registerUserActionRouter, { prefix: "/user-action" });
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, ContentLoader, FormControl, Input } from "@app/components/v2";
|
import { Button, ContentLoader, FormControl, Input, UpgradePlanModal } from "@app/components/v2";
|
||||||
|
import { useSubscription } from "@app/context";
|
||||||
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useGetRateLimit, useUpdateRateLimit } from "@app/hooks/api";
|
import { useGetRateLimit, useUpdateRateLimit } from "@app/hooks/api";
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
@@ -21,7 +23,9 @@ type TRateLimitForm = z.infer<typeof formSchema>;
|
|||||||
|
|
||||||
export const RateLimitPanel = () => {
|
export const RateLimitPanel = () => {
|
||||||
const { data: rateLimit, isLoading } = useGetRateLimit();
|
const { data: rateLimit, isLoading } = useGetRateLimit();
|
||||||
|
const { subscription } = useSubscription();
|
||||||
const { mutateAsync: updateRateLimit } = useUpdateRateLimit();
|
const { mutateAsync: updateRateLimit } = useUpdateRateLimit();
|
||||||
|
const { handlePopUpToggle, handlePopUpOpen, popUp } = usePopUp(["upgradePlan"] as const);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
@@ -44,6 +48,11 @@ export const RateLimitPanel = () => {
|
|||||||
|
|
||||||
const onRateLimitFormSubmit = async (formData: TRateLimitForm) => {
|
const onRateLimitFormSubmit = async (formData: TRateLimitForm) => {
|
||||||
try {
|
try {
|
||||||
|
if (subscription && !subscription.customRateLimits) {
|
||||||
|
handlePopUpOpen("upgradePlan");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
readRateLimit,
|
readRateLimit,
|
||||||
writeRateLimit,
|
writeRateLimit,
|
||||||
@@ -86,9 +95,7 @@ export const RateLimitPanel = () => {
|
|||||||
onSubmit={handleSubmit(onRateLimitFormSubmit)}
|
onSubmit={handleSubmit(onRateLimitFormSubmit)}
|
||||||
>
|
>
|
||||||
<div className="mb-8 flex flex-col justify-start">
|
<div className="mb-8 flex flex-col justify-start">
|
||||||
<div className="mb-4 text-xl font-semibold text-mineshaft-100">
|
<div className="mb-4 text-xl font-semibold text-mineshaft-100">Configure rate limits</div>
|
||||||
Configure rate limits
|
|
||||||
</div>
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="readRateLimit"
|
name="readRateLimit"
|
||||||
@@ -245,6 +252,11 @@ export const RateLimitPanel = () => {
|
|||||||
<Button type="submit" isLoading={isSubmitting} isDisabled={isSubmitting || !isDirty}>
|
<Button type="submit" isLoading={isSubmitting} isDisabled={isSubmitting || !isDirty}>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
text="You can configure custom rate limits if you switch to Infisical's Enterprise plan."
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user