Fix commonjs import/export for patchRouterParam and make secret versioning/snapshots compatible with prev unversioned secrets

This commit is contained in:
Tuan Dang
2022-12-26 17:52:13 -05:00
parent 9f724b5ede
commit 0c6dfbe4b4
5 changed files with 67 additions and 49 deletions

View File

@@ -1,4 +1,6 @@
import { patchRouterParam } from './utils/patchAsyncRoutes';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { patchRouterParam } = require('./utils/patchAsyncRoutes');
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
@@ -6,7 +8,7 @@ import cookieParser from 'cookie-parser';
import dotenv from 'dotenv';
dotenv.config();
import { PORT, NODE_ENV, SITE_URL, LICENSE_KEY } from './config';
import { PORT, NODE_ENV, SITE_URL } from './config';
import { apiLimiter } from './helpers/rateLimiter';
import {
@@ -38,8 +40,8 @@ import { getLogger } from './utils/logger';
import { RouteNotFoundError } from './utils/errors';
import { requestErrorHandler } from './middleware/requestErrorHandler';
//* Patch Async route params to handle Promise Rejections
patchRouterParam()
// patch async route params to handle Promise Rejections
patchRouterParam();
export const app = express();

View File

@@ -19,10 +19,8 @@ class EESecretService {
* @param {String} obj.workspaceId
*/
static async takeSecretSnapshot({
licenseKey,
workspaceId
}: {
licenseKey: string;
workspaceId: string;
}) {
if (!EELicenseService.isLicenseValid) return;

View File

@@ -56,6 +56,7 @@ const pushSecrets = async ({
environment: string;
secrets: PushSecret[];
}): Promise<void> => {
// TODO: clean up function and fix up types
try {
// construct useful data structures
const oldSecrets = await pullSecrets({
@@ -63,10 +64,11 @@ const pushSecrets = async ({
workspaceId,
environment
});
const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) =>
({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s })
, {});
const newSecretsObj = secrets.reduce((accumulator, s) =>
const newSecretsObj: any = secrets.reduce((accumulator, s) =>
({ ...accumulator, [`${s.type}-${s.hashKey}`]: s })
, {});
@@ -79,8 +81,6 @@ const pushSecrets = async ({
if (toDelete.length > 0) {
await Secret.deleteMany({
_id: { $in: toDelete }
}, {
rawResult: true
});
await SecretVersion.updateMany({
@@ -89,31 +89,48 @@ const pushSecrets = async ({
isDeleted: true
});
}
// handle modifying secrets where type or value changed
const toUpdate = secrets
const toUpdate = oldSecrets
.filter((s) => {
if (`${s.type}-${s.hashKey}` in oldSecretsObj) {
if (s.hashValue !== oldSecretsObj[`${s.type}-${s.hashKey}`].secretValueHash) {
if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) {
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue) {
// case: filter secrets where value changed
return true;
}
}
if (!s.version) {
// case: filter (legacy) secrets that were not versioned
return true;
}
}
return false;
});
const operations = toUpdate
.map((s) => {
const {
ciphertextValue,
ivValue,
tagValue,
hashValue
} = newSecretsObj[`${s.type}-${s.secretKeyHash}`];
const update: Update = {
secretValueCiphertext: s.ciphertextValue,
secretValueIV: s.ivValue,
secretValueTag: s.tagValue,
secretValueHash: s.hashValue,
$inc: {
secretValueCiphertext: ciphertextValue,
secretValueIV: ivValue,
secretValueTag: tagValue,
secretValueHash: hashValue
}
if (!s.version) {
// case: (legacy) secret was not versioned
update.version = 1;
} else {
update['$inc'] = {
version: 1
}
};
}
if (s.type === SECRET_PERSONAL) {
// attach user associated with the personal secret
@@ -123,7 +140,7 @@ const pushSecrets = async ({
return {
updateOne: {
filter: {
_id: oldSecretsObj[`${s.type}-${s.hashKey}`]._id
_id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id
},
update
}
@@ -134,28 +151,26 @@ const pushSecrets = async ({
// (EE) add secret versions for updated secrets
await EESecretService.addSecretVersions({
secretVersions: toUpdate.map(({
_id,
version,
type,
ciphertextKey,
ivKey,
tagKey,
hashKey,
ciphertextValue,
ivValue,
tagValue,
hashValue
}) => ({
secret: oldSecretsObj[`${type}-${hashKey}`]._id,
version: oldSecretsObj[`${type}-${hashKey}`].version + 1,
isDeleted: false,
secretKeyCiphertext: ciphertextKey,
secretKeyIV: ivKey,
secretKeyTag: tagKey,
secretKeyHash: hashKey,
secretValueCiphertext: ciphertextValue,
secretValueIV: ivValue,
secretValueTag: tagValue,
secretValueHash: hashValue
}))
secretKeyHash,
}) => {
const newSecret = newSecretsObj[`${type}-${secretKeyHash}`];
return ({
secret: _id,
version: version ? version + 1 : 1,
isDeleted: false,
secretKeyCiphertext: newSecret.ciphertextKey,
secretKeyIV: newSecret.ivKey,
secretKeyTag: newSecret.tagKey,
secretKeyHash: newSecret.hashKey,
secretValueCiphertext: newSecret.ciphertextValue,
secretValueIV: newSecret.ivValue,
secretValueTag: newSecret.tagValue,
secretValueHash: newSecret.hashValue
})
})
});
// handle adding new secrets
@@ -166,6 +181,7 @@ const pushSecrets = async ({
const newSecrets = await Secret.insertMany(
toAdd.map((s, idx) => {
const obj: any = {
version: 1,
workspace: workspaceId,
type: toAdd[idx].type,
environment,
@@ -217,7 +233,6 @@ const pushSecrets = async ({
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
licenseKey: LICENSE_KEY,
workspaceId
})
} catch (err) {

View File

@@ -29,8 +29,7 @@ const secretSchema = new Schema<ISecret>(
{
version: {
type: Number,
default: 1,
required: true
required: true
},
workspace: {
type: Schema.Types.ObjectId,

View File

@@ -45,7 +45,7 @@ function wrap(fn) {
return copyFnProps(fn, newFn);
}
export function patchRouterParam() {
function patchRouterParam() {
const originalParam = Router.prototype.constructor.param;
Router.prototype.constructor.param = function param(name, fn) {
fn = wrap(fn);
@@ -62,4 +62,8 @@ Object.defineProperty(Layer.prototype, 'handle', {
fn = wrap(fn);
this.__handle = fn;
},
});
});
module.exports = {
patchRouterParam
};