From 202900a7a33ae41e652a95aac4ccb13865b7c74b Mon Sep 17 00:00:00 2001 From: akhilmhdh Date: Mon, 17 Jul 2023 23:08:42 +0530 Subject: [PATCH 1/9] feat(secret-import): implemented api for secret import --- backend/src/controllers/v1/index.ts | 4 +- .../controllers/v1/secretImportController.ts | 117 ++++++++++++++++++ .../src/controllers/v2/secretsController.ts | 12 +- .../src/controllers/v3/secretsController.ts | 51 +++++++- backend/src/index.ts | 4 +- backend/src/models/secretImports.ts | 52 ++++++++ backend/src/routes/v1/index.ts | 4 +- backend/src/routes/v1/secretImport.ts | 76 ++++++++++++ backend/src/routes/v2/secrets.ts | 1 + backend/src/routes/v3/secrets.ts | 69 +++++------ backend/src/services/SecretImportService.ts | 82 ++++++++++++ backend/src/services/index.ts | 16 +-- 12 files changed, 438 insertions(+), 50 deletions(-) create mode 100644 backend/src/controllers/v1/secretImportController.ts create mode 100644 backend/src/models/secretImports.ts create mode 100644 backend/src/routes/v1/secretImport.ts create mode 100644 backend/src/services/SecretImportService.ts diff --git a/backend/src/controllers/v1/index.ts b/backend/src/controllers/v1/index.ts index a2664c7b0..422aaa5ec 100644 --- a/backend/src/controllers/v1/index.ts +++ b/backend/src/controllers/v1/index.ts @@ -15,6 +15,7 @@ import * as userController from "./userController"; import * as workspaceController from "./workspaceController"; import * as secretScanningController from "./secretScanningController"; import * as webhookController from "./webhookController"; +import * as secretImportController from "./secretImportController"; export { authController, @@ -33,5 +34,6 @@ export { userController, workspaceController, secretScanningController, - webhookController + webhookController, + secretImportController }; diff --git a/backend/src/controllers/v1/secretImportController.ts b/backend/src/controllers/v1/secretImportController.ts new file mode 100644 index 000000000..a55b20a94 --- /dev/null +++ b/backend/src/controllers/v1/secretImportController.ts @@ -0,0 +1,117 @@ +import { Request, Response } from "express"; +import { validateMembership } from "../../helpers"; +import SecretImport from "../../models/secretImports"; +import { getAllImportedSecrets } from "../../services/SecretImportService"; +import { BadRequestError } from "../../utils/errors"; +import { ADMIN, MEMBER } from "../../variables"; + +export const createSecretImport = async (req: Request, res: Response) => { + const { workspaceId, environment, folderId, secretImport } = req.body; + const importSecDoc = await SecretImport.findOne({ + workspace: workspaceId, + environment, + folderId + }); + + if (!importSecDoc) { + const doc = new SecretImport({ + workspace: workspaceId, + environment, + folderId, + imports: [{ environment: secretImport.environment, secretPath: secretImport.secretPath }] + }); + await doc.save(); + return res.status(200).json({ message: "successfully created secret import" }); + } + + const doesImportExist = importSecDoc.imports.find( + (el) => el.environment === secretImport.environment && el.secretPath === secretImport.secretPath + ); + if (doesImportExist) { + throw BadRequestError({ message: "Secret import already exist" }); + } + + importSecDoc.imports.push({ + environment: secretImport.environment, + secretPath: secretImport.secretPath + }); + await importSecDoc.save(); + return res.status(200).json({ message: "successfully created secret import" }); +}; + +// to keep the ordering, you must pass all the imports in here not the only updated one +// this is because the order decide which import gets overriden +export const updateSecretImport = async (req: Request, res: Response) => { + const { id } = req.params; + const { secretImports } = req.body; + const importSecDoc = await SecretImport.findById(id); + if (!importSecDoc) { + throw BadRequestError({ message: "Import not found" }); + } + + await validateMembership({ + userId: req.user._id.toString(), + workspaceId: importSecDoc.workspace, + acceptedRoles: [ADMIN, MEMBER] + }); + + importSecDoc.imports = secretImports; + await importSecDoc.save(); + return res.status(200).json({ message: "successfully updated secret import" }); +}; + +export const deleteSecretImport = async (req: Request, res: Response) => { + const { id } = req.params; + const { secretImportEnv, secretImportPath } = req.body; + const importSecDoc = await SecretImport.findById(id); + if (!importSecDoc) { + throw BadRequestError({ message: "Import not found" }); + } + + await validateMembership({ + userId: req.user._id.toString(), + workspaceId: importSecDoc.workspace, + acceptedRoles: [ADMIN, MEMBER] + }); + importSecDoc.imports = importSecDoc.imports.filter( + ({ environment, secretPath }) => + !(environment === secretImportEnv && secretPath === secretImportPath) + ); + await importSecDoc.save(); + return res.status(200).json({ message: "successfully delete secret import" }); +}; + +export const getSecretImports = async (req: Request, res: Response) => { + const { workspaceId, environment, folderId } = req.query; + const importSecDoc = await SecretImport.findOne({ + workspace: workspaceId, + environment, + folderId + }); + + if (!importSecDoc) { + return res.status(200).json({ secretImport: {} }); + } + + return res.status(200).json({ secretImport: importSecDoc }); +}; + +export const getAllSecretsFromImport = async (req: Request, res: Response) => { + const { workspaceId, environment, folderId } = req.query as { + workspaceId: string; + environment: string; + folderId: string; + }; + const importSecDoc = await SecretImport.findOne({ + workspace: workspaceId, + environment, + folderId + }); + + if (!importSecDoc) { + return res.status(200).json({ secrets: {} }); + } + + const secrets = await getAllImportedSecrets(workspaceId, environment, folderId); + return res.status(200).json({ secrets }); +}; diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index cc1aae055..ea8098e37 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -35,6 +35,7 @@ import { } from "../../services/FolderService"; import { isValidScope } from "../../helpers/secrets"; import path from "path"; +import { getAllImportedSecrets } from "../../services/SecretImportService"; /** * Peform a batch of any specified CUD secret operations @@ -690,7 +691,7 @@ export const getSecrets = async (req: Request, res: Response) => { } */ - const { tagSlugs, secretPath } = req.query; + const { tagSlugs, secretPath, include_imports } = req.query; let { folderId } = req.query; const workspaceId = req.query.workspaceId as string; const environment = req.query.environment as string; @@ -827,6 +828,12 @@ export const getSecrets = async (req: Request, res: Response) => { secrets = await Secret.find(secretQuery).populate("tags"); } + // TODO(akhilmhdh) - secret-imp change this to org type + let importedSecrets: any[] = []; + if (include_imports) { + importedSecrets = await getAllImportedSecrets(workspaceId, environment, folderId as string); + } + const channel = getChannelFromUserAgent(req.headers["user-agent"]); const readAction = await EELogService.createAction({ @@ -868,7 +875,8 @@ export const getSecrets = async (req: Request, res: Response) => { } return res.status(200).send({ - secrets + secrets, + ...(include_imports && { imports: importedSecrets }) }); }; diff --git a/backend/src/controllers/v3/secretsController.ts b/backend/src/controllers/v3/secretsController.ts index e1edd95ad..cd2d3248e 100644 --- a/backend/src/controllers/v3/secretsController.ts +++ b/backend/src/controllers/v3/secretsController.ts @@ -5,6 +5,10 @@ import { eventPushSecrets } from "../../events"; import { BotService } from "../../services"; import { repackageSecretToRaw } from "../../helpers/secrets"; import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; +import { getAllImportedSecrets } from "../../services/SecretImportService"; +import Folder from "../../models/folder"; +import { getFolderByPath } from "../../services/FolderService"; +import { BadRequestError } from "../../utils/errors"; /** * Return secrets for workspace with id [workspaceId] and environment @@ -16,6 +20,7 @@ export const getSecretsRaw = async (req: Request, res: Response) => { const workspaceId = req.query.workspaceId as string; const environment = req.query.environment as string; const secretPath = req.query.secretPath as string; + const includeImports = req.query.include_imports as string; const secrets = await SecretService.getSecrets({ workspaceId: new Types.ObjectId(workspaceId), @@ -28,13 +33,38 @@ export const getSecretsRaw = async (req: Request, res: Response) => { workspaceId: new Types.ObjectId(workspaceId) }); + if (includeImports) { + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + let folderId = "root"; + // if folder exist get it and replace folderid with new one + if (folders) { + const folder = getFolderByPath(folders.nodes, secretPath as string); + if (!folder) { + throw BadRequestError({ message: "Folder not found" }); + } + folderId = folder.id; + } + const importedSecrets = await getAllImportedSecrets(workspaceId, environment, folderId); + return res.status(200).send({ + secrets: secrets.map((secret) => + repackageSecretToRaw({ + secret, + key + }) + ), + imports: importedSecrets.map((el) => ({ + ...el, + secrets: el.secrets.map((secret) => repackageSecretToRaw({ secret, key })) + })) + }); + } + return res.status(200).send({ secrets: secrets.map((secret) => { const rep = repackageSecretToRaw({ secret, key }); - return rep; }) }); @@ -232,6 +262,7 @@ export const getSecrets = async (req: Request, res: Response) => { const workspaceId = req.query.workspaceId as string; const environment = req.query.environment as string; const secretPath = req.query.secretPath as string; + const includeImports = req.query.include_imports as string; const secrets = await SecretService.getSecrets({ workspaceId: new Types.ObjectId(workspaceId), @@ -240,6 +271,24 @@ export const getSecrets = async (req: Request, res: Response) => { authData: req.authData }); + if (includeImports) { + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + let folderId = "root"; + // if folder exist get it and replace folderid with new one + if (folders) { + const folder = getFolderByPath(folders.nodes, secretPath as string); + if (!folder) { + throw BadRequestError({ message: "Folder not found" }); + } + folderId = folder.id; + } + const importedSecrets = await getAllImportedSecrets(workspaceId, environment, folderId); + return res.status(200).send({ + secrets, + imports: importedSecrets + }); + } + return res.status(200).send({ secrets }); diff --git a/backend/src/index.ts b/backend/src/index.ts index 9733c1fdb..a7a9c5591 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -41,7 +41,8 @@ import { userAction as v1UserActionRouter, user as v1UserRouter, workspace as v1WorkspaceRouter, - webhooks as v1WebhooksRouter + webhooks as v1WebhooksRouter, + secretImport as v1SecretImportRouter } from "./routes/v1"; import { auth as v2AuthRouter, @@ -128,6 +129,7 @@ const main = async () => { app.use("/api/v1/folders", v1SecretsFolder); app.use("/api/v1/secret-scanning", v1SecretScanningRouter); app.use("/api/v1/webhooks", v1WebhooksRouter); + app.use("/api/v1/secret-imports", v1SecretImportRouter); // v2 routes (improvements) app.use("/api/v2/signup", v2SignupRouter); diff --git a/backend/src/models/secretImports.ts b/backend/src/models/secretImports.ts new file mode 100644 index 000000000..0041abc29 --- /dev/null +++ b/backend/src/models/secretImports.ts @@ -0,0 +1,52 @@ +import { Schema, Types, model } from "mongoose"; + +export interface ISecretImports { + _id: Types.ObjectId; + workspace: Types.ObjectId; + environment: string; + folderId: string; + imports: Array<{ + environment: string; + secretPath: string; + }>; +} + +const secretImportSchema = new Schema( + { + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true + }, + environment: { + type: String, + required: true + }, + folderId: { + type: String, + required: true, + default: "root" + }, + imports: { + type: [ + { + environment: { + type: String, + required: true + }, + secretPath: { + type: String, + required: true + } + } + ], + default: [] + } + }, + { + timestamps: true + } +); + +const SecretImport = model("SecretImports", secretImportSchema); +export default SecretImport; diff --git a/backend/src/routes/v1/index.ts b/backend/src/routes/v1/index.ts index b9f26d32d..ce5b5dd58 100644 --- a/backend/src/routes/v1/index.ts +++ b/backend/src/routes/v1/index.ts @@ -17,6 +17,7 @@ import integrationAuth from "./integrationAuth"; import secretsFolder from "./secretsFolder"; import secretScanning from "./secretScanning"; import webhooks from "./webhook"; +import secretImport from "./secretImport"; export { signup, @@ -37,5 +38,6 @@ export { integrationAuth, secretsFolder, secretScanning, - webhooks + webhooks, + secretImport }; diff --git a/backend/src/routes/v1/secretImport.ts b/backend/src/routes/v1/secretImport.ts new file mode 100644 index 000000000..bdfba97a6 --- /dev/null +++ b/backend/src/routes/v1/secretImport.ts @@ -0,0 +1,76 @@ +import express from "express"; +const router = express.Router(); +import { body, param, query } from "express-validator"; +import { secretImportController } from "../../controllers/v1"; +import { requireAuth, requireWorkspaceAuth, validateRequest } from "../../middleware"; +import { ADMIN, AUTH_MODE_JWT, MEMBER } from "../../variables"; + +router.post( + "/", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body" + }), + body("workspaceId").exists().isString().trim().notEmpty(), + body("environment").exists().isString().trim().notEmpty(), + body("folderId").default("root").isString().trim(), + body("secretImport").exists().isObject(), + body("secretImport.environment").isString().exists().trim(), + body("secretImport.secretPath").isString().exists().trim(), + validateRequest, + secretImportController.createSecretImport +); + +router.put( + "/:id", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + param("id").exists().isString().trim(), + body("secretImports").exists().isArray(), + body("secretImports.*.environment").isString().exists().trim(), + body("secretImports.*.secretPath").isString().exists().trim(), + validateRequest, + secretImportController.updateSecretImport +); + +router.delete( + "/:id", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + param("id").exists().isString().trim(), + body("secretImportPath").isString().exists().trim(), + body("secretImportEnv").isString().exists().trim(), + validateRequest, + secretImportController.updateSecretImport +); + +router.get( + "/", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + query("workspaceId").exists().isString().trim().notEmpty(), + query("environment").exists().isString().trim().notEmpty(), + query("folderId").default("root").isString().trim(), + validateRequest, + secretImportController.getSecretImports +); + +router.get( + "/secrets", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + query("workspaceId").exists().isString().trim().notEmpty(), + query("environment").exists().isString().trim().notEmpty(), + query("folderId").default("root").isString().trim(), + validateRequest, + secretImportController.getAllSecretsFromImport +); + +export default router; diff --git a/backend/src/routes/v2/secrets.ts b/backend/src/routes/v2/secrets.ts index 731e58eb0..59665fd03 100644 --- a/backend/src/routes/v2/secrets.ts +++ b/backend/src/routes/v2/secrets.ts @@ -127,6 +127,7 @@ router.get( query("tagSlugs"), query("folderId").default("root").isString().trim(), query("secretPath").optional().isString().trim(), + query("include_imports").optional().default(false).isBoolean(), validateRequest, requireAuth({ acceptedAuthModes: [ diff --git a/backend/src/routes/v3/secrets.ts b/backend/src/routes/v3/secrets.ts index c010151c6..445503dec 100644 --- a/backend/src/routes/v3/secrets.ts +++ b/backend/src/routes/v3/secrets.ts @@ -1,10 +1,6 @@ import express from "express"; const router = express.Router(); -import { - requireAuth, - requireWorkspaceAuth, - validateRequest, -} from "../../middleware"; +import { requireAuth, requireWorkspaceAuth, validateRequest } from "../../middleware"; import { body, param, query } from "express-validator"; import { secretsController } from "../../controllers/v3"; import { @@ -17,7 +13,7 @@ import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS, SECRET_PERSONAL, - SECRET_SHARED, + SECRET_SHARED } from "../../variables"; router.get( @@ -25,14 +21,15 @@ router.get( query("workspaceId").exists().isString().trim(), query("environment").exists().isString().trim(), query("secretPath").default("/").isString().trim(), + query("include_imports").isBoolean().default(false), validateRequest, requireAuth({ acceptedAuthModes: [ AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -40,7 +37,7 @@ router.get( locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true, + requireE2EEOff: true }), secretsController.getSecretsRaw ); @@ -58,8 +55,8 @@ router.get( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -67,7 +64,7 @@ router.get( locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true, + requireE2EEOff: true }), secretsController.getSecretByNameRaw ); @@ -86,8 +83,8 @@ router.post( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -95,7 +92,7 @@ router.post( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true, + requireE2EEOff: true }), secretsController.createSecretRaw ); @@ -114,8 +111,8 @@ router.patch( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -123,7 +120,7 @@ router.patch( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true, + requireE2EEOff: true }), secretsController.updateSecretByNameRaw ); @@ -141,8 +138,8 @@ router.delete( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -150,7 +147,7 @@ router.delete( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true, + requireE2EEOff: true }), secretsController.deleteSecretByNameRaw ); @@ -166,8 +163,8 @@ router.get( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -175,7 +172,7 @@ router.get( locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false, + requireE2EEOff: false }), secretsController.getSecrets ); @@ -201,8 +198,8 @@ router.post( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -210,7 +207,7 @@ router.post( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false, + requireE2EEOff: false }), secretsController.createSecret ); @@ -228,15 +225,15 @@ router.get( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], locationWorkspaceId: "query", locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], - requireBlindIndicesEnabled: true, + requireBlindIndicesEnabled: true }), secretsController.getSecretByName ); @@ -257,8 +254,8 @@ router.patch( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -266,7 +263,7 @@ router.patch( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false, + requireE2EEOff: false }), secretsController.updateSecretByName ); @@ -284,8 +281,8 @@ router.delete( AUTH_MODE_JWT, AUTH_MODE_API_KEY, AUTH_MODE_SERVICE_TOKEN, - AUTH_MODE_SERVICE_ACCOUNT, - ], + AUTH_MODE_SERVICE_ACCOUNT + ] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -293,7 +290,7 @@ router.delete( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false, + requireE2EEOff: false }), secretsController.deleteSecretByName ); diff --git a/backend/src/services/SecretImportService.ts b/backend/src/services/SecretImportService.ts new file mode 100644 index 000000000..ec9f9f5c4 --- /dev/null +++ b/backend/src/services/SecretImportService.ts @@ -0,0 +1,82 @@ +import { Types } from "mongoose"; +import Folder from "../models/folder"; +import Secret, { ISecret } from "../models/secret"; +import SecretImport from "../models/secretImports"; +import { getFolderByPath } from "./FolderService"; + +type TSecretImportFid = { environment: string; folderId: string; secretPath: string }; + +export const getAllImportedSecrets = async ( + workspaceId: string, + environment: string, + folderId = "root" +) => { + const secImports = await SecretImport.findOne({ + workspace: workspaceId, + environment, + folderId + }); + if (!secImports) return []; + if (secImports.imports.length === 0) return []; + + const importedEnv: Record = {}; // to get folders from all environment + secImports.imports.forEach((el) => (importedEnv[el.environment] = true)); + + const folders = await Folder.find({ + workspace: workspaceId, + environment: { $in: Object.keys(importedEnv) } + }); + + const importedSecByFid: TSecretImportFid[] = []; + secImports.imports.forEach((el) => { + const folder = folders.find((fl) => fl.environment === el.environment); + if (folder) { + const secPathFolder = getFolderByPath(folder.nodes, el.secretPath); + if (secPathFolder) + importedSecByFid.push({ + environment: el.environment, + folderId: secPathFolder.id, + secretPath: el.secretPath + }); + } + }); + if (importedSecByFid.length === 0) return []; + + const secsGroupedByRef = await Secret.aggregate([ + { + $match: { + workspace: new Types.ObjectId(workspaceId), + type: "shared" + } + }, + { + $group: { + _id: { + environment: "$environment", + folderId: "$folder" + }, + secrets: { $push: "$$ROOT" } + } + }, + { + $match: { + $or: importedSecByFid.map(({ environment, folderId: fid }) => ({ + "_id.environment": environment, + "_id.folderId": fid + })) + } + } + ]); + + // now let stitch together secrets. + const importedSecrets: Array = []; + importedSecByFid.forEach(({ environment, folderId, secretPath }) => { + const secretsGrouped = secsGroupedByRef.find( + (el) => el._id.environment === environment && el._id.folderId === folderId + ); + if (secretsGrouped) { + importedSecrets.push({ secretPath, folderId, environment, secrets: secretsGrouped.secrets }); + } + }); + return importedSecrets; +}; diff --git a/backend/src/services/index.ts b/backend/src/services/index.ts index ad83bf510..131d3c281 100644 --- a/backend/src/services/index.ts +++ b/backend/src/services/index.ts @@ -8,11 +8,11 @@ import TokenService from "./TokenService"; import SecretService from "./SecretService"; export { - TelemetryService, - DatabaseService, - BotService, - EventService, - IntegrationService, - TokenService, - SecretService, -} \ No newline at end of file + TelemetryService, + DatabaseService, + BotService, + EventService, + IntegrationService, + TokenService, + SecretService +}; From 45584e0c1a596b2af712850f35535f385ec2c62f Mon Sep 17 00:00:00 2001 From: akhilmhdh Date: Mon, 17 Jul 2023 23:08:57 +0530 Subject: [PATCH 2/9] feat(secret-import): implemented ui for secret import --- frontend/package-lock.json | 109 +++++++ frontend/package.json | 3 + frontend/src/hooks/api/index.tsx | 1 + frontend/src/hooks/api/secretImports/index.ts | 2 + .../src/hooks/api/secretImports/mutation.tsx | 78 +++++ .../src/hooks/api/secretImports/queries.tsx | 124 +++++++ frontend/src/hooks/api/secretImports/types.ts | 56 ++++ frontend/src/hooks/api/secrets/mutation.tsx | 69 ++++ frontend/src/hooks/api/secrets/queries.tsx | 4 + frontend/src/hooks/api/secrets/types.ts | 2 + .../src/views/DashboardPage/DashboardPage.tsx | 303 ++++++++++++++---- .../FolderSection/FolderSection.tsx | 2 +- .../SecretImportForm/SecretImportForm.tsx | 86 +++++ .../components/SecretImportForm/index.tsx | 1 + .../SecretImportSection/SecretImportItem.tsx | 144 +++++++++ .../SecretImportSection.tsx | 93 ++++++ .../components/SecretImportSection/index.tsx | 1 + .../SecretInputRow/SecretInputRow.tsx | 2 +- 18 files changed, 1022 insertions(+), 58 deletions(-) create mode 100644 frontend/src/hooks/api/secretImports/index.ts create mode 100644 frontend/src/hooks/api/secretImports/mutation.tsx create mode 100644 frontend/src/hooks/api/secretImports/queries.tsx create mode 100644 frontend/src/hooks/api/secretImports/types.ts create mode 100644 frontend/src/hooks/api/secrets/mutation.tsx create mode 100644 frontend/src/views/DashboardPage/components/SecretImportForm/SecretImportForm.tsx create mode 100644 frontend/src/views/DashboardPage/components/SecretImportForm/index.tsx create mode 100644 frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportItem.tsx create mode 100644 frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportSection.tsx create mode 100644 frontend/src/views/DashboardPage/components/SecretImportSection/index.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index cb3360485..5853ff650 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -5,6 +5,9 @@ "packages": { "": { "dependencies": { + "@dnd-kit/core": "^6.0.8", + "@dnd-kit/modifiers": "^6.0.1", + "@dnd-kit/sortable": "^7.0.2", "@emotion/css": "^11.10.0", "@emotion/server": "^11.10.0", "@fontsource/inter": "^4.5.15", @@ -2468,6 +2471,68 @@ "node": ">=10.0.0" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz", + "integrity": "sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.0.8.tgz", + "integrity": "sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA==", + "dependencies": { + "@dnd-kit/accessibility": "^3.0.0", + "@dnd-kit/utilities": "^3.2.1", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz", + "integrity": "sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==", + "dependencies": { + "@dnd-kit/utilities": "^3.2.1", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.0.6", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.2.tgz", + "integrity": "sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA==", + "dependencies": { + "@dnd-kit/utilities": "^3.2.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.0.7", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.1.tgz", + "integrity": "sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -24491,6 +24556,50 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@dnd-kit/accessibility": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz", + "integrity": "sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@dnd-kit/core": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.0.8.tgz", + "integrity": "sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA==", + "requires": { + "@dnd-kit/accessibility": "^3.0.0", + "@dnd-kit/utilities": "^3.2.1", + "tslib": "^2.0.0" + } + }, + "@dnd-kit/modifiers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz", + "integrity": "sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==", + "requires": { + "@dnd-kit/utilities": "^3.2.1", + "tslib": "^2.0.0" + } + }, + "@dnd-kit/sortable": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.2.tgz", + "integrity": "sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA==", + "requires": { + "@dnd-kit/utilities": "^3.2.0", + "tslib": "^2.0.0" + } + }, + "@dnd-kit/utilities": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.1.tgz", + "integrity": "sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA==", + "requires": { + "tslib": "^2.0.0" + } + }, "@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index f20477e6f..0430844e7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,9 @@ "build-storybook": "storybook build" }, "dependencies": { + "@dnd-kit/core": "^6.0.8", + "@dnd-kit/modifiers": "^6.0.1", + "@dnd-kit/sortable": "^7.0.2", "@emotion/css": "^11.10.0", "@emotion/server": "^11.10.0", "@fontsource/inter": "^4.5.15", diff --git a/frontend/src/hooks/api/index.tsx b/frontend/src/hooks/api/index.tsx index 299629416..18e5b59fb 100644 --- a/frontend/src/hooks/api/index.tsx +++ b/frontend/src/hooks/api/index.tsx @@ -6,6 +6,7 @@ export * from "./integrations"; export * from "./keys"; export * from "./organization"; export * from "./secretFolders"; +export * from "./secretImports"; export * from "./secrets"; export * from "./secretSnapshots"; export * from "./serviceAccounts"; diff --git a/frontend/src/hooks/api/secretImports/index.ts b/frontend/src/hooks/api/secretImports/index.ts new file mode 100644 index 000000000..2e1150cb8 --- /dev/null +++ b/frontend/src/hooks/api/secretImports/index.ts @@ -0,0 +1,2 @@ +export { useCreateSecretImport, useDeleteSecretImport, useUpdateSecretImport } from "./mutation"; +export { useGetImportedSecrets, useGetSecretImports } from "./queries"; diff --git a/frontend/src/hooks/api/secretImports/mutation.tsx b/frontend/src/hooks/api/secretImports/mutation.tsx new file mode 100644 index 000000000..bb01528ea --- /dev/null +++ b/frontend/src/hooks/api/secretImports/mutation.tsx @@ -0,0 +1,78 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; + +import { apiRequest } from "@app/config/request"; + +import { secretImportKeys } from "./queries"; +import { TCreateSecretImportDTO, TDeleteSecretImportDTO, TUpdateSecretImportDTO } from "./types"; + +export const useCreateSecretImport = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, TCreateSecretImportDTO>({ + mutationFn: async ({ secretImport, environment, workspaceId, folderId }) => { + const { data } = await apiRequest.post("/api/v1/secret-imports", { + secretImport, + environment, + workspaceId, + folderId + }); + return data; + }, + onSuccess: (_, { workspaceId, environment, folderId }) => { + queryClient.invalidateQueries( + secretImportKeys.getProjectSecretImports(workspaceId, environment, folderId) + ); + queryClient.invalidateQueries( + secretImportKeys.getSecretImportSecrets(workspaceId, environment, folderId) + ); + } + }); +}; + +export const useUpdateSecretImport = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, TUpdateSecretImportDTO>({ + mutationFn: async ({ environment, workspaceId, folderId, secretImports, id }) => { + const { data } = await apiRequest.put(`/api/v1/secret-imports/${id}`, { + secretImports, + environment, + workspaceId, + folderId + }); + return data; + }, + onSuccess: (_, { workspaceId, environment, folderId }) => { + queryClient.invalidateQueries( + secretImportKeys.getProjectSecretImports(workspaceId, environment, folderId) + ); + queryClient.invalidateQueries( + secretImportKeys.getSecretImportSecrets(workspaceId, environment, folderId) + ); + } + }); +}; + +export const useDeleteSecretImport = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, TDeleteSecretImportDTO>({ + mutationFn: async ({ id, secretImportEnv, secretImportPath }) => { + const { data } = await apiRequest.delete(`/api/v1/secret-imports/${id}`, { + data: { + secretImportPath, + secretImportEnv + } + }); + return data; + }, + onSuccess: (_, { workspaceId, environment, folderId }) => { + queryClient.invalidateQueries( + secretImportKeys.getProjectSecretImports(workspaceId, environment, folderId) + ); + queryClient.invalidateQueries( + secretImportKeys.getSecretImportSecrets(workspaceId, environment, folderId) + ); + } + }); +}; diff --git a/frontend/src/hooks/api/secretImports/queries.tsx b/frontend/src/hooks/api/secretImports/queries.tsx new file mode 100644 index 000000000..7bb07488c --- /dev/null +++ b/frontend/src/hooks/api/secretImports/queries.tsx @@ -0,0 +1,124 @@ +import { useCallback } from "react"; +import { useQuery } from "@tanstack/react-query"; + +import { + decryptAssymmetric, + decryptSymmetric +} from "@app/components/utilities/cryptography/crypto"; +import { apiRequest } from "@app/config/request"; + +import { TGetImportedSecrets, TImportedSecrets, TSecretImports } from "./types"; + +export const secretImportKeys = { + getProjectSecretImports: (workspaceId: string, env: string | string[], folderId?: string) => [ + { workspaceId, env, folderId }, + "secrets-imports" + ], + getSecretImportSecrets: (workspaceId: string, env: string | string[], folderId?: string) => [ + { workspaceId, env, folderId }, + "secrets-import-sec" + ] +}; + +const fetchSecretImport = async (workspaceId: string, environment: string, folderId?: string) => { + const { data } = await apiRequest.get<{ secretImport: TSecretImports }>( + "/api/v1/secret-imports", + { + params: { + workspaceId, + environment, + folderId + } + } + ); + return data.secretImport; +}; + +export const useGetSecretImports = (workspaceId: string, env: string, folderId?: string) => + useQuery({ + enabled: Boolean(workspaceId) && Boolean(env), + queryKey: secretImportKeys.getProjectSecretImports(workspaceId, env, folderId), + queryFn: () => fetchSecretImport(workspaceId, env, folderId) + }); + +const fetchImportedSecrets = async ( + workspaceId: string, + environment: string, + folderId?: string +) => { + const { data } = await apiRequest.get<{ secrets: TImportedSecrets }>( + "/api/v1/secret-imports/secrets", + { + params: { + workspaceId, + environment, + folderId + } + } + ); + return data.secrets; +}; + +export const useGetImportedSecrets = ({ + workspaceId, + environment, + folderId, + decryptFileKey +}: TGetImportedSecrets) => + useQuery({ + enabled: Boolean(workspaceId) && Boolean(environment) && Boolean(decryptFileKey), + queryKey: secretImportKeys.getSecretImportSecrets(workspaceId, environment, folderId), + queryFn: () => fetchImportedSecrets(workspaceId, environment, folderId), + select: useCallback( + (data: TImportedSecrets) => { + const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string; + const latestKey = decryptFileKey; + const key = decryptAssymmetric({ + ciphertext: latestKey.encryptedKey, + nonce: latestKey.nonce, + publicKey: latestKey.sender.publicKey, + privateKey: PRIVATE_KEY + }); + + return data.map((el) => ({ + environment: el.environment, + secretPath: el.secretPath, + folderId: el.folderId, + secrets: el.secrets.map((encSecret) => { + const secretKey = decryptSymmetric({ + ciphertext: encSecret.secretKeyCiphertext, + iv: encSecret.secretKeyIV, + tag: encSecret.secretKeyTag, + key + }); + + const secretValue = decryptSymmetric({ + ciphertext: encSecret.secretValueCiphertext, + iv: encSecret.secretValueIV, + tag: encSecret.secretValueTag, + key + }); + + const secretComment = decryptSymmetric({ + ciphertext: encSecret.secretCommentCiphertext, + iv: encSecret.secretCommentIV, + tag: encSecret.secretCommentTag, + key + }); + + return { + _id: encSecret._id, + env: encSecret.environment, + key: secretKey, + value: secretValue, + tags: encSecret.tags, + comment: secretComment, + createdAt: encSecret.createdAt, + updatedAt: encSecret.updatedAt + }; + }) + })); + }, + [decryptFileKey] + ) + }); diff --git a/frontend/src/hooks/api/secretImports/types.ts b/frontend/src/hooks/api/secretImports/types.ts new file mode 100644 index 000000000..50884225f --- /dev/null +++ b/frontend/src/hooks/api/secretImports/types.ts @@ -0,0 +1,56 @@ +import { EncryptedSecret } from "../secrets/types"; +import { UserWsKeyPair } from "../types"; + +export type TSecretImports = { + _id: string; + workspaceId: string; + environment: string; + folderId: string; + imports: Array<{ environment: string; secretPath: string }>; + createdAt: string; + updatedAt: string; +}; + +export type TImportedSecrets = { + environment: string; + secretPath: string; + folderId: string; + secrets: EncryptedSecret[]; +}[]; + +export type TGetImportedSecrets = { + workspaceId: string; + environment: string; + folderId?: string; + decryptFileKey: UserWsKeyPair; +}; + +export type TCreateSecretImportDTO = { + workspaceId: string; + environment: string; + folderId?: string; + secretImport: { + environment: string; + secretPath: string; + }; +}; + +export type TUpdateSecretImportDTO = { + id: string; + workspaceId: string; + environment: string; + folderId?: string; + secretImports: Array<{ + environment: string; + secretPath: string; + }>; +}; + +export type TDeleteSecretImportDTO = { + id: string; + workspaceId: string; + environment: string; + folderId?: string; + secretImportPath: string; + secretImportEnv: string; +}; diff --git a/frontend/src/hooks/api/secrets/mutation.tsx b/frontend/src/hooks/api/secrets/mutation.tsx new file mode 100644 index 000000000..0047d8435 --- /dev/null +++ b/frontend/src/hooks/api/secrets/mutation.tsx @@ -0,0 +1,69 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; + +import { apiRequest } from "@app/config/request"; + +import { secretKeys } from "./queries"; +import { TCreateSecretImportDTO, TDeleteSecretImportDTO, TUpdateSecretImportDTO } from "./types"; + +export const useCreateSecretImport = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, TCreateSecretImportDTO>({ + mutationFn: async ({ secretImport, environment, workspaceId, folderId }) => { + const { data } = await apiRequest.post("/api/v1/secret-imports", { + secretImport, + environment, + workspaceId, + folderId + }); + return data; + }, + onSuccess: (_, { workspaceId, environment, folderId }) => { + queryClient.invalidateQueries( + secretKeys.getProjectSecretImports(workspaceId, environment, folderId) + ); + } + }); +}; + +export const useUpdateSecretImport = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, TUpdateSecretImportDTO>({ + mutationFn: async ({ environment, workspaceId, folderId, secretImports, id }) => { + const { data } = await apiRequest.put(`/api/v1/secret-imports/${id}`, { + secretImports, + environment, + workspaceId, + folderId + }); + return data; + }, + onSuccess: (_, { workspaceId, environment, folderId }) => { + queryClient.invalidateQueries( + secretKeys.getProjectSecretImports(workspaceId, environment, folderId) + ); + } + }); +}; + +export const useDeleteSecretImport = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, TDeleteSecretImportDTO>({ + mutationFn: async ({ id, secretImportEnv, secretImportPath }) => { + const { data } = await apiRequest.delete(`/api/v1/secret-imports/${id}`, { + data: { + secretImportPath, + secretImportEnv + } + }); + return data; + }, + onSuccess: (_, { workspaceId, environment, folderId }) => { + queryClient.invalidateQueries( + secretKeys.getProjectSecretImports(workspaceId, environment, folderId) + ); + } + }); +}; diff --git a/frontend/src/hooks/api/secrets/queries.tsx b/frontend/src/hooks/api/secrets/queries.tsx index 397f68aa7..1541ff753 100644 --- a/frontend/src/hooks/api/secrets/queries.tsx +++ b/frontend/src/hooks/api/secrets/queries.tsx @@ -24,6 +24,10 @@ export const secretKeys = { { workspaceId, env, folderId }, "secrets" ], + getProjectSecretImports: (workspaceId: string, env: string | string[], folderId?: string) => [ + { workspaceId, env, folderId }, + "secrets-imports" + ], getSecretVersion: (secretId: string) => [{ secretId }, "secret-versions"] }; diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index a622b25eb..b36eb47f7 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -34,6 +34,7 @@ export type DecryptedSecret = { valueOverride?: string; idOverride?: string; overrideAction?: string; + folderId?: string; }; export type EncryptedSecretVersion = { @@ -98,6 +99,7 @@ export type GetProjectSecretsDTO = { folderId?: string; secretPath?: string; isPaused?: boolean; + include_imports?: boolean; onSuccess?: (data: DecryptedSecret[]) => void; }; diff --git a/frontend/src/views/DashboardPage/DashboardPage.tsx b/frontend/src/views/DashboardPage/DashboardPage.tsx index 1cb686414..3b0effb1f 100644 --- a/frontend/src/views/DashboardPage/DashboardPage.tsx +++ b/frontend/src/views/DashboardPage/DashboardPage.tsx @@ -2,6 +2,18 @@ import { useEffect, useRef, useState } from "react"; import { FormProvider, useFieldArray, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useRouter } from "next/router"; +import { + closestCenter, + DndContext, + DragEndEvent, + KeyboardSensor, + MouseSensor, + TouchSensor, + useSensor, + useSensors +} from "@dnd-kit/core"; +import { restrictToVerticalAxis } from "@dnd-kit/modifiers"; +import { arrayMove } from "@dnd-kit/sortable"; import { faArrowLeft, faCheck, @@ -10,6 +22,7 @@ import { faDownload, faEye, faEyeSlash, + faFileImport, faFolderPlus, faMagnifyingGlass, faPlus @@ -41,10 +54,14 @@ import { useLeaveConfirm, usePopUp, useToggle } from "@app/hooks"; import { useBatchSecretsOp, useCreateFolder, + useCreateSecretImport, useCreateWsTag, useDeleteFolder, + useDeleteSecretImport, + useGetImportedSecrets, useGetProjectFolders, useGetProjectSecrets, + useGetSecretImports, useGetSecretVersion, useGetSnapshotSecrets, useGetUserAction, @@ -55,7 +72,8 @@ import { useGetWsTags, usePerformSecretRollback, useRegisterUserAction, - useUpdateFolder + useUpdateFolder, + useUpdateSecretImport } from "@app/hooks/api"; import { secretKeys } from "@app/hooks/api/secrets/queries"; import { WorkspaceEnv } from "@app/hooks/api/types"; @@ -71,6 +89,8 @@ import { import { PitDrawer } from "./components/PitDrawer"; import { SecretDetailDrawer } from "./components/SecretDetailDrawer"; import { SecretDropzone } from "./components/SecretDropzone"; +import { SecretImportForm } from "./components/SecretImportForm"; +import { SecretImportSection } from "./components/SecretImportSection"; import { SecretInputRow } from "./components/SecretInputRow"; import { SecretTableHeader } from "./components/SecretTableHeader"; import { @@ -84,7 +104,7 @@ import { } from "./DashboardPage.utils"; const USER_ACTION_PUSH = "first_time_secrets_pushed"; - +type TDeleteSecretImport = { environment: string; secretPath: string }; /* * Some imp aspects to consider. Here there are multiple stats changing * Thus ideally we need to use a context. But instead we rely on react hook form @@ -113,7 +133,9 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { "compareSecrets", "folderForm", "deleteFolder", - "upgradePlan" + "upgradePlan", + "addSecretImport", + "deleteSecretImport" ] as const); const [isSecretValueHidden, setIsSecretValueHidden] = useToggle(true); const [searchFilter, setSearchFilter] = useState(""); @@ -129,6 +151,8 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { const { currentWorkspace, isLoading } = useWorkspace(); const { currentOrg } = useOrganization(); const workspaceId = currentWorkspace?._id as string; + const selectedEnvSlug = selectedEnv?.slug || ""; + const { data: latestFileKey } = useGetUserWsKey(workspaceId); useEffect(() => { @@ -161,7 +185,7 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { const { data: secrets, isLoading: isSecretsLoading } = useGetProjectSecrets({ workspaceId, - env: selectedEnv?.slug || "", + env: selectedEnvSlug, decryptFileKey: latestFileKey!, isPaused: Boolean(snapshotId), folderId @@ -169,7 +193,7 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { const { data: folderData, isLoading: isFoldersLoading } = useGetProjectFolders({ workspaceId: workspaceId || "", - environment: selectedEnv?.slug || "", + environment: selectedEnvSlug, parentFolderId: folderId, isPaused: isRollbackMode, sortDir @@ -182,7 +206,7 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { isFetchingNextPage } = useGetWorkspaceSecretSnapshots({ workspaceId, - environment: selectedEnv?.slug || "", + environment: selectedEnvSlug, folder: folderId, limit: 10 }); @@ -193,17 +217,18 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { isFetching: isSnapshotChanging } = useGetSnapshotSecrets({ snapshotId: snapshotId || "", - env: selectedEnv?.slug || "", + env: selectedEnvSlug, decryptFileKey: latestFileKey! }); const { data: snapshotCount, isLoading: isLoadingSnapshotCount } = useGetWsSnapshotCount( workspaceId, - selectedEnv?.slug || "", + selectedEnvSlug, folderId ); const { data: wsTags } = useGetWsTags(workspaceId); + // mutation calls const { mutateAsync: batchSecretOp } = useBatchSecretsOp(); const { mutateAsync: performSecretRollback } = usePerformSecretRollback(); @@ -213,6 +238,50 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { const { mutateAsync: updateFolder } = useUpdateFolder(folderId); const { mutateAsync: deleteFolder } = useDeleteFolder(folderId); + const { data: secretImportCfg, isFetching: isSecretImportCfgFetching } = useGetSecretImports( + workspaceId, + selectedEnvSlug, + folderId + ); + + const { data: importedSecrets } = useGetImportedSecrets({ + workspaceId, + decryptFileKey: latestFileKey!, + environment: selectedEnvSlug, + folderId + }); + + // This is for dnd-kit. As react-query state mutation async + // This will act as a placeholder to avoid a glitching animation on dropping items + const [items, setItems] = useState< + Array<{ environment: string; secretPath: string; id: string }> + >([]); + + useEffect(() => { + if ( + !isSecretImportCfgFetching || + // case in which u go to a folder and come back to fill in with cache data + (items.length === 0 && secretImportCfg?.imports?.length !== 0 && isSecretImportCfgFetching) + ) { + setItems( + secretImportCfg?.imports?.map((el) => ({ + ...el, + id: `${el.environment}-${el.secretPath}` + })) || [] + ); + } + }, [isSecretImportCfgFetching]); + + const { mutateAsync: createSecretImport } = useCreateSecretImport(); + const { mutate: updateSecretImportSync } = useUpdateSecretImport(); + const { mutateAsync: deleteSecretImport } = useDeleteSecretImport(); + + const sensors = useSensors( + useSensor(MouseSensor, {}), + useSensor(TouchSensor, {}), + useSensor(KeyboardSensor, {}) + ); + const method = useForm({ // why any: well yup inferred ts expects other keys to defined as undefined defaultValues: secrets as any, @@ -319,14 +388,12 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { await performSecretRollback({ workspaceId, version: snapshotSecret.version, - environment: selectedEnv?.slug || "", + environment: selectedEnvSlug, folderId }); setValue("isSnapshotMode", false); setSnaphotId(null); - queryClient.invalidateQueries( - secretKeys.getProjectSecret(workspaceId, selectedEnv?.slug || "") - ); + queryClient.invalidateQueries(secretKeys.getProjectSecret(workspaceId, selectedEnvSlug)); createNotification({ text: "Successfully rollback secrets", type: "success" @@ -522,6 +589,79 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { } }; + const handleSecretImportCreate = async (env: string, secretPath: string) => { + try { + await createSecretImport({ + workspaceId, + environment: selectedEnv?.slug || "", + folderId, + secretImport: { + environment: env, + secretPath + } + }); + createNotification({ + type: "success", + text: "Successfully create secret link" + }); + handlePopUpClose("addSecretImport"); + } catch (err) { + console.error(err); + createNotification({ + text: "Failed to create secret link", + type: "error" + }); + } + }; + + const handleSecretImportDelete = async () => { + const { environment: importEnv, secretPath: impSecPath } = popUp.deleteSecretImport + ?.data as TDeleteSecretImport; + try { + if (secretImportCfg?._id) { + await deleteSecretImport({ + workspaceId, + environment: selectedEnvSlug, + folderId, + id: secretImportCfg?._id, + secretImportEnv: importEnv, + secretImportPath: impSecPath + }); + handlePopUpClose("deleteSecretImport"); + createNotification({ + type: "success", + text: "Successfully removed secret link" + }); + } + } catch (err) { + console.error(err); + createNotification({ + text: "Failed to remove secret link", + type: "error" + }); + } + }; + + const handleDragEnd = (evt: DragEndEvent) => { + const { active, over } = evt; + if (over?.id && active.id !== over.id) { + const oldIndex = items.findIndex(({ id }) => id === active.id); + const newIndex = items.findIndex(({ id }) => id === over.id); + const newImportOrder = arrayMove(items, oldIndex, newIndex); + setItems(newImportOrder); + updateSecretImportSync({ + workspaceId, + environment: selectedEnvSlug, + folderId, + id: secretImportCfg?._id || "", + secretImports: newImportOrder.map((el) => ({ + environment: el.environment, + secretPath: el.secretPath + })) + }); + } + }; + // when secrets is not loading and secrets list is empty const isDashboardSecretEmpty = !isSecretsLoading && !fields?.length; @@ -664,7 +804,6 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => { -
{
+
+ +
-
+ + + )} + + + + )} { /> + handlePopUpToggle("addSecretImport", isOpen)} + > + + + + { onChange={(isOpen) => handlePopUpToggle("deleteFolder", isOpen)} onDeleteApproved={handleFolderDelete} /> + handlePopUpToggle("deleteSecretImport", isOpen)} + onDeleteApproved={handleSecretImportDelete} + /> handlePopUpToggle("compareSecrets", open)} diff --git a/frontend/src/views/DashboardPage/components/FolderSection/FolderSection.tsx b/frontend/src/views/DashboardPage/components/FolderSection/FolderSection.tsx index 482324246..dbdf57fe0 100644 --- a/frontend/src/views/DashboardPage/components/FolderSection/FolderSection.tsx +++ b/frontend/src/views/DashboardPage/components/FolderSection/FolderSection.tsx @@ -67,7 +67,7 @@ export const FolderSection = ({ ariaLabel="delete" onClick={() => handleFolderDelete(id, name)} > - +
diff --git a/frontend/src/views/DashboardPage/components/SecretImportForm/SecretImportForm.tsx b/frontend/src/views/DashboardPage/components/SecretImportForm/SecretImportForm.tsx new file mode 100644 index 000000000..27adbf24f --- /dev/null +++ b/frontend/src/views/DashboardPage/components/SecretImportForm/SecretImportForm.tsx @@ -0,0 +1,86 @@ +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import * as yup from "yup"; + +import { Button, FormControl, Input, ModalClose, Select, SelectItem } from "@app/components/v2"; + +type Props = { + onCreate: (environment: string, secretPath: string) => Promise; + environments?: Array<{ slug: string; name: string }>; +}; + +const formSchema = yup.object({ + environment: yup.string().required().label("Environment").trim(), + secretPath: yup + .string() + .required() + .label("Secret Path") + .trim() + .transform((val) => + typeof val === "string" && val.at(-1) === "/" && val.length > 1 ? val.slice(0, -1) : val + ) +}); + +type TFormData = yup.InferType; + +export const SecretImportForm = ({ onCreate, environments = [] }: Props): JSX.Element => { + const { + control, + reset, + formState: { isSubmitting }, + handleSubmit + } = useForm({ + resolver: yupResolver(formSchema) + }); + + const onSubmit = async ({ environment, secretPath }: TFormData) => { + await onCreate(environment, secretPath); + reset(); + }; + + return ( +
+ ( + + + + )} + /> + ( + + + + )} + /> +
+ + + + +
+ + ); +}; diff --git a/frontend/src/views/DashboardPage/components/SecretImportForm/index.tsx b/frontend/src/views/DashboardPage/components/SecretImportForm/index.tsx new file mode 100644 index 000000000..c5be50814 --- /dev/null +++ b/frontend/src/views/DashboardPage/components/SecretImportForm/index.tsx @@ -0,0 +1 @@ +export { SecretImportForm } from "./SecretImportForm"; diff --git a/frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportItem.tsx b/frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportItem.tsx new file mode 100644 index 000000000..6e424fc1a --- /dev/null +++ b/frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportItem.tsx @@ -0,0 +1,144 @@ +import { useEffect } from "react"; +import { useSortable } from "@dnd-kit/sortable"; +import { faFileImport, faFolder, faUpDown, faXmark } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { IconButton, TableContainer, Tooltip } from "@app/components/v2"; +import { useWorkspace } from "@app/context"; +import { useToggle } from "@app/hooks/useToggle"; + +type Props = { + onDelete: (environment: string, secretPath: string) => void; + importedEnv: string; + importedSecPath: string; + importedSecrets: { key: string; value: string; overriden: { env: string; secretPath: string } }[]; +}; + +// to show the environment and folder icon +export const EnvFolderIcon = ({ env, secretPath }: { env: string; secretPath: string }) => ( +
+
{env || "-"}
+ {secretPath && ( +
+ + {secretPath} +
+ )} +
+); + +export const SecretImportItem = ({ + importedEnv, + importedSecPath, + onDelete, + importedSecrets = [] +}: Props) => { + const [isExpanded, setIsExpanded] = useToggle(); + const { attributes, listeners, transform, transition, setNodeRef, isDragging } = useSortable({ + id: `${importedEnv}-${importedSecPath}` + }); + const { currentWorkspace } = useWorkspace(); + const rowEnv = currentWorkspace?.environments?.find(({ slug }) => slug === importedEnv); + + useEffect(() => { + if (isDragging) { + setIsExpanded.off(); + } + }, [isDragging]); + + const style = { + transform: transform ? `translateY(${transform.y ? Math.round(transform.y) : 0}px)` : "", + transition + }; + + return ( + <> + setIsExpanded.toggle()} + > + + + + +
+ +
+
+
+ + + + + +
+
+ + { + evt.stopPropagation(); + onDelete(importedEnv, importedSecPath); + }} + > + + + +
+
+ + + + {isExpanded && !isDragging && ( + +
+
Secrets Imported
+ + + + + + + + + + + {importedSecrets.map(({ key, value, overriden }, index) => ( + + + + + + ))} + +
KeyValueOverride
+ {key} + + {value} + + +
+
+
+ + )} + + + ); +}; diff --git a/frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportSection.tsx b/frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportSection.tsx new file mode 100644 index 000000000..6998b6ae3 --- /dev/null +++ b/frontend/src/views/DashboardPage/components/SecretImportSection/SecretImportSection.tsx @@ -0,0 +1,93 @@ +import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; + +import { useWorkspace } from "@app/context"; +import { DecryptedSecret } from "@app/hooks/api/secrets/types"; + +import { SecretImportItem } from "./SecretImportItem"; + +type TImportedSecrets = Array<{ + environment: string; + secretPath: string; + folderId: string; + secrets: DecryptedSecret[]; +}>; + +const SECRET_IN_DASHBOARD = "Present In Dashboard"; + +export const computeImportedSecretRows = ( + importedSecEnv: string, + importedSecPath: string, + importSecrets: TImportedSecrets = [], + secrets: DecryptedSecret[] = [], + environments: { name: string; slug: string }[] = [] +) => { + const importedSecIndex = importSecrets.findIndex( + ({ secretPath, environment }) => + secretPath === importedSecPath && importedSecEnv === environment + ); + if (importedSecIndex === -1) return []; + + const importedSec = importSecrets[importedSecIndex]; + + const overridenSec: Record = {}; + const envSlug2Name: Record = {}; + environments.forEach((el) => { + envSlug2Name[el.slug] = el.name; + }); + + for (let i = importedSecIndex + 1; i < importSecrets.length; i += 1) { + importSecrets[i].secrets.forEach((el) => { + overridenSec[el.key] = { + env: envSlug2Name?.[importSecrets[i].environment] || "unknown", + secretPath: importSecrets[i].secretPath + }; + }); + } + + secrets.forEach((el) => { + overridenSec[el.key] = { env: SECRET_IN_DASHBOARD, secretPath: "" }; + }); + + return importedSec.secrets.map(({ key, value }) => ({ + key, + value, + overriden: overridenSec?.[key] + })); +}; + +type Props = { + secrets?: DecryptedSecret[]; + importedSecrets?: TImportedSecrets; + onSecretImportDelete: (env: string, secPath: string) => void; + items: { id: string; environment: string; secretPath: string }[]; +}; + +export const SecretImportSection = ({ + secrets = [], + importedSecrets = [], + onSecretImportDelete, + items = [] +}: Props) => { + const { currentWorkspace } = useWorkspace(); + const environments = currentWorkspace?.environments || []; + + return ( + + {items.map(({ secretPath: impSecPath, environment: importSecEnv, id }) => ( + + ))} + + ); +}; diff --git a/frontend/src/views/DashboardPage/components/SecretImportSection/index.tsx b/frontend/src/views/DashboardPage/components/SecretImportSection/index.tsx new file mode 100644 index 000000000..837c9ce6d --- /dev/null +++ b/frontend/src/views/DashboardPage/components/SecretImportSection/index.tsx @@ -0,0 +1 @@ +export { SecretImportSection } from "./SecretImportSection"; diff --git a/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx b/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx index fd79785d3..2a99400fb 100644 --- a/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx +++ b/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx @@ -407,7 +407,7 @@ export const SecretInputRow = memo(
Date: Mon, 17 Jul 2023 23:10:14 +0530 Subject: [PATCH 3/9] feat(secret-import): updated cli to support secret import --- cli/packages/api/api.go | 4 ++ cli/packages/api/model.go | 73 +++++++++++++++++++++--------------- cli/packages/cmd/run.go | 8 +++- cli/packages/cmd/secrets.go | 8 +++- cli/packages/models/cli.go | 1 + cli/packages/util/secrets.go | 72 ++++++++++++++++++++++++++++------- 6 files changed, 119 insertions(+), 47 deletions(-) diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index 5afec6782..89c8db76a 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -235,6 +235,10 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req SetQueryParam("environment", request.Environment). SetQueryParam("workspaceId", request.WorkspaceId) + if request.IncludeImport { + httpRequest.SetQueryParam("include_imports", "true") + } + if request.SecretPath != "" { httpRequest.SetQueryParam("secretPath", request.SecretPath) } diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index 09e6779e0..027243ef5 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -272,40 +272,51 @@ type GetNewAccessTokenWithRefreshTokenResponse struct { } type GetEncryptedSecretsV3Request struct { - Environment string `json:"environment"` - WorkspaceId string `json:"workspaceId"` - SecretPath string `json:"secretPath"` + Environment string `json:"environment"` + WorkspaceId string `json:"workspaceId"` + SecretPath string `json:"secretPath"` + IncludeImport bool `json:"include_imports"` +} + +type EncryptedSecretV3 struct { + ID string `json:"_id"` + Version int `json:"version"` + Workspace string `json:"workspace"` + Type string `json:"type"` + Tags []struct { + ID string `json:"_id"` + Name string `json:"name"` + Slug string `json:"slug"` + Workspace string `json:"workspace"` + } `json:"tags"` + Environment string `json:"environment"` + SecretKeyCiphertext string `json:"secretKeyCiphertext"` + SecretKeyIV string `json:"secretKeyIV"` + SecretKeyTag string `json:"secretKeyTag"` + SecretValueCiphertext string `json:"secretValueCiphertext"` + SecretValueIV string `json:"secretValueIV"` + SecretValueTag string `json:"secretValueTag"` + SecretCommentCiphertext string `json:"secretCommentCiphertext"` + SecretCommentIV string `json:"secretCommentIV"` + SecretCommentTag string `json:"secretCommentTag"` + Algorithm string `json:"algorithm"` + KeyEncoding string `json:"keyEncoding"` + Folder string `json:"folder"` + V int `json:"__v"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type ImportedSecretV3 struct { + Environment string `json:"environment"` + FolderId string `json:"folderId"` + SecretPath string `json:"secretPath"` + Secrets []EncryptedSecretV3 `json:"secrets"` } type GetEncryptedSecretsV3Response struct { - Secrets []struct { - ID string `json:"_id"` - Version int `json:"version"` - Workspace string `json:"workspace"` - Type string `json:"type"` - Tags []struct { - ID string `json:"_id"` - Name string `json:"name"` - Slug string `json:"slug"` - Workspace string `json:"workspace"` - } `json:"tags"` - Environment string `json:"environment"` - SecretKeyCiphertext string `json:"secretKeyCiphertext"` - SecretKeyIV string `json:"secretKeyIV"` - SecretKeyTag string `json:"secretKeyTag"` - SecretValueCiphertext string `json:"secretValueCiphertext"` - SecretValueIV string `json:"secretValueIV"` - SecretValueTag string `json:"secretValueTag"` - SecretCommentCiphertext string `json:"secretCommentCiphertext"` - SecretCommentIV string `json:"secretCommentIV"` - SecretCommentTag string `json:"secretCommentTag"` - Algorithm string `json:"algorithm"` - KeyEncoding string `json:"keyEncoding"` - Folder string `json:"folder"` - V int `json:"__v"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - } `json:"secrets"` + Secrets []EncryptedSecretV3 `json:"secrets"` + ImportedSecrets []ImportedSecretV3 `json:"imports,omitempty"` } type CreateSecretV3Request struct { diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index 2303cbe2e..02fe16327 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -87,7 +87,12 @@ var runCmd = &cobra.Command{ util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath}) + includeImports, err := cmd.Flags().GetBool("include-imports") + if err != nil { + util.HandleError(err, "Unable to parse flag") + } + + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports}) if err != nil { util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid") @@ -186,6 +191,7 @@ func init() { runCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") runCmd.Flags().StringP("env", "e", "dev", "Set the environment (dev, prod, etc.) from which your secrets should be pulled from") runCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") + runCmd.Flags().Bool("include-imports", true, "Import linked secrets ") runCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")") runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ") diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 688dd55bf..4d55f4307 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -54,12 +54,17 @@ var secretsCmd = &cobra.Command{ util.HandleError(err) } + includeImports, err := cmd.Flags().GetBool("include-imports") + if err != nil { + util.HandleError(err) + } + tagSlugs, err := cmd.Flags().GetString("tags") if err != nil { util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath}) + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports}) if err != nil { util.HandleError(err) } @@ -647,6 +652,7 @@ func init() { secretsCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") secretsCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on") secretsCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets") + secretsCmd.Flags().Bool("include-imports", true, "Imported linked secrets ") secretsCmd.PersistentFlags().StringP("tags", "t", "", "filter secrets by tag slugs") secretsCmd.Flags().String("path", "/", "get secrets within a folder path") rootCmd.AddCommand(secretsCmd) diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 18a64750f..c388d2d9e 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -65,4 +65,5 @@ type GetAllSecretsParameters struct { TagSlugs string WorkspaceId string SecretsPath string + IncludeImport bool } diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index d49e92607..b20ec4488 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -17,7 +17,7 @@ import ( "github.com/rs/zerolog/log" ) -func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment string, secretPath string) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) { +func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment string, secretPath string, includeImports bool) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) { serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4) if len(serviceTokenParts) < 4 { return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("invalid service token entered. Please double check your service token and try again") @@ -45,9 +45,10 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str } encryptedSecrets, err := api.CallGetSecretsV3(httpClient, api.GetEncryptedSecretsV3Request{ - WorkspaceId: serviceTokenDetails.Workspace, - Environment: environment, - SecretPath: secretPath, + WorkspaceId: serviceTokenDetails.Workspace, + Environment: environment, + SecretPath: secretPath, + IncludeImport: includeImports, }) if err != nil { @@ -64,15 +65,22 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("unable to decrypt the required workspace key") } - plainTextSecrets, err := GetPlainTextSecrets(plainTextWorkspaceKey, encryptedSecrets) + plainTextSecrets, err := GetPlainTextSecrets(plainTextWorkspaceKey, encryptedSecrets.Secrets) if err != nil { return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("unable to decrypt your secrets [err=%v]", err) } + if includeImports { + plainTextSecrets, err = InjectImportedSecret(plainTextWorkspaceKey, plainTextSecrets, encryptedSecrets.ImportedSecrets) + if err != nil { + return nil, api.GetServiceTokenDetailsResponse{}, err + } + } + return plainTextSecrets, serviceTokenDetails, nil } -func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string, secretsPath string) ([]models.SingleEnvironmentVariable, error) { +func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string, secretsPath string, includeImports bool) ([]models.SingleEnvironmentVariable, error) { httpClient := resty.New() httpClient.SetAuthToken(JTWToken). SetHeader("Accept", "application/json") @@ -114,8 +122,9 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work plainTextWorkspaceKey := crypto.DecryptAsymmetric(encryptedWorkspaceKey, encryptedWorkspaceKeyNonce, encryptedWorkspaceKeySenderPublicKey, currentUsersPrivateKey) getSecretsRequest := api.GetEncryptedSecretsV3Request{ - WorkspaceId: workspaceId, - Environment: environmentName, + WorkspaceId: workspaceId, + Environment: environmentName, + IncludeImport: includeImports, // TagSlugs: tagSlugs, } @@ -124,19 +133,53 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work } encryptedSecrets, err := api.CallGetSecretsV3(httpClient, getSecretsRequest) - if err != nil { return nil, err } - plainTextSecrets, err := GetPlainTextSecrets(plainTextWorkspaceKey, encryptedSecrets) + plainTextSecrets, err := GetPlainTextSecrets(plainTextWorkspaceKey, encryptedSecrets.Secrets) if err != nil { return nil, fmt.Errorf("unable to decrypt your secrets [err=%v]", err) } + if includeImports { + plainTextSecrets, err = InjectImportedSecret(plainTextWorkspaceKey, plainTextSecrets, encryptedSecrets.ImportedSecrets) + if err != nil { + return nil, err + } + } + return plainTextSecrets, nil } +func InjectImportedSecret(plainTextWorkspaceKey []byte, secrets []models.SingleEnvironmentVariable, importedSecrets []api.ImportedSecretV3) ([]models.SingleEnvironmentVariable, error) { + if importedSecrets == nil { + return secrets, nil + } + + hasOverriden := make(map[string]bool) + for _, sec := range secrets { + hasOverriden[sec.Key] = true + } + + for i := len(importedSecrets) - 1; i >= 0; i-- { + importSec := importedSecrets[i] + plainTextImportedSecrets, err := GetPlainTextSecrets(plainTextWorkspaceKey, importSec.Secrets) + fmt.Println(plainTextImportedSecrets) + if err != nil { + return nil, fmt.Errorf("unable to decrypt your imported secrets [err=%v]", err) + } + + for _, sec := range plainTextImportedSecrets { + if _, ok := hasOverriden[sec.Key]; !ok { + secrets = append(secrets, sec) + hasOverriden[sec.Key] = true + } + } + } + return secrets, nil +} + func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models.SingleEnvironmentVariable, error) { var infisicalToken string if params.InfisicalToken == "" { @@ -179,7 +222,8 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models return nil, fmt.Errorf("unable to validate environment name because [err=%s]", err) } - secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, workspaceFile.WorkspaceId, params.Environment, params.TagSlugs, params.SecretsPath) + secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, workspaceFile.WorkspaceId, + params.Environment, params.TagSlugs, params.SecretsPath, params.IncludeImport) log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn) backupSecretsEncryptionKey := []byte(loggedInUserDetails.UserCredentials.PrivateKey)[0:32] @@ -199,7 +243,7 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models } else { log.Debug().Msg("Trying to fetch secrets using service token") - secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(infisicalToken, params.Environment, params.SecretsPath) + secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(infisicalToken, params.Environment, params.SecretsPath, params.IncludeImport) } return secretsToReturn, errorToReturn @@ -427,9 +471,9 @@ func OverrideSecrets(secrets []models.SingleEnvironmentVariable, secretType stri return secretsToReturn } -func GetPlainTextSecrets(key []byte, encryptedSecrets api.GetEncryptedSecretsV3Response) ([]models.SingleEnvironmentVariable, error) { +func GetPlainTextSecrets(key []byte, encryptedSecrets []api.EncryptedSecretV3) ([]models.SingleEnvironmentVariable, error) { plainTextSecrets := []models.SingleEnvironmentVariable{} - for _, secret := range encryptedSecrets.Secrets { + for _, secret := range encryptedSecrets { // Decrypt key key_iv, err := base64.StdEncoding.DecodeString(secret.SecretKeyIV) if err != nil { From 23cd6fd8613129a185020af1e9ce75ac20e53f22 Mon Sep 17 00:00:00 2001 From: akhilmhdh Date: Mon, 17 Jul 2023 23:10:42 +0530 Subject: [PATCH 4/9] doc(secret-imports): updated docs for secret import --- .../platform/secret-reference.mdx | 14 +++++++++++++- docs/images/secret-import-add.png | Bin 0 -> 99629 bytes docs/images/secret-import-change-order.png | Bin 0 -> 103473 bytes 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 docs/images/secret-import-add.png create mode 100644 docs/images/secret-import-change-order.png diff --git a/docs/documentation/platform/secret-reference.mdx b/docs/documentation/platform/secret-reference.mdx index ce9b50db5..8df6fce72 100644 --- a/docs/documentation/platform/secret-reference.mdx +++ b/docs/documentation/platform/secret-reference.mdx @@ -1,5 +1,5 @@ --- -title: "Reference Secrets" +title: "Reference/Import Secrets" description: "How to use reference secrets in Infisical" --- @@ -34,4 +34,16 @@ For instance, to access a secret 'A' composed of secrets 'B' and 'C' from differ When using [service tokens](./token) to fetch referenced secrets, ensure the service token has read access to all referenced environments and folders. Without proper permissions, the final secret value may be incomplete. +## Import multiple secrets from a environment secret path +You can import or link another environment's folder to your dashboard to inherit its secrets. This is useful when you need to share secrets across multiple environments. + +To add an import/link, just click on `Secret Link` button and provide an `environment` and `secret path` to which the secrets must be pulled. + +![secret import change order](../../images/secret-import-add.png) + +The import hierarchy is "last one wins." This means that the order in which you import matters. The last folder you import will override the secrets from any previous folders. Additionally, any secrets you define in your dashboard will override the secrets from any imported folders. + +You can change the order by dragging and positioning according using the `Change Order` drag handle. + +![secret import change order](../../images/secret-import-change-order.png diff --git a/docs/images/secret-import-add.png b/docs/images/secret-import-add.png new file mode 100644 index 0000000000000000000000000000000000000000..1376fd41211c8e5746d47676585e7ebcc44bdbc8 GIT binary patch literal 99629 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

