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:
Maidul Islam
2024-06-14 09:33:41 -04:00
committed by GitHub
12 changed files with 44 additions and 19 deletions
+1 -1
View File
@@ -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";
+2
View File
@@ -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,
@@ -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();
-5
View File
@@ -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 -1
View File
@@ -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();
+8 -4
View File
@@ -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", {
-2
View File
@@ -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>
); );
}; };