mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 00:27:35 +00:00
feat: updated ui to reflect secret import and approval
This commit is contained in:
@@ -677,7 +677,9 @@ export const registerRoutes = async (
|
||||
secretApprovalPolicyService,
|
||||
secretBlindIndexDAL,
|
||||
secretApprovalRequestDAL,
|
||||
secretApprovalRequestSecretDAL
|
||||
secretApprovalRequestSecretDAL,
|
||||
secretQueueService,
|
||||
snapshotService
|
||||
});
|
||||
const secretRotationQueue = secretRotationQueueFactory({
|
||||
telemetryService,
|
||||
|
||||
@@ -79,7 +79,7 @@ export const fnSecretsFromImports = async ({
|
||||
let secretsFromDeeperImports: TSecretImportSecrets[] = [];
|
||||
if (deeperImports.length) {
|
||||
secretsFromDeeperImports = await fnSecretsFromImports({
|
||||
allowedImports: deeperImports,
|
||||
allowedImports: deeperImports.filter(({ isReplication }) => !isReplication),
|
||||
secretImportDAL,
|
||||
folderDAL,
|
||||
secretDAL,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||
import { TSecretDALFactory } from "../secret/secret-dal";
|
||||
import { TSecretQueueFactory } from "../secret/secret-queue";
|
||||
import { SecretOperations } from "../secret/secret-types";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretImportDALFactory } from "./secret-import-dal";
|
||||
import { fnSecretsFromImports } from "./secret-import-fns";
|
||||
@@ -26,7 +27,7 @@ type TSecretImportServiceFactoryDep = {
|
||||
projectDAL: Pick<TProjectDALFactory, "checkProjectUpgradeStatus">;
|
||||
projectEnvDAL: TProjectEnvDALFactory;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets">;
|
||||
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets" | "replicateSecrets">;
|
||||
};
|
||||
|
||||
const ERR_SEC_IMP_NOT_FOUND = new BadRequestError({ message: "Secret import not found" });
|
||||
@@ -53,7 +54,7 @@ export const secretImportServiceFactory = ({
|
||||
isReplication,
|
||||
path
|
||||
}: TCreateSecretImportDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
const { permission, membership } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
@@ -108,12 +109,27 @@ export const secretImportServiceFactory = ({
|
||||
);
|
||||
});
|
||||
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath: secImport.importPath,
|
||||
projectId,
|
||||
environmentSlug: importEnv.slug,
|
||||
excludeReplication: true
|
||||
});
|
||||
if (secImport.isReplication) {
|
||||
const importedSecrets = await secretDAL.find({ folderId: sourceFolder?.id });
|
||||
await secretQueueService.replicateSecrets({
|
||||
secretPath: secImport.importPath,
|
||||
projectId,
|
||||
environmentSlug: importEnv.slug,
|
||||
pickOnlyImportIds: [secImport.id],
|
||||
folderId: sourceFolder?.id as string,
|
||||
secrets: importedSecrets.map(({ id, version }) => ({ operation: SecretOperations.Create, version, id })),
|
||||
// TODO(akhilmhdh): approval based replication this will fail for identity
|
||||
membershipId: membership?.id as string,
|
||||
environmentId: importEnv.id
|
||||
});
|
||||
} else {
|
||||
await secretQueueService.syncSecrets({
|
||||
secretPath: secImport.importPath,
|
||||
projectId,
|
||||
environmentSlug: importEnv.slug,
|
||||
excludeReplication: true
|
||||
});
|
||||
}
|
||||
|
||||
return { ...secImport, importEnv };
|
||||
};
|
||||
@@ -283,7 +299,7 @@ export const secretImportServiceFactory = ({
|
||||
if (!folder) return [];
|
||||
// this will already order by position
|
||||
// so anything based on this order will also be in right position
|
||||
const secretImports = await secretImportDAL.find({ folderId: folder.id });
|
||||
const secretImports = await secretImportDAL.find({ folderId: folder.id, isReplication: false });
|
||||
|
||||
const allowedImports = secretImports.filter(({ importEnv, importPath }) =>
|
||||
permission.can(
|
||||
|
||||
@@ -64,12 +64,15 @@ export const secretReplicationServiceFactory = ({
|
||||
}: TSecretReplicationServiceFactoryDep) => {
|
||||
queueService.start(QueueName.SecretReplication, async (job) => {
|
||||
logger.info(job.data, "Replication started");
|
||||
const { secrets, folderId, secretPath, environmentId, projectId, membershipId } = job.data;
|
||||
const secretImports = await secretImportDAL.find({
|
||||
const { secrets, folderId, secretPath, environmentId, projectId, membershipId, pickOnlyImportIds } = job.data;
|
||||
let secretImports = await secretImportDAL.find({
|
||||
importPath: secretPath,
|
||||
importEnv: environmentId,
|
||||
isReplication: true
|
||||
});
|
||||
secretImports = pickOnlyImportIds
|
||||
? secretImports.filter(({ id }) => pickOnlyImportIds?.includes(id))
|
||||
: secretImports;
|
||||
if (!secretImports.length || !secrets.length) return;
|
||||
|
||||
// unfiltered secrets to be replicated
|
||||
|
||||
@@ -143,6 +143,18 @@ export const secretQueueFactory = ({
|
||||
});
|
||||
};
|
||||
|
||||
const replicateSecrets = async (dto: TSyncSecretsDTO) => {
|
||||
await queueService.queue(QueueName.SecretReplication, QueueJobs.SecretReplication, dto, {
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000
|
||||
},
|
||||
removeOnComplete: true,
|
||||
removeOnFail: true
|
||||
});
|
||||
};
|
||||
|
||||
const removeSecretReminder = async (dto: TRemoveSecretReminderDTO) => {
|
||||
const appCfg = getConfig();
|
||||
await queueService.stopRepeatableJob(
|
||||
@@ -361,22 +373,17 @@ export const secretQueueFactory = ({
|
||||
}
|
||||
);
|
||||
await syncIntegrations({ secretPath, projectId, environment });
|
||||
if (!excludeReplication) {
|
||||
await queueService.queue(
|
||||
QueueName.SecretReplication,
|
||||
QueueJobs.SecretReplication,
|
||||
{ environmentId, projectId, secretPath, folderId, secrets, membershipId },
|
||||
{
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: "exponential",
|
||||
delay: 2000
|
||||
},
|
||||
removeOnComplete: true,
|
||||
removeOnFail: true
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!excludeReplication)
|
||||
await replicateSecrets({
|
||||
environmentId,
|
||||
projectId,
|
||||
secretPath,
|
||||
folderId,
|
||||
secrets,
|
||||
membershipId,
|
||||
excludeReplication,
|
||||
environmentSlug: environment
|
||||
});
|
||||
});
|
||||
|
||||
queueService.start(QueueName.IntegrationSync, async (job) => {
|
||||
@@ -394,7 +401,8 @@ export const secretQueueFactory = ({
|
||||
const linkSourceDto = {
|
||||
projectId,
|
||||
importEnv: folder.environment.id,
|
||||
importPath: secretPath
|
||||
importPath: secretPath,
|
||||
isReplication: false
|
||||
};
|
||||
const imports = await secretImportDAL.find(linkSourceDto);
|
||||
|
||||
@@ -598,6 +606,7 @@ export const secretQueueFactory = ({
|
||||
syncIntegrations,
|
||||
addSecretReminder,
|
||||
removeSecretReminder,
|
||||
handleSecretReminder
|
||||
handleSecretReminder,
|
||||
replicateSecrets
|
||||
};
|
||||
};
|
||||
|
||||
@@ -550,7 +550,8 @@ export const secretServiceFactory = ({
|
||||
|
||||
if (includeImports) {
|
||||
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
|
||||
const allowedImports = secretImports.filter(({ importEnv, importPath }) =>
|
||||
const allowedImports = secretImports.filter(({ importEnv, importPath, isReplication }) =>
|
||||
!isReplication &&
|
||||
// if its service token allow full access over imported one
|
||||
actor === ActorType.SERVICE
|
||||
? true
|
||||
@@ -655,7 +656,7 @@ export const secretServiceFactory = ({
|
||||
// then search for imported secrets
|
||||
// here we consider the import order also thus starting from bottom
|
||||
if (!secret && includeImports) {
|
||||
const secretImports = await secretImportDAL.find({ folderId });
|
||||
const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
|
||||
const allowedImports = secretImports.filter(({ importEnv, importPath }) =>
|
||||
// if its service token allow full access over imported one
|
||||
actor === ActorType.SERVICE
|
||||
|
||||
@@ -389,6 +389,8 @@ export type TSyncSecretsDTO<T extends boolean = false> = {
|
||||
environmentId: string;
|
||||
folderId: string;
|
||||
membershipId: string;
|
||||
// used for import creation to trigger replication
|
||||
pickOnlyImportIds?: string[];
|
||||
secrets: {
|
||||
operation: SecretOperations;
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user