From afb5820113fdb38dac7fcb4c353ba827f6afa74d Mon Sep 17 00:00:00 2001 From: = Date: Tue, 3 Sep 2024 15:02:49 +0530 Subject: [PATCH] feat: added 1-N sink import pattern testing and fixed padding issue --- .../e2e-test/routes/v1/secret-import.spec.ts | 185 +++++++++++++++++- .../secret-v2-bridge/secret-v2-bridge-fns.ts | 22 ++- 2 files changed, 190 insertions(+), 17 deletions(-) diff --git a/backend/e2e-test/routes/v1/secret-import.spec.ts b/backend/e2e-test/routes/v1/secret-import.spec.ts index d84afef30..dd4f9c4ca 100644 --- a/backend/e2e-test/routes/v1/secret-import.spec.ts +++ b/backend/e2e-test/routes/v1/secret-import.spec.ts @@ -21,14 +21,15 @@ describe("Secret Import Router", async () => { expect(payload).toEqual( expect.objectContaining({ id: expect.any(String), - importPath: expect.any(String), + importPath, importEnv: expect.objectContaining({ name: expect.any(String), - slug: expect.any(String), + slug: importEnv, id: expect.any(String) }) }) ); + await deleteSecretImport({ id: payload.id, workspaceId: seedData1.project.id, @@ -76,10 +77,19 @@ describe("Secret Import Router", async () => { expect.arrayContaining([ expect.objectContaining({ id: expect.any(String), - importPath: expect.any(String), + importPath: "/", importEnv: expect.objectContaining({ name: expect.any(String), - slug: expect.any(String), + slug: "prod", + id: expect.any(String) + }) + }), + expect.objectContaining({ + id: expect.any(String), + importPath: "/", + importEnv: expect.objectContaining({ + name: expect.any(String), + slug: "staging", id: expect.any(String) }) }) @@ -219,10 +229,10 @@ describe("Secret Import Router", async () => { expect(deletedImport).toEqual( expect.objectContaining({ id: expect.any(String), - importPath: expect.any(String), + importPath: "/", importEnv: expect.objectContaining({ name: expect.any(String), - slug: expect.any(String), + slug: "prod", id: expect.any(String) }) }) @@ -461,7 +471,7 @@ describe.each([{ path: "/" }, { path: "/deep" }])( // dev <- stage, dev <- prod describe.each([{ path: "/" }, { path: "/deep" }])( - "Secret import 1-N pattern testing - %path", + "Secret import multiple destination to one source pattern testing - %path", ({ path: testSuitePath }) => { beforeAll(async () => { let prodFolder: { id: string }; @@ -635,3 +645,164 @@ describe.each([{ path: "/" }, { path: "/deep" }])( }); } ); + +// dev -> stage, prod +describe.each([{ path: "/" }, { path: "/deep" }])( + "Secret import one source to multiple destination pattern testing - %path", + ({ path: testSuitePath }) => { + beforeAll(async () => { + let prodFolder: { id: string }; + let stagingFolder: { id: string }; + let devFolder: { id: string }; + + if (testSuitePath !== "/") { + prodFolder = await createFolder({ + authToken: jwtAuthToken, + environmentSlug: "prod", + workspaceId: seedData1.projectV3.id, + secretPath: "/", + name: "deep" + }); + + stagingFolder = await createFolder({ + authToken: jwtAuthToken, + environmentSlug: "staging", + workspaceId: seedData1.projectV3.id, + secretPath: "/", + name: "deep" + }); + + devFolder = await createFolder({ + authToken: jwtAuthToken, + environmentSlug: seedData1.environment.slug, + workspaceId: seedData1.projectV3.id, + secretPath: "/", + name: "deep" + }); + } + + const stageImportFromDev = await createSecretImport({ + authToken: jwtAuthToken, + secretPath: testSuitePath, + environmentSlug: "staging", + workspaceId: seedData1.projectV3.id, + importPath: testSuitePath, + importEnv: seedData1.environment.slug + }); + + const prodImportFromDev = await createSecretImport({ + authToken: jwtAuthToken, + secretPath: testSuitePath, + environmentSlug: "prod", + workspaceId: seedData1.projectV3.id, + importPath: testSuitePath, + importEnv: seedData1.environment.slug + }); + + return async () => { + await deleteSecretImport({ + id: prodImportFromDev.id, + workspaceId: seedData1.projectV3.id, + environmentSlug: "prod", + secretPath: testSuitePath, + authToken: jwtAuthToken + }); + + await deleteSecretImport({ + id: stageImportFromDev.id, + workspaceId: seedData1.projectV3.id, + environmentSlug: "staging", + secretPath: testSuitePath, + authToken: jwtAuthToken + }); + + if (prodFolder) { + await deleteFolder({ + authToken: jwtAuthToken, + secretPath: "/", + id: prodFolder.id, + workspaceId: seedData1.projectV3.id, + environmentSlug: "prod" + }); + } + + if (stagingFolder) { + await deleteFolder({ + authToken: jwtAuthToken, + secretPath: "/", + id: stagingFolder.id, + workspaceId: seedData1.projectV3.id, + environmentSlug: "staging" + }); + } + + if (devFolder) { + await deleteFolder({ + authToken: jwtAuthToken, + secretPath: "/", + id: devFolder.id, + workspaceId: seedData1.projectV3.id, + environmentSlug: seedData1.environment.slug + }); + } + }; + }); + + test("Check imported secret exist", async () => { + await createSecretV2({ + environmentSlug: seedData1.environment.slug, + workspaceId: seedData1.projectV3.id, + secretPath: testSuitePath, + authToken: jwtAuthToken, + key: "STAGING_KEY", + value: "stage-value" + }); + + await createSecretV2({ + environmentSlug: seedData1.environment.slug, + workspaceId: seedData1.projectV3.id, + secretPath: testSuitePath, + authToken: jwtAuthToken, + key: "PROD_KEY", + value: "prod-value" + }); + + const stagingSecret = await getSecretByNameV2({ + environmentSlug: "staging", + workspaceId: seedData1.projectV3.id, + secretPath: testSuitePath, + authToken: jwtAuthToken, + key: "STAGING_KEY" + }); + + expect(stagingSecret.secretKey).toBe("STAGING_KEY"); + expect(stagingSecret.secretValue).toBe("stage-value"); + + const prodSecret = await getSecretByNameV2({ + environmentSlug: "prod", + workspaceId: seedData1.projectV3.id, + secretPath: testSuitePath, + authToken: jwtAuthToken, + key: "PROD_KEY" + }); + + expect(prodSecret.secretKey).toBe("PROD_KEY"); + expect(prodSecret.secretValue).toBe("prod-value"); + + await deleteSecretV2({ + environmentSlug: seedData1.environment.slug, + workspaceId: seedData1.projectV3.id, + secretPath: testSuitePath, + authToken: jwtAuthToken, + key: "STAGING_KEY" + }); + await deleteSecretV2({ + environmentSlug: seedData1.environment.slug, + workspaceId: seedData1.projectV3.id, + secretPath: testSuitePath, + authToken: jwtAuthToken, + key: "PROD_KEY" + }); + }); + } +); diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index 58a54afb9..7079c17ef 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -399,8 +399,8 @@ export const expandSecretReferencesFactory = ({ const secrets = await secretDAL.findByFolderId(folder.id); const decryptedSecret = secrets.reduce>((prev, secret) => { - // eslint-disable-next-line - prev[secret.key] = decryptSecret(secret.encryptedValue) || ""; + // eslint-disable-next-line no-param-reassign + prev[secret.key] = decryptSecret(secret.encryptedValue) || ""; return prev; }, {}); @@ -417,21 +417,23 @@ export const expandSecretReferencesFactory = ({ while (stack.length) { const { value, secretPath, environment, depth } = stack.pop()!; - // eslint-disable-next-line - if (depth > MAX_SECRET_REFERENCE_DEPTH) continue; + // eslint-disable-next-line no-continue + if (depth > MAX_SECRET_REFERENCE_DEPTH) continue; const refs = value?.match(INTERPOLATION_SYNTAX_REG); if (refs) { for (const interpolationSyntax of refs) { const interpolationKey = interpolationSyntax.slice(2, interpolationSyntax.length - 1); const entities = interpolationKey.trim().split("."); - // eslint-disable-next-line - if (!entities.length) continue; + + // eslint-disable-next-line no-continue + if (!entities.length) continue; if (entities.length === 1) { const [secretKey] = entities; - // eslint-disable-next-line - const referedValue = await fetchSecret(environment, secretPath, secretKey); + + // eslint-disable-next-line no-continue,no-await-in-loop + const referedValue = await fetchSecret(environment, secretPath, secretKey); const cacheKey = getCacheUniqueKey(environment, secretPath); secretCache[cacheKey][secretKey] = referedValue; if (INTERPOLATION_SYNTAX_REG.test(referedValue)) { @@ -448,8 +450,8 @@ export const expandSecretReferencesFactory = ({ const secretReferencePath = path.join("/", ...entities.slice(1, entities.length - 1)); const secretReferenceKey = entities[entities.length - 1]; - // eslint-disable-next-line - let referedValue = await fetchSecret(secretReferenceEnvironment, secretReferencePath, secretReferenceKey); + // eslint-disable-next-line no-await-in-loop + const referedValue = await fetchSecret(secretReferenceEnvironment, secretReferencePath, secretReferenceKey); const cacheKey = getCacheUniqueKey(secretReferenceEnvironment, secretReferencePath); secretCache[cacheKey][secretReferenceKey] = referedValue; if (INTERPOLATION_SYNTAX_REG.test(referedValue)) {