olQIuWjS0BbX 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 Date: Tue, 18 Jul 2023 00:29:42 +0530 Subject: [PATCH 5/9] fix(secret-import): resolved build failure in frontend --- frontend/src/hooks/api/secrets/mutation.tsx | 69 --------------------- 1 file changed, 69 deletions(-) delete mode 100644 frontend/src/hooks/api/secrets/mutation.tsx diff --git a/frontend/src/hooks/api/secrets/mutation.tsx b/frontend/src/hooks/api/secrets/mutation.tsx deleted file mode 100644 index 0047d8435..000000000 --- a/frontend/src/hooks/api/secrets/mutation.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useMutation, useQueryClient } from "@tanstack/react-query"; - -import { apiRequest } from "@app/config/request"; - -import { secretKeys } from "./queries"; -import { TCreateSecretImportDTO, TDeleteSecretImportDTO, TUpdateSecretImportDTO } from "./types"; - -export const useCreateSecretImport = () => { - const queryClient = useQueryClient(); - - return useMutation<{}, {}, TCreateSecretImportDTO>({ - mutationFn: async ({ secretImport, environment, workspaceId, folderId }) => { - const { data } = await apiRequest.post("/api/v1/secret-imports", { - secretImport, - environment, - workspaceId, - folderId - }); - return data; - }, - onSuccess: (_, { workspaceId, environment, folderId }) => { - queryClient.invalidateQueries( - secretKeys.getProjectSecretImports(workspaceId, environment, folderId) - ); - } - }); -}; - -export const useUpdateSecretImport = () => { - const queryClient = useQueryClient(); - - return useMutation<{}, {}, TUpdateSecretImportDTO>({ - mutationFn: async ({ environment, workspaceId, folderId, secretImports, id }) => { - const { data } = await apiRequest.put(`/api/v1/secret-imports/${id}`, { - secretImports, - environment, - workspaceId, - folderId - }); - return data; - }, - onSuccess: (_, { workspaceId, environment, folderId }) => { - queryClient.invalidateQueries( - secretKeys.getProjectSecretImports(workspaceId, environment, folderId) - ); - } - }); -}; - -export const useDeleteSecretImport = () => { - const queryClient = useQueryClient(); - - return useMutation<{}, {}, TDeleteSecretImportDTO>({ - mutationFn: async ({ id, secretImportEnv, secretImportPath }) => { - const { data } = await apiRequest.delete(`/api/v1/secret-imports/${id}`, { - data: { - secretImportPath, - secretImportEnv - } - }); - return data; - }, - onSuccess: (_, { workspaceId, environment, folderId }) => { - queryClient.invalidateQueries( - secretKeys.getProjectSecretImports(workspaceId, environment, folderId) - ); - } - }); -}; From cef29f5dd7758fd2fbe717ae8964b4678f1f449f Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Mon, 17 Jul 2023 21:39:05 -0700 Subject: [PATCH 6/9] minor style update --- .../src/views/DashboardPage/DashboardPage.tsx | 115 ++++++++---------- 1 file changed, 49 insertions(+), 66 deletions(-) diff --git a/frontend/src/views/DashboardPage/DashboardPage.tsx b/frontend/src/views/DashboardPage/DashboardPage.tsx index 3b0effb1f..1cf24dcb4 100644 --- a/frontend/src/views/DashboardPage/DashboardPage.tsx +++ b/frontend/src/views/DashboardPage/DashboardPage.tsx @@ -15,6 +15,7 @@ import { import { restrictToVerticalAxis } from "@dnd-kit/modifiers"; import { arrayMove } from "@dnd-kit/sortable"; import { + faAngleDown, faArrowLeft, faCheck, faClockRotateLeft, @@ -29,6 +30,7 @@ import { } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { yupResolver } from "@hookform/resolvers/yup"; +import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu"; import { useQueryClient } from "@tanstack/react-query"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; @@ -792,63 +794,11 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => {

{!isReadOnly && !isRollbackMode && ( - <> -
- - handlePopUpOpen("folderForm")} - > - - - -
-
- - { - if (secretContainer.current) { - secretContainer.current.scroll({ - top: 0, - behavior: "smooth" - }); - } - prepend(DEFAULT_SECRET_VALUE, { shouldFocus: false }); - }} - > - - - -
-
- -
-
- -
-
- -
- + } + }} + className="font-semibold bg-mineshaft-600 border border-mineshaft-500 p-2 rounded-l-md text-sm text-mineshaft-300 cursor-pointer hover:bg-primary/[0.1] hover:border-primary/40 pr-4 duration-200" + > + Add Secret + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ )} {isRollbackMode && (