feat: Implement enterprise plan check for Chef connections and update documentation

This commit is contained in:
Piyush Gupta
2025-11-03 19:27:56 +05:30
parent 0f461816cc
commit ebab43716e
8 changed files with 49 additions and 9 deletions

View File

@@ -5,10 +5,10 @@ import { request } from "@app/lib/config/request";
import { BadRequestError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn";
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
import { TChefDataBagItemContent } from "../../secret-sync/chef/chef-sync-types";
import { AppConnection } from "../../../../services/app-connection/app-connection-enums";
import { ChefConnectionMethod } from "./chef-connection-enums";
import {
TChefConnection,

View File

@@ -1,7 +1,8 @@
import { ForbiddenRequestError } from "@app/lib/errors";
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
import { OrgServiceActor } from "@app/lib/types";
import { AppConnection } from "../../../../services/app-connection/app-connection-enums";
import { TLicenseServiceFactory } from "../../license/license-service";
import { listChefDataBagItems, listChefDataBags } from "./chef-connection-fns";
import { TChefConnection } from "./chef-connection-types";
@@ -11,8 +12,23 @@ type TGetAppConnectionFunc = (
actor: OrgServiceActor
) => Promise<TChefConnection>;
export const chefConnectionService = (getAppConnection: TGetAppConnectionFunc) => {
// Enterprise check
export const checkPlan = async (licenseService: Pick<TLicenseServiceFactory, "getPlan">, orgId: string) => {
const plan = await licenseService.getPlan(orgId);
if (!plan.enterpriseAppConnections)
throw new BadRequestError({
message:
"Failed to use app connection due to plan restriction. Upgrade plan to access enterprise app connections."
});
};
export const chefConnectionService = (
getAppConnection: TGetAppConnectionFunc,
licenseService: Pick<TLicenseServiceFactory, "getPlan">
) => {
const listDataBags = async (appConnectionId: string, actor: OrgServiceActor) => {
await checkPlan(licenseService, actor.orgId);
const appConnection = await getAppConnection(AppConnection.Chef, appConnectionId, actor);
if (!appConnection) {
@@ -23,6 +39,8 @@ export const chefConnectionService = (getAppConnection: TGetAppConnectionFunc) =
};
const listDataBagItems = async (appConnectionId: string, dataBagName: string, actor: OrgServiceActor) => {
await checkPlan(licenseService, actor.orgId);
const appConnection = await getAppConnection(AppConnection.Chef, appConnectionId, actor);
if (!appConnection) {

View File

@@ -1,7 +1,7 @@
import z from "zod";
import { DiscriminativePick } from "@app/lib/types";
import { TChefDataBagItemContent } from "@app/ee/services/secret-sync/chef";
import { DiscriminativePick } from "@app/lib/types";
import { AppConnection } from "../../../../services/app-connection/app-connection-enums";
import {

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ChefSyncListItemSchema, ChefSyncSchema } from "@app/ee/services/secret-sync/chef";
import { OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "@app/ee/services/secret-sync/oci-vault";
import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter";
@@ -24,7 +25,6 @@ import { AzureKeyVaultSyncListItemSchema, AzureKeyVaultSyncSchema } from "@app/s
import { BitbucketSyncListItemSchema, BitbucketSyncSchema } from "@app/services/secret-sync/bitbucket";
import { CamundaSyncListItemSchema, CamundaSyncSchema } from "@app/services/secret-sync/camunda";
import { ChecklySyncListItemSchema, ChecklySyncSchema } from "@app/services/secret-sync/checkly/checkly-sync-schemas";
import { ChefSyncListItemSchema, ChefSyncSchema } from "@app/ee/services/secret-sync/chef";
import {
CloudflarePagesSyncListItemSchema,
CloudflarePagesSyncSchema

View File

@@ -885,6 +885,6 @@ export const appConnectionServiceFactory = ({
northflank: northflankConnectionService(connectAppConnectionById),
okta: oktaConnectionService(connectAppConnectionById),
laravelForge: laravelForgeConnectionService(connectAppConnectionById),
chef: chefConnectionService(connectAppConnectionById)
chef: chefConnectionService(connectAppConnectionById, licenseService)
};
};

View File

@@ -290,7 +290,9 @@ export const SecretSyncFns = {
case SecretSync.Chef:
return ChefSyncFns.syncSecrets(secretSync, schemaSecretMap);
default:
throw new Error(`Unhandled sync destination for sync secrets fns: ${secretSync.destination}`);
throw new Error(
`Unhandled sync destination for sync secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
);
}
},
getSecrets: async (
@@ -413,7 +415,9 @@ export const SecretSyncFns = {
secretMap = await ChefSyncFns.getSecrets(secretSync);
break;
default:
throw new Error(`Unhandled sync destination for get secrets fns: ${secretSync.destination}`);
throw new Error(
`Unhandled sync destination for get secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
);
}
const filtered = filterForSchema(secretMap, secretSync.environment?.slug || "", secretSync.syncOptions.keySchema);
@@ -510,7 +514,9 @@ export const SecretSyncFns = {
case SecretSync.Chef:
return ChefSyncFns.removeSecrets(secretSync, schemaSecretMap);
default:
throw new Error(`Unhandled sync destination for remove secrets fns: ${secretSync.destination}`);
throw new Error(
`Unhandled sync destination for remove secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}`
);
}
}
};

View File

@@ -3,6 +3,14 @@ title: "Chef Connection"
description: "Learn how to configure a Chef Connection for Infisical."
---
<Info>
Chef App Connection is a paid feature.
If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical,
then you should contact team@infisical.com to purchase an enterprise license to use it.
</Info>
Infisical supports the use of User Private Key to connect with Chef Server.
Please access your **starter kit** to get all the required information to create a Chef Connection.

View File

@@ -3,6 +3,14 @@ title: "Chef Sync"
description: "Learn how to configure a Chef Sync for Infisical."
---
<Info>
Chef Sync is a paid feature.
If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical,
then you should contact team@infisical.com to purchase an enterprise license to use it.
</Info>
**Prerequisites:**
- Create a [Chef Connection](/integrations/app-connections/chef)