fix(core): Reduce memory usage in credentials risk auditing (#7663)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-11-09 14:39:16 +01:00 committed by GitHub
parent 5edf722209
commit 9fd6319583
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,13 +1,16 @@
import type { FindOperator } from 'typeorm'; import { In, MoreThanOrEqual } from 'typeorm';
import { MoreThanOrEqual } from 'typeorm';
import { DateUtils } from 'typeorm/util/DateUtils'; import { DateUtils } from 'typeorm/util/DateUtils';
import { Container } from 'typedi'; import { Container } from 'typedi';
import * as Db from '@/Db'; import type { IWorkflowBase } from 'n8n-workflow';
import config from '@/config'; import config from '@/config';
import { CREDENTIALS_REPORT } from '@/audit/constants'; import { CREDENTIALS_REPORT } from '@/audit/constants';
import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import type { Risk } from '@/audit/types'; import type { Risk } from '@/audit/types';
import { ExecutionRepository } from '@db/repositories'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity';
import {
CredentialsRepository,
ExecutionDataRepository,
ExecutionRepository,
} from '@db/repositories';
async function getAllCredsInUse(workflows: WorkflowEntity[]) { async function getAllCredsInUse(workflows: WorkflowEntity[]) {
const credsInAnyUse = new Set<string>(); const credsInAnyUse = new Set<string>();
@ -34,36 +37,43 @@ async function getAllCredsInUse(workflows: WorkflowEntity[]) {
} }
async function getAllExistingCreds() { async function getAllExistingCreds() {
const credentials = await Db.collections.Credentials.find({ select: ['id', 'name'] }); const credentials = await Container.get(CredentialsRepository).find({ select: ['id', 'name'] });
return credentials.map(({ id, name }) => ({ kind: 'credential' as const, id, name })); return credentials.map(({ id, name }) => ({ kind: 'credential' as const, id, name }));
} }
async function getExecutionsInPastDays(days: number) { async function getExecutedWorkflowsInPastDays(days: number): Promise<IWorkflowBase[]> {
const date = new Date(); const date = new Date();
date.setDate(date.getDate() - days); date.setDate(date.getDate() - days);
const utcDate = DateUtils.mixedDateToUtcDatetimeString(date) as string; const executionIds = await Container.get(ExecutionRepository)
.find({
return Container.get(ExecutionRepository).findMultipleExecutions( select: ['id'],
{
where: { where: {
startedAt: MoreThanOrEqual(utcDate) as unknown as FindOperator<Date>, startedAt: MoreThanOrEqual(DateUtils.mixedDateToUtcDatetimeString(date) as Date),
}, },
}, })
{ includeData: true }, .then((executions) => executions.map(({ id }) => id));
);
return Container.get(ExecutionDataRepository)
.find({
select: ['workflowData'],
where: {
executionId: In(executionIds),
},
})
.then((executionData) => executionData.map(({ workflowData }) => workflowData));
} }
/** /**
* Return IDs of credentials in workflows executed in the past n days. * Return IDs of credentials in workflows executed in the past n days.
*/ */
async function getCredsInRecentlyExecutedWorkflows(days: number) { async function getCredsInRecentlyExecutedWorkflows(days: number) {
const recentExecutions = await getExecutionsInPastDays(days); const executedWorkflows = await getExecutedWorkflowsInPastDays(days);
return recentExecutions.reduce<Set<string>>((acc, execution) => { return executedWorkflows.reduce<Set<string>>((acc, { nodes }) => {
execution.workflowData?.nodes.forEach((node) => { nodes.forEach((node) => {
if (node.credentials) { if (node.credentials) {
Object.values(node.credentials).forEach((c) => { Object.values(node.credentials).forEach((c) => {
if (c.id) acc.add(c.id); if (c.id) acc.add(c.id);