Merge pull request #1285 from Infisical/query-by-secret-version

Add version query param to GET secret raw and regular endpoints
This commit is contained in:
Maidul Islam
2024-01-07 16:07:49 -05:00
committed by GitHub
5 changed files with 102 additions and 26 deletions

View File

@@ -348,7 +348,7 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
}
*/
const {
query: { secretPath, environment, workspaceId, type, include_imports },
query: { secretPath, environment, workspaceId, type, include_imports, version },
params: { secretName }
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
@@ -371,7 +371,8 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
type,
secretPath,
authData: req.authData,
include_imports
include_imports,
version
});
const key = await BotService.getWorkspaceKeyWithBot({
@@ -865,7 +866,7 @@ export const getSecrets = async (req: Request, res: Response) => {
*/
export const getSecretByName = async (req: Request, res: Response) => {
const {
query: { secretPath, environment, workspaceId, type, include_imports },
query: { secretPath, environment, workspaceId, type, include_imports, version },
params: { secretName }
} = await validateRequest(reqValidator.GetSecretByNameV3, req);
@@ -888,7 +889,8 @@ export const getSecretByName = async (req: Request, res: Response) => {
type,
secretPath,
authData: req.authData,
include_imports
include_imports,
version
});
return res.status(200).send({

View File

@@ -611,42 +611,81 @@ export const getSecretHelper = async ({
type,
authData,
secretPath = "/",
include_imports = true
include_imports = true,
version
}: GetSecretParams) => {
const secretBlindIndex = await generateSecretBlindIndexHelper({
secretName,
workspaceId: new Types.ObjectId(workspaceId)
});
let secret: ISecret | null | undefined = null;
// if using service token filter towards the folderId by secretpath
const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath);
// try getting personal secret first (if exists)
secret = await Secret.findOne({
secretBlindIndex,
workspace: new Types.ObjectId(workspaceId),
environment,
folder: folderId,
type: type ?? SECRET_PERSONAL,
...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {})
}).lean();
if (!secret) {
// case: failed to find personal secret matching criteria
// -> find shared secret matching criteria
if (version === undefined) {
secret = await Secret.findOne({
secretBlindIndex,
workspace: new Types.ObjectId(workspaceId),
environment,
folder: folderId,
type: SECRET_SHARED
type: type ?? SECRET_PERSONAL,
...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {})
}).lean();
} else {
const secretVersion = await SecretVersion.findOne({
secretBlindIndex,
workspace: new Types.ObjectId(workspaceId),
environment,
folder: folderId,
type: type ?? SECRET_PERSONAL,
version
}).lean();
if (secretVersion) {
secret = await new Secret({
...secretVersion,
_id: secretVersion?.secret
});
}
}
if (!secret) {
// case: failed to find personal secret matching criteria
// -> find shared secret matching criteria
if (version === undefined) {
secret = await Secret.findOne({
secretBlindIndex,
workspace: new Types.ObjectId(workspaceId),
environment,
folder: folderId,
type: SECRET_SHARED
}).lean();
} else {
const secretVersion = await SecretVersion.findOne({
secretBlindIndex,
workspace: new Types.ObjectId(workspaceId),
environment,
folder: folderId,
type: SECRET_SHARED,
version
}).lean();
if (secretVersion) {
secret = await new Secret({
...secretVersion,
_id: secretVersion?.secret
});
}
}
}
if (!secret && include_imports) {
// if still no secret found search in imported secret and retreive
secret = await getAnImportedSecret(secretName, workspaceId.toString(), environment, folderId);
secret = await getAnImportedSecret(secretName, workspaceId.toString(), environment, folderId, version);
}
if (!secret) throw SecretNotFoundError();

View File

@@ -38,6 +38,7 @@ export interface GetSecretParams {
type?: "shared" | "personal";
authData: AuthData;
include_imports?: boolean;
version?: number;
}
export interface UpdateSecretParams {

View File

@@ -1,5 +1,6 @@
import { Types } from "mongoose";
import { generateSecretBlindIndexHelper } from "../helpers";
import { SecretVersion } from "../ee/models";
import { Folder, ISecret, Secret, SecretImport } from "../models";
import { getFolderByPath } from "./FolderService";
@@ -9,7 +10,8 @@ export const getAnImportedSecret = async (
secretName: string,
workspaceId: string,
environment: string,
folderId = "root"
folderId = "root",
version?: number
) => {
const secretBlindIndex = await generateSecretBlindIndexHelper({
secretName,
@@ -48,10 +50,26 @@ export const getAnImportedSecret = async (
});
if (importedSecByFid.length === 0) return;
const secret = await Secret.findOne({
workspace: workspaceId,
secretBlindIndex
}).or(importedSecByFid.map(({ environment, folderId }) => ({ environment, folder: folderId }))).lean()
let secret;
if (version === undefined) {
secret = await Secret.findOne({
workspace: workspaceId,
secretBlindIndex
}).or(importedSecByFid.map(({ environment, folderId }) => ({ environment, folder: folderId }))).lean()
} else {
const secretVersion = await SecretVersion.findOne({
workspace: workspaceId,
secretBlindIndex,
version
}).or(importedSecByFid.map(({ environment, folderId }) => ({ environment, folder: folderId }))).lean();
if (secretVersion) {
secret = await new Secret({
...secretVersion,
_id: secretVersion.secret,
});
}
}
return secret;
};

View File

@@ -246,7 +246,15 @@ export const GetSecretByNameRawV3 = z.object({
include_imports: z
.enum(["true", "false"])
.default("true")
.transform((value) => value === "true")
.transform((value) => value === "true"),
version: z
.string()
.trim()
.optional()
.transform((value) => value === undefined ? undefined : parseInt(value, 10))
.refine((value) => value === undefined || !isNaN(value), {
message: "Version must be a number",
})
})
});
@@ -318,7 +326,15 @@ export const GetSecretByNameV3 = z.object({
include_imports: z
.enum(["true", "false"])
.default("true")
.transform((value) => value === "true")
.transform((value) => value === "true"),
version: z
.string()
.trim()
.optional()
.transform((value) => value === undefined ? undefined : parseInt(value, 10))
.refine((value) => value === undefined || !isNaN(value), {
message: "Version must be a number",
})
}),
params: z.object({
secretName: z.string().trim()