mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 21:27:10 +00:00
Add single secrets v2 operations
This commit is contained in:
@@ -7,6 +7,39 @@ const { ValidationError } = mongoose.Error;
|
|||||||
import { BadRequestError, InternalServerError, UnauthorizedRequestError, ValidationError as RouteValidationError } from '../../utils/errors';
|
import { BadRequestError, InternalServerError, UnauthorizedRequestError, ValidationError as RouteValidationError } from '../../utils/errors';
|
||||||
import { AnyBulkWriteOperation } from 'mongodb';
|
import { AnyBulkWriteOperation } from 'mongodb';
|
||||||
import { SECRET_PERSONAL, SECRET_SHARED } from "../../variables";
|
import { SECRET_PERSONAL, SECRET_SHARED } from "../../variables";
|
||||||
|
import { validateMembership } from "../../helpers/membership";
|
||||||
|
import { ADMIN, MEMBER } from '../../variables';
|
||||||
|
|
||||||
|
export const createSingleSecret = async (req: Request, res: Response) => {
|
||||||
|
const secretToCreate: CreateSecretRequestBody = req.body.secret;
|
||||||
|
const { workspaceId, environmentName } = req.params
|
||||||
|
const sanitizedSecret: SanitizedSecretForCreate = {
|
||||||
|
secretKeyCiphertext: secretToCreate.secretKeyCiphertext,
|
||||||
|
secretKeyIV: secretToCreate.secretKeyIV,
|
||||||
|
secretKeyTag: secretToCreate.secretKeyTag,
|
||||||
|
secretKeyHash: secretToCreate.secretKeyHash,
|
||||||
|
secretValueCiphertext: secretToCreate.secretValueCiphertext,
|
||||||
|
secretValueIV: secretToCreate.secretValueIV,
|
||||||
|
secretValueTag: secretToCreate.secretValueTag,
|
||||||
|
secretValueHash: secretToCreate.secretValueHash,
|
||||||
|
secretCommentCiphertext: secretToCreate.secretCommentCiphertext,
|
||||||
|
secretCommentIV: secretToCreate.secretCommentIV,
|
||||||
|
secretCommentTag: secretToCreate.secretCommentTag,
|
||||||
|
secretCommentHash: secretToCreate.secretCommentHash,
|
||||||
|
workspace: new Types.ObjectId(workspaceId),
|
||||||
|
environment: environmentName,
|
||||||
|
type: secretToCreate.type,
|
||||||
|
user: new Types.ObjectId(req.user._id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const [error, newlyCreatedSecret] = await to(Secret.create(sanitizedSecret).then())
|
||||||
|
if (error instanceof ValidationError) {
|
||||||
|
throw RouteValidationError({ message: error.message, stack: error.stack })
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send()
|
||||||
|
}
|
||||||
|
|
||||||
export const batchCreateSecrets = async (req: Request, res: Response) => {
|
export const batchCreateSecrets = async (req: Request, res: Response) => {
|
||||||
const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets;
|
const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets;
|
||||||
@@ -48,16 +81,6 @@ export const batchCreateSecrets = async (req: Request, res: Response) => {
|
|||||||
res.status(200).send()
|
res.status(200).send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const createSingleSecret = async (req: Request, res: Response) => {
|
|
||||||
try {
|
|
||||||
const secretFromDB = await Secret.findById(req.params.secretId)
|
|
||||||
return res.status(200).send(secretFromDB);
|
|
||||||
} catch (e) {
|
|
||||||
throw BadRequestError({ message: "Unable to find the requested secret" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const batchDeleteSecrets = async (req: Request, res: Response) => {
|
export const batchDeleteSecrets = async (req: Request, res: Response) => {
|
||||||
const { workspaceId, environmentName } = req.params
|
const { workspaceId, environmentName } = req.params
|
||||||
const secretIdsToDelete: string[] = req.body.secretIds
|
const secretIdsToDelete: string[] = req.body.secretIds
|
||||||
@@ -90,6 +113,33 @@ export const batchDeleteSecrets = async (req: Request, res: Response) => {
|
|||||||
res.status(200).send()
|
res.status(200).send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteSingleSecret = async (req: Request, res: Response) => {
|
||||||
|
const { secretId } = req.params;
|
||||||
|
|
||||||
|
const [error, singleSecretRetrieved] = await to(Secret.findById(secretId).then())
|
||||||
|
if (error instanceof ValidationError) {
|
||||||
|
throw RouteValidationError({ message: "Unable to get secret, please try again", stack: error.stack })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (singleSecretRetrieved) {
|
||||||
|
const [membershipValidationError, membership] = await to(validateMembership({
|
||||||
|
userId: req.user._id,
|
||||||
|
workspaceId: singleSecretRetrieved.workspace._id.toString(),
|
||||||
|
acceptedRoles: [ADMIN, MEMBER]
|
||||||
|
}))
|
||||||
|
|
||||||
|
if (membershipValidationError || !membership) {
|
||||||
|
throw UnauthorizedRequestError()
|
||||||
|
}
|
||||||
|
|
||||||
|
await Secret.findByIdAndDelete(secretId)
|
||||||
|
|
||||||
|
res.status(200).send()
|
||||||
|
} else {
|
||||||
|
throw BadRequestError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const batchModifySecrets = async (req: Request, res: Response) => {
|
export const batchModifySecrets = async (req: Request, res: Response) => {
|
||||||
const { workspaceId, environmentName } = req.params
|
const { workspaceId, environmentName } = req.params
|
||||||
const secretsModificationsRequested: ModifySecretRequestBody[] = req.body.secrets;
|
const secretsModificationsRequested: ModifySecretRequestBody[] = req.body.secrets;
|
||||||
@@ -101,7 +151,6 @@ export const batchModifySecrets = async (req: Request, res: Response) => {
|
|||||||
const secretsUserCanModifySet: Set<string> = new Set(secretIdsUserCanModify.map(objectId => objectId._id.toString()));
|
const secretsUserCanModifySet: Set<string> = new Set(secretIdsUserCanModify.map(objectId => objectId._id.toString()));
|
||||||
const updateOperationsToPerform: any = []
|
const updateOperationsToPerform: any = []
|
||||||
|
|
||||||
|
|
||||||
secretsModificationsRequested.forEach(userModifiedSecret => {
|
secretsModificationsRequested.forEach(userModifiedSecret => {
|
||||||
if (secretsUserCanModifySet.has(userModifiedSecret._id.toString())) {
|
if (secretsUserCanModifySet.has(userModifiedSecret._id.toString())) {
|
||||||
const sanitizedSecret: SanitizedSecretModify = {
|
const sanitizedSecret: SanitizedSecretModify = {
|
||||||
@@ -138,6 +187,38 @@ export const batchModifySecrets = async (req: Request, res: Response) => {
|
|||||||
return res.status(200).send()
|
return res.status(200).send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const modifySingleSecrets = async (req: Request, res: Response) => {
|
||||||
|
const { workspaceId, environmentName } = req.params
|
||||||
|
const secretModificationsRequested: ModifySecretRequestBody = req.body.secret;
|
||||||
|
|
||||||
|
const [secretIdUserCanModifyError, secretIdUserCanModify] = await to(Secret.findOne({ workspace: workspaceId, environment: environmentName }, { _id: 1 }).then())
|
||||||
|
if (secretIdUserCanModifyError && !secretIdUserCanModify) {
|
||||||
|
throw BadRequestError()
|
||||||
|
}
|
||||||
|
|
||||||
|
const sanitizedSecret: SanitizedSecretModify = {
|
||||||
|
secretKeyCiphertext: secretModificationsRequested.secretKeyCiphertext,
|
||||||
|
secretKeyIV: secretModificationsRequested.secretKeyIV,
|
||||||
|
secretKeyTag: secretModificationsRequested.secretKeyTag,
|
||||||
|
secretKeyHash: secretModificationsRequested.secretKeyHash,
|
||||||
|
secretValueCiphertext: secretModificationsRequested.secretValueCiphertext,
|
||||||
|
secretValueIV: secretModificationsRequested.secretValueIV,
|
||||||
|
secretValueTag: secretModificationsRequested.secretValueTag,
|
||||||
|
secretValueHash: secretModificationsRequested.secretValueHash,
|
||||||
|
secretCommentCiphertext: secretModificationsRequested.secretCommentCiphertext,
|
||||||
|
secretCommentIV: secretModificationsRequested.secretCommentIV,
|
||||||
|
secretCommentTag: secretModificationsRequested.secretCommentTag,
|
||||||
|
secretCommentHash: secretModificationsRequested.secretCommentHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
const [error, singleModificationUpdate] = await to(Secret.updateOne({ _id: secretModificationsRequested._id, workspace: workspaceId }, { $inc: { version: 1 }, $set: sanitizedSecret }).then())
|
||||||
|
if (error instanceof ValidationError) {
|
||||||
|
throw RouteValidationError({ message: "Unable to apply modifications, please try again", stack: error.stack })
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).send(singleModificationUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
export const fetchAllSecrets = async (req: Request, res: Response) => {
|
export const fetchAllSecrets = async (req: Request, res: Response) => {
|
||||||
const { environment } = req.query;
|
const { environment } = req.query;
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
@@ -166,3 +247,30 @@ export const fetchAllSecrets = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
return res.json(allSecrets)
|
return res.json(allSecrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fetchSingleSecret = async (req: Request, res: Response) => {
|
||||||
|
const { secretId } = req.params;
|
||||||
|
|
||||||
|
const [error, singleSecretRetrieved] = await to(Secret.findById(secretId).then())
|
||||||
|
|
||||||
|
if (error instanceof ValidationError) {
|
||||||
|
throw RouteValidationError({ message: "Unable to get secret, please try again", stack: error.stack })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (singleSecretRetrieved) {
|
||||||
|
const [membershipValidationError, membership] = await to(validateMembership({
|
||||||
|
userId: req.user._id,
|
||||||
|
workspaceId: singleSecretRetrieved.workspace._id.toString(),
|
||||||
|
acceptedRoles: [ADMIN, MEMBER]
|
||||||
|
}))
|
||||||
|
|
||||||
|
if (membershipValidationError || !membership) {
|
||||||
|
throw UnauthorizedRequestError()
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(singleSecretRetrieved)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw BadRequestError()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { body, param, query } from 'express-validator';
|
|||||||
import { ADMIN, MEMBER } from '../../variables';
|
import { ADMIN, MEMBER } from '../../variables';
|
||||||
import { CreateSecretRequestBody, ModifySecretRequestBody } from '../../types/secret';
|
import { CreateSecretRequestBody, ModifySecretRequestBody } from '../../types/secret';
|
||||||
import { secretController } from '../../controllers/v2';
|
import { secretController } from '../../controllers/v2';
|
||||||
import { fetchAllSecrets } from '../../controllers/v2/secretController';
|
import { fetchAllSecrets, fetchSingleSecret } from '../../controllers/v2/secretController';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
@@ -26,6 +26,24 @@ router.post(
|
|||||||
secretController.batchCreateSecrets
|
secretController.batchCreateSecrets
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create single secret for a given workspace and environmentName
|
||||||
|
*/
|
||||||
|
router.post(
|
||||||
|
'/workspace/:workspaceId/environment/:environmentName',
|
||||||
|
requireAuth({
|
||||||
|
acceptedAuthModes: ['jwt']
|
||||||
|
}),
|
||||||
|
requireWorkspaceAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER]
|
||||||
|
}),
|
||||||
|
param('workspaceId').exists().isMongoId().trim(),
|
||||||
|
param('environmentName').exists().trim(),
|
||||||
|
body('secret').exists().isObject(),
|
||||||
|
validateRequest,
|
||||||
|
secretController.createSingleSecret
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all secrets for a given environment and workspace id
|
* Get all secrets for a given environment and workspace id
|
||||||
*/
|
*/
|
||||||
@@ -43,6 +61,18 @@ router.get(
|
|||||||
fetchAllSecrets
|
fetchAllSecrets
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get single secret by id
|
||||||
|
*/
|
||||||
|
router.get(
|
||||||
|
'/:secretId',
|
||||||
|
requireAuth({
|
||||||
|
acceptedAuthModes: ['jwt', 'serviceToken']
|
||||||
|
}),
|
||||||
|
validateRequest,
|
||||||
|
fetchSingleSecret
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Batch delete secrets in a given workspace and environment name
|
* Batch delete secrets in a given workspace and environment name
|
||||||
*/
|
*/
|
||||||
@@ -62,6 +92,19 @@ router.delete(
|
|||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete single secret by id
|
||||||
|
*/
|
||||||
|
router.delete(
|
||||||
|
'/:secretId',
|
||||||
|
requireAuth({
|
||||||
|
acceptedAuthModes: ['jwt']
|
||||||
|
}),
|
||||||
|
param('secretId').isMongoId(),
|
||||||
|
validateRequest,
|
||||||
|
secretController.deleteSingleSecret
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply modifications to many existing secrets in a given workspace and environment
|
* Apply modifications to many existing secrets in a given workspace and environment
|
||||||
*/
|
*/
|
||||||
@@ -80,4 +123,22 @@ router.patch(
|
|||||||
secretController.batchModifySecrets
|
secretController.batchModifySecrets
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply modifications to single existing secret in a given workspace and environment
|
||||||
|
*/
|
||||||
|
router.patch(
|
||||||
|
'/workspace/:workspaceId/environment/:environmentName',
|
||||||
|
requireAuth({
|
||||||
|
acceptedAuthModes: ['jwt']
|
||||||
|
}),
|
||||||
|
body('secret').isObject(),
|
||||||
|
param('workspaceId').exists().isMongoId().trim(),
|
||||||
|
param('environmentName').exists().trim(),
|
||||||
|
requireWorkspaceAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER]
|
||||||
|
}),
|
||||||
|
validateRequest,
|
||||||
|
secretController.modifySingleSecrets
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
Reference in New Issue
Block a user