mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Improve types and maps for secret sync warning logic
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||
import { SecretSync, SecretSyncPlanType } from "@app/services/secret-sync/secret-sync-enums";
|
||||
import { DestinationDuplicateCheckFn } from "@app/services/secret-sync/secret-sync-types";
|
||||
|
||||
export const SECRET_SYNC_NAME_MAP: Record<SecretSync, string> = {
|
||||
[SecretSync.AWSParameterStore]: "AWS Parameter Store",
|
||||
@@ -99,3 +100,101 @@ export const SECRET_SYNC_PLAN_MAP: Record<SecretSync, SecretSyncPlanType> = {
|
||||
[SecretSync.Netlify]: SecretSyncPlanType.Regular,
|
||||
[SecretSync.Bitbucket]: SecretSyncPlanType.Regular
|
||||
};
|
||||
|
||||
export const SECRET_SYNC_SKIP_FIELDS_MAP: Record<SecretSync, string[]> = {
|
||||
[SecretSync.AWSParameterStore]: [],
|
||||
[SecretSync.AWSSecretsManager]: ["mappingBehavior", "secretName"],
|
||||
[SecretSync.GitHub]: [],
|
||||
[SecretSync.GCPSecretManager]: [],
|
||||
[SecretSync.AzureKeyVault]: [],
|
||||
[SecretSync.AzureAppConfiguration]: ["label"],
|
||||
[SecretSync.AzureDevOps]: ["devopsProjectName"],
|
||||
[SecretSync.Databricks]: [],
|
||||
[SecretSync.Humanitec]: [],
|
||||
[SecretSync.TerraformCloud]: ["variableSetName", "workspaceName"],
|
||||
[SecretSync.Camunda]: [],
|
||||
[SecretSync.Vercel]: ["appName"],
|
||||
[SecretSync.Windmill]: [],
|
||||
[SecretSync.HCVault]: [],
|
||||
[SecretSync.TeamCity]: [],
|
||||
[SecretSync.OCIVault]: [],
|
||||
[SecretSync.OnePass]: ["valueLabel"],
|
||||
[SecretSync.Heroku]: ["appName"],
|
||||
[SecretSync.Render]: [],
|
||||
[SecretSync.Flyio]: [],
|
||||
[SecretSync.GitLab]: [
|
||||
"projectName",
|
||||
"shouldProtectSecrets",
|
||||
"shouldMaskSecrets",
|
||||
"shouldHideSecrets",
|
||||
"targetEnvironment",
|
||||
"groupName",
|
||||
"groupId",
|
||||
"projectId"
|
||||
],
|
||||
[SecretSync.CloudflarePages]: [],
|
||||
[SecretSync.CloudflareWorkers]: [],
|
||||
[SecretSync.Supabase]: ["projectName"],
|
||||
[SecretSync.Zabbix]: ["hostName", "macroType"],
|
||||
[SecretSync.Railway]: ["projectName", "environmentName", "serviceName"],
|
||||
[SecretSync.Checkly]: ["groupName", "accountName"],
|
||||
[SecretSync.DigitalOceanAppPlatform]: ["appName"],
|
||||
[SecretSync.Netlify]: ["accountName", "siteName"],
|
||||
[SecretSync.Bitbucket]: []
|
||||
};
|
||||
|
||||
const defaultDuplicateCheck: DestinationDuplicateCheckFn = () => true;
|
||||
|
||||
export const DESTINATION_DUPLICATE_CHECK_MAP: Record<SecretSync, DestinationDuplicateCheckFn> = {
|
||||
[SecretSync.AWSParameterStore]: defaultDuplicateCheck,
|
||||
[SecretSync.AWSSecretsManager]: defaultDuplicateCheck,
|
||||
[SecretSync.GitHub]: defaultDuplicateCheck,
|
||||
[SecretSync.GCPSecretManager]: defaultDuplicateCheck,
|
||||
[SecretSync.AzureKeyVault]: defaultDuplicateCheck,
|
||||
[SecretSync.AzureAppConfiguration]: defaultDuplicateCheck,
|
||||
[SecretSync.AzureDevOps]: defaultDuplicateCheck,
|
||||
[SecretSync.Databricks]: defaultDuplicateCheck,
|
||||
[SecretSync.Humanitec]: defaultDuplicateCheck,
|
||||
[SecretSync.TerraformCloud]: defaultDuplicateCheck,
|
||||
[SecretSync.Camunda]: defaultDuplicateCheck,
|
||||
[SecretSync.Vercel]: defaultDuplicateCheck,
|
||||
[SecretSync.Windmill]: defaultDuplicateCheck,
|
||||
[SecretSync.HCVault]: defaultDuplicateCheck,
|
||||
[SecretSync.TeamCity]: defaultDuplicateCheck,
|
||||
[SecretSync.OCIVault]: defaultDuplicateCheck,
|
||||
[SecretSync.OnePass]: defaultDuplicateCheck,
|
||||
[SecretSync.Heroku]: defaultDuplicateCheck,
|
||||
[SecretSync.Render]: defaultDuplicateCheck,
|
||||
[SecretSync.Flyio]: defaultDuplicateCheck,
|
||||
[SecretSync.GitLab]: (existingConfig, newConfig) => {
|
||||
const existingTargetEnv = existingConfig.targetEnvironment as string | undefined;
|
||||
const newTargetEnv = newConfig.targetEnvironment as string | undefined;
|
||||
|
||||
const wildcardValues = ["*", ""];
|
||||
// If either has wildcard, it conflicts with any targetEnvironment
|
||||
if (
|
||||
!existingTargetEnv ||
|
||||
!newTargetEnv ||
|
||||
wildcardValues.includes(existingTargetEnv) ||
|
||||
wildcardValues.includes(newTargetEnv)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
existingTargetEnv === newTargetEnv &&
|
||||
((newConfig.scope as string) === "group"
|
||||
? existingConfig.groupId === newConfig.groupId
|
||||
: existingConfig.projectId === newConfig.projectId)
|
||||
);
|
||||
},
|
||||
[SecretSync.CloudflarePages]: defaultDuplicateCheck,
|
||||
[SecretSync.CloudflareWorkers]: defaultDuplicateCheck,
|
||||
[SecretSync.Supabase]: defaultDuplicateCheck,
|
||||
[SecretSync.Zabbix]: defaultDuplicateCheck,
|
||||
[SecretSync.Railway]: defaultDuplicateCheck,
|
||||
[SecretSync.Checkly]: defaultDuplicateCheck,
|
||||
[SecretSync.DigitalOceanAppPlatform]: defaultDuplicateCheck,
|
||||
[SecretSync.Netlify]: defaultDuplicateCheck,
|
||||
[SecretSync.Bitbucket]: defaultDuplicateCheck
|
||||
};
|
||||
|
||||
@@ -37,7 +37,12 @@ import {
|
||||
|
||||
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
||||
import { TSecretSyncDALFactory } from "./secret-sync-dal";
|
||||
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "./secret-sync-maps";
|
||||
import {
|
||||
DESTINATION_DUPLICATE_CHECK_MAP,
|
||||
SECRET_SYNC_CONNECTION_MAP,
|
||||
SECRET_SYNC_NAME_MAP,
|
||||
SECRET_SYNC_SKIP_FIELDS_MAP
|
||||
} from "./secret-sync-maps";
|
||||
import { TSecretSyncQueueFactory } from "./secret-sync-queue";
|
||||
|
||||
type TSecretSyncServiceFactoryDep = {
|
||||
@@ -698,83 +703,11 @@ export const secretSyncServiceFactory = ({
|
||||
return updatedSecretSync as TSecretSync;
|
||||
};
|
||||
|
||||
const getSkipFieldsForDestination = (destination: SecretSync): string[] => {
|
||||
switch (destination) {
|
||||
case SecretSync.AWSSecretsManager:
|
||||
return ["mappingBehavior", "secretName"];
|
||||
case SecretSync.OnePass:
|
||||
return ["valueLabel"];
|
||||
case SecretSync.AzureAppConfiguration:
|
||||
return ["label"];
|
||||
case SecretSync.AzureDevOps:
|
||||
return ["devopsProjectName"];
|
||||
case SecretSync.Checkly:
|
||||
return ["groupName", "accountName"];
|
||||
case SecretSync.DigitalOceanAppPlatform:
|
||||
return ["appName"];
|
||||
case SecretSync.GitLab:
|
||||
return [
|
||||
"projectName",
|
||||
"shouldProtectSecrets",
|
||||
"shouldMaskSecrets",
|
||||
"shouldHideSecrets",
|
||||
"targetEnvironment",
|
||||
"groupName",
|
||||
"groupId",
|
||||
"projectId"
|
||||
];
|
||||
case SecretSync.Heroku:
|
||||
return ["appName"];
|
||||
case SecretSync.Netlify:
|
||||
return ["accountName", "siteName"];
|
||||
case SecretSync.Railway:
|
||||
return ["projectName", "environmentName", "serviceName"];
|
||||
case SecretSync.Supabase:
|
||||
return ["projectName"];
|
||||
case SecretSync.TerraformCloud:
|
||||
return ["variableSetName", "workspaceName"];
|
||||
case SecretSync.Vercel:
|
||||
return ["appName"];
|
||||
case SecretSync.Zabbix:
|
||||
return ["hostName", "macroType"];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const handleSpecialCaseDuplicateCheck = (
|
||||
destination: SecretSync,
|
||||
existingConfig: Record<string, unknown>,
|
||||
newConfig: Record<string, unknown>
|
||||
): boolean => {
|
||||
switch (destination) {
|
||||
case SecretSync.GitLab: {
|
||||
const existingTargetEnv = existingConfig.targetEnvironment as string | undefined;
|
||||
const newTargetEnv = newConfig.targetEnvironment as string | undefined;
|
||||
|
||||
// If either has wildcard '*', it conflicts with any targetEnvironment
|
||||
if (existingTargetEnv === "*" || newTargetEnv === "*") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
existingTargetEnv === newTargetEnv &&
|
||||
((newConfig.scope as string) === "group"
|
||||
? existingConfig.groupId === newConfig.groupId
|
||||
: existingConfig.projectId === newConfig.projectId)
|
||||
);
|
||||
}
|
||||
default:
|
||||
// For other sync types, no special handling needed
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const checkDuplicateDestination = async (
|
||||
{ destination, destinationConfig, excludeSyncId, projectId }: TCheckDuplicateDestinationDTO,
|
||||
actor: OrgServiceActor
|
||||
) => {
|
||||
const skipFields = getSkipFieldsForDestination(destination);
|
||||
const skipFields = SECRET_SYNC_SKIP_FIELDS_MAP[destination];
|
||||
const { permission } = await permissionService.getProjectPermission({
|
||||
actor: actor.type,
|
||||
actorId: actor.id,
|
||||
@@ -804,8 +737,7 @@ export const secretSyncServiceFactory = ({
|
||||
try {
|
||||
const baseFieldsMatch = deepEqualSkipFields(sync.destinationConfig, destinationConfig, skipFields);
|
||||
if (baseFieldsMatch) {
|
||||
return handleSpecialCaseDuplicateCheck(
|
||||
destination,
|
||||
return DESTINATION_DUPLICATE_CHECK_MAP[destination](
|
||||
sync.destinationConfig as Record<string, unknown>,
|
||||
destinationConfig
|
||||
);
|
||||
|
||||
@@ -415,3 +415,8 @@ export type TSecretMap = Record<
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
}
|
||||
>;
|
||||
|
||||
export type DestinationDuplicateCheckFn = (
|
||||
existingConfig: Record<string, unknown>,
|
||||
newConfig: Record<string, unknown>
|
||||
) => boolean;
|
||||
|
||||
Reference in New Issue
Block a user