From 16f240596a591203a2f3beb347f0e52dd9b34761 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 27 Dec 2022 12:30:33 -0500 Subject: [PATCH] Add audit logs to pulls, still need to refactor --- .../src/controllers/v1/secretController.ts | 8 +- .../src/controllers/v2/workspaceController.ts | 8 +- backend/src/helpers/secret.ts | 89 +++++++++++++++++-- backend/src/variables/action.ts | 4 +- backend/src/variables/index.ts | 4 +- 5 files changed, 100 insertions(+), 13 deletions(-) diff --git a/backend/src/controllers/v1/secretController.ts b/backend/src/controllers/v1/secretController.ts index 238b38cedc..1b756ecc70 100644 --- a/backend/src/controllers/v1/secretController.ts +++ b/backend/src/controllers/v1/secretController.ts @@ -123,7 +123,9 @@ export const pullSecrets = async (req: Request, res: Response) => { secrets = await pull({ userId: req.user._id.toString(), workspaceId, - environment + environment, + channel: channel ? channel : 'cli', + ipAddress: req.ip }); key = await Key.findOne({ @@ -188,7 +190,9 @@ export const pullSecretsServiceToken = async (req: Request, res: Response) => { secrets = await pull({ userId: req.serviceToken.user._id.toString(), workspaceId, - environment + environment, + channel: 'cli', + ipAddress: req.ip }); key = { diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index b9aa6406f5..cfe1f239e1 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -459,7 +459,9 @@ export const pullSecrets = async (req: Request, res: Response) => { secrets = await pull({ userId: req.user._id.toString(), workspaceId, - environment + environment, + channel, + ipAddress: req.ip }); key = await Key.findOne({ @@ -526,7 +528,9 @@ export const pullSecrets = async (req: Request, res: Response) => { secrets = await pull({ userId: req.serviceToken.user._id.toString(), workspaceId, - environment + environment, + channel: 'cli', + ipAddress: req.ip }); key = { diff --git a/backend/src/helpers/secret.ts b/backend/src/helpers/secret.ts index 79d99960ff..93cbb648a6 100644 --- a/backend/src/helpers/secret.ts +++ b/backend/src/helpers/secret.ts @@ -22,7 +22,8 @@ import { SECRET_PERSONAL, ACTION_ADD_SECRETS, ACTION_UPDATE_SECRETS, - ACTION_DELETE_SECRETS + ACTION_DELETE_SECRETS, + ACTION_READ_SECRETS } from '../variables'; interface V1PushSecret { @@ -78,7 +79,7 @@ const v1PushSecrets = async ({ userId, workspaceId, environment, - secrets + secrets, }: { userId: string; workspaceId: string; @@ -88,7 +89,7 @@ const v1PushSecrets = async ({ // TODO: clean up function and fix up types try { // construct useful data structures - const oldSecrets = await pullSecrets({ + const oldSecrets = await getSecrets({ userId, workspaceId, environment @@ -317,7 +318,7 @@ const v1PushSecrets = async ({ const actions: IAction[] = []; // construct useful data structures - const oldSecrets = await pullSecrets({ + const oldSecrets = await getSecrets({ userId, workspaceId, environment @@ -642,9 +643,8 @@ const v1PushSecrets = async ({ * @param {String} obj.userId -id of user to pull secrets for * @param {String} obj.workspaceId - id of workspace to pull from * @param {String} obj.environment - environment for secrets - * */ -const pullSecrets = async ({ + const getSecrets = async ({ userId, workspaceId, environment @@ -681,9 +681,84 @@ const pullSecrets = async ({ return secrets; }; +/** + * Pull secrets for user with id [userId] for workspace + * with id [workspaceId] with environment [environment] + * @param {Object} obj + * @param {String} obj.userId -id of user to pull secrets for + * @param {String} obj.workspaceId - id of workspace to pull from + * @param {String} obj.environment - environment for secrets + * @param {String} obj.channel - channel (web/cli/auto) + * @param {String} obj.ipAddress - ip address of request to push secrets + */ +const pullSecrets = async ({ + userId, + workspaceId, + environment, + channel, + ipAddress +}: { + userId: string; + workspaceId: string; + environment: string; + channel: string; + ipAddress: string; +}): Promise => { + let secrets: any; // TODO: FIX any + + try { + secrets = await getSecrets({ + userId, + workspaceId, + environment + }) + + // add audit log for new secrets + const readLatestSecretVersions = (await SecretVersion.aggregate([ + { + $match: { secret: { $in: secrets.map((n: any) => n._id) } } + }, + { + $group: { + _id: '$secret', + version: { $max: '$version' } + } + }, + { + $sort: { version: -1 } + } + ]) + .exec()) + .map((s) => s._id); + + const readAction = await new Action({ + name: ACTION_READ_SECRETS, + user: new Types.ObjectId(userId), + workspace: new Types.ObjectId(workspaceId), + payload: { + secretVersions: readLatestSecretVersions + } + }).save(); + + await EELogService.createLog({ + userId, + workspaceId, + actions: [readAction], + channel, + ipAddress + }); + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + throw new Error('Failed to pull shared and personal secrets'); + } + + return secrets; +}; + /** * Reformat output of pullSecrets() to be compatible with how existing - * clients handle secrets + * web client handle secrets * @param {Object} obj * @param {Object} obj.secrets */ diff --git a/backend/src/variables/action.ts b/backend/src/variables/action.ts index c8b0130d25..512eb8e8d7 100644 --- a/backend/src/variables/action.ts +++ b/backend/src/variables/action.ts @@ -1,9 +1,11 @@ const ACTION_ADD_SECRETS = 'addSecrets'; const ACTION_DELETE_SECRETS = 'deleteSecrets'; const ACTION_UPDATE_SECRETS = 'updateSecrets'; +const ACTION_READ_SECRETS = 'readSecrets'; export { ACTION_ADD_SECRETS, ACTION_DELETE_SECRETS, - ACTION_UPDATE_SECRETS + ACTION_UPDATE_SECRETS, + ACTION_READ_SECRETS } \ No newline at end of file diff --git a/backend/src/variables/index.ts b/backend/src/variables/index.ts index 1d9241e2b4..e8a373e747 100644 --- a/backend/src/variables/index.ts +++ b/backend/src/variables/index.ts @@ -36,7 +36,8 @@ import { EVENT_PUSH_SECRETS, EVENT_PULL_SECRETS } from './event'; import { ACTION_ADD_SECRETS, ACTION_UPDATE_SECRETS, - ACTION_DELETE_SECRETS + ACTION_DELETE_SECRETS, + ACTION_READ_SECRETS } from './action'; import { SMTP_HOST_SENDGRID, SMTP_HOST_MAILGUN } from './smtp'; import { PLAN_STARTER, PLAN_PRO } from './stripe'; @@ -75,6 +76,7 @@ export { ACTION_ADD_SECRETS, ACTION_UPDATE_SECRETS, ACTION_DELETE_SECRETS, + ACTION_READ_SECRETS, INTEGRATION_OPTIONS, SMTP_HOST_SENDGRID, SMTP_HOST_MAILGUN,