diff --git a/docs/documentation/platform/folder.mdx b/docs/documentation/platform/folder.mdx index a3636a2ea..eab62549e 100644 --- a/docs/documentation/platform/folder.mdx +++ b/docs/documentation/platform/folder.mdx @@ -3,10 +3,10 @@ title: "Folders" description: "Learn how to organize secrets with folders." --- -Infisical Folders enable users to organize secrets using custom structures dependent on the intended use case (also known as **path-based secret storage**). +Infisical Folders enable users to organize secrets using custom structures dependent on the intended use case (also known as **path-based secret storage**). -It is great for organizing secrets around hierarchies with multiple services or types of secrets involved at large quantities. -Infisical Folders can be infinitely nested to mirror your application architecture – whether it's microservices, monorepos, +It is great for organizing secrets around hierarchies with multiple services or types of secrets involved at large quantities. +Infisical Folders can be infinitely nested to mirror your application architecture – whether it's microservices, monorepos, or any logical grouping that best suits your needs. Consider the following structure for a microservice architecture: @@ -22,7 +22,7 @@ Consider the following structure for a microservice architecture: ... ``` -In this example, we store environment variables for each microservice under each respective `/envars` folder. +In this example, we store environment variables for each microservice under each respective `/envars` folder. We also store user-specific secrets for micro-service 1 under `/service1/users`. With this folder structure in place, your applications only need to specify a path like `/microservice1/envars` to fetch secrets from there. By extending this example, you can see how path-based secret storage provides a versatile approach to manage secrets for any architecture. @@ -45,7 +45,27 @@ To delete a folder, hover over it and press the **X** button that appears on the It's possible to compare the contents of folders across environments in the **Secrets Overview** page. When you click on a folder, the table will display the items within it across environments. -In the image below, you can see that the **Development** environment is the only one that contains items +In the image below, you can see that the **Development** environment is the only one that contains items in the `/users` folder, being other folders `/user-a`, `/user-b`, ... `/user-f`. -![comparing folders](../../images/platform/folder/folders-secrets-overview.png) \ No newline at end of file +![comparing folders](../../images/platform/folder/folders-secrets-overview.png) + +### Replicating Folder Contents + +If you want to copy secrets or folders from one path to another, you can utilize the **Replicate Secrets** functionality located in the **Add Secret** dropdown. + +![replicate secrets](../../images/platform/folder/replicate-secrets.png) + +![replicate secrets modal](../../images/platform/folder/replicate-secrets-modal.png) + +First, select the **Source Environment** and the **Source Root Path** you want to copy secrets *from*. In the example provided, we select `/dev-folder` as the source root path from the Development environment. This means any secrets within `/dev-folder` from Development will be replicated. By default, these secrets are copied into the *currently active* folder/path in your target environment (e.g., the root folder of your Staging environment in this scenario). + +As a final step, you can select the specific secrets you wish to copy and then click **Replicate Secrets**. + +![replicate secrets modal](../../images/platform/folder/replicate-secrets-result.png) + +The result shows two secrets successfully copied from the `/dev-folder` in the Development environment into the root folder of the Staging environment. + + + If you do not select a **Source Root Path**, the replication will consider the contents of the *entire root* of the **Source Environment** (e.g., the Development environment). In this example that would mean copying the `/dev-folder` itself rather than just its contents. + diff --git a/docs/images/platform/folder/replicate-secrets-modal.png b/docs/images/platform/folder/replicate-secrets-modal.png new file mode 100644 index 000000000..eb9eeebf9 Binary files /dev/null and b/docs/images/platform/folder/replicate-secrets-modal.png differ diff --git a/docs/images/platform/folder/replicate-secrets-result.png b/docs/images/platform/folder/replicate-secrets-result.png new file mode 100644 index 000000000..473ad38d0 Binary files /dev/null and b/docs/images/platform/folder/replicate-secrets-result.png differ diff --git a/docs/images/platform/folder/replicate-secrets.png b/docs/images/platform/folder/replicate-secrets.png new file mode 100644 index 000000000..77e36d62c Binary files /dev/null and b/docs/images/platform/folder/replicate-secrets.png differ diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx index d31c83512..e48a3c468 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx @@ -380,7 +380,7 @@ export const ActionBar = ({ } }; - // Replicate Folder Logic + // Replicate Secrets Logic const createSecretCount = Object.keys( (popUp.confirmUpload?.data as TSecOverwriteOpt)?.create || {} ).length; @@ -439,17 +439,22 @@ export const ActionBar = ({ const processBatches = async () => { await secretBatches.reduce(async (previous, batch) => { await previous; + try { + const { secrets: batchSecrets } = await fetchDashboardProjectSecretsByKeys({ + secretPath: normalizedPath, + environment, + projectId, + keys: batch + }); - const { secrets: batchSecrets } = await fetchDashboardProjectSecretsByKeys({ - secretPath: normalizedPath, - environment, - projectId, - keys: batch - }); - - batchSecrets.forEach((secret) => { - existingSecretLookup.add(`${normalizedPath}-${secret.secretKey}`); - }); + batchSecrets.forEach((secret) => { + existingSecretLookup.add(`${normalizedPath}-${secret.secretKey}`); + }); + } catch (error) { + if (!(error instanceof AxiosError && error.response?.status === 404)) { + throw error; + } + } }, Promise.resolve()); }; @@ -1050,7 +1055,7 @@ export const ActionBar = ({ className="h-10 text-left" isFullWidth > - Replicate Folder + Replicate Secrets )} diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ReplicateFolderFromBoard/ReplicateFolderFromBoard.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ReplicateFolderFromBoard/ReplicateFolderFromBoard.tsx index d0a9ed886..08fe0153c 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ReplicateFolderFromBoard/ReplicateFolderFromBoard.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ReplicateFolderFromBoard/ReplicateFolderFromBoard.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useState } from "react"; import { Controller, useForm } from "react-hook-form"; -import { faClone } from "@fortawesome/free-solid-svg-icons"; +import { faArrowUpRightFromSquare, faBookOpen, faClone } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; @@ -226,8 +226,27 @@ export const ReplicateFolderFromBoard = ({ + Replicate Secrets + +
+ + Docs + +
+
+ + } + subTitle="Copy folder contents from other locations into this context" >
@@ -235,7 +254,12 @@ export const ReplicateFolderFromBoard = ({ control={control} name="environment" render={({ field: { value, onChange } }) => ( - + ( - +
-
- ( - - - - )} - /> -
- { - setValue("secrets", []); - setShouldIncludeValues(isChecked as boolean); - }} + ( + - Include secret values - -
-
- - -
+ + + )} + /> +
+ { + setValue("secrets", []); + setShouldIncludeValues(isChecked as boolean); + }} + > + Include secret values + +
+
+ +