From 1a55dff687b72eeb17597e0859707bcb83286007 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Thu, 9 Oct 2025 20:48:25 +0530 Subject: [PATCH 01/22] fix: tag editor modal --- .../tags/CreateTagModal/CreateTagModal.tsx | 18 +++++++++---- .../components/SecretListView/SecretItem.tsx | 6 ++--- .../SecretListView/SecretListView.tsx | 26 ++++++++++++++++++- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx index d48b7d95f..75c240ffb 100644 --- a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx +++ b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx @@ -17,6 +17,7 @@ import { } from "@app/components/v2"; import { useProject } from "@app/context"; import { useCreateWsTag } from "@app/hooks/api"; +import { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types"; import { slugSchema } from "@app/lib/schemas"; export const secretTagsColors = [ @@ -85,6 +86,8 @@ const isValidHexColor = (hexColor: string) => { type Props = { isOpen?: boolean; onToggle: (isOpen: boolean) => void; + append: (data: WsTag) => void; + currentSecret?: SecretV3RawSanitized; }; const createTagSchema = z.object({ @@ -100,7 +103,7 @@ type TagColor = { name: string; }; -export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => { +export const CreateTagModal = ({ isOpen, onToggle, append, currentSecret }: Props): JSX.Element => { const { control, reset, @@ -128,11 +131,12 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => { const onFormSubmit = async ({ slug, color }: FormData) => { try { - await createWsTag({ + const data = await createWsTag({ projectId, tagColor: color, tagSlug: slug }); + append(data); onToggle(false); reset(); createNotification({ @@ -151,8 +155,12 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => { return (
{ isDisabled={isSubmitting} isLoading={isSubmitting} > - Create + {currentSecret ? "Create and Add" : "Create"} @@ -927,7 +927,7 @@ export const SecretItem = memo( className="h-3 w-3" /> } - onClick={onCreateTag} + onClick={() => onCreateTag(secret)} > Create a tag diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx index 4fc314bdd..bd43e1271 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx @@ -465,6 +465,22 @@ export const SecretListView = ({ [environment, secretPath, isProtectedBranch, isBatchMode, projectId, addPendingChange] ); + // Function to append newly created tag to the current secret + const append = useCallback( + (newTag: WsTag) => { + const currentSecret = popUp.createTag.data as SecretV3RawSanitized; + if (!currentSecret) return; + + const updatedTags = [...(currentSecret.tags || []), { id: newTag.id, slug: newTag.slug }]; + + handleSaveSecret(currentSecret, { + ...currentSecret, + tags: updatedTags + }); + }, + [popUp.createTag.data, handleSaveSecret] + ); + const handleSecretDelete = useCallback(async () => { const { key, @@ -552,7 +568,13 @@ export const SecretListView = ({ ]); // for optimization on minimise re-rendering of secret items - const onCreateTag = useCallback(() => handlePopUpOpen("createTag"), []); + const onCreateTag = useCallback((secret?: SecretV3RawSanitized) => { + if (secret) { + handlePopUpOpen("createTag", secret); + } else { + handlePopUpOpen("createTag"); + } + }, []); const onDeleteSecret = useCallback( (sec: SecretV3RawSanitized) => handlePopUpOpen("deleteSecret", sec), [] @@ -640,6 +662,8 @@ export const SecretListView = ({ handlePopUpToggle("createTag", isOpen)} + append={append} + currentSecret={popUp.createTag.data} /> From 24595c405cf16f8014c77eb7d89b65e3f736d14d Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Fri, 10 Oct 2025 05:10:05 +0400 Subject: [PATCH 02/22] docs: aws cloudhsm integration --- backend/src/ee/services/hsm/hsm-fns.ts | 2 +- .../platform/kms/hsm-integration.mdx | 508 +++++++++++++++++- 2 files changed, 501 insertions(+), 9 deletions(-) diff --git a/backend/src/ee/services/hsm/hsm-fns.ts b/backend/src/ee/services/hsm/hsm-fns.ts index 8eec7ceb7..54c2f5f23 100644 --- a/backend/src/ee/services/hsm/hsm-fns.ts +++ b/backend/src/ee/services/hsm/hsm-fns.ts @@ -25,7 +25,7 @@ export const initializeHsmModule = (envConfig: Pick # Replace with the version you want to use + infisical/infisical: # Replace with the version you want to use ``` We recommend reading further about [using Infisical with Docker](/self-hosting/deployment-options/standalone-infisical). @@ -309,7 +308,7 @@ Enabling HSM encryption has a set of key benefits: -e DB_CONNECTION_URI="<>" \ -e REDIS_URL="<>" \ -e SITE_URL="<>" \ - infisical/infisical-fips: # Replace with the version you want to use + infisical/infisical: # Replace with the version you want to use ``` @@ -319,6 +318,192 @@ Enabling HSM encryption has a set of key benefits: After following these steps, your Docker setup will be ready to use Fortanix HSM encryption. + + + + + + ### Prerequisites + + - An [activated AWS CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) with at least 1 HSM device. + - A [HSM user with the `Crypto User` role](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html). In this guide we are using a user with the username `testUser` and the password `testPassword`. + + + + + + Before using the CloudHSM client, it must be configured properly so Infisical can use it for cryptographic operations. + + + **1. Download the AWS CloudHSM client** + + You can download the AWS CloudHSM client from [the AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-library-install.html). + + + Note that the AWS CloudHSM client is only available for Linux and Windows. + If you're on a different operating system, you'll need to access a Linux machine to configure the client, such as an AWS EC2 Debian instance. + + + **2. Configure the CloudHSM client** + + After installing the CloudHSM client, you should see all related files in the `/opt/cloudhsm/` directory on your machine. + + You need to run the `configure-pkcs11` binary which will configure the client to connect with your AWS CloudHSM cluster. Depending on if you have multiple HSM's inside your cluster, you'll need to run the command with different arguments. Below you'll find the appropriate command for your use case: + + + + + + ```bash + sudo /opt/cloudhsm/bin/configure-pkcs11 -a --disable-key-availability-check + ``` + + + To use a single HSM, you must first manage client key durability settings by setting `disable_key_availability_check` to true by passing the `--disable-key-availability-check` flag. For more information read the [Key Synchronization](https://docs.aws.amazon.com/cloudhsm/latest/userguide/manage-key-sync.html) section in the AWS CloudHSM documentation. + + + + + ```bash + sudo /opt/cloudhsm/bin/configure-pkcs11 -a ... --disable-key-availability-check + ``` + + + + At this point it is assumed that you have: + 1. [Activated the CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) + 2. [Created a Crypto User HSM user](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html) + 3. Downloaded and configured the CloudHSM client as described in the previous steps. + + **3. Download the configured HSM client files** + + After configuring the CloudHSM client, you should notice that the PKCS11 configuration file has been updated to include the HSM's ENI IP address. You can find this file in the `/opt/cloudhsm/etc/cloudhsm-pkcs11.cfg` directory, and it should look like this: + + ```json cloudhsm-pkcs11.cfg + { + "clusters": [ + { + "type": "hsm1", + "cluster": { + // Your issuing CA certificate. + // As per AWS documentation, this defaults to `/opt/cloudhsm/etc/customerCA.crt`. + "hsm_ca_file": "/opt/cloudhsm/etc/customerCA.crt", + "servers": [ + { + "hostname": "", + "port": 2223, + "enable": true + }, + { + "hostname": "", + "port": 2223, + "enable": true + } + ], + // Only relevant if you passed the --disable-key-availability-check flag + "options": { + "disable_key_availability_check": true + } + } + } + ], + "logging": { + "log_type": "file", + "log_file": "/opt/cloudhsm/run/cloudhsm-pkcs11.log", + "log_level": "info", + "log_interval": "daily" + } + } + ``` + + Save the entire `/opt/cloudhsm` folder, as you will need to mount this to your Infisical Docker container in the later steps. In this guide we will be saving all the files from the folder as `/etc/cloudhsm` and mounting it to the `/etc/cloudhsm` directory in the Docker container. + + + + + On the same machine that you configured the CloudHSM client, you can use `pkcs11-tool` to find the HSM slot number and to verify that the client is working correctly. + + First, install the `pkcs11-tool` package: + + ```bash + sudo apt-get install opensc -y + ``` + + Then, run the following command to find the HSM slot number: + + ```bash + pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots --login + ``` + + It'll prompt you to log in with your PIN, which is your username and password seperated by a colon. Example: `testUser:testPassword`. + + This will output the HSM slot number like so: + + ```bash + ubuntu@ec-2:~$ pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots + Available slots: + Slot 0 (0x2000000000000001): hsm1 + token label : hsm1 + token manufacturer : Marvell Semiconductors, Inc. + token model : LS2 + token flags : login required, rng, token initialized + hardware version : 66.48 + firmware version : 10.2 + serial num : + pin min/max : 8/32 + ``` + + In this case we see that the HSM has a slot in the position of `0`. This slot number will be used in the later steps to set the `HSM_SLOT` environment variable. + + + + When you initialized your HSM, you were prompted to download the cluster CSR and sign it. + In order to use the HSM with Infisical, you need to obtain the issuer CA certificate that was used to sign the cluster CSR. + + If you followed [the official AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html), you should have a CA certificate called `customerCA.crt`. + + Save the CA certificate to a path, as this will need to be mounted as a Docker volume in the next step. For this example, we'll save it to `/aws-files/customerCA.crt`. + + + + Running Docker with HSM encryption requires setting the HSM-related environment variables as mentioned previously in the [HSM setup instructions](#setup-instructions). You can set these environment variables in your Docker run command. + + We are setting the environment variables for Docker via the command line in this example, but you can also pass in a `.env` file to set these environment variables. + + + If no key is found with the provided key label, the HSM will create a new key with the provided label. + Infisical depends on an AES and HMAC key to be present in the HSM. If these keys are not present, Infisical will create them. The AES key label will be the value of the `HSM_KEY_LABEL` environment variable, and the HMAC key label will be the value of the `HSM_KEY_LABEL` environment variable with the suffix `_HMAC`. + + + ```bash + docker run -p 80:8080 \ + + # Mount the HSM client files to "/opt/cloudhsm" + -v /etc/cloudhsm:/opt/cloudhsm \ + # Mount the issuer CA certificate to "/opt/cloudhsm/etc/customerCA.crt" + -v /aws-files/customerCA.crt:/opt/cloudhsm/etc/customerCA.crt \ + + # Set the HSM library path to whats expected within Docker (/opt/cloudhsm/lib/libcloudhsm_pkcs11.so) + -e HSM_LIB_PATH="/opt/cloudhsm/lib/libcloudhsm_pkcs11.so" \ + # Set the HSM PIN to the username and password of the HSM user, seperated by a colon + -e HSM_PIN=CryptoUserUsername:CryptoUserPassword \ + # Set the HSM slot number to the slot number of the HSM device as found in the previous step + -e HSM_SLOT= \ + # Set the HSM key label to a label that will be used to identify the encryption key in the HSM. This key label does not need to exist before hand. + -e HSM_KEY_LABEL=infisical-crypto-key \ + + # The rest of your environment variables ... + # -e ... + infisical/infisical: # Replace with the version you want to use + ``` + + We recommend reading further about [using Infisical with Docker](/self-hosting/deployment-options/standalone-infisical). + + + + After following these steps, your Docker setup will be ready to use HSM encryption. + + @@ -326,6 +511,7 @@ Enabling HSM encryption has a set of key benefits: + This is only supported on helm chart version `1.4.1` and above. Please see the [Helm Chart Changelog](https://github.com/Infisical/infisical/blob/main/helm-charts/infisical-standalone-postgres/CHANGELOG.md#141-march-19-2025) for more information. @@ -591,13 +777,11 @@ Enabling HSM encryption has a set of key benefits: After we've successfully configured the PVC and updated our environment variables, we are ready to update the deployment configuration so that the pods it creates can access the HSM client files. - We need to update the Docker image of the deployment to use `infisical/infisical-fips`. The `infisical/infisical-fips` image is a functionally identical image to the `infisical/infisical` image, but it is built with HSM support. - ```yaml # ... The rest of the values.yaml file ... image: - repository: infisical/infisical-fips # Very important: Must use "infisical/infisical-fips" + repository: infisical/infisical tag: "v0.117.1-postgres" pullPolicy: IfNotPresent @@ -757,13 +941,13 @@ Enabling HSM encryption has a set of key benefits: - Update your Helm values to use the FIPS-compliant image and mount the Fortanix HSM files: + Update your Helm values to mount the Fortanix HSM files: ```yaml # ... The rest of the values.yaml file ... image: - repository: infisical/infisical-fips # Must use "infisical/infisical-fips" + repository: infisical/infisical tag: "v0.117.1-postgres" pullPolicy: IfNotPresent @@ -800,6 +984,314 @@ Enabling HSM encryption has a set of key benefits: After following these steps, your Kubernetes setup will be ready to use Fortanix HSM encryption. + + + + ### Prerequisites + + - An [activated AWS CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) with at least 1 HSM device. + - A [HSM user with the `Crypto User` role](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html). In this guide we are using a user with the username `testUser` and the password `testPassword`. + - A Kubernetes cluster + + + AWS CloudHSM is supported on helm chart version `1.4.1` and above. Please see the [Helm Chart Changelog](https://github.com/Infisical/infisical/blob/main/helm-charts/infisical-standalone-postgres/CHANGELOG.md#141-march-19-2025) for more information. + + + + + + Before using the CloudHSM client with Kubernetes, it must be configured properly so Infisical can use it for cryptographic operations. + + **1. Download and configure the AWS CloudHSM client** + + You can download the AWS CloudHSM client from [the AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-library-install.html). + + + Note that the AWS CloudHSM client is only available for Linux and Windows. + If you're on a different operating system, you'll need to access a Linux machine to configure the client, such as an AWS EC2 Debian instance. + + + After installing the CloudHSM client, you should see all related files in the `/opt/cloudhsm/` directory on your machine. + + You need to run the `configure-pkcs11` binary which will configure the client to connect with your AWS CloudHSM cluster. Depending on if you have multiple HSM's inside your cluster, you'll need to run the command with different arguments. Below you'll find the appropriate command for your use case: + + + + + ```bash + sudo /opt/cloudhsm/bin/configure-pkcs11 -a --disable-key-availability-check + ``` + + + To use a single HSM, you must first manage client key durability settings by setting `disable_key_availability_check` to true by passing the `--disable-key-availability-check` flag. For more information read the [Key Synchronization](https://docs.aws.amazon.com/cloudhsm/latest/userguide/manage-key-sync.html) section in the AWS CloudHSM documentation. + + + + + ```bash + sudo /opt/cloudhsm/bin/configure-pkcs11 -a ... --disable-key-availability-check + ``` + + + + At this point it is assumed that you have: + 1. [Activated the CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) + 2. [Created a Crypto User HSM user](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html) + 3. Downloaded and configured the CloudHSM client as described in the previous steps. + + **2. Verify the configuration file** + + After configuring the CloudHSM client, you should notice that the PKCS11 configuration file has been updated to include the HSM's ENI IP address. You can find this file in the `/opt/cloudhsm/etc/cloudhsm-pkcs11.cfg` directory, and it should look like this: + + ```json cloudhsm-pkcs11.cfg + { + "clusters": [ + { + "type": "hsm1", + "cluster": { + // Your issuing CA certificate. + // As per AWS documentation, this defaults to `/opt/cloudhsm/etc/customerCA.crt`. + "hsm_ca_file": "/opt/cloudhsm/etc/customerCA.crt", + "servers": [ + { + "hostname": "", + "port": 2223, + "enable": true + }, + { + "hostname": "", + "port": 2223, + "enable": true + } + ], + // Only relevant if you passed the --disable-key-availability-check flag + "options": { + "disable_key_availability_check": true + } + } + } + ], + "logging": { + "log_type": "file", + "log_file": "/opt/cloudhsm/run/cloudhsm-pkcs11.log", + "log_level": "info", + "log_interval": "daily" + } + } + ``` + + **3. Copy the CloudHSM client files to a staging directory** + + Create a directory to stage the CloudHSM client files for Kubernetes: + + ```bash + mkdir -p /etc/cloudhsm-k8s + ``` + + Copy the entire `/opt/cloudhsm` directory to your staging location: + + ```bash + cp -r /opt/cloudhsm/* /etc/cloudhsm-k8s/ + ``` + + Ensure the configuration file paths are correct. The `cloudhsm-pkcs11.cfg` file should reference `/opt/cloudhsm/etc/customerCA.crt` as shown above, since this is where files will be mounted inside the Kubernetes container. + + + + + On the same machine that you configured the CloudHSM client, you can use `pkcs11-tool` to find the HSM slot number and to verify that the client is working correctly. + + First, install the `pkcs11-tool` package: + + ```bash + sudo apt-get install opensc -y + ``` + + Then, run the following command to find the HSM slot number: + + ```bash + pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots --login + ``` + + It'll prompt you to log in with your PIN, which is your username and password separated by a colon. Example: `testUser:testPassword`. + + This will output the HSM slot number like so: + + ```bash + ubuntu@ec-2:~$ pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots + Available slots: + Slot 0 (0x2000000000000001): hsm1 + token label : hsm1 + token manufacturer : Marvell Semiconductors, Inc. + token model : LS2 + token flags : login required, rng, token initialized + hardware version : 66.48 + firmware version : 10.2 + serial num : + pin min/max : 8/32 + ``` + + In this case we see that the HSM has a slot in the position of `0`. This slot number will be used in the later steps to set the `HSM_SLOT` environment variable. + + + + When you initialized your HSM, you were prompted to download the cluster CSR and sign it. + In order to use the HSM with Infisical, you need to obtain the issuer CA certificate that was used to sign the cluster CSR. + + If you followed [the official AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html), you should have a CA certificate called `customerCA.crt`. + + Copy the CA certificate to your staging directory: + + ```bash + cp /path/to/customerCA.crt /etc/cloudhsm-k8s/etc/customerCA.crt + ``` + + Ensure the file is at `/etc/cloudhsm-k8s/etc/customerCA.crt` as this is what the configuration file expects. + + + + You need to create a Persistent Volume Claim (PVC) to mount the HSM client files to the Infisical deployment. + + ```bash + kubectl apply -f - < + + + Next we need to update the environment variables used for the deployment. If you followed the [setup instructions for Kubernetes deployments](/self-hosting/deployment-options/kubernetes-helm), you should have a Kubernetes secret called `infisical-secrets`. + We need to update the secret with the following environment variables: + + - `HSM_LIB_PATH` - The path to the CloudHSM PKCS#11 library _(mapped to `/opt/cloudhsm/lib/libcloudhsm_pkcs11.so`)_ + - `HSM_PIN` - The PIN for the HSM device, which is the username and password of your Crypto User separated by a colon (e.g., `testUser:testPassword`) + - `HSM_SLOT` - The slot number for the HSM device that you found in the previous step + - `HSM_KEY_LABEL` - The label for the HSM key. If no key is found with the provided key label, the HSM will create a new key with the provided label. + + The following is an example of the secret that you should update: + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: infisical-secrets + type: Opaque + stringData: + # ... Other environment variables ... + HSM_LIB_PATH: "/opt/cloudhsm/lib/libcloudhsm_pkcs11.so" + HSM_PIN: "testUser:testPassword" # Replace with your actual Crypto User credentials + HSM_SLOT: "0" # Replace with your actual slot number + HSM_KEY_LABEL: "infisical-crypto-key" + ``` + + Save the file after updating the environment variables, and apply the secret changes + + ```bash + kubectl apply -f ./secret-file-name.yaml + ``` + + + + After we've successfully configured the PVC and updated our environment variables, we are ready to update the deployment configuration so that the pods it creates can access the HSM client files. + + ```yaml + # ... The rest of the values.yaml file ... + + image: + repository: infisical/infisical + tag: "v0.117.1-postgres" + pullPolicy: IfNotPresent + + extraVolumeMounts: + - name: cloudhsm-data + mountPath: /opt/cloudhsm # The path we will mount the HSM client files to + + extraVolumes: + - name: cloudhsm-data + persistentVolumeClaim: + claimName: cloudhsm-data-pvc # The PVC we created in the previous step + + # ... The rest of the values.yaml file ... + ``` + + + Ensure that the configuration file at `/opt/cloudhsm/etc/cloudhsm-pkcs11.cfg` references the correct path for the issuer CA certificate (`/opt/cloudhsm/etc/customerCA.crt`). This should already be configured correctly if you followed the previous steps. + + + + + + After updating the values.yaml file, you need to upgrade the Helm chart in order for the changes to take effect. + + ```bash + helm upgrade --install infisical infisical-helm-charts/infisical-standalone --values /path/to/values.yaml + ``` + + + After upgrading the Helm chart, you need to restart the deployment in order for the changes to take effect. + + ```bash + kubectl rollout restart deployment/infisical-infisical + ``` + + + After following these steps, your Kubernetes setup will be ready to use AWS CloudHSM encryption. + From 1418da5c36c1cf2de61b0675dba8e5890ac4e513 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Fri, 10 Oct 2025 18:18:52 +0530 Subject: [PATCH 03/22] fix: review changes --- frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx index 75c240ffb..c05d2e398 100644 --- a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx +++ b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx @@ -158,7 +158,7 @@ export const CreateTagModal = ({ isOpen, onToggle, append, currentSecret }: Prop title={currentSecret ? `Create tag for ${currentSecret.key}` : "Create tag"} subTitle={ currentSecret - ? "Create a new tag and it will be automatically added to this secret." + ? `Create a new tag, and it will be automatically linked to secret: ${currentSecret.key}.` : "Specify your tag name, and the slug will be created automatically." } > From 9e60350b89a38e5cd5c72235c4b6fbb7dad89db7 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Fri, 10 Oct 2025 16:50:55 +0400 Subject: [PATCH 04/22] Update hsm-integration.mdx --- .../platform/kms/hsm-integration.mdx | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/documentation/platform/kms/hsm-integration.mdx b/docs/documentation/platform/kms/hsm-integration.mdx index 2c6f40090..a0677f48a 100644 --- a/docs/documentation/platform/kms/hsm-integration.mdx +++ b/docs/documentation/platform/kms/hsm-integration.mdx @@ -370,7 +370,7 @@ Enabling HSM encryption has a set of key benefits: - At this point it is assumed that you have: + At this point you should have: 1. [Activated the CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) 2. [Created a Crypto User HSM user](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html) 3. Downloaded and configured the CloudHSM client as described in the previous steps. @@ -1034,7 +1034,7 @@ Enabling HSM encryption has a set of key benefits: - At this point it is assumed that you have: + At this point you should have: 1. [Activated the CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) 2. [Created a Crypto User HSM user](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html) 3. Downloaded and configured the CloudHSM client as described in the previous steps. @@ -1251,20 +1251,20 @@ Enabling HSM encryption has a set of key benefits: ```yaml # ... The rest of the values.yaml file ... - - image: - repository: infisical/infisical - tag: "v0.117.1-postgres" - pullPolicy: IfNotPresent + infisical: + image: + repository: infisical/infisical + tag: "v0.117.1-postgres" + pullPolicy: IfNotPresent - extraVolumeMounts: - - name: cloudhsm-data - mountPath: /opt/cloudhsm # The path we will mount the HSM client files to + extraVolumeMounts: + - name: cloudhsm-data + mountPath: /opt/cloudhsm # The path we will mount the HSM client files to - extraVolumes: - - name: cloudhsm-data - persistentVolumeClaim: - claimName: cloudhsm-data-pvc # The PVC we created in the previous step + extraVolumes: + - name: cloudhsm-data + persistentVolumeClaim: + claimName: cloudhsm-data-pvc # The PVC we created in the previous step # ... The rest of the values.yaml file ... ``` @@ -1279,6 +1279,7 @@ Enabling HSM encryption has a set of key benefits: After updating the values.yaml file, you need to upgrade the Helm chart in order for the changes to take effect. ```bash + helm repo update helm upgrade --install infisical infisical-helm-charts/infisical-standalone --values /path/to/values.yaml ``` From 8c50c5adf23b2d2750966b3cf1104d700035f69a Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Mon, 13 Oct 2025 09:18:32 -0300 Subject: [PATCH 05/22] Add missing projectId to useMoveSecrets mutation --- frontend/src/hooks/api/secrets/mutations.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/hooks/api/secrets/mutations.tsx b/frontend/src/hooks/api/secrets/mutations.tsx index 5c1986b21..989dacfca 100644 --- a/frontend/src/hooks/api/secrets/mutations.tsx +++ b/frontend/src/hooks/api/secrets/mutations.tsx @@ -337,7 +337,8 @@ export const useMoveSecrets = ({ destinationSecretPath, secretIds, shouldOverwrite, - projectSlug + projectSlug, + projectId }) => { const { data } = await apiRequest.post<{ isSourceUpdated: boolean; @@ -349,7 +350,8 @@ export const useMoveSecrets = ({ destinationSecretPath, secretIds, shouldOverwrite, - projectSlug + projectSlug, + projectId }); return data; From 8ea569c68a0d019181b763c595729891840ed192 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Mon, 13 Oct 2025 18:29:28 +0530 Subject: [PATCH 06/22] fix: docs dev command --- docs/CONTRIBUTING.MD | 6 +++--- docs/contributing/platform/developing.mdx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/CONTRIBUTING.MD b/docs/CONTRIBUTING.MD index a74f0985e..b43137f28 100644 --- a/docs/CONTRIBUTING.MD +++ b/docs/CONTRIBUTING.MD @@ -1,8 +1,8 @@ # Contributing to the documentation ## Getting familiar with Mintlify -New to Mintlify. [Start Here](https://mintlify.com/docs/quickstart) +New to Mintlify. [Start Here](https://mintlify.com/docs/quickstart) ## 👩‍💻 Development @@ -15,10 +15,10 @@ npm i -g mintlify Run the following command at the root of your documentation (where mint.json is) ``` -mintlify dev +mint dev ``` ## Troubleshooting -- Mintlify dev isn't running - Run `mintlify install` it'll re-install dependencies. +- Mint dev isn't running - Run `mintlify install` it'll re-install dependencies. - Page loads as a 404 - Make sure you are running in a folder with `mint.json`. Check the `/docs` folder diff --git a/docs/contributing/platform/developing.mdx b/docs/contributing/platform/developing.mdx index 68add4603..2df137237 100644 --- a/docs/contributing/platform/developing.mdx +++ b/docs/contributing/platform/developing.mdx @@ -57,9 +57,9 @@ yarn global add mintlify #### Running the docs -Go to `docs` directory and run `mintlify dev`. This will start up the docs on `localhost:3000` +Go to `docs` directory and run `mint dev`. This will start up the docs on `localhost:3000` ```bash # From the root directory -cd docs; mintlify dev; +cd docs; mint dev; ``` From f33424141b9f987a36a02ae8f674077ccccb03bc Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Mon, 13 Oct 2025 18:31:33 +0530 Subject: [PATCH 07/22] fix: update troubleshooting instructions in CONTRIBUTING.md --- docs/CONTRIBUTING.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.MD b/docs/CONTRIBUTING.MD index b43137f28..71d2e30ae 100644 --- a/docs/CONTRIBUTING.MD +++ b/docs/CONTRIBUTING.MD @@ -20,5 +20,5 @@ mint dev ## Troubleshooting -- Mint dev isn't running - Run `mintlify install` it'll re-install dependencies. +- `mint dev` isn't running - Run `mintlify install` it'll re-install dependencies. - Page loads as a 404 - Make sure you are running in a folder with `mint.json`. Check the `/docs` folder From 928829ac3e179920c2abd7f0985dfe2d5ee66493 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Mon, 13 Oct 2025 23:53:53 +0530 Subject: [PATCH 08/22] fix: mint CLI commands --- docs/CONTRIBUTING.MD | 6 +++--- docs/contributing/platform/developing.mdx | 6 +++--- package.json | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/CONTRIBUTING.MD b/docs/CONTRIBUTING.MD index 71d2e30ae..6983ad8f4 100644 --- a/docs/CONTRIBUTING.MD +++ b/docs/CONTRIBUTING.MD @@ -6,10 +6,10 @@ New to Mintlify. [Start Here](https://mintlify.com/docs/quickstart) ## 👩‍💻 Development -Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command +Install the [Mint CLI](https://www.npmjs.com/package/mint) to preview the documentation changes locally. To install, use the following command ``` -npm i -g mintlify +npm i -g mint ``` Run the following command at the root of your documentation (where mint.json is) @@ -20,5 +20,5 @@ mint dev ## Troubleshooting -- `mint dev` isn't running - Run `mintlify install` it'll re-install dependencies. +- `mint dev` isn't running - Run `mint update` to update the Mint CLI. - Page loads as a 404 - Make sure you are running in a folder with `mint.json`. Check the `/docs` folder diff --git a/docs/contributing/platform/developing.mdx b/docs/contributing/platform/developing.mdx index 2df137237..69710baf3 100644 --- a/docs/contributing/platform/developing.mdx +++ b/docs/contributing/platform/developing.mdx @@ -43,16 +43,16 @@ docker compose -f docker-compose.dev.yml down We use [Mintlify](https://mintlify.com/) for our docs. -#### Install Mintlify CLI. +#### Install Mint CLI. ```bash -npm i -g mintlify +npm i -g mint ``` or ```bash -yarn global add mintlify +yarn global add mint ``` #### Running the docs diff --git a/package.json b/package.json index db15de3fb..c5c99d7ab 100644 --- a/package.json +++ b/package.json @@ -26,5 +26,6 @@ "dependencies": { "@radix-ui/react-radio-group": "^1.1.3", "secrets.js-grempe": "^2.0.0" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } From 17291721eb9cd233893beef436967bd58aa16cd4 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Mon, 13 Oct 2025 23:54:45 +0530 Subject: [PATCH 09/22] chore: refactor --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index c5c99d7ab..db15de3fb 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,5 @@ "dependencies": { "@radix-ui/react-radio-group": "^1.1.3", "secrets.js-grempe": "^2.0.0" - }, - "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" + } } From f2ba1048f3eaa84c15cb8cdf847a0909e0a00c23 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 13 Oct 2025 23:16:37 +0400 Subject: [PATCH 10/22] Update hsm-fns.ts --- backend/src/ee/services/hsm/hsm-fns.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/ee/services/hsm/hsm-fns.ts b/backend/src/ee/services/hsm/hsm-fns.ts index 8eec7ceb7..54c2f5f23 100644 --- a/backend/src/ee/services/hsm/hsm-fns.ts +++ b/backend/src/ee/services/hsm/hsm-fns.ts @@ -25,7 +25,7 @@ export const initializeHsmModule = (envConfig: Pick Date: Mon, 13 Oct 2025 23:42:56 +0400 Subject: [PATCH 11/22] Update hsm-integration.mdx --- .../platform/kms/hsm-integration.mdx | 519 ++++++++++++------ 1 file changed, 354 insertions(+), 165 deletions(-) diff --git a/docs/documentation/platform/kms/hsm-integration.mdx b/docs/documentation/platform/kms/hsm-integration.mdx index a0677f48a..b5dcbf1c3 100644 --- a/docs/documentation/platform/kms/hsm-integration.mdx +++ b/docs/documentation/platform/kms/hsm-integration.mdx @@ -999,157 +999,135 @@ Enabling HSM encryption has a set of key benefits: - - Before using the CloudHSM client with Kubernetes, it must be configured properly so Infisical can use it for cryptographic operations. - - **1. Download and configure the AWS CloudHSM client** - - You can download the AWS CloudHSM client from [the AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-library-install.html). - - - Note that the AWS CloudHSM client is only available for Linux and Windows. - If you're on a different operating system, you'll need to access a Linux machine to configure the client, such as an AWS EC2 Debian instance. - - - After installing the CloudHSM client, you should see all related files in the `/opt/cloudhsm/` directory on your machine. - - You need to run the `configure-pkcs11` binary which will configure the client to connect with your AWS CloudHSM cluster. Depending on if you have multiple HSM's inside your cluster, you'll need to run the command with different arguments. Below you'll find the appropriate command for your use case: - - - - - ```bash - sudo /opt/cloudhsm/bin/configure-pkcs11 -a --disable-key-availability-check - ``` - - - To use a single HSM, you must first manage client key durability settings by setting `disable_key_availability_check` to true by passing the `--disable-key-availability-check` flag. For more information read the [Key Synchronization](https://docs.aws.amazon.com/cloudhsm/latest/userguide/manage-key-sync.html) section in the AWS CloudHSM documentation. - - - - - ```bash - sudo /opt/cloudhsm/bin/configure-pkcs11 -a ... --disable-key-availability-check - ``` - - - - At this point you should have: - 1. [Activated the CloudHSM cluster](https://docs.aws.amazon.com/cloudhsm/latest/userguide/activate-cluster.html) - 2. [Created a Crypto User HSM user](https://docs.aws.amazon.com/cloudhsm/latest/userguide/cloudhsm_cli-user-create.html) - 3. Downloaded and configured the CloudHSM client as described in the previous steps. - - **2. Verify the configuration file** - - After configuring the CloudHSM client, you should notice that the PKCS11 configuration file has been updated to include the HSM's ENI IP address. You can find this file in the `/opt/cloudhsm/etc/cloudhsm-pkcs11.cfg` directory, and it should look like this: - - ```json cloudhsm-pkcs11.cfg - { - "clusters": [ - { - "type": "hsm1", - "cluster": { - // Your issuing CA certificate. - // As per AWS documentation, this defaults to `/opt/cloudhsm/etc/customerCA.crt`. - "hsm_ca_file": "/opt/cloudhsm/etc/customerCA.crt", - "servers": [ - { - "hostname": "", - "port": 2223, - "enable": true - }, - { - "hostname": "", - "port": 2223, - "enable": true - } - ], - // Only relevant if you passed the --disable-key-availability-check flag - "options": { - "disable_key_availability_check": true - } - } - } - ], - "logging": { - "log_type": "file", - "log_file": "/opt/cloudhsm/run/cloudhsm-pkcs11.log", - "log_level": "info", - "log_interval": "daily" - } - } - ``` - - **3. Copy the CloudHSM client files to a staging directory** - - Create a directory to stage the CloudHSM client files for Kubernetes: - - ```bash - mkdir -p /etc/cloudhsm-k8s - ``` - - Copy the entire `/opt/cloudhsm` directory to your staging location: - - ```bash - cp -r /opt/cloudhsm/* /etc/cloudhsm-k8s/ - ``` - - Ensure the configuration file paths are correct. The `cloudhsm-pkcs11.cfg` file should reference `/opt/cloudhsm/etc/customerCA.crt` as shown above, since this is where files will be mounted inside the Kubernetes container. - - - - - On the same machine that you configured the CloudHSM client, you can use `pkcs11-tool` to find the HSM slot number and to verify that the client is working correctly. - - First, install the `pkcs11-tool` package: - - ```bash - sudo apt-get install opensc -y - ``` - - Then, run the following command to find the HSM slot number: - - ```bash - pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots --login - ``` - - It'll prompt you to log in with your PIN, which is your username and password separated by a colon. Example: `testUser:testPassword`. - - This will output the HSM slot number like so: - - ```bash - ubuntu@ec-2:~$ pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots - Available slots: - Slot 0 (0x2000000000000001): hsm1 - token label : hsm1 - token manufacturer : Marvell Semiconductors, Inc. - token model : LS2 - token flags : login required, rng, token initialized - hardware version : 66.48 - firmware version : 10.2 - serial num : - pin min/max : 8/32 - ``` - - In this case we see that the HSM has a slot in the position of `0`. This slot number will be used in the later steps to set the `HSM_SLOT` environment variable. - - - - When you initialized your HSM, you were prompted to download the cluster CSR and sign it. - In order to use the HSM with Infisical, you need to obtain the issuer CA certificate that was used to sign the cluster CSR. - - If you followed [the official AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html), you should have a CA certificate called `customerCA.crt`. - - Copy the CA certificate to your staging directory: - - ```bash - cp /path/to/customerCA.crt /etc/cloudhsm-k8s/etc/customerCA.crt - ``` - - Ensure the file is at `/etc/cloudhsm-k8s/etc/customerCA.crt` as this is what the configuration file expects. - - + + If you're using AWS EKS, you need to specify a storage class for the PVC and ensure that the EBS CSI Driver is installed and running. + + By default, EKS exposes `gp2` as the default storage class. Below are the steps required for setting the default storage class and ensuring the EBS CSI Driver is installed and running: + + + + + + Enable OIDC authentication for the EKS cluster: + ```bash + eksctl utils associate-iam-oidc-provider \ + --region \ + --cluster \ + --approve + ``` + + * Replace `` with your AWS region. + * Replace `` with your cluster name. + + + + + + 1. Check if EBS CSI Driver is installed and running by running the following command: + + ```bash + kubectl get pods -n kube-system | grep ebs-csi + ``` + + If you see no pods, you need to install the EBS CSI Driver as seen in the next step. + + + + Create a new IAM service account for the EBS CSI Driver: + + ```bash + eksctl create iamserviceaccount \ + --name ebs-csi-controller-sa \ + --namespace kube-system \ + --region \ + --cluster \ + --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \ + --approve \ + --role-only \ + --role-name AmazonEKS_EBS_CSI_DriverRole + ``` + + * Replace `` with your cluster name. + * Replace `` with your AWS region. + + Install the EBS CSI Driver: + + ```bash + eksctl create addon \ + --name aws-ebs-csi-driver \ + --cluster \ + --region \ + --service-account-role-arn arn:aws:iam:::role/AmazonEKS_EBS_CSI_DriverRole \ + --force + ``` + + * Replace `` with your cluster name. + * Replace `` with your AWS region. + * Replace `` with your actual account ID. Can be obtained by running `aws sts get-caller-identity --query Account --output text`. + + + + Verify the EBS CSI Driver is installed and running by running the following command: + + ```bash + kubectl get pods -n kube-system | grep ebs-csi + ``` + + You should see an output like this: + + ```bash + kubectl get pods -n kube-system | grep ebs-csi + ebs-csi-controller-6b6bbf996-rvf8r 6/6 Running 0 21s + ebs-csi-controller-6b6bbf996-vk4ng 6/6 Running 0 21s + ebs-csi-node-c6vbb 3/3 Running 0 21s + ebs-csi-node-s9zlr 3/3 Running 0 21s + ``` + + + + You can find the enabled storage class by running the following command: + + ```bash + kubectl get storageclass + ``` + + You should see an output like this: + + ```bash + $ kubectl get storageclass + + NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE + gp2 kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 65m + ``` + + In this case, the enabled storage class is `gp2`. + + + + You can set the default PVC storage class by patching the storage class with the following command: + + ```bash + kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' + ``` + + This will set the `gp2` storage class as the default storage class. + + + Now when you run `kubectl get storageclass`, you should see that `gp2` is the default storage class. + + ```bash + $ kubectl get storageclass + + NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE + gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 68m + ``` + + Notice the `(default)` next to the `gp2` storage class. + + + + You need to create a Persistent Volume Claim (PVC) to mount the HSM client files to the Infisical deployment. ```bash @@ -1179,8 +1157,8 @@ Enabling HSM encryption has a set of key benefits: spec: containers: - name: setup - image: busybox - command: ["/bin/sh", "-c", "sleep 3600"] + image: debian:bookworm + command: ["/bin/sh", "-c", "sleep 7200"] volumeMounts: - name: cloudhsm-data mountPath: /data @@ -1191,27 +1169,226 @@ Enabling HSM encryption has a set of key benefits: EOF ``` - The above command will create a pod named `cloudhsm-setup-pod` with a busybox image. The pod will sleep for 3600 seconds _(one hour)_, which is enough time to upload the HSM client files to the PVC. + The above command will create a pod named `cloudhsm-setup-pod` with a Debian image. The pod will sleep for 7200 seconds _(two hours)_, which is enough time to set up the PVC and configure the HSM client. Ensure that the pod is running and is healthy by running the following command: ```bash - kubectl wait --for=condition=Ready pod/cloudhsm-setup-pod --timeout=60s + kubectl wait --for=condition=Ready pod/cloudhsm-setup-pod --timeout=120s ``` + - Next we need to copy the HSM client files into the PVC. + - ```bash - kubectl exec cloudhsm-setup-pod -- mkdir -p /data/ # Create the data directory - kubectl cp /etc/cloudhsm-k8s/. cloudhsm-setup-pod:/data/ # Copy the HSM client files into the PVC - kubectl exec cloudhsm-setup-pod -- chmod -R 755 /data/ # Set the correct permissions for the HSM client files - ``` + We need to configure the PVC to work with the CloudHSM, so Infiscial can consume the HSM client files. - Finally, we are ready to delete the temporary pod, as we have successfully uploaded the HSM client files to the PVC. This step may take a few minutes to complete. + **2.1. Start a shell in the PVC pod:** + + This will allow us to run commands directly within the setup pod. We'll use this to configure the CloudHSM client and to validate that it's working correctly. + + ```bash + kubectl exec -it cloudhsm-setup-pod -- /bin/sh + ``` + + **2.2. Create the data directory:** + + This will create a directory called `/data/` within the setup pod. This directory will remain even after the setup pod is deleted, as it's mounted as a volume from the PVC. + + ```bash + mkdir -p /data/ + ``` + + **2.3. Install the necessary packages:** + + This will install the necessary packages to allow us to test and install the CloudHSM client. + + ```bash + apt-get update -y + apt-get install opensc telnet wget -y + ``` + + **2.4. Try to reach the HSM device:** + + We need to validate that we're able to reach the HSM device from within Kubernetes. You can use telnet to ping the HSM device like so: + + ```bash + telnet 2223 + ``` + + You should see an output like this: + ```bash + $ telnet 2223 + Trying ... + Connected to . + ``` + + If it gets stuck on `Trying ....`, you may have configured your HSM client's security group incorrectly. Make sure you configure the security group to allow traffic from EKS on port 2223-2225. + + **2.5. Install the AWS CloudHSM client:** + + The Infisical images run on Debian, so we need to install a Debian-compatible version of the AWS CloudHSM client. + + ```bash + wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/Jammy/cloudhsm-pkcs11_latest_u22.04_amd64.deb + apt-get install ./cloudhsm-pkcs11_latest_u22.04_amd64.deb -y + ``` + + **2.6. Configure the CloudHSM client:** + + After installing the CloudHSM client, you should see all related files in the `/opt/cloudhsm/` directory on the CloudHSM setup pod. + + You need to run the `configure-pkcs11` binary which will configure the client to connect with your AWS CloudHSM cluster. Depending on if you have multiple HSM's inside your cluster, you'll need to run the command with different arguments. Below you'll find the appropriate command for your use case: + + + + + ```bash + /opt/cloudhsm/bin/configure-pkcs11 -a --disable-key-availability-check + ``` + + + To use a single HSM, you must first manage client key durability settings by setting `disable_key_availability_check` to true by passing the `--disable-key-availability-check` flag. For more information read the [Key Synchronization](https://docs.aws.amazon.com/cloudhsm/latest/userguide/manage-key-sync.html) section in the AWS CloudHSM documentation. + + + + + ```bash + /opt/cloudhsm/bin/configure-pkcs11 -a ... --disable-key-availability-check + ``` + + + + **2.7. Verify the CloudHSM client is configured correctly:** + + You can verify the CloudHSM client is configured correctly by running the following command: + ```bash + cat /opt/cloudhsm/etc/cloudhsm-pkcs11.cfg + ``` + + You should see an output like this: + + ```json + { + "clusters": [ + { + "type": "hsm1", + "cluster": { + "hsm_ca_file": "/opt/cloudhsm/etc/customerCA.crt", + "servers": [ + { + "hostname": "172.31.39.155", + "port": 2223, + "enable": true + } + ], + "options": { + "disable_key_availability_check": true + } + } + } + ], + "logging": { + "log_type": "file", + "log_file": "/opt/cloudhsm/run/cloudhsm-pkcs11.log", + "log_level": "info", + "log_interval": "daily" + } + } + ``` + + **2.8. Exit the pod:** + + Exit the pod by running the following command: + ```bash + exit + ``` + + **2.9. Copy your issuer CA certificate to the PVC:** + + When you initialized your HSM, you were prompted to download the cluster CSR and sign it. + In order to use the HSM with Infisical, you need to obtain the issuer CA certificate that was used to sign the cluster CSR. + + If you followed [the official AWS documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html), you should have a CA certificate called `customerCA.crt`. + + Copy the CA certificate from your local machine to the setup pod: + + ```bash + kubectl cp /path/to/customerCA.crt cloudhsm-setup-pod:/opt/cloudhsm/etc/customerCA.crt + ``` + + Ensure that the file is at `/opt/cloudhsm/etc/customerCA.crt` inside the setup pod by running the following command: + ```bash + kubectl exec -it cloudhsm-setup-pod -- cat /opt/cloudhsm/etc/customerCA.crt + ``` + + **2.10. Test the HSM client:** + + Finally, after we're done configuring the HSM client, we need to test it to ensure that it's working correctly. + + First, start a new shell into the setup pod by running the same shell command as before: + ```bash + kubectl exec -it cloudhsm-setup-pod -- /bin/sh + ``` + + Next, try generating a random 32 bytes long string by running the following command: + ```bash + pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so \ + --login --pin : \ + --generate-random 32 | base64 + ``` + + You should see an output like this: + ```bash + Using slot 0 with a present token (0x2000000000000001) + av1dlhVEsssjpcTNS+ysGUoKWH6+/PCaEDIdal5oQc0= + ``` + + + + **2.12. Copy the configured client to the PVC:** + + Copy from the HSM files into the `/data` directory in the PVC, which is what will be mounted for the Infisical deployment. + ```bash + cp -r /opt/cloudhsm/. /data/ + ``` + + Verify the files were copied correctly by running the following command: + ```bash + ls -la /data/ + ``` + + You should see an output like this: + ```bash + drwxr-xr-x. 8 root root 4096 Oct 13 18:50 . + drwxr-xr-x. 1 root root 131 Oct 13 18:29 .. + drwxr-xr-x. 2 root root 4096 Oct 13 18:50 bin + drwxr-xr-x. 3 root root 4096 Oct 13 18:50 doc + drwxr-xr-x. 2 root root 4096 Oct 13 18:50 etc + drwxr-xr-x. 3 root root 4096 Oct 13 18:50 include + drwxr-xr-x. 2 root root 4096 Oct 13 18:50 lib + drwxr-xr-t. 2 root root 4096 Oct 13 18:50 run + ``` + + **2.13. Set the correct permissions for the HSM client files:** + + ```bash + chmod -R 755 /data/ + ``` + + **2.14. Exit the pod:** + + Exit the pod by running the following command: + ```bash + exit + ``` + + **2.15. Delete the setup pod:** + + Delete the setup pod by running the following command: + ```bash + kubectl delete pod cloudhsm-setup-pod + ``` - ```bash - kubectl delete pod cloudhsm-setup-pod - ``` @@ -1304,4 +1481,16 @@ To disable HSM encryption, navigate to Infisical's Server Admin Console and set In order to disable HSM encryption, the Infisical instance must be able to access the HSM device. If the HSM device is no longer accessible, you will not be able to disable HSM encryption. - \ No newline at end of file + + + + +## Troubleshooting + + + + If you're using EKS, you may encounter an error like the following: `no persistent volumes available for this claim and no storage class is set` + + + + \ No newline at end of file From 2c5a9744b257e24fd15c675765ccd41dd930cc35 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 14 Oct 2025 01:39:11 +0400 Subject: [PATCH 12/22] Update hsm-integration.mdx --- docs/documentation/platform/kms/hsm-integration.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/documentation/platform/kms/hsm-integration.mdx b/docs/documentation/platform/kms/hsm-integration.mdx index b5dcbf1c3..2c90e79e7 100644 --- a/docs/documentation/platform/kms/hsm-integration.mdx +++ b/docs/documentation/platform/kms/hsm-integration.mdx @@ -1044,7 +1044,6 @@ Enabling HSM encryption has a set of key benefits: --cluster \ --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \ --approve \ - --role-only \ --role-name AmazonEKS_EBS_CSI_DriverRole ``` From c1ccaaad03da7fe5676dd6d5ede97f02bd303f8f Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Mon, 13 Oct 2025 14:52:21 -0700 Subject: [PATCH 13/22] wip --- frontend/public/locales/en/translations.json | 4 +-- frontend/src/components/v2/Badge/Badge.tsx | 9 ++++++- frontend/src/components/v2/Menu/Menu.tsx | 9 +++++-- .../components/v2/PageHeader/PageHeader.tsx | 25 ++++++++++++++++--- frontend/src/components/v2/Tabs/Tabs.tsx | 12 +++++++-- frontend/src/index.css | 2 ++ frontend/src/layouts/KmsLayout/KmsLayout.tsx | 15 +++++------ .../components/NavBar/Navbar.tsx | 17 +++++++++---- .../components/OrgSidebar/OrgSidebar.tsx | 21 +++++++++------- frontend/src/layouts/PamLayout/PamLayout.tsx | 16 ++++++------ .../PkiManagerLayout/PkiManagerLayout.tsx | 24 +++++++++--------- .../ProjectSelect/ProjectSelect.tsx | 19 ++++++++------ .../SecretManagerLayout.tsx | 20 ++++++++------- .../SecretScanningLayout.tsx | 15 +++++------ frontend/src/layouts/SshLayout/SshLayout.tsx | 15 +++++------ .../AccessManagementPage.tsx | 1 + .../AuthenticationPage/AuthenticationPage.tsx | 1 + .../pages/admin/CachingPage/CachingPage.tsx | 6 ++++- .../admin/EncryptionPage/EncryptionPage.tsx | 1 + .../admin/EnvironmentPage/EnvironmentPage.tsx | 1 + .../pages/admin/GeneralPage/GeneralPage.tsx | 1 + .../IntegrationsPage/IntegrationsPage.tsx | 1 + .../ResourceOverviewPage.tsx | 1 + .../components/UserIdentitiesTable.tsx | 2 +- .../AlertingPage/AlertingPage.tsx | 1 + .../CertAuthDetailsByIDPage.tsx | 2 +- .../CertificateAuthoritiesPage.tsx | 1 + .../CertificatesPage/CertificatesPage.tsx | 1 + .../IntegrationsListPage.tsx | 1 + .../PkiCollectionDetailsByIDPage.tsx | 2 +- .../PkiSubscriberDetailsByIDPage.tsx | 2 +- .../PkiSubscribersPage/PkiSubscribersPage.tsx | 1 + .../PkiTemplateListPage.tsx | 1 + .../SettingsPage/SettingsPage.tsx | 2 +- frontend/src/pages/kms/KmipPage/KmipPage.tsx | 1 + .../pages/kms/OverviewPage/OverviewPage.tsx | 3 ++- .../pages/kms/SettingsPage/SettingsPage.tsx | 2 +- .../AccessManagementPage.tsx | 5 ++-- .../AppConnectionsPage/AppConnectionsPage.tsx | 1 + .../AuditLogsPage/AuditLogsPage.tsx | 3 ++- .../organization/BillingPage/BillingPage.tsx | 3 ++- .../BillingTabGroup/BillingTabGroup.tsx | 4 ++- .../GroupDetailsByIDPage.tsx | 2 +- .../IdentityDetailsByIDPage.tsx | 2 +- .../NetworkingPage/NetworkingPage.tsx | 1 + .../NetworkingTabGroup/NetworkingTabGroup.tsx | 2 +- .../ProjectsPage/ProjectsPage.tsx | 3 ++- .../RoleByIDPage/RoleByIDPage.tsx | 1 + .../SecretSharingPage/SecretSharingPage.tsx | 1 + .../SecretSharingSettingsPage.tsx | 2 +- .../SettingsPage/SettingsPage.tsx | 2 +- .../components/OrgTabGroup/OrgTabGroup.tsx | 2 +- .../UserDetailsByIDPage.tsx | 1 + .../pam/PamAccountsPage/PamAccountsPage.tsx | 6 ++++- .../pam/PamResourcesPage/PamResourcesPage.tsx | 1 + .../PamSessionByIDPage.tsx | 1 + .../pam/PamSessionsPage/PamSessionsPage.tsx | 1 + .../pages/pam/SettingsPage/SettingsPage.tsx | 2 +- .../AccessControlPage/AccessControlPage.tsx | 1 + .../AppConnectionsPage/AppConnectionsPage.tsx | 1 + .../project/AuditLogsPage/AuditLogsPage.tsx | 1 + .../GroupDetailsByIDPage.tsx | 2 +- .../IdentityDetailsByIDPage.tsx | 1 + .../MemberDetailsByIDPage.tsx | 1 + .../RoleDetailsBySlugPage.tsx | 1 + .../CommitDetailsTab/CommitDetailsTab.tsx | 1 + .../RollbackPreviewTab/RollbackPreviewTab.tsx | 1 + .../CommitsPage/CommitsPage.tsx | 1 + .../IntegrationsDetailsByIDPage.tsx | 1 + .../IntegrationsListPage.tsx | 1 + .../OverviewPage/OverviewPage.tsx | 1 + .../SecretApprovalsPage.tsx | 1 + .../SecretDashboardPage.tsx | 1 + .../SecretRotationPage/SecretRotationPage.tsx | 1 + .../SettingsPage/SettingsPage.tsx | 1 + .../SecretScanningDataSourcesPage.tsx | 1 + .../SecretScanningFindingsPage.tsx | 6 ++++- .../SettingsPage/SettingsPage.tsx | 1 + .../pages/ssh/SettingsPage/SettingsPage.tsx | 6 ++++- .../pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx | 2 +- .../src/pages/ssh/SshCasPage/SshCasPage.tsx | 1 + .../pages/ssh/SshCertsPage/SshCertsPage.tsx | 1 + .../SshHostGroupDetailsByIDPage.tsx | 2 +- .../pages/ssh/SshHostsPage/SshHostsPage.tsx | 1 + 84 files changed, 234 insertions(+), 109 deletions(-) diff --git a/frontend/public/locales/en/translations.json b/frontend/public/locales/en/translations.json index fdfefcf93..de3b99f11 100644 --- a/frontend/public/locales/en/translations.json +++ b/frontend/public/locales/en/translations.json @@ -270,7 +270,7 @@ "description": "This page shows the members of the selected project, and allows you to modify their permissions." }, "org": { - "title": "Organization Settings", + "title": "Settings", "description": "Manage members of your organization. These users could afterwards be formed into projects." }, "personal": { @@ -290,7 +290,7 @@ } }, "project": { - "title": "Project Settings", + "title": "Settings", "description": "These settings only apply to the currently selected Project.", "danger-zone": "Danger Zone", "delete-project": "Delete Project", diff --git a/frontend/src/components/v2/Badge/Badge.tsx b/frontend/src/components/v2/Badge/Badge.tsx index f902002c2..51bbdaeaa 100644 --- a/frontend/src/components/v2/Badge/Badge.tsx +++ b/frontend/src/components/v2/Badge/Badge.tsx @@ -17,7 +17,14 @@ const badgeVariants = cva( variant: { primary: "bg-yellow/20 text-yellow", danger: "bg-red/20 text-red", - success: "bg-green/20 text-green" + success: "bg-green/20 text-green", + org: "bg-org-v1/20 text-org-v1 [&_svg]:text-org-v1 flex items-center opacity-100 hover:bg-org-v1/10 [&_svg]:size-3 gap-x-1 w-min whitespace-nowrap", + namespace: + "bg-namespace-v1/20 text-namespace-v1 [&_svg]:text-namespace-v1 flex opacity-100 hover:bg-namespace-v1/10 items-center [&_svg]:size-3.5 gap-x-1 w-min whitespace-nowrap", + project: + "bg-primary/10 text-primary [&_svg]:text-primary opacity-100 hover:bg-primary/10 flex items-center [&_svg]:size-3 gap-x-1 w-min whitespace-nowrap", + instance: + "bg-mineshaft-200/20 text-mineshaft-200 [&_svg]:text-mineshaft-200 opacity-100 hover:bg-mineshaft-200/20 flex items-center [&_svg]:size-3 gap-x-1 w-min whitespace-nowrap" } } } diff --git a/frontend/src/components/v2/Menu/Menu.tsx b/frontend/src/components/v2/Menu/Menu.tsx index 3a222d0e8..29e659f14 100644 --- a/frontend/src/components/v2/Menu/Menu.tsx +++ b/frontend/src/components/v2/Menu/Menu.tsx @@ -33,16 +33,21 @@ export const MenuItem = ({ description, // wrapping in forward ref with generic component causes the loss of ts definitions on props inputRef, + variant, ...props -}: MenuItemProps & ComponentPropsWithRef): JSX.Element => { +}: MenuItemProps & + ComponentPropsWithRef & { variant?: "project" | "namespace" | "org" }): JSX.Element => { return ( ( +const SCOPE_NAME: Record, { label: string; icon: IconDefinition }> = { + org: { label: "Organization", icon: faGlobe }, + project: { label: "Project", icon: faCube }, + namespace: { label: "Namespace", icon: faCubes }, + instance: { label: "Server", icon: faServer } +}; + +export const PageHeader = ({ title, description, children, className, scope }: Props) => (
-
-

{title}

+
+

{title}

+ {scope && ( + + + {SCOPE_NAME[scope].label} + + )}
{children}
diff --git a/frontend/src/components/v2/Tabs/Tabs.tsx b/frontend/src/components/v2/Tabs/Tabs.tsx index 7e8466850..4100fd144 100644 --- a/frontend/src/components/v2/Tabs/Tabs.tsx +++ b/frontend/src/components/v2/Tabs/Tabs.tsx @@ -22,10 +22,18 @@ export const TabList = ({ className, children, ...props }: TabListProps) => ( export type TabProps = TabsPrimitive.TabsTriggerProps; -export const Tab = ({ className, children, ...props }: TabProps) => ( +export const Tab = ({ + className, + children, + variant = "project", + ...props +}: TabProps & { variant?: "project" | "namespace" | "org" }) => ( { }} > {({ isActive }) => ( - +
@@ -55,7 +55,7 @@ export const KmsLayout = () => { }} > {({ isActive }) => ( - +
@@ -74,12 +74,12 @@ export const KmsLayout = () => { }} > {({ isActive }) => ( - +
- Access Management + Project Access
)} @@ -91,7 +91,7 @@ export const KmsLayout = () => { }} > {({ isActive }) => ( - +
@@ -108,12 +108,12 @@ export const KmsLayout = () => { }} > {({ isActive }) => ( - +
- Settings + Project Settings
)} @@ -125,6 +125,7 @@ export const KmsLayout = () => { diff --git a/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx b/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx index a42c9e973..596202bf6 100644 --- a/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx @@ -4,11 +4,11 @@ import { faCircleQuestion, faUserCircle } from "@fortawesome/free-regular-svg-ic import { faArrowUpRightFromSquare, faBook, - faBuilding, faCaretDown, faCheck, faEnvelope, faExclamationTriangle, + faGlobe, faInfo, faInfoCircle, faServer, @@ -20,11 +20,13 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useQueryClient } from "@tanstack/react-query"; import { Link, useLocation, useNavigate, useRouter, useRouterState } from "@tanstack/react-router"; +import { twMerge } from "tailwind-merge"; import { Mfa } from "@app/components/auth/Mfa"; import { createNotification } from "@app/components/notifications"; import SecurityClient from "@app/components/utilities/SecurityClient"; import { + Badge, BreadcrumbContainer, Button, DropdownMenu, @@ -199,6 +201,8 @@ export const Navbar = () => { const isServerAdminPanel = location.pathname.startsWith("/admin"); + const isOrgScope = breadcrumbs?.length === 1; // TODO: scott/akhil is this adequate? + return (
@@ -230,10 +234,13 @@ export const Navbar = () => {
-
- -
-
{currentOrg?.name}
+ + + {currentOrg?.name} +
{getPlan(subscription)}
diff --git a/frontend/src/layouts/OrganizationLayout/components/OrgSidebar/OrgSidebar.tsx b/frontend/src/layouts/OrganizationLayout/components/OrgSidebar/OrgSidebar.tsx index 0f4bed355..51e14721e 100644 --- a/frontend/src/layouts/OrganizationLayout/components/OrgSidebar/OrgSidebar.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/OrgSidebar/OrgSidebar.tsx @@ -52,31 +52,31 @@ export const OrgSidebar = ({ isHidden }: Props) => { {({ isActive }) => ( - +
- Projects + Overview
)} {({ isActive }) => ( - +
- Access Control + Organization Access
)} {({ isActive }) => ( - +
@@ -88,7 +88,7 @@ export const OrgSidebar = ({ isHidden }: Props) => { {({ isActive }) => ( - +
@@ -100,7 +100,7 @@ export const OrgSidebar = ({ isHidden }: Props) => { {({ isActive }) => ( - +
@@ -114,7 +114,7 @@ export const OrgSidebar = ({ isHidden }: Props) => { {({ isActive }) => ( - +
@@ -126,7 +126,7 @@ export const OrgSidebar = ({ isHidden }: Props) => { {({ isActive }) => ( - +
@@ -145,6 +145,7 @@ export const OrgSidebar = ({ isHidden }: Props) => { !subscription.has_used_trial && ( { )} @@ -183,6 +185,7 @@ export const OrgSidebar = ({ isHidden }: Props) => { {user.superAdmin && ( diff --git a/frontend/src/layouts/PamLayout/PamLayout.tsx b/frontend/src/layouts/PamLayout/PamLayout.tsx index 6039050eb..48f6af116 100644 --- a/frontend/src/layouts/PamLayout/PamLayout.tsx +++ b/frontend/src/layouts/PamLayout/PamLayout.tsx @@ -59,7 +59,7 @@ export const PamLayout = () => { }} > {({ isActive }) => ( - +
@@ -76,7 +76,7 @@ export const PamLayout = () => { }} > {({ isActive }) => ( - +
@@ -93,7 +93,7 @@ export const PamLayout = () => { }} > {({ isActive }) => ( - +
@@ -112,12 +112,12 @@ export const PamLayout = () => { }} > {({ isActive }) => ( - +
- Access Management + Project Access
)} @@ -129,7 +129,7 @@ export const PamLayout = () => { }} > {({ isActive }) => ( - +
@@ -146,12 +146,12 @@ export const PamLayout = () => { }} > {({ isActive }) => ( - +
- Settings + Project Settings
)} diff --git a/frontend/src/layouts/PkiManagerLayout/PkiManagerLayout.tsx b/frontend/src/layouts/PkiManagerLayout/PkiManagerLayout.tsx index cb186f4fa..93fa04ac9 100644 --- a/frontend/src/layouts/PkiManagerLayout/PkiManagerLayout.tsx +++ b/frontend/src/layouts/PkiManagerLayout/PkiManagerLayout.tsx @@ -54,7 +54,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -71,7 +71,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -88,7 +88,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -105,7 +105,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -122,7 +122,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -139,7 +139,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -156,7 +156,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -175,12 +175,12 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
- Access Management + Project Access
)} @@ -192,7 +192,7 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -209,12 +209,12 @@ export const PkiManagerLayout = () => { }} > {({ isActive }) => ( - +
- Settings + Project Settings
)} diff --git a/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx b/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx index 1c2c08d23..a35c3ab55 100644 --- a/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx +++ b/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx @@ -3,10 +3,10 @@ import { faStar } from "@fortawesome/free-regular-svg-icons"; import { faCaretDown, faCheck, + faCube, faMagnifyingGlass, faPlus, - faStar as faSolidStar, - faTable + faStar as faSolidStar } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link, linkOptions } from "@tanstack/react-router"; @@ -16,6 +16,7 @@ import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { NewProjectModal } from "@app/components/projects"; import { + Badge, DropdownMenu, DropdownMenuContent, DropdownMenuItem, @@ -106,14 +107,16 @@ export const ProjectSelect = () => { projectId: currentWorkspace.id }} > -
-
- -
+
-
+ + + {currentWorkspace?.name} -
+
diff --git a/frontend/src/layouts/SecretManagerLayout/SecretManagerLayout.tsx b/frontend/src/layouts/SecretManagerLayout/SecretManagerLayout.tsx index a99dff2a7..e986d87c3 100644 --- a/frontend/src/layouts/SecretManagerLayout/SecretManagerLayout.tsx +++ b/frontend/src/layouts/SecretManagerLayout/SecretManagerLayout.tsx @@ -82,6 +82,7 @@ export const SecretManagerLayout = () => { > {({ isActive }) => ( { }} > {({ isActive }) => ( - +
@@ -123,7 +124,7 @@ export const SecretManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -141,7 +142,7 @@ export const SecretManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -166,7 +167,7 @@ export const SecretManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -185,12 +186,12 @@ export const SecretManagerLayout = () => { }} > {({ isActive }) => ( - +
- Access Management + Project Access
)} @@ -202,7 +203,7 @@ export const SecretManagerLayout = () => { }} > {({ isActive }) => ( - +
@@ -219,12 +220,12 @@ export const SecretManagerLayout = () => { }} > {({ isActive }) => ( - +
- Settings + Project Settings
)} @@ -236,6 +237,7 @@ export const SecretManagerLayout = () => { diff --git a/frontend/src/layouts/SecretScanningLayout/SecretScanningLayout.tsx b/frontend/src/layouts/SecretScanningLayout/SecretScanningLayout.tsx index fb86cfe48..b4c79786b 100644 --- a/frontend/src/layouts/SecretScanningLayout/SecretScanningLayout.tsx +++ b/frontend/src/layouts/SecretScanningLayout/SecretScanningLayout.tsx @@ -69,7 +69,7 @@ export const SecretScanningLayout = () => { }} > {({ isActive }) => ( - +
@@ -86,7 +86,7 @@ export const SecretScanningLayout = () => { }} > {({ isActive }) => ( - +
@@ -108,7 +108,7 @@ export const SecretScanningLayout = () => { }} > {({ isActive }) => ( - +
@@ -127,12 +127,12 @@ export const SecretScanningLayout = () => { }} > {({ isActive }) => ( - +
- Access Management + Project Access
)} @@ -144,7 +144,7 @@ export const SecretScanningLayout = () => { }} > {({ isActive }) => ( - +
@@ -166,7 +166,7 @@ export const SecretScanningLayout = () => {
- Settings + Project Settings
)} @@ -178,6 +178,7 @@ export const SecretScanningLayout = () => { diff --git a/frontend/src/layouts/SshLayout/SshLayout.tsx b/frontend/src/layouts/SshLayout/SshLayout.tsx index d6f318f3a..0d68a7548 100644 --- a/frontend/src/layouts/SshLayout/SshLayout.tsx +++ b/frontend/src/layouts/SshLayout/SshLayout.tsx @@ -51,7 +51,7 @@ export const SshLayout = () => { }} > {({ isActive }) => ( - +
@@ -74,7 +74,7 @@ export const SshLayout = () => { }} > {({ isActive }) => ( - +
@@ -97,12 +97,12 @@ export const SshLayout = () => { }} > {({ isActive }) => ( - +
- Access Management + Project Access
)} @@ -114,7 +114,7 @@ export const SshLayout = () => { }} > {({ isActive }) => ( - +
@@ -131,12 +131,12 @@ export const SshLayout = () => { }} > {({ isActive }) => ( - +
- Settings + Project Settings
)} @@ -148,6 +148,7 @@ export const SshLayout = () => { diff --git a/frontend/src/pages/admin/AccessManagementPage/AccessManagementPage.tsx b/frontend/src/pages/admin/AccessManagementPage/AccessManagementPage.tsx index 8128a53e0..0bc494ae2 100644 --- a/frontend/src/pages/admin/AccessManagementPage/AccessManagementPage.tsx +++ b/frontend/src/pages/admin/AccessManagementPage/AccessManagementPage.tsx @@ -16,6 +16,7 @@ export const AccessManagementPage = () => {
diff --git a/frontend/src/pages/admin/AuthenticationPage/AuthenticationPage.tsx b/frontend/src/pages/admin/AuthenticationPage/AuthenticationPage.tsx index f803d3f5c..f1c88f4cf 100644 --- a/frontend/src/pages/admin/AuthenticationPage/AuthenticationPage.tsx +++ b/frontend/src/pages/admin/AuthenticationPage/AuthenticationPage.tsx @@ -16,6 +16,7 @@ export const AuthenticationPage = () => {
diff --git a/frontend/src/pages/admin/CachingPage/CachingPage.tsx b/frontend/src/pages/admin/CachingPage/CachingPage.tsx index db8089813..96592d284 100644 --- a/frontend/src/pages/admin/CachingPage/CachingPage.tsx +++ b/frontend/src/pages/admin/CachingPage/CachingPage.tsx @@ -15,7 +15,11 @@ export const CachingPage = () => {
- +
diff --git a/frontend/src/pages/admin/EncryptionPage/EncryptionPage.tsx b/frontend/src/pages/admin/EncryptionPage/EncryptionPage.tsx index 96af9a712..45b40c621 100644 --- a/frontend/src/pages/admin/EncryptionPage/EncryptionPage.tsx +++ b/frontend/src/pages/admin/EncryptionPage/EncryptionPage.tsx @@ -16,6 +16,7 @@ export const EncryptionPage = () => {
diff --git a/frontend/src/pages/admin/EnvironmentPage/EnvironmentPage.tsx b/frontend/src/pages/admin/EnvironmentPage/EnvironmentPage.tsx index 000dd1f0d..1c0409c00 100644 --- a/frontend/src/pages/admin/EnvironmentPage/EnvironmentPage.tsx +++ b/frontend/src/pages/admin/EnvironmentPage/EnvironmentPage.tsx @@ -16,6 +16,7 @@ export const EnvironmentPage = () => {
diff --git a/frontend/src/pages/admin/GeneralPage/GeneralPage.tsx b/frontend/src/pages/admin/GeneralPage/GeneralPage.tsx index e5a76e93c..1025bf093 100644 --- a/frontend/src/pages/admin/GeneralPage/GeneralPage.tsx +++ b/frontend/src/pages/admin/GeneralPage/GeneralPage.tsx @@ -18,6 +18,7 @@ export const GeneralPage = () => {
diff --git a/frontend/src/pages/admin/IntegrationsPage/IntegrationsPage.tsx b/frontend/src/pages/admin/IntegrationsPage/IntegrationsPage.tsx index e5edd375c..d62842482 100644 --- a/frontend/src/pages/admin/IntegrationsPage/IntegrationsPage.tsx +++ b/frontend/src/pages/admin/IntegrationsPage/IntegrationsPage.tsx @@ -16,6 +16,7 @@ export const IntegrationsPage = () => {
diff --git a/frontend/src/pages/admin/ResourceOverviewPage/ResourceOverviewPage.tsx b/frontend/src/pages/admin/ResourceOverviewPage/ResourceOverviewPage.tsx index e9096d39a..5c700fc9d 100644 --- a/frontend/src/pages/admin/ResourceOverviewPage/ResourceOverviewPage.tsx +++ b/frontend/src/pages/admin/ResourceOverviewPage/ResourceOverviewPage.tsx @@ -16,6 +16,7 @@ export const ResourceOverviewPage = () => {
diff --git a/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx b/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx index 74e9d5e7e..7b5b2c3d5 100644 --- a/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx +++ b/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx @@ -153,7 +153,7 @@ const UserPanelTable = ({ icon={adminsOnly && } iconPos="right" > -
+
Server Admins
diff --git a/frontend/src/pages/cert-manager/AlertingPage/AlertingPage.tsx b/frontend/src/pages/cert-manager/AlertingPage/AlertingPage.tsx index 97d50b9bf..9921ea306 100644 --- a/frontend/src/pages/cert-manager/AlertingPage/AlertingPage.tsx +++ b/frontend/src/pages/cert-manager/AlertingPage/AlertingPage.tsx @@ -16,6 +16,7 @@ export const AlertingPage = () => {
diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx index 00c92aa11..8bfdcacca 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx @@ -87,7 +87,7 @@ const Page = () => {
{data && (
- +
diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx index a2bff12ed..7e2c9fd70 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx @@ -17,6 +17,7 @@ export const CertificateAuthoritiesPage = () => {
diff --git a/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx b/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx index f4258a4d5..56b0fb72d 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx @@ -33,6 +33,7 @@ export const CertificatesPage = () => {
diff --git a/frontend/src/pages/cert-manager/IntegrationsListPage/IntegrationsListPage.tsx b/frontend/src/pages/cert-manager/IntegrationsListPage/IntegrationsListPage.tsx index 10851d0e1..6545636f0 100644 --- a/frontend/src/pages/cert-manager/IntegrationsListPage/IntegrationsListPage.tsx +++ b/frontend/src/pages/cert-manager/IntegrationsListPage/IntegrationsListPage.tsx @@ -45,6 +45,7 @@ export const IntegrationsListPage = () => {
diff --git a/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx index 5ca305743..79835a96d 100644 --- a/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx @@ -73,7 +73,7 @@ export const PkiCollectionPage = () => {
{data && (
- +
diff --git a/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/PkiSubscriberDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/PkiSubscriberDetailsByIDPage.tsx index 682ed4253..2a7fdf56d 100644 --- a/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/PkiSubscriberDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/PkiSubscriberDetailsByIDPage.tsx @@ -78,7 +78,7 @@ const Page = () => {
{data && (
- +
diff --git a/frontend/src/pages/cert-manager/PkiSubscribersPage/PkiSubscribersPage.tsx b/frontend/src/pages/cert-manager/PkiSubscribersPage/PkiSubscribersPage.tsx index c95e9490e..bdb525b59 100644 --- a/frontend/src/pages/cert-manager/PkiSubscribersPage/PkiSubscribersPage.tsx +++ b/frontend/src/pages/cert-manager/PkiSubscribersPage/PkiSubscribersPage.tsx @@ -16,6 +16,7 @@ export const PkiSubscribersPage = () => {
diff --git a/frontend/src/pages/cert-manager/PkiTemplateListPage/PkiTemplateListPage.tsx b/frontend/src/pages/cert-manager/PkiTemplateListPage/PkiTemplateListPage.tsx index fe8f98aea..409b0415f 100644 --- a/frontend/src/pages/cert-manager/PkiTemplateListPage/PkiTemplateListPage.tsx +++ b/frontend/src/pages/cert-manager/PkiTemplateListPage/PkiTemplateListPage.tsx @@ -106,6 +106,7 @@ export const PkiTemplateListPage = () => {
diff --git a/frontend/src/pages/cert-manager/SettingsPage/SettingsPage.tsx b/frontend/src/pages/cert-manager/SettingsPage/SettingsPage.tsx index 22c1a6961..261b06df9 100644 --- a/frontend/src/pages/cert-manager/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/cert-manager/SettingsPage/SettingsPage.tsx @@ -21,7 +21,7 @@ export const SettingsPage = () => { {t("common.head-title", { title: t("settings.project.title") })}
- + {tabs.map((tab) => ( diff --git a/frontend/src/pages/kms/KmipPage/KmipPage.tsx b/frontend/src/pages/kms/KmipPage/KmipPage.tsx index 9c337bba3..b2ef8a5f0 100644 --- a/frontend/src/pages/kms/KmipPage/KmipPage.tsx +++ b/frontend/src/pages/kms/KmipPage/KmipPage.tsx @@ -18,6 +18,7 @@ export const KmipPage = () => {
diff --git a/frontend/src/pages/kms/OverviewPage/OverviewPage.tsx b/frontend/src/pages/kms/OverviewPage/OverviewPage.tsx index d7b4b9fec..71f0534e9 100644 --- a/frontend/src/pages/kms/OverviewPage/OverviewPage.tsx +++ b/frontend/src/pages/kms/OverviewPage/OverviewPage.tsx @@ -18,7 +18,8 @@ export const OverviewPage = () => {
{ {t("common.head-title", { title: t("settings.project.title") })}
- + {tabs.map((tab) => ( diff --git a/frontend/src/pages/organization/AccessManagementPage/AccessManagementPage.tsx b/frontend/src/pages/organization/AccessManagementPage/AccessManagementPage.tsx index 74908e948..4ac727332 100644 --- a/frontend/src/pages/organization/AccessManagementPage/AccessManagementPage.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/AccessManagementPage.tsx @@ -82,7 +82,8 @@ export const AccessManagementPage = () => {
{!currentOrg.shouldUseNewPrivilegeSystem && ( @@ -115,7 +116,7 @@ export const AccessManagementPage = () => { {tabSections .filter((el) => !el.isHidden) .map((el) => ( - + {el.label} ))} diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/AppConnectionsPage.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/AppConnectionsPage.tsx index acb559847..b44fad6ea 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/AppConnectionsPage.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/AppConnectionsPage.tsx @@ -22,6 +22,7 @@ export const AppConnectionsPage = withPermission(
{
diff --git a/frontend/src/pages/organization/BillingPage/BillingPage.tsx b/frontend/src/pages/organization/BillingPage/BillingPage.tsx index e49314f13..3fb473f2c 100644 --- a/frontend/src/pages/organization/BillingPage/BillingPage.tsx +++ b/frontend/src/pages/organization/BillingPage/BillingPage.tsx @@ -18,8 +18,9 @@ export const BillingPage = () => {
-
+
diff --git a/frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx b/frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx index 64d80d332..7cd567b23 100644 --- a/frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx +++ b/frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx @@ -25,7 +25,9 @@ export const BillingTabGroup = withPermission( {tabsFiltered.map((tab) => ( - {tab.name} + + {tab.name} + ))} diff --git a/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx b/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx index da7643c50..f0bd24900 100644 --- a/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx +++ b/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx @@ -83,7 +83,7 @@ const Page = () => {
{data && (
- +
diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx index 446e54885..adf6dfce8 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx @@ -75,7 +75,7 @@ const Page = () => {
{data && (
- +
diff --git a/frontend/src/pages/organization/NetworkingPage/NetworkingPage.tsx b/frontend/src/pages/organization/NetworkingPage/NetworkingPage.tsx index 660e4b26d..e7f3937d5 100644 --- a/frontend/src/pages/organization/NetworkingPage/NetworkingPage.tsx +++ b/frontend/src/pages/organization/NetworkingPage/NetworkingPage.tsx @@ -14,6 +14,7 @@ export const NetworkingPage = () => {
diff --git a/frontend/src/pages/organization/NetworkingPage/components/NetworkingTabGroup/NetworkingTabGroup.tsx b/frontend/src/pages/organization/NetworkingPage/components/NetworkingTabGroup/NetworkingTabGroup.tsx index c59d64e1b..956a4d1ed 100644 --- a/frontend/src/pages/organization/NetworkingPage/components/NetworkingTabGroup/NetworkingTabGroup.tsx +++ b/frontend/src/pages/organization/NetworkingPage/components/NetworkingTabGroup/NetworkingTabGroup.tsx @@ -22,7 +22,7 @@ export const NetworkingTabGroup = () => { {tabs.map((tab) => ( - + {tab.name} ))} diff --git a/frontend/src/pages/organization/ProjectsPage/ProjectsPage.tsx b/frontend/src/pages/organization/ProjectsPage/ProjectsPage.tsx index 2e4b43cbe..92654c1e7 100644 --- a/frontend/src/pages/organization/ProjectsPage/ProjectsPage.tsx +++ b/frontend/src/pages/organization/ProjectsPage/ProjectsPage.tsx @@ -65,7 +65,8 @@ export const ProjectsPage = () => {
diff --git a/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx b/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx index ac67f0d54..8b25247be 100644 --- a/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx +++ b/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx @@ -81,6 +81,7 @@ export const Page = () => { {data && (
diff --git a/frontend/src/pages/organization/SecretSharingPage/SecretSharingPage.tsx b/frontend/src/pages/organization/SecretSharingPage/SecretSharingPage.tsx index a026b86f3..ec3885f5b 100644 --- a/frontend/src/pages/organization/SecretSharingPage/SecretSharingPage.tsx +++ b/frontend/src/pages/organization/SecretSharingPage/SecretSharingPage.tsx @@ -22,6 +22,7 @@ export const SecretSharingPage = () => {
diff --git a/frontend/src/pages/organization/SecretSharingSettingsPage/SecretSharingSettingsPage.tsx b/frontend/src/pages/organization/SecretSharingSettingsPage/SecretSharingSettingsPage.tsx index ae1aa3772..6ee73a03d 100644 --- a/frontend/src/pages/organization/SecretSharingSettingsPage/SecretSharingSettingsPage.tsx +++ b/frontend/src/pages/organization/SecretSharingSettingsPage/SecretSharingSettingsPage.tsx @@ -21,7 +21,7 @@ export const SecretSharingSettingsPage = withPermission(
- +
diff --git a/frontend/src/pages/organization/SettingsPage/SettingsPage.tsx b/frontend/src/pages/organization/SettingsPage/SettingsPage.tsx index 263672313..52fc99f53 100644 --- a/frontend/src/pages/organization/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/organization/SettingsPage/SettingsPage.tsx @@ -15,7 +15,7 @@ export const SettingsPage = () => {
- +
diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx index 42a8e5839..ad867238b 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx @@ -58,7 +58,7 @@ export const OrgTabGroup = () => { {tabs.map((tab) => ( - + {tab.name} ))} diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx index 03a720b98..3153c5fd5 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx @@ -119,6 +119,7 @@ const Page = withPermission( {membership && (
{
- +
diff --git a/frontend/src/pages/pam/PamResourcesPage/PamResourcesPage.tsx b/frontend/src/pages/pam/PamResourcesPage/PamResourcesPage.tsx index e8238d8a9..13e9028e6 100644 --- a/frontend/src/pages/pam/PamResourcesPage/PamResourcesPage.tsx +++ b/frontend/src/pages/pam/PamResourcesPage/PamResourcesPage.tsx @@ -24,6 +24,7 @@ export const PamResourcesPage = () => {
diff --git a/frontend/src/pages/pam/PamSessionsByIDPage/PamSessionByIDPage.tsx b/frontend/src/pages/pam/PamSessionsByIDPage/PamSessionByIDPage.tsx index b82c6b6e7..af5b85fc6 100644 --- a/frontend/src/pages/pam/PamSessionsByIDPage/PamSessionByIDPage.tsx +++ b/frontend/src/pages/pam/PamSessionsByIDPage/PamSessionByIDPage.tsx @@ -23,6 +23,7 @@ const Page = () => { {session && (
diff --git a/frontend/src/pages/pam/PamSessionsPage/PamSessionsPage.tsx b/frontend/src/pages/pam/PamSessionsPage/PamSessionsPage.tsx index 03ca60a3b..526507564 100644 --- a/frontend/src/pages/pam/PamSessionsPage/PamSessionsPage.tsx +++ b/frontend/src/pages/pam/PamSessionsPage/PamSessionsPage.tsx @@ -24,6 +24,7 @@ export const PamSessionPage = () => {
diff --git a/frontend/src/pages/pam/SettingsPage/SettingsPage.tsx b/frontend/src/pages/pam/SettingsPage/SettingsPage.tsx index 81a0a1d07..b8b23cebd 100644 --- a/frontend/src/pages/pam/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/pam/SettingsPage/SettingsPage.tsx @@ -13,7 +13,7 @@ export const SettingsPage = () => { {t("common.head-title", { title: t("settings.project.title") })}
- + General diff --git a/frontend/src/pages/project/AccessControlPage/AccessControlPage.tsx b/frontend/src/pages/project/AccessControlPage/AccessControlPage.tsx index 9da8770d2..c010fcc39 100644 --- a/frontend/src/pages/project/AccessControlPage/AccessControlPage.tsx +++ b/frontend/src/pages/project/AccessControlPage/AccessControlPage.tsx @@ -40,6 +40,7 @@ const Page = () => {
diff --git a/frontend/src/pages/project/AppConnectionsPage/AppConnectionsPage.tsx b/frontend/src/pages/project/AppConnectionsPage/AppConnectionsPage.tsx index 84fb69b83..78665e624 100644 --- a/frontend/src/pages/project/AppConnectionsPage/AppConnectionsPage.tsx +++ b/frontend/src/pages/project/AppConnectionsPage/AppConnectionsPage.tsx @@ -23,6 +23,7 @@ export const AppConnectionsPage = withProjectPermission(
{
diff --git a/frontend/src/pages/project/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx b/frontend/src/pages/project/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx index d6bda7ea1..409d78633 100644 --- a/frontend/src/pages/project/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx +++ b/frontend/src/pages/project/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx @@ -34,7 +34,7 @@ const Page = () => {
{groupMembership ? (
- +
diff --git a/frontend/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx b/frontend/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx index 993320e56..061d537b1 100644 --- a/frontend/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx +++ b/frontend/src/pages/project/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx @@ -117,6 +117,7 @@ const Page = () => { {identityMembershipDetails ? ( <> diff --git a/frontend/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx b/frontend/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx index 23b8299da..717226cfc 100644 --- a/frontend/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx +++ b/frontend/src/pages/project/MemberDetailsByIDPage/MemberDetailsByIDPage.tsx @@ -119,6 +119,7 @@ export const Page = () => { {membershipDetails ? ( <> { {data && (
diff --git a/frontend/src/pages/secret-manager/CommitDetailsPage/components/CommitDetailsTab/CommitDetailsTab.tsx b/frontend/src/pages/secret-manager/CommitDetailsPage/components/CommitDetailsTab/CommitDetailsTab.tsx index 714695890..60f634289 100644 --- a/frontend/src/pages/secret-manager/CommitDetailsPage/components/CommitDetailsTab/CommitDetailsTab.tsx +++ b/frontend/src/pages/secret-manager/CommitDetailsPage/components/CommitDetailsTab/CommitDetailsTab.tsx @@ -260,6 +260,7 @@ export const CommitDetailsTab = ({ Commit History diff --git a/frontend/src/pages/secret-manager/CommitDetailsPage/components/RollbackPreviewTab/RollbackPreviewTab.tsx b/frontend/src/pages/secret-manager/CommitDetailsPage/components/RollbackPreviewTab/RollbackPreviewTab.tsx index 89124e3b9..a3a25b1cc 100644 --- a/frontend/src/pages/secret-manager/CommitDetailsPage/components/RollbackPreviewTab/RollbackPreviewTab.tsx +++ b/frontend/src/pages/secret-manager/CommitDetailsPage/components/RollbackPreviewTab/RollbackPreviewTab.tsx @@ -307,6 +307,7 @@ export const RollbackPreviewTab = (): JSX.Element => {
diff --git a/frontend/src/pages/secret-manager/CommitsPage/CommitsPage.tsx b/frontend/src/pages/secret-manager/CommitsPage/CommitsPage.tsx index 2dba8ad55..e456bbdf3 100644 --- a/frontend/src/pages/secret-manager/CommitsPage/CommitsPage.tsx +++ b/frontend/src/pages/secret-manager/CommitsPage/CommitsPage.tsx @@ -49,6 +49,7 @@ export const CommitsPage = () => {
diff --git a/frontend/src/pages/secret-manager/IntegrationsDetailsByIDPage/IntegrationsDetailsByIDPage.tsx b/frontend/src/pages/secret-manager/IntegrationsDetailsByIDPage/IntegrationsDetailsByIDPage.tsx index 98dc087ea..0eaa7dfac 100644 --- a/frontend/src/pages/secret-manager/IntegrationsDetailsByIDPage/IntegrationsDetailsByIDPage.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsDetailsByIDPage/IntegrationsDetailsByIDPage.tsx @@ -94,6 +94,7 @@ export const IntegrationDetailsByIDPage = () => { {integration ? (
diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx index 647af2039..4e2a0a703 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx @@ -48,6 +48,7 @@ export const IntegrationsListPage = () => {
diff --git a/frontend/src/pages/secret-manager/OverviewPage/OverviewPage.tsx b/frontend/src/pages/secret-manager/OverviewPage/OverviewPage.tsx index 860f161e9..022b33f88 100644 --- a/frontend/src/pages/secret-manager/OverviewPage/OverviewPage.tsx +++ b/frontend/src/pages/secret-manager/OverviewPage/OverviewPage.tsx @@ -914,6 +914,7 @@ export const OverviewPage = () => {
diff --git a/frontend/src/pages/secret-manager/SecretApprovalsPage/SecretApprovalsPage.tsx b/frontend/src/pages/secret-manager/SecretApprovalsPage/SecretApprovalsPage.tsx index 77106a57c..6813aac07 100644 --- a/frontend/src/pages/secret-manager/SecretApprovalsPage/SecretApprovalsPage.tsx +++ b/frontend/src/pages/secret-manager/SecretApprovalsPage/SecretApprovalsPage.tsx @@ -40,6 +40,7 @@ export const SecretApprovalsPage = () => {
diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx index 2760e8626..da31fcf09 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx @@ -762,6 +762,7 @@ const Page = () => { return (
diff --git a/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx b/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx index 0b9263803..f4b474b9e 100644 --- a/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx +++ b/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx @@ -147,6 +147,7 @@ const Page = () => { return (
diff --git a/frontend/src/pages/secret-manager/SettingsPage/SettingsPage.tsx b/frontend/src/pages/secret-manager/SettingsPage/SettingsPage.tsx index ad037b125..a97775013 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/SettingsPage.tsx @@ -42,6 +42,7 @@ export const SettingsPage = () => {
diff --git a/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/SecretScanningDataSourcesPage.tsx b/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/SecretScanningDataSourcesPage.tsx index d681c34af..71ffd8286 100644 --- a/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/SecretScanningDataSourcesPage.tsx +++ b/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/SecretScanningDataSourcesPage.tsx @@ -26,6 +26,7 @@ export const SecretScanningDataSourcesPage = () => {
diff --git a/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/SecretScanningFindingsPage.tsx b/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/SecretScanningFindingsPage.tsx index 1eddf5eee..320d29428 100644 --- a/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/SecretScanningFindingsPage.tsx +++ b/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/SecretScanningFindingsPage.tsx @@ -23,7 +23,11 @@ export const SecretScanningFindingsPage = () => {
- +
diff --git a/frontend/src/pages/secret-scanning/SettingsPage/SettingsPage.tsx b/frontend/src/pages/secret-scanning/SettingsPage/SettingsPage.tsx index 07161c360..84a885cff 100644 --- a/frontend/src/pages/secret-scanning/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/secret-scanning/SettingsPage/SettingsPage.tsx @@ -19,6 +19,7 @@ export const SettingsPage = () => {
diff --git a/frontend/src/pages/ssh/SettingsPage/SettingsPage.tsx b/frontend/src/pages/ssh/SettingsPage/SettingsPage.tsx index 841bb119f..e820e1488 100644 --- a/frontend/src/pages/ssh/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/ssh/SettingsPage/SettingsPage.tsx @@ -17,7 +17,11 @@ export const SettingsPage = () => { {t("common.head-title", { title: t("settings.project.title") })}
- + General diff --git a/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx b/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx index 06567b121..4f8325594 100644 --- a/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx +++ b/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx @@ -70,7 +70,7 @@ const Page = () => {
{data && (
- +
diff --git a/frontend/src/pages/ssh/SshCasPage/SshCasPage.tsx b/frontend/src/pages/ssh/SshCasPage/SshCasPage.tsx index 669e26404..1156de3f0 100644 --- a/frontend/src/pages/ssh/SshCasPage/SshCasPage.tsx +++ b/frontend/src/pages/ssh/SshCasPage/SshCasPage.tsx @@ -16,6 +16,7 @@ export const SshCasPage = () => {
diff --git a/frontend/src/pages/ssh/SshCertsPage/SshCertsPage.tsx b/frontend/src/pages/ssh/SshCertsPage/SshCertsPage.tsx index 617f480a3..0078bd4b2 100644 --- a/frontend/src/pages/ssh/SshCertsPage/SshCertsPage.tsx +++ b/frontend/src/pages/ssh/SshCertsPage/SshCertsPage.tsx @@ -16,6 +16,7 @@ export const SshCertsPage = () => {
diff --git a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx index 1605286a8..8cbca6848 100644 --- a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx +++ b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx @@ -71,7 +71,7 @@ const Page = () => {
{data && (
- +
diff --git a/frontend/src/pages/ssh/SshHostsPage/SshHostsPage.tsx b/frontend/src/pages/ssh/SshHostsPage/SshHostsPage.tsx index c6efa9670..7c83eff1d 100644 --- a/frontend/src/pages/ssh/SshHostsPage/SshHostsPage.tsx +++ b/frontend/src/pages/ssh/SshHostsPage/SshHostsPage.tsx @@ -16,6 +16,7 @@ export const SshHostsPage = () => {
From 76a62c9c1e36dfecad3718d56f1557f7097b0984 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 14 Oct 2025 03:13:40 +0400 Subject: [PATCH 14/22] Update hsm-fns.ts --- backend/src/ee/services/hsm/hsm-fns.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/ee/services/hsm/hsm-fns.ts b/backend/src/ee/services/hsm/hsm-fns.ts index 54c2f5f23..1afccdafe 100644 --- a/backend/src/ee/services/hsm/hsm-fns.ts +++ b/backend/src/ee/services/hsm/hsm-fns.ts @@ -25,7 +25,9 @@ export const initializeHsmModule = (envConfig: Pick Date: Tue, 14 Oct 2025 03:22:15 +0400 Subject: [PATCH 15/22] Update hsm-integration.mdx requested changes Update hsm-integration.mdx --- .../platform/kms/hsm-integration.mdx | 72 ++++++++----------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/docs/documentation/platform/kms/hsm-integration.mdx b/docs/documentation/platform/kms/hsm-integration.mdx index 2c90e79e7..45d883977 100644 --- a/docs/documentation/platform/kms/hsm-integration.mdx +++ b/docs/documentation/platform/kms/hsm-integration.mdx @@ -435,7 +435,7 @@ Enabling HSM encryption has a set of key benefits: pkcs11-tool --module /opt/cloudhsm/lib/libcloudhsm_pkcs11.so --list-slots --login ``` - It'll prompt you to log in with your PIN, which is your username and password seperated by a colon. Example: `testUser:testPassword`. + It'll prompt you to log in with your PIN, which is your username and password separated by a colon. Example: `testUser:testPassword`. This will output the HSM slot number like so: @@ -485,7 +485,7 @@ Enabling HSM encryption has a set of key benefits: # Set the HSM library path to whats expected within Docker (/opt/cloudhsm/lib/libcloudhsm_pkcs11.so) -e HSM_LIB_PATH="/opt/cloudhsm/lib/libcloudhsm_pkcs11.so" \ - # Set the HSM PIN to the username and password of the HSM user, seperated by a colon + # Set the HSM PIN to the username and password of the HSM user, separated by a colon -e HSM_PIN=CryptoUserUsername:CryptoUserPassword \ # Set the HSM slot number to the slot number of the HSM device as found in the previous step -e HSM_SLOT= \ @@ -513,7 +513,7 @@ Enabling HSM encryption has a set of key benefits: - This is only supported on helm chart version `1.4.1` and above. Please see the [Helm Chart Changelog](https://github.com/Infisical/infisical/blob/main/helm-charts/infisical-standalone-postgres/CHANGELOG.md#141-march-19-2025) for more information. + This is only supported on helm chart version `1.7.1` and above. Please see the [Helm Chart Changelog](https://github.com/Infisical/infisical/blob/main/helm-charts/infisical-standalone-postgres/CHANGELOG.md#141-march-19-2025) for more information. @@ -994,7 +994,7 @@ Enabling HSM encryption has a set of key benefits: - A Kubernetes cluster - AWS CloudHSM is supported on helm chart version `1.4.1` and above. Please see the [Helm Chart Changelog](https://github.com/Infisical/infisical/blob/main/helm-charts/infisical-standalone-postgres/CHANGELOG.md#141-march-19-2025) for more information. + AWS CloudHSM is supported on helm chart version `1.7.1` and above. Please see the [Helm Chart Changelog](https://github.com/Infisical/infisical/blob/main/helm-charts/infisical-standalone-postgres/CHANGELOG.md#141-march-19-2025) for more information. @@ -1022,7 +1022,7 @@ Enabling HSM encryption has a set of key benefits: - + 1. Check if EBS CSI Driver is installed and running by running the following command: @@ -1179,7 +1179,7 @@ Enabling HSM encryption has a set of key benefits: - We need to configure the PVC to work with the CloudHSM, so Infiscial can consume the HSM client files. + We need to configure the PVC to work with the CloudHSM, so Infisical can consume the HSM client files. **2.1. Start a shell in the PVC pod:** @@ -1189,15 +1189,7 @@ Enabling HSM encryption has a set of key benefits: kubectl exec -it cloudhsm-setup-pod -- /bin/sh ``` - **2.2. Create the data directory:** - - This will create a directory called `/data/` within the setup pod. This directory will remain even after the setup pod is deleted, as it's mounted as a volume from the PVC. - - ```bash - mkdir -p /data/ - ``` - - **2.3. Install the necessary packages:** + **2.2. Install the necessary packages:** This will install the necessary packages to allow us to test and install the CloudHSM client. @@ -1206,7 +1198,7 @@ Enabling HSM encryption has a set of key benefits: apt-get install opensc telnet wget -y ``` - **2.4. Try to reach the HSM device:** + **2.3. Try to reach the HSM device:** We need to validate that we're able to reach the HSM device from within Kubernetes. You can use telnet to ping the HSM device like so: @@ -1223,7 +1215,7 @@ Enabling HSM encryption has a set of key benefits: If it gets stuck on `Trying ....`, you may have configured your HSM client's security group incorrectly. Make sure you configure the security group to allow traffic from EKS on port 2223-2225. - **2.5. Install the AWS CloudHSM client:** + **2.4. Install the AWS CloudHSM client:** The Infisical images run on Debian, so we need to install a Debian-compatible version of the AWS CloudHSM client. @@ -1232,7 +1224,7 @@ Enabling HSM encryption has a set of key benefits: apt-get install ./cloudhsm-pkcs11_latest_u22.04_amd64.deb -y ``` - **2.6. Configure the CloudHSM client:** + **2.5. Configure the CloudHSM client:** After installing the CloudHSM client, you should see all related files in the `/opt/cloudhsm/` directory on the CloudHSM setup pod. @@ -1257,7 +1249,7 @@ Enabling HSM encryption has a set of key benefits: - **2.7. Verify the CloudHSM client is configured correctly:** + **2.6. Verify the CloudHSM client is configured correctly:** You can verify the CloudHSM client is configured correctly by running the following command: ```bash @@ -1295,14 +1287,14 @@ Enabling HSM encryption has a set of key benefits: } ``` - **2.8. Exit the pod:** + **2.7. Exit the pod:** Exit the pod by running the following command: ```bash exit ``` - **2.9. Copy your issuer CA certificate to the PVC:** + **2.8. Copy your issuer CA certificate to the PVC:** When you initialized your HSM, you were prompted to download the cluster CSR and sign it. In order to use the HSM with Infisical, you need to obtain the issuer CA certificate that was used to sign the cluster CSR. @@ -1320,7 +1312,7 @@ Enabling HSM encryption has a set of key benefits: kubectl exec -it cloudhsm-setup-pod -- cat /opt/cloudhsm/etc/customerCA.crt ``` - **2.10. Test the HSM client:** + **2.9. Test the HSM client:** Finally, after we're done configuring the HSM client, we need to test it to ensure that it's working correctly. @@ -1342,9 +1334,15 @@ Enabling HSM encryption has a set of key benefits: av1dlhVEsssjpcTNS+ysGUoKWH6+/PCaEDIdal5oQc0= ``` + + Replace the `:` with your username and password combination of the Crypto user you have created that you want to use to perform cryptographic operations. + + In AWS CloudHSM, the PIN is always the username and password separated by a colon. + - **2.12. Copy the configured client to the PVC:** + + **2.10. Copy the configured client to the PVC:** Copy from the HSM files into the `/data` directory in the PVC, which is what will be mounted for the Infisical deployment. ```bash @@ -1368,20 +1366,20 @@ Enabling HSM encryption has a set of key benefits: drwxr-xr-t. 2 root root 4096 Oct 13 18:50 run ``` - **2.13. Set the correct permissions for the HSM client files:** + **2.11. Set the correct permissions for the HSM client files:** ```bash chmod -R 755 /data/ ``` - **2.14. Exit the pod:** + **2.12. Exit the pod:** Exit the pod by running the following command: ```bash exit ``` - **2.15. Delete the setup pod:** + **2.13. Delete the setup pod:** Delete the setup pod by running the following command: ```bash @@ -1430,7 +1428,7 @@ Enabling HSM encryption has a set of key benefits: infisical: image: repository: infisical/infisical - tag: "v0.117.1-postgres" + tag: "v0.151.0-nightly-20251013.1" pullPolicy: IfNotPresent extraVolumeMounts: @@ -1445,6 +1443,10 @@ Enabling HSM encryption has a set of key benefits: # ... The rest of the values.yaml file ... ``` + + Make sure to set the `tag` to **`v0.151.0-nightly-20251013.1` or above**, as this is the minimum Infisical version that supports AWS CloudHSM. + + Ensure that the configuration file at `/opt/cloudhsm/etc/cloudhsm-pkcs11.cfg` references the correct path for the issuer CA certificate (`/opt/cloudhsm/etc/customerCA.crt`). This should already be configured correctly if you followed the previous steps. @@ -1463,7 +1465,7 @@ Enabling HSM encryption has a set of key benefits: After upgrading the Helm chart, you need to restart the deployment in order for the changes to take effect. ```bash - kubectl rollout restart deployment/infisical-infisical + kubectl rollout restart deployment/infisical-infisical-standalone-infisical ``` @@ -1480,16 +1482,4 @@ To disable HSM encryption, navigate to Infisical's Server Admin Console and set In order to disable HSM encryption, the Infisical instance must be able to access the HSM device. If the HSM device is no longer accessible, you will not be able to disable HSM encryption. - - - - -## Troubleshooting - - - - If you're using EKS, you may encounter an error like the following: `no persistent volumes available for this claim and no storage class is set` - - - - \ No newline at end of file + \ No newline at end of file From 56e04d8cf0a3dbc3aeb95f132de95c69d4a0200d Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Mon, 13 Oct 2025 21:11:44 -0300 Subject: [PATCH 16/22] Fix identity count used by the license server, removed the status filter as identities accept memberships by default --- backend/src/ee/services/license/license-dal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/ee/services/license/license-dal.ts b/backend/src/ee/services/license/license-dal.ts index 891d60922..a2bd7ec51 100644 --- a/backend/src/ee/services/license/license-dal.ts +++ b/backend/src/ee/services/license/license-dal.ts @@ -44,7 +44,7 @@ export const licenseDALFactory = (db: TDbClient) => { // count org identities const identityDoc = await (tx || db.replicaNode())(TableName.Membership) - .where({ status: OrgMembershipStatus.Accepted, scope: AccessScope.Organization }) + .where({ scope: AccessScope.Organization }) .whereNotNull(`${TableName.Membership}.actorIdentityId`) .where((bd) => { if (orgId) { From 1169940cf11a1bd7337644e0a728032e2a52cbe0 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Tue, 14 Oct 2025 01:56:38 -0400 Subject: [PATCH 17/22] add replication docs --- docs/docs.json | 1 + docs/self-hosting/guides/replication.mdx | 162 +++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 docs/self-hosting/guides/replication.mdx diff --git a/docs/docs.json b/docs/docs.json index 444f74b5d..ee817ab9f 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -316,6 +316,7 @@ "self-hosting/deployment-options/linux-upgrade" ] }, + "self-hosting/guides/replication", "self-hosting/guides/upgrading-infisical", "self-hosting/configuration/envars", "self-hosting/guides/releases", diff --git a/docs/self-hosting/guides/replication.mdx b/docs/self-hosting/guides/replication.mdx new file mode 100644 index 000000000..4767da6fa --- /dev/null +++ b/docs/self-hosting/guides/replication.mdx @@ -0,0 +1,162 @@ +--- + +title: "Replication" +description: "Learn how Infisical supports multi-region replication" + +--- + + + Infisical replication is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact team@infisical.com to purchase an enterprise license to use it. + + +Multi-region replication is available in Infisical Enterprise to support globally distributed deployments. Understanding the architecture, use cases, and operational considerations is essential before implementing this feature in production environments. + +Infisical uses a primary/secondary (1:N) architecture with asynchronous PostgreSQL replication. This design prioritizes high availability and minimal read latency for applications deployed across multiple geographic regions. + +## Use cases + +- **Multi-Region Deployments**: Serving secrets to applications distributed across continents from a single region introduces unacceptable latency. A centralized deployment also creates a single point of failure: regional outages can render secrets inaccessible globally, and network connectivity issues impact availability. + +- **Geographic Data Locality**: Global organizations need to minimize the time it takes for applications to retrieve secrets and configurations. Regional replicas enable applications to fetch data from nearby instances rather than making cross-continental requests. + +- **Disaster Recovery**: Organizations need resilience against primary region failures. Secondary regions with read replicas can be promoted to primary status when needed, maintaining operations during outages or disasters. + +## Design Goals + +In order to address the common use cases, the implementation reflects several core goals: + +- **Optimized Read Performance**: Applications need fast access to secrets regardless of their location. Regional instances use Redis for aggressive caching and read from local PostgreSQL replicas, eliminating cross-region round trips for most read operations. + +- **Conflict-Free Architecture**: All mutations flow through the primary instance exclusively. This prevents write conflicts and split-brain scenarios that plague multi-master systems. The trade-off ensures data integrity without requiring conflict resolution strategies. + +- **Zero Client Changes**: Existing Infisical integrations, SDKs, and CLI tools work without modification. Regional instances route write operations to the primary while handling reads locally. Authentication tokens and API keys function identically across all instances. + +- **Operational Simplicity**: Deploying additional regions requires minimal configuration. PostgreSQL handles replication complexity, and the stateless application tier scales horizontally without coordination overhead. + +# Architecture + +Infisical distinguishes between _primary_ and _secondary_ instances. The primary holds write authority and is the sole instance permitted to modify the PostgreSQL database. Secondary instances handle read traffic locally and proxy write operations to the primary. + +## Infrastructure components + +Two data stores form Infisical's persistence layer: + +- **PostgreSQL** maintains the authoritative dataset including secrets with their version history, authentication credentials, user identities, project configurations, access policies, audit trails, and integration settings. All persistent state lives in PostgreSQL. + +- **Redis** accelerates read operations through caching and manages asynchronous job queues. Each regional deployment maintains an independent Redis instance optimized for local access patterns. + +The Infisical application servers are stateless and therefore hold no persistent data internally. This design simplifies regional deployment and horizontal scaling. + + + + + A primary deployment consists of three core components: + + - **Application Servers**: Process all API requests directly, handling both read and write operations without forwarding + - **PostgreSQL Primary Database**: Accepts read and write queries, serving as the authoritative source of truth + - **Redis Cache**: Stores frequently accessed data and executes all background jobs including secret synchronization, scheduled tasks, and audit log processing + + + + Each secondary deployment mirrors the primary structure with key differences: + + - **Application Servers**: Service read requests from local infrastructure but forward any write requests to the primary region + - **PostgreSQL Read Replica**: Continuously streams changes from the primary database via PostgreSQL replication + - **PostgreSQL Primary Database**: Connection string to the primary database for write forwarding + - **Redis Cache**: Maintains a local cache but processes only audit logs (other background jobs remain disabled) + + Configuring a secondary region requires four main environment variables: + + 1. `INFISICAL_PRIMARY_INSTANCE_URL`: The primary region's Infisical API endpoint + 2. Postgres primary instance connection details. View related [environment variables](/self-hosting/configuration/envars#postgresql). + 3. Postgres read replica connection details. View related [environment variables](/self-hosting/configuration/envars#postgresql). + 4. Redis connection details. View related [environment variables](/self-hosting/configuration/envars#redis). + + + + +## How requests are processed + +When a client sends a read request to a secondary instance, the application first checks the local Redis cache for the requested data. If the data exists in cache, it's returned immediately to the client. Otherwise, the application queries the local PostgreSQL read replica, caches the result in Redis for future requests, and returns the response to the client. + +Write operations follow a different path. When a secondary receives a write request, it forwards the complete request to the primary instance URL. The primary processes the mutation against the authoritative database and returns a response, which the secondary then forwards back to the client. PostgreSQL subsequently streams these changes to all replicas asynchronously. + +Operations against the primary instance are more straightforward, as both reads and writes execute directly against local infrastructure without any forwarding. + +## Replication mechanism + +PostgreSQL streaming replication handles all data synchronization. When transactions commit on the primary, changes are written to the write-ahead log (WAL) and streamed to all configured replicas, which apply the entries to maintain consistency. Replication lag typically remains under one second. + +This approach replicates all data stored in PostgreSQL: secrets and their version histories, user accounts and permissions, authentication tokens, project configurations, access policies, audit logs, integration settings, and all other application metadata. Replicas are eventually consistent. This means that all replicas eventually converge to the same state, typically under 1 second. The application layer remains unaware of replication mechanics and operates identically across all instances. + +## Caching behavior + +Redis caches are regional and independent (no coordination occurs between instances): + +- Secondary instances populate caches on demand from read requests +- Cache hits serve data without touching PostgreSQL +- Cache misses fetch from the local replica and populate the cache +- Each region maintains its own hot dataset based on local access patterns + +Secrets use versioned caching. When a secret changes, its version identifier changes, causing automatic cache misses. This ensures subsequent reads fetch the updated value from PostgreSQL without requiring active cache invalidation. + +# Technical Details + +Understanding the implementation details can help evaluate whether Infisical's replication characteristics align with your requirements. +The following sections provide deeper insight into performance behavior, failure modes, and the underlying mechanisms that drive the replication system. + +### PostgreSQL streaming replication + +Infisical relies on PostgreSQL's native replication, which provides: + +- **Asynchronous operation**: The primary commits transactions immediately without waiting for replicas to confirm receipt. Replicas receive and apply changes continuously with typical lag measured in milliseconds to low seconds, depending on network conditions and write volume. + +- **Binary-level consistency**: Replication occurs at the storage layer using write-ahead logs, guaranteeing replicas are byte-for-byte identical to the primary at the block level. + +- **Promotion capability**: Read replicas can be promoted to primary during disaster recovery. Promotion requires updating Infisical configuration to designate the promoted instance as primary and reconfiguring other secondaries. + +Consult PostgreSQL's official documentation for replication setup instructions specific to your hosting environment (RDS, Cloud SQL, self-managed, etc.). + +### Version management + +All Infisical instances must run identical versions (mixing versions risks database schema mismatches or incompatible API behavior). Database migrations execute only on the primary and replicate to secondaries through standard PostgreSQL mechanisms. + +During upgrades: +1. Upgrade the primary instance (migrations run automatically) +2. Upgrade secondary instances to match +3. All instances can continue running during the upgrade process since database migrations don't immediately drop tables/columns + +### Request proxying + +When a secondary receives a mutation request (POST, PUT, PATCH, DELETE), it functions as a transparent proxy: + +1. Preserve the original request completely (headers, authentication context, request body) +2. Forward to the primary instance URL specified in configuration +3. Primary processes the request as a direct client request +4. Return the primary's response unmodified to the client + +### Cache management + +Infisical uses versioned caching rather than active invalidation: + +1. Secrets and other cached entities include version identifiers +2. When data mutates, its version changes in the database +3. Cache lookups include the version in the cache key +4. Version changes cause automatic cache misses +5. Cache misses fetch updated data from PostgreSQL +6. Fresh data populates the cache with the new version + +This strategy ensures correctness without requiring cross-region cache invalidation protocols. + +### Background job processing + +Secondary instances run with restricted background job capabilities: + +**Active**: Audit log processing +**Disabled**: Secret synchronization to third-party systems, scheduled tasks, cron jobs, time-triggered operations + +Limiting background jobs to the primary prevents duplicate processing and ensures integrations execute once. + From 72deda5e9a75f83e6db59effe8ea741bee803c60 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Tue, 14 Oct 2025 10:56:48 -0300 Subject: [PATCH 18/22] Add missing condition to filter non-accepted memberships on the organization members count --- backend/src/services/org/org-dal.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index 288926f90..d987c890c 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -5,6 +5,7 @@ import { AccessScope, OrganizationsSchema, OrgMembershipRole, + OrgMembershipStatus, TableName, TMemberships, TMembershipsInsert, @@ -346,6 +347,7 @@ export const orgDALFactory = (db: TDbClient) => { .replicaNode()(TableName.Membership) .where(`${TableName.Membership}.scopeOrgId`, orgId) .where(`${TableName.Membership}.scope`, AccessScope.Organization) + .where(`${TableName.Membership}.status`, OrgMembershipStatus.Accepted) .whereNotNull(`${TableName.Membership}.actorUserId`) .count("*") .join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`) From 8ce9473f667704a00850ec1f269b22782e15be34 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 14 Oct 2025 20:10:16 +0400 Subject: [PATCH 19/22] fix: auto binary release strict check --- .../release-standalone-docker-img-postgres-offical.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-standalone-docker-img-postgres-offical.yml b/.github/workflows/release-standalone-docker-img-postgres-offical.yml index 9dc767e31..5d9f384f7 100644 --- a/.github/workflows/release-standalone-docker-img-postgres-offical.yml +++ b/.github/workflows/release-standalone-docker-img-postgres-offical.yml @@ -135,7 +135,9 @@ jobs: TAG_NAME="${{ github.ref_name }}" echo "Checking for tag: $TAG_NAME" - if gh api repos/Infisical/infisical-omnibus/git/refs/tags/$TAG_NAME --silent 2>/dev/null; then + EXACT_MATCH=$(gh api repos/Infisical/infisical-omnibus/git/refs/tags/$TAG_NAME | jq -r 'if type == "array" then .[].ref else .ref end' | grep -x "refs/tags/$TAG_NAME") + + if [ "$EXACT_MATCH" == "refs/tags/$TAG_NAME" ]; then echo "Tag $TAG_NAME already exists, skipping..." else echo "Creating tag in Infisical/infisical-omnibus: $TAG_NAME" From 98f0ad683c0de5248bac4b0d90d120f8805a65d6 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 14 Oct 2025 20:47:57 +0400 Subject: [PATCH 20/22] fix: clean install failing --- Dockerfile.fips.standalone-infisical | 2 +- Dockerfile.standalone-infisical | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.fips.standalone-infisical b/Dockerfile.fips.standalone-infisical index 1c03f752a..4dbf7872b 100644 --- a/Dockerfile.fips.standalone-infisical +++ b/Dockerfile.fips.standalone-infisical @@ -6,7 +6,7 @@ ARG CAPTCHA_SITE_KEY=captcha-site-key FROM node:20.19.5-trixie-slim AS base # Fixes NPM vulnerability: https://security.snyk.io/vuln/SNYK-JS-CROSSSPAWN-8303230 -RUN npm install -g npm@11 +RUN npm install -g npm@10.9.0 FROM base AS frontend-dependencies WORKDIR /app diff --git a/Dockerfile.standalone-infisical b/Dockerfile.standalone-infisical index bea94d6b6..bc80130be 100644 --- a/Dockerfile.standalone-infisical +++ b/Dockerfile.standalone-infisical @@ -6,7 +6,7 @@ ARG CAPTCHA_SITE_KEY=captcha-site-key FROM node:20.19.5-trixie-slim AS base # Fixes NPM vulnerability: https://security.snyk.io/vuln/SNYK-JS-CROSSSPAWN-8303230 -RUN npm install -g npm@11 +RUN npm install -g npm@10.9.0 FROM base AS frontend-dependencies From f478ef99c39efa3cda1a010b8dc7d7805ff835d0 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Tue, 14 Oct 2025 18:43:33 -0300 Subject: [PATCH 21/22] Fix api call to fetch the secret value, if there is a secret on the folder it should take precedence rather than an import secret --- .../components/SecretOverviewTableRow/SecretEditRow.tsx | 6 ++++-- .../SecretOverviewTableRow/SecretOverviewTableRow.tsx | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx index b0f9f7666..0ba6314d1 100644 --- a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx +++ b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx @@ -82,6 +82,7 @@ type Props = { isImported: boolean; }[]; }[]; + isSecretPresent?: boolean; }; export const SecretEditRow = ({ @@ -101,7 +102,8 @@ export const SecretEditRow = ({ isRotatedSecret, importedBy, importedSecret, - isEmpty + isEmpty, + isSecretPresent }: Props) => { const { handlePopUpOpen, handlePopUpToggle, handlePopUpClose, popUp } = usePopUp([ "editSecret" @@ -113,7 +115,7 @@ export const SecretEditRow = ({ const [isFieldFocused, setIsFieldFocused] = useToggle(); - const fetchSecretValueParams = importedSecret + const fetchSecretValueParams = importedSecret && !isSecretPresent ? { environment: importedSecret.environment, secretPath: importedSecret.secretPath, diff --git a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretOverviewTableRow.tsx b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretOverviewTableRow.tsx index 2a2e1a76a..2099d812d 100644 --- a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretOverviewTableRow.tsx +++ b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretOverviewTableRow.tsx @@ -284,6 +284,7 @@ export const SecretOverviewTableRow = ({ environment={slug} isRotatedSecret={secret?.isRotatedSecret} importedBy={importedBy} + isSecretPresent={Boolean(secret)} /> From fad4b13758e16d736ec2a531bc21eb370375b385 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Tue, 14 Oct 2025 19:12:33 -0300 Subject: [PATCH 22/22] Lint fix --- .../SecretOverviewTableRow/SecretEditRow.tsx | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx index 0ba6314d1..1a33bbca1 100644 --- a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx +++ b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx @@ -115,20 +115,21 @@ export const SecretEditRow = ({ const [isFieldFocused, setIsFieldFocused] = useToggle(); - const fetchSecretValueParams = importedSecret && !isSecretPresent - ? { - environment: importedSecret.environment, - secretPath: importedSecret.secretPath, - secretKey: importedSecret.secret?.key ?? "", - projectId: currentProject.id - } - : { - environment, - secretPath, - secretKey: secretName, - projectId: currentProject.id, - isOverride - }; + const fetchSecretValueParams = + importedSecret && !isSecretPresent + ? { + environment: importedSecret.environment, + secretPath: importedSecret.secretPath, + secretKey: importedSecret.secret?.key ?? "", + projectId: currentProject.id + } + : { + environment, + secretPath, + secretKey: secretName, + projectId: currentProject.id, + isOverride + }; // scott: only fetch value if secret exists, has non-empty value and user has permission const canFetchValue = Boolean(importedSecret ?? secretId) && !isEmpty && !secretValueHidden;