feat: added support for getting imported secrets in v3 getSecret api

This commit is contained in:
Akhil Mohan
2023-09-26 12:25:23 +05:30
parent a255af6ad8
commit 4c1324baa9
5 changed files with 79 additions and 9 deletions
@@ -146,7 +146,7 @@ export const getSecretsRaw = async (req: Request, res: Response) => {
*/ */
export const getSecretByNameRaw = async (req: Request, res: Response) => { export const getSecretByNameRaw = async (req: Request, res: Response) => {
const { const {
query: { secretPath, environment, workspaceId, type }, query: { secretPath, environment, workspaceId, type, include_imports },
params: { secretName } params: { secretName }
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req); } = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
@@ -172,7 +172,8 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
environment, environment,
type, type,
secretPath, secretPath,
authData: req.authData authData: req.authData,
include_imports
}); });
const key = await BotService.getWorkspaceKeyWithBot({ const key = await BotService.getWorkspaceKeyWithBot({
@@ -483,7 +484,7 @@ export const getSecrets = async (req: Request, res: Response) => {
*/ */
export const getSecretByName = async (req: Request, res: Response) => { export const getSecretByName = async (req: Request, res: Response) => {
const { const {
query: { secretPath, environment, workspaceId, type }, query: { secretPath, environment, workspaceId, type, include_imports },
params: { secretName } params: { secretName }
} = await validateRequest(reqValidator.GetSecretByNameV3, req); } = await validateRequest(reqValidator.GetSecretByNameV3, req);
@@ -509,7 +510,8 @@ export const getSecretByName = async (req: Request, res: Response) => {
environment, environment,
type, type,
secretPath, secretPath,
authData: req.authData authData: req.authData,
include_imports
}); });
return res.status(200).send({ return res.status(200).send({
+9 -2
View File
@@ -48,6 +48,7 @@ import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/aut
import { getFolderByPath, getFolderIdFromServiceToken } from "../services/FolderService"; import { getFolderByPath, getFolderIdFromServiceToken } from "../services/FolderService";
import picomatch from "picomatch"; import picomatch from "picomatch";
import path from "path"; import path from "path";
import { getAnImportedSecret } from "../services/SecretImportService";
export const isValidScope = ( export const isValidScope = (
authPayload: IServiceTokenData, authPayload: IServiceTokenData,
@@ -622,13 +623,14 @@ export const getSecretHelper = async ({
environment, environment,
type, type,
authData, authData,
secretPath = "/" secretPath = "/",
include_imports = true
}: GetSecretParams) => { }: GetSecretParams) => {
const secretBlindIndex = await generateSecretBlindIndexHelper({ const secretBlindIndex = await generateSecretBlindIndexHelper({
secretName, secretName,
workspaceId: new Types.ObjectId(workspaceId) workspaceId: new Types.ObjectId(workspaceId)
}); });
let secret: ISecret | null = null; let secret: ISecret | null | undefined = null;
// if using service token filter towards the folderId by secretpath // if using service token filter towards the folderId by secretpath
const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath);
@@ -655,6 +657,11 @@ export const getSecretHelper = async ({
}).lean(); }).lean();
} }
if (!secret && include_imports) {
// if still no secret found search in imported secret and retreive
secret = await getAnImportedSecret(secretName, workspaceId.toString(), environment, folderId);
}
if (!secret) throw SecretNotFoundError(); if (!secret) throw SecretNotFoundError();
// (EE) create (audit) log // (EE) create (audit) log
@@ -19,7 +19,7 @@ export interface CreateSecretParams {
secretPath: string; secretPath: string;
metadata?: { metadata?: {
source?: string; source?: string;
} };
} }
export interface GetSecretsParams { export interface GetSecretsParams {
@@ -37,6 +37,7 @@ export interface GetSecretParams {
environment: string; environment: string;
type?: "shared" | "personal"; type?: "shared" | "personal";
authData: AuthData; authData: AuthData;
include_imports?: boolean;
} }
export interface UpdateSecretParams { export interface UpdateSecretParams {
@@ -1,9 +1,61 @@
import { Types } from "mongoose"; import { Types } from "mongoose";
import { generateSecretBlindIndexHelper } from "../helpers";
import { Folder, ISecret, Secret, SecretImport } from "../models"; import { Folder, ISecret, Secret, SecretImport } from "../models";
import { getFolderByPath } from "./FolderService"; import { getFolderByPath } from "./FolderService";
type TSecretImportFid = { environment: string; folderId: string; secretPath: string }; type TSecretImportFid = { environment: string; folderId: string; secretPath: string };
export const getAnImportedSecret = async (
secretName: string,
workspaceId: string,
environment: string,
folderId = "root"
) => {
const secretBlindIndex = await generateSecretBlindIndexHelper({
secretName,
workspaceId: new Types.ObjectId(workspaceId)
});
const secImports = await SecretImport.findOne({
workspace: workspaceId,
environment,
folderId
});
if (!secImports) return;
if (secImports.imports.length === 0) return;
const folders = await Folder.find({
workspace: workspaceId,
environment: { $in: secImports.imports.map((el) => el.environment) }
});
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
});
} else {
if (el.secretPath === "/") {
// this happens when importing with a fresh env without any folders
importedSecByFid.push({ environment: el.environment, folderId: "root", secretPath: "/" });
}
}
});
if (importedSecByFid.length === 0) return;
const secret = await Secret.findOne({
workspace: workspaceId,
secretBlindIndex
}).or(importedSecByFid.map(({ environment, folderId }) => ({ environment, folder: folderId })));
return secret;
};
export const getAllImportedSecrets = async ( export const getAllImportedSecrets = async (
workspaceId: string, workspaceId: string,
environment: string, environment: string,
+10 -2
View File
@@ -244,7 +244,11 @@ export const GetSecretByNameRawV3 = z.object({
workspaceId: z.string().trim(), workspaceId: z.string().trim(),
environment: z.string().trim(), environment: z.string().trim(),
secretPath: z.string().trim().default("/"), secretPath: z.string().trim().default("/"),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional() type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional(),
include_imports: z
.enum(["true", "false"])
.default("true")
.transform((value) => value === "true")
}) })
}); });
@@ -305,7 +309,11 @@ export const GetSecretByNameV3 = z.object({
workspaceId: z.string().trim(), workspaceId: z.string().trim(),
environment: z.string().trim(), environment: z.string().trim(),
secretPath: z.string().trim().default("/"), secretPath: z.string().trim().default("/"),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional() type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional(),
include_imports: z
.enum(["true", "false"])
.default("true")
.transform((value) => value === "true")
}), }),
params: z.object({ params: z.object({
secretName: z.string().trim() secretName: z.string().trim()