Complete first iteration of CRUD secrets operations by name

This commit is contained in:
Tuan Dang
2023-04-17 11:09:45 +03:00
parent d9afe90885
commit df83e8ceb9
29 changed files with 1231 additions and 229 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
import { Request, Response } from 'express';
import { Types } from 'mongoose';
import * as Sentry from '@sentry/node';
import { Bot, BotKey } from '../../models';
import { createBot } from '../../helpers/bot';
@@ -29,7 +30,7 @@ export const getBotByWorkspaceId = async (req: Request, res: Response) => {
// -> create a new bot and return it
bot = await createBot({
name: 'Infisical Bot',
workspaceId
workspaceId: new Types.ObjectId(workspaceId)
});
}
} catch (err) {
+11 -23
View File
@@ -2,7 +2,7 @@ import to from 'await-to-js';
import { Types } from 'mongoose';
import { Request, Response } from 'express';
import { ISecret, Secret } from '../../models';
import { IAction } from '../../ee/models';
import { IAction, SecretVersion } from '../../ee/models';
import {
SECRET_PERSONAL,
SECRET_SHARED,
@@ -33,6 +33,7 @@ import {
* @param res
*/
export const batchSecrets = async (req: Request, res: Response) => {
const channel = getChannelFromUserAgent(req.headers['user-agent']);
const postHogClient = TelemetryService.getPostHogClient();
@@ -146,7 +147,7 @@ export const batchSecrets = async (req: Request, res: Response) => {
await Secret.bulkWrite(updateOperations);
const secretVersions = updateSecrets.map((u) => ({
const secretVersions = updateSecrets.map((u) => new SecretVersion({
secret: new Types.ObjectId(u._id),
version: listedSecretsObj[u._id.toString()].version,
workspace: new Types.ObjectId(workspaceId),
@@ -253,7 +254,7 @@ export const batchSecrets = async (req: Request, res: Response) => {
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId
workspaceId: new Types.ObjectId(workspaceId)
});
const resObj: { [key: string]: ISecret[] | string[] } = {}
@@ -422,13 +423,8 @@ export const createSecrets = async (req: Request, res: Response) => {
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
tags
}) => ({
_id: new Types.ObjectId(),
secretValueTag
}) => new SecretVersion({
secret: _id,
version,
workspace,
@@ -441,11 +437,7 @@ export const createSecrets = async (req: Request, res: Response) => {
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
tags
secretValueTag
}))
});
@@ -471,7 +463,7 @@ export const createSecrets = async (req: Request, res: Response) => {
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId
workspaceId: new Types.ObjectId(workspaceId)
});
const postHogClient = TelemetryService.getPostHogClient();
@@ -872,7 +864,7 @@ export const updateSecrets = async (req: Request, res: Response) => {
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: key
workspaceId: new Types.ObjectId(key)
})
const postHogClient = TelemetryService.getPostHogClient();
@@ -955,10 +947,6 @@ export const deleteSecrets = async (req: Request, res: Response) => {
}
*/
return res.status(200).send({
message: 'delete secrets!!'
});
const channel = getChannelFromUserAgent(req.headers['user-agent'])
const toDelete = req.secrets.map((s: any) => s._id);
@@ -1012,8 +1000,8 @@ export const deleteSecrets = async (req: Request, res: Response) => {
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: key
})
workspaceId: new Types.ObjectId(key)
});
const postHogClient = TelemetryService.getPostHogClient();
if (postHogClient) {
+174 -55
View File
@@ -1,14 +1,8 @@
import { Request, Response } from 'express';
import { Types } from 'mongoose';
import {
Secret
} from '../../models';
import crypto from 'crypto';
import { SecretService } from '../../services';
// TODO: modularize argon2id
import * as argon2 from 'argon2';
import { SecretService, TelemetryService } from '../../services';
import { getAuthDataPayloadIdObj } from '../../utils/auth';
import { BadRequestError } from '../../utils/errors';
/**
* Get secrets for workspace with id [workspaceId] and environment
@@ -17,41 +11,92 @@ import * as argon2 from 'argon2';
* @param res
*/
export const getSecrets = async (req: Request, res: Response) => {
return res.status(200).send({
const workspaceId = req.query.workspaceId as string;
const environment = req.query.environment as string;
const secrets = await SecretService.getSecrets({
workspaceId: new Types.ObjectId(workspaceId),
environment,
authData: req.authData
});
const postHogClient = TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: 'secrets pulled',
distinctId: TelemetryService.getDistinctId({
user: req.user,
serviceAccount: req.serviceAccount,
serviceTokenData: req.serviceTokenData
}),
properties: {
numberOfSecrets: secrets.length,
environment,
workspaceId,
channel: req.authData.authChannel,
userAgent: req.headers?.['user-agent']
}
});
}
return res.status(200).send({
secrets
});
}
/**
* Return secret with name [secretName] for workspace with id [workspaceId]
* and environment [environment]
* Get secret with name [secretName]
* @param req
* @param res
*/
export const getSecretByName = async (req: Request, res: Response) => {
const { secretName } = req.params;
const workspaceId = req.query.workspaceId as string;
const environment = req.query.workspaceId as string;
const environment = req.query.environment as string;
const type = req.query.type as 'shared' | 'personal' | undefined;
const secret = await SecretService.getSecret({
secretName,
workspaceId: new Types.ObjectId(workspaceId),
environment,
type,
authData: req.authData
});
const postHogClient = TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: 'secrets pull',
distinctId: TelemetryService.getDistinctId({
user: req.user,
serviceAccount: req.serviceAccount,
serviceTokenData: req.serviceTokenData
}),
properties: {
numberOfSecrets: 1,
environment,
workspaceId,
channel: req.authData.authChannel,
userAgent: req.headers?.['user-agent']
}
});
}
return res.status(200).send({
secret
});
}
/**
* Create secret for workspace with id [workspaceId] and
* environment [environment]
* Create secret with name [secretName]
* @param req
* @param res
*/
export const createSecret = async (req: Request, res: Response) => {
// TODO: the middleware should've prevalidated that the
// workspace with id [workspaceId] has disabled E2EE
const { secretName } = req.params;
const {
workspaceId,
environment,
value,
type,
secretKeyCiphertext,
secretKeyIV,
@@ -61,66 +106,140 @@ export const createSecret = async (req: Request, res: Response) => {
secretValueTag
} = req.body;
const secretBlindIndex = await SecretService.createSecretBlindIndex({
const secret = await SecretService.createSecret({
secretName,
workspaceId: new Types.ObjectId(workspaceId)
workspaceId: new Types.ObjectId(workspaceId),
environment,
type,
authData: req.authData,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag
});
// // use workspace salt
// const randomBytes = crypto.randomBytes(16);
// // generate blind index
// // TODO 1: abstract away into create blind index function
// // TODO 2: create a get blind index function
// const secretBlindIndex = (await argon2.hash(secretName, {
// type: argon2.argon2id,
// salt: randomBytes,
// saltLength: 16, // default 16 bytes
// memoryCost: 65536, // default pool of 64 MiB per thread.
// hashLength: 32,
// parallelism: 1,
// raw: true
// })).toString('base64');
// const secret = await new Secret({
// workspace: new Types.ObjectId(workspaceId),
// environment,
// type,
// secretBlindIndex,
// secretKeyCiphertext,
// secretKeyIV,
// secretKeyTag,
// secretValueCiphertext,
// secretValueIV,
// secretValueTag
// }).save();
const postHogClient = TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: 'secrets added',
distinctId: TelemetryService.getDistinctId({
user: req.user,
serviceAccount: req.serviceAccount,
serviceTokenData: req.serviceTokenData
}),
properties: {
numberOfSecrets: 1,
environment,
workspaceId,
channel: req.authData.authChannel,
userAgent: req.headers?.['user-agent']
}
});
}
const secretWithoutBlindIndex = secret.toObject();
delete secretWithoutBlindIndex.secretBlindIndex;
return res.status(200).send({
secret: secretWithoutBlindIndex
});
}
/**
* Update secret with name [secretName] in workspace with id [workspaceId]
* Update secret with name [secretName]
* @param req
* @param res
*/
export const updateSecretByName = async (req: Request, res: Response) => {
const { secretName } = req.params;
const {
workspaceId,
environment,
type,
secretValueCiphertext,
secretValueIV,
secretValueTag
} = req.body;
const secret = await SecretService.updateSecret({
secretName,
workspaceId,
environment,
type,
authData: req.authData,
secretValueCiphertext,
secretValueIV,
secretValueTag
});
const postHogClient = TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: 'secrets modified',
distinctId: TelemetryService.getDistinctId({
user: req.user,
serviceAccount: req.serviceAccount,
serviceTokenData: req.serviceTokenData
}),
properties: {
numberOfSecrets: 1,
environment,
workspaceId,
channel: req.authData.authChannel,
userAgent: req.headers?.['user-agent']
}
});
}
return res.status(200).send({
secret
});
}
/**
* Delete secret with name [secretName] in workspace with id [workspaceId]
* Delete secret with name [secretName]
* @param req
* @param res
*/
export const deleteSecretByName = async (req: Request, res: Response) => {
const { secretName } = req.params;
const {
workspaceId,
environment,
type
} = req.body;
const { secret, secrets } = await SecretService.deleteSecret({
secretName,
workspaceId,
environment,
type,
authData: req.authData
});
const postHogClient = TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: 'secrets deleted',
distinctId: TelemetryService.getDistinctId({
user: req.user,
serviceAccount: req.serviceAccount,
serviceTokenData: req.serviceTokenData
}),
properties: {
numberOfSecrets: secrets.length,
environment,
workspaceId,
channel: req.authData.authChannel,
userAgent: req.headers?.['user-agent']
}
});
}
return res.status(200).send({
secret
});
}