mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 13:27:22 +00:00
app connection + finishing touches
This commit is contained in:
+5
-5
@@ -1,16 +1,16 @@
|
|||||||
import z from "zod";
|
import z from "zod";
|
||||||
|
|
||||||
import { readLimit } from "@app/server/config/rateLimiter";
|
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
|
||||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
|
||||||
import {
|
import {
|
||||||
CreateOCIConnectionSchema,
|
CreateOCIConnectionSchema,
|
||||||
SanitizedOCIConnectionSchema,
|
SanitizedOCIConnectionSchema,
|
||||||
UpdateOCIConnectionSchema
|
UpdateOCIConnectionSchema
|
||||||
} from "@app/services/app-connection/oci";
|
} from "@app/ee/services/app-connections/oci";
|
||||||
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
|
import { registerAppConnectionEndpoints } from "../../../../server/routes/v1/app-connection-routers/app-connection-endpoints";
|
||||||
|
|
||||||
export const registerOCIConnectionRouter = async (server: FastifyZodProvider) => {
|
export const registerOCIConnectionRouter = async (server: FastifyZodProvider) => {
|
||||||
registerAppConnectionEndpoints({
|
registerAppConnectionEndpoints({
|
||||||
+23
-2
@@ -1,7 +1,9 @@
|
|||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
import { logger } from "@app/lib/logger";
|
import { logger } from "@app/lib/logger";
|
||||||
import { OrgServiceActor } from "@app/lib/types";
|
import { OrgServiceActor } from "@app/lib/types";
|
||||||
|
|
||||||
import { AppConnection } from "../app-connection-enums";
|
import { AppConnection } from "../../../../services/app-connection/app-connection-enums";
|
||||||
|
import { TLicenseServiceFactory } from "../../license/license-service";
|
||||||
import { listOCICompartments, listOCIVaultKeys, listOCIVaults } from "./oci-connection-fns";
|
import { listOCICompartments, listOCIVaultKeys, listOCIVaults } from "./oci-connection-fns";
|
||||||
import { TOCIConnection } from "./oci-connection-types";
|
import { TOCIConnection } from "./oci-connection-types";
|
||||||
|
|
||||||
@@ -22,8 +24,23 @@ type TListOCIVaultKeysDTO = {
|
|||||||
vaultOcid: string;
|
vaultOcid: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ociConnectionService = (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 ociConnectionService = (
|
||||||
|
getAppConnection: TGetAppConnectionFunc,
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">
|
||||||
|
) => {
|
||||||
const listCompartments = async (connectionId: string, actor: OrgServiceActor) => {
|
const listCompartments = async (connectionId: string, actor: OrgServiceActor) => {
|
||||||
|
await checkPlan(licenseService, actor.orgId);
|
||||||
|
|
||||||
const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor);
|
const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -36,6 +53,8 @@ export const ociConnectionService = (getAppConnection: TGetAppConnectionFunc) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const listVaults = async ({ connectionId, compartmentOcid }: TListOCIVaultsDTO, actor: OrgServiceActor) => {
|
const listVaults = async ({ connectionId, compartmentOcid }: TListOCIVaultsDTO, actor: OrgServiceActor) => {
|
||||||
|
await checkPlan(licenseService, actor.orgId);
|
||||||
|
|
||||||
const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor);
|
const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -51,6 +70,8 @@ export const ociConnectionService = (getAppConnection: TGetAppConnectionFunc) =>
|
|||||||
{ connectionId, compartmentOcid, vaultOcid }: TListOCIVaultKeysDTO,
|
{ connectionId, compartmentOcid, vaultOcid }: TListOCIVaultKeysDTO,
|
||||||
actor: OrgServiceActor
|
actor: OrgServiceActor
|
||||||
) => {
|
) => {
|
||||||
|
await checkPlan(licenseService, actor.orgId);
|
||||||
|
|
||||||
const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor);
|
const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
+1
-1
@@ -2,7 +2,7 @@ import z from "zod";
|
|||||||
|
|
||||||
import { DiscriminativePick } from "@app/lib/types";
|
import { DiscriminativePick } from "@app/lib/types";
|
||||||
|
|
||||||
import { AppConnection } from "../app-connection-enums";
|
import { AppConnection } from "../../../../services/app-connection/app-connection-enums";
|
||||||
import {
|
import {
|
||||||
CreateOCIConnectionSchema,
|
CreateOCIConnectionSchema,
|
||||||
OCIConnectionSchema,
|
OCIConnectionSchema,
|
||||||
@@ -29,7 +29,9 @@ export const getDefaultOnPremFeatures = () => {
|
|||||||
secretApproval: true,
|
secretApproval: true,
|
||||||
secretRotation: true,
|
secretRotation: true,
|
||||||
caCrl: false,
|
caCrl: false,
|
||||||
sshHostGroups: false
|
sshHostGroups: false,
|
||||||
|
enterpriseSecretSyncs: false,
|
||||||
|
enterpriseAppConnections: false
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
kmip: false,
|
kmip: false,
|
||||||
gateway: false,
|
gateway: false,
|
||||||
sshHostGroups: false,
|
sshHostGroups: false,
|
||||||
enterpriseSecretSyncs: false
|
enterpriseSecretSyncs: false,
|
||||||
|
enterpriseAppConnections: false
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setupLicenseRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
export const setupLicenseRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export type TFeatureSet = {
|
|||||||
gateway: false;
|
gateway: false;
|
||||||
sshHostGroups: false;
|
sshHostGroups: false;
|
||||||
enterpriseSecretSyncs: false;
|
enterpriseSecretSyncs: false;
|
||||||
|
enterpriseAppConnections: false;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TOrgPlansTableDTO = {
|
export type TOrgPlansTableDTO = {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { secrets, vault } from "oci-sdk";
|
import { secrets, vault } from "oci-sdk";
|
||||||
|
|
||||||
|
import { getOCIProvider } from "@app/ee/services/app-connections/oci";
|
||||||
import {
|
import {
|
||||||
TCreateOCIVaultVariable,
|
TCreateOCIVaultVariable,
|
||||||
TDeleteOCIVaultVariable,
|
TDeleteOCIVaultVariable,
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
TUpdateOCIVaultVariable
|
TUpdateOCIVaultVariable
|
||||||
} from "@app/ee/services/secret-sync/oci-vault/oci-vault-sync-types";
|
} from "@app/ee/services/secret-sync/oci-vault/oci-vault-sync-types";
|
||||||
import { delay } from "@app/lib/delay";
|
import { delay } from "@app/lib/delay";
|
||||||
import { getOCIProvider } from "@app/services/app-connection/oci";
|
|
||||||
import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
|
import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
|
||||||
import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns";
|
import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns";
|
||||||
import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
|
import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { SimpleAuthenticationDetailsProvider } from "oci-sdk";
|
import { SimpleAuthenticationDetailsProvider } from "oci-sdk";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { TOCIConnection } from "@app/services/app-connection/oci";
|
import { TOCIConnection } from "@app/ee/services/app-connections/oci";
|
||||||
|
|
||||||
import { CreateOCIVaultSyncSchema, OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "./oci-vault-sync-schemas";
|
import { CreateOCIVaultSyncSchema, OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "./oci-vault-sync-schemas";
|
||||||
|
|
||||||
|
|||||||
@@ -1015,7 +1015,8 @@ export const registerRoutes = async (
|
|||||||
secretVersionV2BridgeDAL,
|
secretVersionV2BridgeDAL,
|
||||||
secretVersionTagV2BridgeDAL,
|
secretVersionTagV2BridgeDAL,
|
||||||
resourceMetadataDAL,
|
resourceMetadataDAL,
|
||||||
appConnectionDAL
|
appConnectionDAL,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
|
|
||||||
const secretQueueService = secretQueueFactory({
|
const secretQueueService = secretQueueFactory({
|
||||||
@@ -1632,7 +1633,8 @@ export const registerRoutes = async (
|
|||||||
const appConnectionService = appConnectionServiceFactory({
|
const appConnectionService = appConnectionServiceFactory({
|
||||||
appConnectionDAL,
|
appConnectionDAL,
|
||||||
permissionService,
|
permissionService,
|
||||||
kmsService
|
kmsService,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
|
|
||||||
const secretSyncService = secretSyncServiceFactory({
|
const secretSyncService = secretSyncServiceFactory({
|
||||||
@@ -1643,7 +1645,8 @@ export const registerRoutes = async (
|
|||||||
folderDAL,
|
folderDAL,
|
||||||
secretSyncQueue,
|
secretSyncQueue,
|
||||||
projectBotService,
|
projectBotService,
|
||||||
keyStore
|
keyStore,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
|
|
||||||
const kmipService = kmipServiceFactory({
|
const kmipService = kmipServiceFactory({
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { OCIConnectionListItemSchema, SanitizedOCIConnectionSchema } from "@app/ee/services/app-connections/oci";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { ApiDocsTags } from "@app/lib/api-docs";
|
import { ApiDocsTags } from "@app/lib/api-docs";
|
||||||
import { readLimit } from "@app/server/config/rateLimiter";
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
@@ -38,7 +39,6 @@ import {
|
|||||||
} from "@app/services/app-connection/humanitec";
|
} from "@app/services/app-connection/humanitec";
|
||||||
import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap";
|
import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap";
|
||||||
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
||||||
import { OCIConnectionListItemSchema, SanitizedOCIConnectionSchema } from "@app/services/app-connection/oci";
|
|
||||||
import {
|
import {
|
||||||
PostgresConnectionListItemSchema,
|
PostgresConnectionListItemSchema,
|
||||||
SanitizedPostgresConnectionSchema
|
SanitizedPostgresConnectionSchema
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
|
|
||||||
|
import { registerOCIConnectionRouter } from "../../../../ee/routes/v1/app-connection-routers/oci-connection-router";
|
||||||
import { registerAuth0ConnectionRouter } from "./auth0-connection-router";
|
import { registerAuth0ConnectionRouter } from "./auth0-connection-router";
|
||||||
import { registerAwsConnectionRouter } from "./aws-connection-router";
|
import { registerAwsConnectionRouter } from "./aws-connection-router";
|
||||||
import { registerAzureAppConfigurationConnectionRouter } from "./azure-app-configuration-connection-router";
|
import { registerAzureAppConfigurationConnectionRouter } from "./azure-app-configuration-connection-router";
|
||||||
@@ -13,7 +14,6 @@ import { registerHCVaultConnectionRouter } from "./hc-vault-connection-router";
|
|||||||
import { registerHumanitecConnectionRouter } from "./humanitec-connection-router";
|
import { registerHumanitecConnectionRouter } from "./humanitec-connection-router";
|
||||||
import { registerLdapConnectionRouter } from "./ldap-connection-router";
|
import { registerLdapConnectionRouter } from "./ldap-connection-router";
|
||||||
import { registerMsSqlConnectionRouter } from "./mssql-connection-router";
|
import { registerMsSqlConnectionRouter } from "./mssql-connection-router";
|
||||||
import { registerOCIConnectionRouter } from "./oci-connection-router";
|
|
||||||
import { registerPostgresConnectionRouter } from "./postgres-connection-router";
|
import { registerPostgresConnectionRouter } from "./postgres-connection-router";
|
||||||
import { registerTeamCityConnectionRouter } from "./teamcity-connection-router";
|
import { registerTeamCityConnectionRouter } from "./teamcity-connection-router";
|
||||||
import { registerTerraformCloudConnectionRouter } from "./terraform-cloud-router";
|
import { registerTerraformCloudConnectionRouter } from "./terraform-cloud-router";
|
||||||
|
|||||||
@@ -66,3 +66,8 @@ export enum AWSRegion {
|
|||||||
// South America
|
// South America
|
||||||
SA_EAST_1 = "sa-east-1" // Sao Paulo
|
SA_EAST_1 = "sa-east-1" // Sao Paulo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum AppConnectionPlanType {
|
||||||
|
Enterprise = "enterprise",
|
||||||
|
Regular = "regular"
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import {
|
|||||||
} from "@app/services/app-connection/shared/sql";
|
} from "@app/services/app-connection/shared/sql";
|
||||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getOCIConnectionListItem,
|
||||||
|
OCIConnectionMethod,
|
||||||
|
validateOCIConnectionCredentials
|
||||||
|
} from "../../ee/services/app-connections/oci";
|
||||||
import { AppConnection } from "./app-connection-enums";
|
import { AppConnection } from "./app-connection-enums";
|
||||||
import { TAppConnectionServiceFactoryDep } from "./app-connection-service";
|
import { TAppConnectionServiceFactoryDep } from "./app-connection-service";
|
||||||
import {
|
import {
|
||||||
@@ -53,7 +58,6 @@ import {
|
|||||||
} from "./humanitec";
|
} from "./humanitec";
|
||||||
import { getLdapConnectionListItem, LdapConnectionMethod, validateLdapConnectionCredentials } from "./ldap";
|
import { getLdapConnectionListItem, LdapConnectionMethod, validateLdapConnectionCredentials } from "./ldap";
|
||||||
import { getMsSqlConnectionListItem, MsSqlConnectionMethod } from "./mssql";
|
import { getMsSqlConnectionListItem, MsSqlConnectionMethod } from "./mssql";
|
||||||
import { getOCIConnectionListItem, OCIConnectionMethod, validateOCIConnectionCredentials } from "./oci";
|
|
||||||
import { getPostgresConnectionListItem, PostgresConnectionMethod } from "./postgres";
|
import { getPostgresConnectionListItem, PostgresConnectionMethod } from "./postgres";
|
||||||
import {
|
import {
|
||||||
getTeamCityConnectionListItem,
|
getTeamCityConnectionListItem,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AppConnection } from "./app-connection-enums";
|
import { AppConnection, AppConnectionPlanType } from "./app-connection-enums";
|
||||||
|
|
||||||
export const APP_CONNECTION_NAME_MAP: Record<AppConnection, string> = {
|
export const APP_CONNECTION_NAME_MAP: Record<AppConnection, string> = {
|
||||||
[AppConnection.AWS]: "AWS",
|
[AppConnection.AWS]: "AWS",
|
||||||
@@ -21,3 +21,25 @@ export const APP_CONNECTION_NAME_MAP: Record<AppConnection, string> = {
|
|||||||
[AppConnection.TeamCity]: "TeamCity",
|
[AppConnection.TeamCity]: "TeamCity",
|
||||||
[AppConnection.OCI]: "OCI"
|
[AppConnection.OCI]: "OCI"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const APP_CONNECTION_PLAN_MAP: Record<AppConnection, AppConnectionPlanType> = {
|
||||||
|
[AppConnection.AWS]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.GitHub]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.GCP]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.AzureKeyVault]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.AzureAppConfiguration]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.AzureClientSecrets]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Databricks]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Humanitec]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.TerraformCloud]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Vercel]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Postgres]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.MsSql]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Camunda]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Windmill]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.Auth0]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.HCVault]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.LDAP]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.TeamCity]: AppConnectionPlanType.Regular,
|
||||||
|
[AppConnection.OCI]: AppConnectionPlanType.Enterprise
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ForbiddenError, subject } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
|
|
||||||
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { OrgPermissionAppConnectionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
import { OrgPermissionAppConnectionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { generateHash } from "@app/lib/crypto/encryption";
|
import { generateHash } from "@app/lib/crypto/encryption";
|
||||||
@@ -17,9 +18,11 @@ import {
|
|||||||
import { auth0ConnectionService } from "@app/services/app-connection/auth0/auth0-connection-service";
|
import { auth0ConnectionService } from "@app/services/app-connection/auth0/auth0-connection-service";
|
||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
|
|
||||||
|
import { ValidateOCIConnectionCredentialsSchema } from "../../ee/services/app-connections/oci";
|
||||||
|
import { ociConnectionService } from "../../ee/services/app-connections/oci/oci-connection-service";
|
||||||
import { TAppConnectionDALFactory } from "./app-connection-dal";
|
import { TAppConnectionDALFactory } from "./app-connection-dal";
|
||||||
import { AppConnection } from "./app-connection-enums";
|
import { AppConnection, AppConnectionPlanType } from "./app-connection-enums";
|
||||||
import { APP_CONNECTION_NAME_MAP } from "./app-connection-maps";
|
import { APP_CONNECTION_NAME_MAP, APP_CONNECTION_PLAN_MAP } from "./app-connection-maps";
|
||||||
import {
|
import {
|
||||||
TAppConnection,
|
TAppConnection,
|
||||||
TAppConnectionConfig,
|
TAppConnectionConfig,
|
||||||
@@ -49,8 +52,6 @@ import { ValidateHumanitecConnectionCredentialsSchema } from "./humanitec";
|
|||||||
import { humanitecConnectionService } from "./humanitec/humanitec-connection-service";
|
import { humanitecConnectionService } from "./humanitec/humanitec-connection-service";
|
||||||
import { ValidateLdapConnectionCredentialsSchema } from "./ldap";
|
import { ValidateLdapConnectionCredentialsSchema } from "./ldap";
|
||||||
import { ValidateMsSqlConnectionCredentialsSchema } from "./mssql";
|
import { ValidateMsSqlConnectionCredentialsSchema } from "./mssql";
|
||||||
import { ValidateOCIConnectionCredentialsSchema } from "./oci";
|
|
||||||
import { ociConnectionService } from "./oci/oci-connection-service";
|
|
||||||
import { ValidatePostgresConnectionCredentialsSchema } from "./postgres";
|
import { ValidatePostgresConnectionCredentialsSchema } from "./postgres";
|
||||||
import { ValidateTeamCityConnectionCredentialsSchema } from "./teamcity";
|
import { ValidateTeamCityConnectionCredentialsSchema } from "./teamcity";
|
||||||
import { teamcityConnectionService } from "./teamcity/teamcity-connection-service";
|
import { teamcityConnectionService } from "./teamcity/teamcity-connection-service";
|
||||||
@@ -65,6 +66,7 @@ export type TAppConnectionServiceFactoryDep = {
|
|||||||
appConnectionDAL: TAppConnectionDALFactory;
|
appConnectionDAL: TAppConnectionDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TAppConnectionServiceFactory = ReturnType<typeof appConnectionServiceFactory>;
|
export type TAppConnectionServiceFactory = ReturnType<typeof appConnectionServiceFactory>;
|
||||||
@@ -94,7 +96,8 @@ const VALIDATE_APP_CONNECTION_CREDENTIALS_MAP: Record<AppConnection, TValidateAp
|
|||||||
export const appConnectionServiceFactory = ({
|
export const appConnectionServiceFactory = ({
|
||||||
appConnectionDAL,
|
appConnectionDAL,
|
||||||
permissionService,
|
permissionService,
|
||||||
kmsService
|
kmsService,
|
||||||
|
licenseService
|
||||||
}: TAppConnectionServiceFactoryDep) => {
|
}: TAppConnectionServiceFactoryDep) => {
|
||||||
const listAppConnectionsByOrg = async (actor: OrgServiceActor, app?: AppConnection) => {
|
const listAppConnectionsByOrg = async (actor: OrgServiceActor, app?: AppConnection) => {
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
@@ -191,6 +194,16 @@ export const appConnectionServiceFactory = ({
|
|||||||
OrgPermissionSubjects.AppConnections
|
OrgPermissionSubjects.AppConnections
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (APP_CONNECTION_PLAN_MAP[app] === AppConnectionPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseAppConnections)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to create app connection due to plan restriction. Upgrade plan to access enterprise app connections."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const validatedCredentials = await validateAppConnectionCredentials({
|
const validatedCredentials = await validateAppConnectionCredentials({
|
||||||
app,
|
app,
|
||||||
credentials,
|
credentials,
|
||||||
@@ -253,6 +266,16 @@ export const appConnectionServiceFactory = ({
|
|||||||
|
|
||||||
if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
|
if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (APP_CONNECTION_PLAN_MAP[appConnection.app as AppConnection] === AppConnectionPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseAppConnections)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to update app connection due to plan restriction. Upgrade plan to access enterprise app connections."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
actor.type,
|
actor.type,
|
||||||
actor.id,
|
actor.id,
|
||||||
@@ -399,6 +422,16 @@ export const appConnectionServiceFactory = ({
|
|||||||
|
|
||||||
if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
|
if (!appConnection) throw new NotFoundError({ message: `Could not find App Connection with ID ${connectionId}` });
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (APP_CONNECTION_PLAN_MAP[app] === AppConnectionPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseAppConnections)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to connect app connection due to plan restriction. Upgrade plan to access enterprise app connections."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission: orgPermission } = await permissionService.getOrgPermission(
|
const { permission: orgPermission } = await permissionService.getOrgPermission(
|
||||||
actor.type,
|
actor.type,
|
||||||
actor.id,
|
actor.id,
|
||||||
@@ -468,6 +501,6 @@ export const appConnectionServiceFactory = ({
|
|||||||
hcvault: hcVaultConnectionService(connectAppConnectionById),
|
hcvault: hcVaultConnectionService(connectAppConnectionById),
|
||||||
windmill: windmillConnectionService(connectAppConnectionById),
|
windmill: windmillConnectionService(connectAppConnectionById),
|
||||||
teamcity: teamcityConnectionService(connectAppConnectionById),
|
teamcity: teamcityConnectionService(connectAppConnectionById),
|
||||||
oci: ociConnectionService(connectAppConnectionById)
|
oci: ociConnectionService(connectAppConnectionById, licenseService)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ import { TAppConnectionDALFactory } from "@app/services/app-connection/app-conne
|
|||||||
import { TSqlConnectionConfig } from "@app/services/app-connection/shared/sql/sql-connection-types";
|
import { TSqlConnectionConfig } from "@app/services/app-connection/shared/sql/sql-connection-types";
|
||||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
||||||
|
|
||||||
|
import {
|
||||||
|
TOCIConnection,
|
||||||
|
TOCIConnectionConfig,
|
||||||
|
TOCIConnectionInput,
|
||||||
|
TValidateOCIConnectionCredentialsSchema
|
||||||
|
} from "../../ee/services/app-connections/oci";
|
||||||
import { AWSRegion } from "./app-connection-enums";
|
import { AWSRegion } from "./app-connection-enums";
|
||||||
import {
|
import {
|
||||||
TAuth0Connection,
|
TAuth0Connection,
|
||||||
@@ -76,12 +82,6 @@ import {
|
|||||||
TValidateLdapConnectionCredentialsSchema
|
TValidateLdapConnectionCredentialsSchema
|
||||||
} from "./ldap";
|
} from "./ldap";
|
||||||
import { TMsSqlConnection, TMsSqlConnectionInput, TValidateMsSqlConnectionCredentialsSchema } from "./mssql";
|
import { TMsSqlConnection, TMsSqlConnectionInput, TValidateMsSqlConnectionCredentialsSchema } from "./mssql";
|
||||||
import {
|
|
||||||
TOCIConnection,
|
|
||||||
TOCIConnectionConfig,
|
|
||||||
TOCIConnectionInput,
|
|
||||||
TValidateOCIConnectionCredentialsSchema
|
|
||||||
} from "./oci";
|
|
||||||
import {
|
import {
|
||||||
TPostgresConnection,
|
TPostgresConnection,
|
||||||
TPostgresConnectionInput,
|
TPostgresConnectionInput,
|
||||||
|
|||||||
@@ -26,3 +26,8 @@ export enum SecretSyncImportBehavior {
|
|||||||
PrioritizeSource = "prioritize-source",
|
PrioritizeSource = "prioritize-source",
|
||||||
PrioritizeDestination = "prioritize-destination"
|
PrioritizeDestination = "prioritize-destination"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SecretSyncPlanType {
|
||||||
|
Enterprise = "enterprise",
|
||||||
|
Regular = "regular"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
import { SecretSync, SecretSyncPlanType } from "@app/services/secret-sync/secret-sync-enums";
|
||||||
|
|
||||||
export const SECRET_SYNC_NAME_MAP: Record<SecretSync, string> = {
|
export const SECRET_SYNC_NAME_MAP: Record<SecretSync, string> = {
|
||||||
[SecretSync.AWSParameterStore]: "AWS Parameter Store",
|
[SecretSync.AWSParameterStore]: "AWS Parameter Store",
|
||||||
@@ -36,3 +36,21 @@ export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
|
|||||||
[SecretSync.TeamCity]: AppConnection.TeamCity,
|
[SecretSync.TeamCity]: AppConnection.TeamCity,
|
||||||
[SecretSync.OCIVault]: AppConnection.OCI
|
[SecretSync.OCIVault]: AppConnection.OCI
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const SECRET_SYNC_PLAN_MAP: Record<SecretSync, SecretSyncPlanType> = {
|
||||||
|
[SecretSync.AWSParameterStore]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.AWSSecretsManager]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.GitHub]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.GCPSecretManager]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.AzureKeyVault]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.AzureAppConfiguration]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.Databricks]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.Humanitec]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.TerraformCloud]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.Camunda]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.Vercel]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.Windmill]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.HCVault]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.TeamCity]: SecretSyncPlanType.Regular,
|
||||||
|
[SecretSync.OCIVault]: SecretSyncPlanType.Enterprise
|
||||||
|
};
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import { Job } from "bullmq";
|
|||||||
import { ProjectMembershipRole, SecretType } from "@app/db/schemas";
|
import { ProjectMembershipRole, SecretType } from "@app/db/schemas";
|
||||||
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore";
|
import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
import { logger } from "@app/lib/logger";
|
import { logger } from "@app/lib/logger";
|
||||||
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
||||||
import { decryptAppConnectionCredentials } from "@app/services/app-connection/app-connection-fns";
|
import { decryptAppConnectionCredentials } from "@app/services/app-connection/app-connection-fns";
|
||||||
@@ -29,11 +31,12 @@ import { TSecretSyncDALFactory } from "@app/services/secret-sync/secret-sync-dal
|
|||||||
import {
|
import {
|
||||||
SecretSync,
|
SecretSync,
|
||||||
SecretSyncImportBehavior,
|
SecretSyncImportBehavior,
|
||||||
SecretSyncInitialSyncBehavior
|
SecretSyncInitialSyncBehavior,
|
||||||
|
SecretSyncPlanType
|
||||||
} from "@app/services/secret-sync/secret-sync-enums";
|
} from "@app/services/secret-sync/secret-sync-enums";
|
||||||
import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
|
import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors";
|
||||||
import { parseSyncErrorMessage, SecretSyncFns } from "@app/services/secret-sync/secret-sync-fns";
|
import { parseSyncErrorMessage, SecretSyncFns } from "@app/services/secret-sync/secret-sync-fns";
|
||||||
import { SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
|
import { SECRET_SYNC_NAME_MAP, SECRET_SYNC_PLAN_MAP } from "@app/services/secret-sync/secret-sync-maps";
|
||||||
import {
|
import {
|
||||||
SecretSyncAction,
|
SecretSyncAction,
|
||||||
SecretSyncStatus,
|
SecretSyncStatus,
|
||||||
@@ -93,6 +96,7 @@ type TSecretSyncQueueFactoryDep = {
|
|||||||
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
|
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
|
||||||
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SecretSyncActionJob = Job<
|
type SecretSyncActionJob = Job<
|
||||||
@@ -133,7 +137,8 @@ export const secretSyncQueueFactory = ({
|
|||||||
secretVersionTagDAL,
|
secretVersionTagDAL,
|
||||||
secretVersionV2BridgeDAL,
|
secretVersionV2BridgeDAL,
|
||||||
secretVersionTagV2BridgeDAL,
|
secretVersionTagV2BridgeDAL,
|
||||||
resourceMetadataDAL
|
resourceMetadataDAL,
|
||||||
|
licenseService
|
||||||
}: TSecretSyncQueueFactoryDep) => {
|
}: TSecretSyncQueueFactoryDep) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
|
|
||||||
@@ -323,7 +328,22 @@ export const secretSyncQueueFactory = ({
|
|||||||
secretSync: TSecretSyncWithCredentials,
|
secretSync: TSecretSyncWithCredentials,
|
||||||
importBehavior: SecretSyncImportBehavior
|
importBehavior: SecretSyncImportBehavior
|
||||||
): Promise<TSecretMap> => {
|
): Promise<TSecretMap> => {
|
||||||
const { projectId, environment, folder } = secretSync;
|
const {
|
||||||
|
projectId,
|
||||||
|
environment,
|
||||||
|
folder,
|
||||||
|
destination,
|
||||||
|
connection: { orgId }
|
||||||
|
} = secretSync;
|
||||||
|
|
||||||
|
// Enterprise Check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[destination] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to import secrets due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!environment || !folder)
|
if (!environment || !folder)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -400,6 +420,15 @@ export const secretSyncQueueFactory = ({
|
|||||||
|
|
||||||
if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
|
if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
|
||||||
|
|
||||||
|
// Enterprise Check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[secretSync.destination as SecretSync] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(secretSync.connection.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to sync secrets due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await secretSyncDAL.updateById(syncId, {
|
await secretSyncDAL.updateById(syncId, {
|
||||||
syncStatus: SecretSyncStatus.Running
|
syncStatus: SecretSyncStatus.Running
|
||||||
});
|
});
|
||||||
@@ -659,6 +688,16 @@ export const secretSyncQueueFactory = ({
|
|||||||
|
|
||||||
if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
|
if (!secretSync) throw new Error(`Cannot find secret sync with ID ${syncId}`);
|
||||||
|
|
||||||
|
// Enterprise Check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[secretSync.destination as SecretSync] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(secretSync.connection.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to access secret sync due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await secretSyncDAL.updateById(syncId, {
|
await secretSyncDAL.updateById(syncId, {
|
||||||
removeStatus: SecretSyncStatus.Running
|
removeStatus: SecretSyncStatus.Running
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
|
||||||
import { ActionProjectType } from "@app/db/schemas";
|
import { ActionProjectType } from "@app/db/schemas";
|
||||||
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { throwIfMissingSecretReadValueOrDescribePermission } from "@app/ee/services/permission/permission-fns";
|
import { throwIfMissingSecretReadValueOrDescribePermission } from "@app/ee/services/permission/permission-fns";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import {
|
import {
|
||||||
@@ -15,7 +16,7 @@ import { OrgServiceActor } from "@app/lib/types";
|
|||||||
import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
|
import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
|
||||||
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
||||||
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
||||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
import { SecretSync, SecretSyncPlanType } from "@app/services/secret-sync/secret-sync-enums";
|
||||||
import { listSecretSyncOptions } from "@app/services/secret-sync/secret-sync-fns";
|
import { listSecretSyncOptions } from "@app/services/secret-sync/secret-sync-fns";
|
||||||
import {
|
import {
|
||||||
SecretSyncStatus,
|
SecretSyncStatus,
|
||||||
@@ -34,7 +35,7 @@ import {
|
|||||||
|
|
||||||
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
||||||
import { TSecretSyncDALFactory } from "./secret-sync-dal";
|
import { TSecretSyncDALFactory } from "./secret-sync-dal";
|
||||||
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "./secret-sync-maps";
|
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP, SECRET_SYNC_PLAN_MAP } from "./secret-sync-maps";
|
||||||
import { TSecretSyncQueueFactory } from "./secret-sync-queue";
|
import { TSecretSyncQueueFactory } from "./secret-sync-queue";
|
||||||
|
|
||||||
type TSecretSyncServiceFactoryDep = {
|
type TSecretSyncServiceFactoryDep = {
|
||||||
@@ -49,6 +50,7 @@ type TSecretSyncServiceFactoryDep = {
|
|||||||
TSecretSyncQueueFactory,
|
TSecretSyncQueueFactory,
|
||||||
"queueSecretSyncSyncSecretsById" | "queueSecretSyncImportSecretsById" | "queueSecretSyncRemoveSecretsById"
|
"queueSecretSyncSyncSecretsById" | "queueSecretSyncImportSecretsById" | "queueSecretSyncRemoveSecretsById"
|
||||||
>;
|
>;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TSecretSyncServiceFactory = ReturnType<typeof secretSyncServiceFactory>;
|
export type TSecretSyncServiceFactory = ReturnType<typeof secretSyncServiceFactory>;
|
||||||
@@ -61,7 +63,8 @@ export const secretSyncServiceFactory = ({
|
|||||||
appConnectionService,
|
appConnectionService,
|
||||||
projectBotService,
|
projectBotService,
|
||||||
secretSyncQueue,
|
secretSyncQueue,
|
||||||
keyStore
|
keyStore,
|
||||||
|
licenseService
|
||||||
}: TSecretSyncServiceFactoryDep) => {
|
}: TSecretSyncServiceFactoryDep) => {
|
||||||
const listSecretSyncsByProjectId = async (
|
const listSecretSyncsByProjectId = async (
|
||||||
{ projectId, destination }: TListSecretSyncsByProjectId,
|
{ projectId, destination }: TListSecretSyncsByProjectId,
|
||||||
@@ -191,6 +194,16 @@ export const secretSyncServiceFactory = ({
|
|||||||
{ projectId, secretPath, environment, ...params }: TCreateSecretSyncDTO,
|
{ projectId, secretPath, environment, ...params }: TCreateSecretSyncDTO,
|
||||||
actor: OrgServiceActor
|
actor: OrgServiceActor
|
||||||
) => {
|
) => {
|
||||||
|
// Enterprise check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[params.destination] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to create secret sync due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission: projectPermission } = await permissionService.getProjectPermission({
|
const { permission: projectPermission } = await permissionService.getProjectPermission({
|
||||||
actor: actor.type,
|
actor: actor.type,
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
@@ -260,6 +273,16 @@ export const secretSyncServiceFactory = ({
|
|||||||
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID ${syncId}`
|
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID ${syncId}`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[secretSync.destination as SecretSync] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to update secret sync due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor: actor.type,
|
actor: actor.type,
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
@@ -408,6 +431,16 @@ export const secretSyncServiceFactory = ({
|
|||||||
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
|
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[secretSync.destination as SecretSync] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to trigger secret sync due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor: actor.type,
|
actor: actor.type,
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
@@ -463,6 +496,16 @@ export const secretSyncServiceFactory = ({
|
|||||||
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
|
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[secretSync.destination as SecretSync] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to trigger secret sync due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor: actor.type,
|
actor: actor.type,
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
@@ -512,6 +555,16 @@ export const secretSyncServiceFactory = ({
|
|||||||
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
|
message: `Could not find ${SECRET_SYNC_NAME_MAP[destination]} Sync with ID "${syncId}"`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enterprise check
|
||||||
|
if (SECRET_SYNC_PLAN_MAP[secretSync.destination as SecretSync] === SecretSyncPlanType.Enterprise) {
|
||||||
|
const plan = await licenseService.getPlan(actor.orgId);
|
||||||
|
if (!plan.enterpriseSecretSyncs)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to trigger secret sync due to plan restriction. Upgrade plan to access enterprise secret syncs."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor: actor.type,
|
actor: actor.type,
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ title: "OCI Connection"
|
|||||||
description: "Learn how to configure an Oracle Cloud Infrastructure Connection for Infisical."
|
description: "Learn how to configure an Oracle Cloud Infrastructure Connection for Infisical."
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<Info>
|
||||||
|
OCI 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 [email protected] to purchase an enterprise license to use it.
|
||||||
|
</Info>
|
||||||
|
|
||||||
Infisical supports the use of [API Signing Key Authentication](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm) to connect with OCI.
|
Infisical supports the use of [API Signing Key Authentication](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm) to connect with OCI.
|
||||||
|
|
||||||
## Create OCI User
|
## Create OCI User
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ title: "OCI Vault Sync"
|
|||||||
description: "Learn how to configure an Oracle Cloud Infrastructure Vault Sync for Infisical."
|
description: "Learn how to configure an Oracle Cloud Infrastructure Vault Sync for Infisical."
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<Info>
|
||||||
|
OCI Vault 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 [email protected] to purchase an enterprise license to use it.
|
||||||
|
</Info>
|
||||||
|
|
||||||
**Prerequisites:**
|
**Prerequisites:**
|
||||||
- Create an [OCI Connection](/integrations/app-connections/oci) with the required **Secret Sync** permissions
|
- Create an [OCI Connection](/integrations/app-connections/oci) with the required **Secret Sync** permissions
|
||||||
- [Create](https://docs.oracle.com/en-us/iaas/Content/Identity/compartments/To_create_a_compartment.htm) or use an existing OCI Compartment (which the OCI Connection is authorized to access)
|
- [Create](https://docs.oracle.com/en-us/iaas/Content/Identity/compartments/To_create_a_compartment.htm) or use an existing OCI Compartment (which the OCI Connection is authorized to access)
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { faWrench } from "@fortawesome/free-solid-svg-icons";
|
import { faWrench } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import { Spinner, Tooltip } from "@app/components/v2";
|
import { Spinner, Tooltip } from "@app/components/v2";
|
||||||
import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
|
|
||||||
import { SecretSync, useSecretSyncOptions } from "@app/hooks/api/secretSyncs";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
import { UpgradePlanModal } from "../license/UpgradePlanModal";
|
|
||||||
import { usePopUp } from "@app/hooks";
|
|
||||||
import { useSubscription } from "@app/context";
|
import { useSubscription } from "@app/context";
|
||||||
|
import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
|
||||||
|
import { usePopUp } from "@app/hooks";
|
||||||
|
import { SecretSync, useSecretSyncOptions } from "@app/hooks/api/secretSyncs";
|
||||||
|
|
||||||
|
import { UpgradePlanModal } from "../license/UpgradePlanModal";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSelect: (destination: SecretSync) => void;
|
onSelect: (destination: SecretSync) => void;
|
||||||
@@ -52,7 +53,7 @@ export const SecretSyncSelect = ({ onSelect }: Props) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{enterprise && !subscription.enterpriseSecretSyncs && (
|
{enterprise && !subscription.enterpriseSecretSyncs && (
|
||||||
<div className="absolute h-full w-full backdrop-blur-[1px]"></div>
|
<div className="absolute h-full w-full backdrop-blur-[1px]" />
|
||||||
)}
|
)}
|
||||||
<img
|
<img
|
||||||
src={`/images/integrations/${image}`}
|
src={`/images/integrations/${image}`}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import { OCIConnectionMethod } from "@app/hooks/api/appConnections/types/oci-con
|
|||||||
|
|
||||||
export const APP_CONNECTION_MAP: Record<
|
export const APP_CONNECTION_MAP: Record<
|
||||||
AppConnection,
|
AppConnection,
|
||||||
{ name: string; image: string; size?: number }
|
{ name: string; image: string; size?: number; enterprise?: boolean }
|
||||||
> = {
|
> = {
|
||||||
[AppConnection.AWS]: { name: "AWS", image: "Amazon Web Services.png" },
|
[AppConnection.AWS]: { name: "AWS", image: "Amazon Web Services.png" },
|
||||||
[AppConnection.GitHub]: { name: "GitHub", image: "GitHub.png" },
|
[AppConnection.GitHub]: { name: "GitHub", image: "GitHub.png" },
|
||||||
@@ -63,7 +63,7 @@ export const APP_CONNECTION_MAP: Record<
|
|||||||
[AppConnection.HCVault]: { name: "Hashicorp Vault", image: "Vault.png", size: 65 },
|
[AppConnection.HCVault]: { name: "Hashicorp Vault", image: "Vault.png", size: 65 },
|
||||||
[AppConnection.LDAP]: { name: "LDAP", image: "LDAP.png", size: 65 },
|
[AppConnection.LDAP]: { name: "LDAP", image: "LDAP.png", size: 65 },
|
||||||
[AppConnection.TeamCity]: { name: "TeamCity", image: "TeamCity.png" },
|
[AppConnection.TeamCity]: { name: "TeamCity", image: "TeamCity.png" },
|
||||||
[AppConnection.OCI]: { name: "OCI", image: "Oracle.png" }
|
[AppConnection.OCI]: { name: "OCI", image: "Oracle.png", enterprise: true }
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAppConnectionMethodDetails = (method: TAppConnection["method"]) => {
|
export const getAppConnectionMethodDetails = (method: TAppConnection["method"]) => {
|
||||||
|
|||||||
@@ -51,4 +51,5 @@ export type SubscriptionPlan = {
|
|||||||
projectTemplates: boolean;
|
projectTemplates: boolean;
|
||||||
kmip: boolean;
|
kmip: boolean;
|
||||||
enterpriseSecretSyncs: boolean;
|
enterpriseSecretSyncs: boolean;
|
||||||
|
enterpriseAppConnections: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
+48
-18
@@ -1,8 +1,12 @@
|
|||||||
import { faWrench } from "@fortawesome/free-solid-svg-icons";
|
import { faWrench } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||||
import { Spinner, Tooltip } from "@app/components/v2";
|
import { Spinner, Tooltip } from "@app/components/v2";
|
||||||
|
import { useSubscription } from "@app/context";
|
||||||
import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
|
import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
|
||||||
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useAppConnectionOptions } from "@app/hooks/api/appConnections";
|
import { useAppConnectionOptions } from "@app/hooks/api/appConnections";
|
||||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||||
|
|
||||||
@@ -11,8 +15,11 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const AppConnectionsSelect = ({ onSelect }: Props) => {
|
export const AppConnectionsSelect = ({ onSelect }: Props) => {
|
||||||
|
const { subscription } = useSubscription();
|
||||||
const { isPending, data: appConnectionOptions } = useAppConnectionOptions();
|
const { isPending, data: appConnectionOptions } = useAppConnectionOptions();
|
||||||
|
|
||||||
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
|
||||||
|
|
||||||
if (isPending) {
|
if (isPending) {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-col items-center justify-center py-2.5">
|
<div className="flex h-full flex-col items-center justify-center py-2.5">
|
||||||
@@ -25,29 +32,52 @@ export const AppConnectionsSelect = ({ onSelect }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-4 gap-2">
|
<div className="grid grid-cols-4 gap-2">
|
||||||
{appConnectionOptions?.map((option) => {
|
{appConnectionOptions?.map((option) => {
|
||||||
const { image, name, size = 50 } = APP_CONNECTION_MAP[option.app];
|
const { image, name, size = 50, enterprise = false } = APP_CONNECTION_MAP[option.app];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Tooltip
|
||||||
type="button"
|
content={
|
||||||
key={option.app}
|
enterprise && !subscription.enterpriseAppConnections
|
||||||
onClick={() => onSelect(option.app)}
|
? "Enterprise Plan Only"
|
||||||
className="group relative flex h-28 cursor-pointer flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-700 p-4 duration-200 hover:bg-mineshaft-600"
|
: undefined
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<img
|
<button
|
||||||
src={`/images/integrations/${image}`}
|
type="button"
|
||||||
style={{
|
key={option.app}
|
||||||
width: `${size}px`
|
onClick={() =>
|
||||||
}}
|
enterprise && !subscription.enterpriseAppConnections
|
||||||
className="mt-auto"
|
? handlePopUpOpen("upgradePlan")
|
||||||
alt={`${name} logo`}
|
: onSelect(option.app)
|
||||||
/>
|
}
|
||||||
<div className="mt-auto max-w-xs text-center text-xs font-medium text-gray-300 duration-200 group-hover:text-gray-200">
|
className={twMerge(
|
||||||
{name}
|
"group relative flex h-28 cursor-pointer flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-700 p-4 duration-200 hover:bg-mineshaft-600",
|
||||||
</div>
|
enterprise && !subscription.enterpriseAppConnections ? "border-0 bg-opacity-0" : ""
|
||||||
</button>
|
)}
|
||||||
|
>
|
||||||
|
{enterprise && !subscription.enterpriseAppConnections && (
|
||||||
|
<div className="absolute h-full w-full backdrop-blur-[1px]" />
|
||||||
|
)}
|
||||||
|
<img
|
||||||
|
src={`/images/integrations/${image}`}
|
||||||
|
style={{
|
||||||
|
width: `${size}px`
|
||||||
|
}}
|
||||||
|
className="mt-auto"
|
||||||
|
alt={`${name} logo`}
|
||||||
|
/>
|
||||||
|
<div className="mt-auto max-w-xs text-center text-xs font-medium text-gray-300 duration-200 group-hover:text-gray-200">
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
text="You can use every App Connection if you switch to Infisical's Enterprise plan."
|
||||||
|
/>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
side="bottom"
|
side="bottom"
|
||||||
className="max-w-sm py-4"
|
className="max-w-sm py-4"
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
|
|||||||
Reference in New Issue
Block a user