mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 13:27:22 +00:00
feat: resolved personal secret breaking secret replication
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { TDbClient } from "@app/db";
|
import { TDbClient } from "@app/db";
|
||||||
import { TableName, TSecretVersions } from "@app/db/schemas";
|
import { SecretType, TableName, TSecretVersions } from "@app/db/schemas";
|
||||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||||
|
|
||||||
export type TSecretReplicationDALFactory = ReturnType<typeof secretReplicationDALFactory>;
|
export type TSecretReplicationDALFactory = ReturnType<typeof secretReplicationDALFactory>;
|
||||||
@@ -9,7 +9,10 @@ export type TSecretReplicationDALFactory = ReturnType<typeof secretReplicationDA
|
|||||||
export const secretReplicationDALFactory = (db: TDbClient) => {
|
export const secretReplicationDALFactory = (db: TDbClient) => {
|
||||||
const orm = ormify(db, TableName.SecretVersion);
|
const orm = ormify(db, TableName.SecretVersion);
|
||||||
|
|
||||||
const findSecrets = async (filter: { folderId: string; secrets: { id: string; version: number }[] }, tx?: Knex) => {
|
const findSecretVersions = async (
|
||||||
|
filter: { folderId: string; secrets: { id: string; version: number }[] },
|
||||||
|
tx?: Knex
|
||||||
|
) => {
|
||||||
if (!filter.secrets) return [];
|
if (!filter.secrets) return [];
|
||||||
|
|
||||||
const sqlRawDocs = await (tx || db)(TableName.SecretVersion)
|
const sqlRawDocs = await (tx || db)(TableName.SecretVersion)
|
||||||
@@ -18,7 +21,8 @@ export const secretReplicationDALFactory = (db: TDbClient) => {
|
|||||||
filter.secrets.forEach((el) => {
|
filter.secrets.forEach((el) => {
|
||||||
void bd.orWhere({
|
void bd.orWhere({
|
||||||
[`${TableName.SecretVersion}.secretId` as "secretId"]: el.id,
|
[`${TableName.SecretVersion}.secretId` as "secretId"]: el.id,
|
||||||
[`${TableName.SecretVersion}.version` as "version"]: el.version
|
[`${TableName.SecretVersion}.version` as "version"]: el.version,
|
||||||
|
[`${TableName.SecretVersion}.type` as "type"]: SecretType.Shared
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -39,7 +43,7 @@ export const secretReplicationDALFactory = (db: TDbClient) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
findSecrets,
|
findSecretVersions,
|
||||||
...orm
|
...orm
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,13 +80,16 @@ export const secretReplicationServiceFactory = ({
|
|||||||
if (!secretImports.length || !secrets.length) return;
|
if (!secretImports.length || !secrets.length) return;
|
||||||
|
|
||||||
// unfiltered secrets to be replicated
|
// unfiltered secrets to be replicated
|
||||||
const toBeReplicatedSecrets = await secretReplicationDAL.findSecrets({ folderId, secrets });
|
const toBeReplicatedSecrets = await secretReplicationDAL.findSecretVersions({ folderId, secrets });
|
||||||
const replicatedSecrets = toBeReplicatedSecrets.filter(
|
const replicatedSecrets = toBeReplicatedSecrets.filter(
|
||||||
({ version, latestReplicatedVersion, secretBlindIndex }) =>
|
({ version, latestReplicatedVersion, secretBlindIndex }) =>
|
||||||
secretBlindIndex && (version === 1 || latestReplicatedVersion <= version)
|
secretBlindIndex && (version === 1 || latestReplicatedVersion <= version)
|
||||||
);
|
);
|
||||||
|
|
||||||
const replicatedSecretsGroupBySecretId = groupBy(replicatedSecrets, (i) => i.secretId);
|
const replicatedSecretsGroupBySecretId = groupBy(replicatedSecrets, (i) => i.secretId);
|
||||||
|
// this is to filter out personal secrets
|
||||||
|
const sanitizedSecrets = secrets.filter(({ id }) => Object.hasOwn(replicatedSecretsGroupBySecretId, id));
|
||||||
|
if (!sanitizedSecrets.length) return;
|
||||||
|
|
||||||
const lock = await keyStore.acquireLock(
|
const lock = await keyStore.acquireLock(
|
||||||
replicatedSecrets.map(({ id }) => id),
|
replicatedSecrets.map(({ id }) => id),
|
||||||
5000
|
5000
|
||||||
@@ -118,20 +121,20 @@ export const secretReplicationServiceFactory = ({
|
|||||||
});
|
});
|
||||||
const localSecretsGroupedByBlindIndex = groupBy(localSecrets, (i) => i.secretBlindIndex as string);
|
const localSecretsGroupedByBlindIndex = groupBy(localSecrets, (i) => i.secretBlindIndex as string);
|
||||||
|
|
||||||
const locallyCreatedSecrets = secrets.filter(({ operation, id }) => {
|
const locallyCreatedSecrets = sanitizedSecrets.filter(({ operation, id }) => {
|
||||||
return (
|
return (
|
||||||
(operation === SecretOperations.Create || operation === SecretOperations.Update) &&
|
(operation === SecretOperations.Create || operation === SecretOperations.Update) &&
|
||||||
!localSecretsGroupedByBlindIndex[replicatedSecretsGroupBySecretId[id][0].secretBlindIndex as string]?.[0]
|
!localSecretsGroupedByBlindIndex[replicatedSecretsGroupBySecretId[id][0].secretBlindIndex as string]?.[0]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const locallyUpdatedSecrets = secrets.filter(
|
const locallyUpdatedSecrets = sanitizedSecrets.filter(
|
||||||
({ operation, id }) =>
|
({ operation, id }) =>
|
||||||
(operation === SecretOperations.Create || operation === SecretOperations.Update) &&
|
(operation === SecretOperations.Create || operation === SecretOperations.Update) &&
|
||||||
localSecretsGroupedByBlindIndex[replicatedSecretsGroupBySecretId[id][0].secretBlindIndex as string]?.[0]
|
localSecretsGroupedByBlindIndex[replicatedSecretsGroupBySecretId[id][0].secretBlindIndex as string]?.[0]
|
||||||
);
|
);
|
||||||
|
|
||||||
const locallyDeletedSecrets = secrets.filter(
|
const locallyDeletedSecrets = sanitizedSecrets.filter(
|
||||||
({ operation, id }) =>
|
({ operation, id }) =>
|
||||||
operation === SecretOperations.Delete &&
|
operation === SecretOperations.Delete &&
|
||||||
Boolean(replicatedSecretsGroupBySecretId[id]?.[0]?.secretBlindIndex) &&
|
Boolean(replicatedSecretsGroupBySecretId[id]?.[0]?.secretBlindIndex) &&
|
||||||
@@ -333,6 +336,7 @@ export const secretReplicationServiceFactory = ({
|
|||||||
/* eslint-enable no-await-in-loop */
|
/* eslint-enable no-await-in-loop */
|
||||||
} finally {
|
} finally {
|
||||||
await lock.release();
|
await lock.release();
|
||||||
|
logger.info(job.data, "Replication finished");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user