Skip to content

Commit

Permalink
Merge pull request #171 from Infisical/secret-versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
dangtony98 authored Dec 26, 2022
2 parents 0e78336 + e3b0512 commit a07bfbe
Show file tree
Hide file tree
Showing 24 changed files with 638 additions and 70 deletions.
17 changes: 14 additions & 3 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { patchRouterParam } = require('./utils/patchAsyncRoutes');

import { patchRouterParam } from './utils/patchAsyncRoutes';
import express from 'express';
import helmet from 'helmet';
import cors from 'cors';
Expand All @@ -10,6 +11,11 @@ dotenv.config();
import { PORT, NODE_ENV, SITE_URL } from './config';
import { apiLimiter } from './helpers/rateLimiter';

import {
workspace as eeWorkspaceRouter,
secret as eeSecretRouter
} from './ee/routes';

import {
signup as signupRouter,
auth as authRouter,
Expand All @@ -29,12 +35,13 @@ import {
integration as integrationRouter,
integrationAuth as integrationAuthRouter
} from './routes';

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();

Expand All @@ -56,6 +63,10 @@ if (NODE_ENV === 'production') {
app.use(helmet());
}

// /ee routers
app.use('/api/v1/secret', eeSecretRouter);
app.use('/api/v1/workspace', eeWorkspaceRouter);

// routers
app.use('/api/v1/signup', signupRouter);
app.use('/api/v1/auth', authRouter);
Expand Down
4 changes: 3 additions & 1 deletion backend/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const STRIPE_PUBLISHABLE_KEY = process.env.STRIPE_PUBLISHABLE_KEY!;
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY!;
const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET!;
const TELEMETRY_ENABLED = process.env.TELEMETRY_ENABLED! !== 'false' && true;
const LICENSE_KEY = process.env.LICENSE_KEY!;

export {
PORT,
Expand Down Expand Up @@ -83,5 +84,6 @@ export {
STRIPE_PUBLISHABLE_KEY,
STRIPE_SECRET_KEY,
STRIPE_WEBHOOK_SECRET,
TELEMETRY_ENABLED
TELEMETRY_ENABLED,
LICENSE_KEY
};
7 changes: 2 additions & 5 deletions backend/src/controllers/secretController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
import { Key } from '../models';
import { Key, Secret } from '../models';
import {
pushSecrets as push,
pullSecrets as pull,
Expand Down Expand Up @@ -169,9 +169,6 @@ export const pullSecrets = async (req: Request, res: Response) => {
* @returns
*/
export const pullSecretsServiceToken = async (req: Request, res: Response) => {
// get (encrypted) secrets from workspace with id [workspaceId]
// service token route

let secrets;
let key;
try {
Expand Down Expand Up @@ -225,4 +222,4 @@ export const pullSecretsServiceToken = async (req: Request, res: Response) => {
secrets: reformatPullSecrets({ secrets }),
key
});
};
};
2 changes: 1 addition & 1 deletion backend/src/controllers/workspaceController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Integration,
IntegrationAuth,
IUser,
ServiceToken
ServiceToken,
} from '../models';
import {
createWorkspace as create,
Expand Down
6 changes: 5 additions & 1 deletion backend/src/ee/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import * as stripeController from './stripeController';
import * as secretController from './secretController';
import * as workspaceController from './workspaceController';

export {
stripeController
stripeController,
secretController,
workspaceController
}
35 changes: 35 additions & 0 deletions backend/src/ee/controllers/secretController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
import { SecretVersion } from '../models';

/**
* Return secret versions for secret with id [secretId]
* @param req
* @param res
*/
export const getSecretVersions = async (req: Request, res: Response) => {
let secretVersions;
try {
const { secretId } = req.params;

const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);

secretVersions = await SecretVersion.find({
secret: secretId
})
.skip(offset)
.limit(limit);

} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to get secret versions'
});
}

return res.status(200).send({
secretVersions
});
}
35 changes: 35 additions & 0 deletions backend/src/ee/controllers/workspaceController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
import { SecretSnapshot } from '../models';

/**
* Return secret snapshots for workspace with id [workspaceId]
* @param req
* @param res
*/
export const getWorkspaceSecretSnapshots = async (req: Request, res: Response) => {
let secretSnapshots;
try {
const { workspaceId } = req.params;

const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);

secretSnapshots = await SecretSnapshot.find({
workspace: workspaceId
})
.skip(offset)
.limit(limit);

} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to get secret snapshots'
});
}

return res.status(200).send({
secretSnapshots
});
}
21 changes: 0 additions & 21 deletions backend/src/ee/helpers/license.ts

This file was deleted.

74 changes: 74 additions & 0 deletions backend/src/ee/helpers/secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as Sentry from '@sentry/node';
import {
Secret
} from '../../models';
import {
SecretSnapshot,
SecretVersion,
ISecretVersion
} from '../models';

/**
* Save a copy of the current state of secrets in workspace with id
* [workspaceId] under a new snapshot with incremented version under the
* secretsnapshots collection.
* @param {Object} obj
* @param {String} obj.workspaceId
*/
const takeSecretSnapshotHelper = async ({
workspaceId
}: {
workspaceId: string;
}) => {
try {
const secrets = await Secret.find({
workspace: workspaceId
});

const latestSecretSnapshot = await SecretSnapshot.findOne({
workspace: workspaceId
}).sort({ version: -1 });

if (!latestSecretSnapshot) {
// case: no snapshots exist for workspace -> create first snapshot
await new SecretSnapshot({
workspace: workspaceId,
version: 1,
secrets
}).save();

return;
}

// case: snapshots exist for workspace
await new SecretSnapshot({
workspace: workspaceId,
version: latestSecretSnapshot.version + 1,
secrets
}).save();

} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed to take a secret snapshot');
}
}

const addSecretVersionsHelper = async ({
secretVersions
}: {
secretVersions: ISecretVersion[]
}) => {
try {
await SecretVersion.insertMany(secretVersions);
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed to add secret versions');
}
}

export {
takeSecretSnapshotHelper,
addSecretVersionsHelper
}
9 changes: 9 additions & 0 deletions backend/src/ee/models/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import SecretSnapshot, { ISecretSnapshot } from "./secretSnapshot";
import SecretVersion, { ISecretVersion } from "./secretVersion";

export {
SecretSnapshot,
ISecretSnapshot,
SecretVersion,
ISecretVersion
}
Loading

0 comments on commit a07bfbe

Please sign in to comment.