From 3acbae2c1d2e3cfbc8e1762837a5b9860dacdcd1 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Tue, 25 Nov 2025 00:27:59 +0530 Subject: [PATCH 01/26] fix: copy secret audit log --- .../SecretOverviewTableRow/SecretEditRow.tsx | 51 +++++-------------- .../components/SecretListView/SecretItem.tsx | 47 ++++++----------- 2 files changed, 28 insertions(+), 70 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 1a33bbca1..48d2eacd2 100644 --- a/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx +++ b/frontend/src/pages/secret-manager/OverviewPage/components/SecretOverviewTableRow/SecretEditRow.tsx @@ -10,7 +10,6 @@ import { faXmark } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { useQueryClient } from "@tanstack/react-query"; import { twMerge } from "tailwind-merge"; import { createNotification } from "@app/components/notifications"; @@ -33,11 +32,7 @@ import { } from "@app/context"; import { ProjectPermissionSecretActions } from "@app/context/ProjectPermissionContext/types"; import { usePopUp, useToggle } from "@app/hooks"; -import { - dashboardKeys, - fetchSecretValue, - useGetSecretValue -} from "@app/hooks/api/dashboard/queries"; +import { useGetSecretValue } from "@app/hooks/api/dashboard/queries"; import { ProjectEnv, SecretType, SecretV3RawSanitized } from "@app/hooks/api/types"; import { hasSecretReadValueOrDescribePermission } from "@app/lib/fn/permission"; import { CollapsibleSecretImports } from "@app/pages/secret-manager/SecretDashboardPage/components/SecretListView/CollapsibleSecretImports"; @@ -109,8 +104,6 @@ export const SecretEditRow = ({ "editSecret" ] as const); - const queryClient = useQueryClient(); - const { currentProject } = useProject(); const [isFieldFocused, setIsFieldFocused] = useToggle(); @@ -137,19 +130,18 @@ export const SecretEditRow = ({ const { data: secretValueData, isPending: isPendingSecretValueData, - isError: isErrorFetchingSecretValue + isError: isErrorFetchingSecretValue, + refetch: refetchSecretValue } = useGetSecretValue(fetchSecretValueParams, { enabled: canFetchValue && (isVisible || isFieldFocused) }); const isFetchingSecretValue = canFetchValue && isPendingSecretValueData; - const isSecretValueFetched = Boolean(secretValueData); const { handleSubmit, control, reset, - getValues, setValue, formState: { isDirty, isSubmitting } } = useForm({ @@ -178,34 +170,17 @@ export const SecretEditRow = ({ }; const handleCopySecretToClipboard = async () => { - if (!isSecretValueFetched && !isDirty) { - try { - const data = await fetchSecretValue(fetchSecretValueParams); + try { + const { data } = await refetchSecretValue(); - queryClient.setQueryData(dashboardKeys.getSecretValue(fetchSecretValueParams), data); - - await window.navigator.clipboard.writeText(data.valueOverride ?? data.value); - createNotification({ type: "success", text: "Copied secret to clipboard" }); - return; - } catch (e) { - console.error(e); - createNotification({ - type: "error", - text: "Failed to fetch secret value." - }); - return; - } - } - - const { value } = getValues(); - if (value) { - try { - await window.navigator.clipboard.writeText(value); - createNotification({ type: "success", text: "Copied secret to clipboard" }); - } catch (error) { - console.log(error); - createNotification({ type: "error", text: "Failed to copy secret to clipboard" }); - } + await window.navigator.clipboard.writeText(data?.valueOverride ?? data?.value ?? ""); + createNotification({ type: "success", text: "Copied secret to clipboard" }); + } catch (e) { + console.error(e); + createNotification({ + type: "error", + text: "Failed to fetch secret value." + }); } }; diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx index a57995b72..27f180ee9 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx @@ -47,13 +47,9 @@ import { faEyeSlash, faKey, faRotate, faWarning } from "@fortawesome/free-solid- import { PendingAction } from "@app/hooks/api/secretFolders/types"; import { format } from "date-fns"; import { CreateReminderForm } from "@app/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm"; -import { - dashboardKeys, - fetchSecretValue, - useGetSecretValue -} from "@app/hooks/api/dashboard/queries"; +import { useGetSecretValue } from "@app/hooks/api/dashboard/queries"; import { createNotification } from "@app/components/notifications"; -import { useQueryClient } from "@tanstack/react-query"; +import { DashboardSecretValue } from "@app/hooks/api/dashboard/types"; import { FontAwesomeSpriteName, formSchema, @@ -124,7 +120,6 @@ export const SecretItem = memo( const { removePendingChange } = useBatchModeActions(); const [isFieldFocused, setIsFieldFocused] = useToggle(); - const queryClient = useQueryClient(); const canFetchSecretValue = !originalSecret.secretValueHidden && @@ -142,7 +137,8 @@ export const SecretItem = memo( const { data: secretValueData, isPending: isPendingSecretValueData, - isError: isErrorFetchingSecretValue + isError: isErrorFetchingSecretValue, + refetch: refetchSecretValueData } = useGetSecretValue(fetchSecretValueParams, { enabled: canFetchSecretValue && (isVisible || isFieldFocused) }); @@ -210,7 +206,6 @@ export const SecretItem = memo( watch, setValue, reset, - getValues, trigger, formState: { isDirty, isSubmitting, errors }, getFieldState @@ -386,37 +381,25 @@ export const SecretItem = memo( } }; - const fetchValue = async () => { - if (secretValueData) return secretValueData; - - try { - const data = await fetchSecretValue(fetchSecretValueParams); - - queryClient.setQueryData(dashboardKeys.getSecretValue(fetchSecretValueParams), data); - - return data; - } catch (e) { - console.error(e); + const fetchValue = async (): Promise => { + const { data, isRefetchError } = await refetchSecretValueData(); + if (isRefetchError) { createNotification({ type: "error", text: "Failed to fetch secret value" }); - throw e; } + if (!data) return undefined; + + return data; }; const copyTokenToClipboard = async () => { - if (hasFetchedSecretValue) { - const [overrideValue, value] = getValues(["value", "valueOverride"]); - if (isOverridden) { - navigator.clipboard.writeText(value as string); - } else { - navigator.clipboard.writeText(overrideValue as string); - } - } else { - const data = await fetchValue(); - navigator.clipboard.writeText((data.valueOverride ?? data.value) as string); - } + const data = await fetchValue(); + if (!data) return; + + navigator.clipboard.writeText((data.valueOverride ?? data.value) as string); + setIsSecValueCopied.on(); }; From 95fdff7747fe3e192b065b9f98b4cc8e65fe89a4 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Mon, 24 Nov 2025 19:59:00 -0300 Subject: [PATCH 02/26] documentation update --- .env.example | 15 +- .../getting-started/introduction.mdx | 8 - docker-swarm/.env-example | 16 -- .../overview/examples/integration.mdx | 90 -------- docs/docs.json | 84 +------- docs/documentation/guides/nextjs-vercel.mdx | 29 +-- docs/documentation/platform/integrations.mdx | 12 -- docs/integrations/app-connections/gitlab.mdx | 2 + .../integrations/app-connections/overview.mdx | 4 - .../{cloud => cicd}/aws-amplify.mdx | 2 +- docs/integrations/cicd/bitbucket.mdx | 24 +-- docs/integrations/{cloud => cicd}/checkly.mdx | 0 docs/integrations/cicd/circleci.mdx | 40 ---- docs/integrations/cicd/codefresh.mdx | 32 --- docs/integrations/cicd/githubactions.mdx | 204 +----------------- docs/integrations/cicd/gitlab.mdx | 74 +------ docs/integrations/cicd/octopus-deploy.mdx | 76 ------- docs/integrations/cicd/rundeck.mdx | 32 --- .../integrations/{cloud => cicd}/teamcity.mdx | 0 docs/integrations/cicd/travisci.mdx | 31 --- .../cloud/aws-parameter-store.mdx | 8 - .../integrations/cloud/aws-secret-manager.mdx | 8 - .../cloud/azure-app-configuration.mdx | 8 - docs/integrations/cloud/azure-devops.mdx | 55 ----- docs/integrations/cloud/azure-key-vault.mdx | 8 - docs/integrations/cloud/cloud-66.mdx | 48 ----- docs/integrations/cloud/cloudflare-pages.mdx | 39 ---- .../integrations/cloud/cloudflare-workers.mdx | 39 ---- docs/integrations/cloud/databricks.mdx | 8 - .../cloud/digital-ocean-app-platform.mdx | 32 --- docs/integrations/cloud/flyio.mdx | 32 --- .../integrations/cloud/gcp-secret-manager.mdx | 8 - docs/integrations/cloud/hashicorp-vault.mdx | 8 - docs/integrations/cloud/hasura-cloud.mdx | 31 --- docs/integrations/cloud/heroku.mdx | 71 ------ docs/integrations/cloud/laravel-forge.mdx | 38 ---- docs/integrations/cloud/netlify.mdx | 66 ------ docs/integrations/cloud/northflank.mdx | 33 --- docs/integrations/cloud/qovery.mdx | 38 ---- docs/integrations/cloud/railway.mdx | 47 ---- docs/integrations/cloud/render.mdx | 9 - docs/integrations/cloud/supabase.mdx | 39 ---- docs/integrations/cloud/terraform-cloud.mdx | 8 - docs/integrations/cloud/vercel.mdx | 8 - docs/integrations/cloud/windmill.mdx | 8 - docs/integrations/overview.mdx | 61 ------ docs/integrations/secret-syncs/overview.mdx | 6 +- docs/self-hosting/configuration/envars.mdx | 104 --------- 48 files changed, 21 insertions(+), 1622 deletions(-) delete mode 100644 docs/api-reference/overview/examples/integration.mdx delete mode 100644 docs/documentation/platform/integrations.mdx rename docs/integrations/{cloud => cicd}/aws-amplify.mdx (96%) rename docs/integrations/{cloud => cicd}/checkly.mdx (100%) delete mode 100644 docs/integrations/cicd/circleci.mdx delete mode 100644 docs/integrations/cicd/codefresh.mdx delete mode 100644 docs/integrations/cicd/octopus-deploy.mdx delete mode 100644 docs/integrations/cicd/rundeck.mdx rename docs/integrations/{cloud => cicd}/teamcity.mdx (100%) delete mode 100644 docs/integrations/cicd/travisci.mdx delete mode 100644 docs/integrations/cloud/aws-parameter-store.mdx delete mode 100644 docs/integrations/cloud/aws-secret-manager.mdx delete mode 100644 docs/integrations/cloud/azure-app-configuration.mdx delete mode 100644 docs/integrations/cloud/azure-devops.mdx delete mode 100644 docs/integrations/cloud/azure-key-vault.mdx delete mode 100644 docs/integrations/cloud/cloud-66.mdx delete mode 100644 docs/integrations/cloud/cloudflare-pages.mdx delete mode 100644 docs/integrations/cloud/cloudflare-workers.mdx delete mode 100644 docs/integrations/cloud/databricks.mdx delete mode 100644 docs/integrations/cloud/digital-ocean-app-platform.mdx delete mode 100644 docs/integrations/cloud/flyio.mdx delete mode 100644 docs/integrations/cloud/gcp-secret-manager.mdx delete mode 100644 docs/integrations/cloud/hashicorp-vault.mdx delete mode 100644 docs/integrations/cloud/hasura-cloud.mdx delete mode 100644 docs/integrations/cloud/heroku.mdx delete mode 100644 docs/integrations/cloud/laravel-forge.mdx delete mode 100644 docs/integrations/cloud/netlify.mdx delete mode 100644 docs/integrations/cloud/northflank.mdx delete mode 100644 docs/integrations/cloud/qovery.mdx delete mode 100644 docs/integrations/cloud/railway.mdx delete mode 100644 docs/integrations/cloud/render.mdx delete mode 100644 docs/integrations/cloud/supabase.mdx delete mode 100644 docs/integrations/cloud/terraform-cloud.mdx delete mode 100644 docs/integrations/cloud/vercel.mdx delete mode 100644 docs/integrations/cloud/windmill.mdx delete mode 100644 docs/integrations/overview.mdx diff --git a/.env.example b/.env.example index f67488c23..9da28e528 100644 --- a/.env.example +++ b/.env.example @@ -31,25 +31,14 @@ SMTP_FROM_NAME= SMTP_USERNAME= SMTP_PASSWORD= -# Integration -# Optional only if integration is used -CLIENT_ID_HEROKU= -CLIENT_ID_VERCEL= -CLIENT_ID_NETLIFY= +# CICD Integration CLIENT_ID_GITHUB= CLIENT_ID_GITHUB_APP= CLIENT_SLUG_GITHUB_APP= -CLIENT_ID_GITLAB= -CLIENT_ID_BITBUCKET= -CLIENT_SECRET_HEROKU= -CLIENT_SECRET_VERCEL= -CLIENT_SECRET_NETLIFY= CLIENT_SECRET_GITHUB= CLIENT_SECRET_GITHUB_APP= +CLIENT_ID_GITLAB= CLIENT_SECRET_GITLAB= -CLIENT_SECRET_BITBUCKET= -CLIENT_SLUG_VERCEL= - CLIENT_PRIVATE_KEY_GITHUB_APP= CLIENT_APP_ID_GITHUB_APP= diff --git a/company/documentation/getting-started/introduction.mdx b/company/documentation/getting-started/introduction.mdx index 55b483194..74694703e 100644 --- a/company/documentation/getting-started/introduction.mdx +++ b/company/documentation/getting-started/introduction.mdx @@ -95,12 +95,4 @@ Depending on your use case, it might be helpful to look into some of the resourc > Fetch secrets via HTTP request. - - Explore integrations for GitHub, Vercel, AWS, and more. - diff --git a/docker-swarm/.env-example b/docker-swarm/.env-example index a30e3bba6..8a132914b 100644 --- a/docker-swarm/.env-example +++ b/docker-swarm/.env-example @@ -25,22 +25,6 @@ SMTP_FROM_NAME= SMTP_USERNAME= SMTP_PASSWORD= -# Integration -# Optional only if integration is used -CLIENT_ID_HEROKU= -CLIENT_ID_VERCEL= -CLIENT_ID_NETLIFY= -CLIENT_ID_GITHUB= -CLIENT_ID_GITLAB= -CLIENT_ID_BITBUCKET= -CLIENT_SECRET_HEROKU= -CLIENT_SECRET_VERCEL= -CLIENT_SECRET_NETLIFY= -CLIENT_SECRET_GITHUB= -CLIENT_SECRET_GITLAB= -CLIENT_SECRET_BITBUCKET= -CLIENT_SLUG_VERCEL= - # Sentry (optional) for monitoring errors SENTRY_DSN= diff --git a/docs/api-reference/overview/examples/integration.mdx b/docs/api-reference/overview/examples/integration.mdx deleted file mode 100644 index 71f5b6de4..000000000 --- a/docs/api-reference/overview/examples/integration.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Configure native integrations via API" -description: "How to use Infisical API to sync secrets to external secret managers" ---- - -The Infisical API allows you to create programmatic integrations that connect with third-party secret managers to synchronize secrets from Infisical. - -This guide will primarily demonstrate the process using AWS Secret Store Manager (AWS SSM), but the steps are generally applicable to other secret management integrations. - - - For details on setting up AWS SSM synchronization and understanding its prerequisites, refer to the [AWS SSM integration setup documentation](../../../integrations/cloud/aws-secret-manager). - - - - - Authentication is required for all integrations. Use the [Integration Auth API](../../endpoints/integrations/create-auth) with the following parameters to authenticate. - - - Set this parameter to **aws-secret-manager**. - - - The Infisical project ID for the integration. - - - The AWS IAM User Access ID. - - - The AWS IAM User Access Secret Key. - - - ```bash Request - curl --request POST \ - --url https://app.infisical.com/api/v1/integration-auth/access-token \ - --header 'Authorization: ' \ - --header 'Content-Type: application/json' \ - --data '{ - "workspaceId": "", - "integration": "aws-secret-manager", - "accessId": "", - "accessToken": "" - }' - ``` - - - - Once authentication between AWS SSM and Infisical is established, you can configure the synchronization behavior. - This involves specifying the source (environment and secret path in Infisical) and the destination in SSM to which the secrets will be synchronized. - - Use the [integration API](../../endpoints/integrations/create) with the following parameters to configure the sync source and destination. - - - The ID of the integration authentication object used with AWS, obtained from the previous API response. - - - Indicates whether the integration should be active or inactive. - - - The secret name for saving in AWS SSM, which can be arbitrarily chosen. - - - The AWS region where the SSM is located, e.g., `us-east-1`. - - - The Infisical environment slug from which secrets will be synchronized, e.g., `dev`. - - - The Infisical folder path from which secrets will be synchronized, e.g., `/some/path`. The root path is `/`. - - - ```bash Request - curl --request POST \ - --url https://app.infisical.com/api/v1/integration \ - --header 'Authorization: ' \ - --header 'Content-Type: application/json' \ - --data '{ - "integrationAuthId": "", - "sourceEnvironment": "", - "secretPath": "", - "app": "", - "region": "" - }' - ``` - - - - - -Congratulations! You have successfully set up an integration to synchronize secrets from Infisical with AWS SSM. -For more information, [view the integration API reference](../../endpoints/integrations). - \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json index 57f44596f..04b9e5efa 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -568,71 +568,15 @@ } ] }, - { - "group": "Native Integrations", - "pages": [ - { - "group": "AWS", - "pages": [ - "integrations/cloud/aws-parameter-store", - "integrations/cloud/aws-secret-manager", - "integrations/cloud/aws-amplify" - ] - }, - "integrations/cloud/vercel", - "integrations/cloud/azure-key-vault", - "integrations/cloud/azure-app-configuration", - "integrations/cloud/azure-devops", - "integrations/cloud/gcp-secret-manager", - { - "group": "Cloudflare", - "pages": [ - "integrations/cloud/cloudflare-pages", - "integrations/cloud/cloudflare-workers" - ] - }, - "integrations/cloud/terraform-cloud", - "integrations/cloud/databricks", - { - "group": "View more", - "pages": [ - "integrations/cloud/digital-ocean-app-platform", - "integrations/cloud/heroku", - "integrations/cloud/netlify", - "integrations/cloud/flyio", - "integrations/cloud/railway", - "integrations/cloud/render", - "integrations/cloud/laravel-forge", - "integrations/cloud/supabase", - "integrations/cloud/northflank", - "integrations/cloud/hasura-cloud", - "integrations/cloud/qovery", - "integrations/cloud/hashicorp-vault", - "integrations/cloud/cloud-66", - "integrations/cloud/windmill" - ] - } - ] - }, { "group": "CI/CD Integrations", "pages": [ - "integrations/cicd/jenkins", + "integrations/cicd/aws-amplify", + "integrations/cicd/bitbucket", + "integrations/cicd/checkly", "integrations/cicd/githubactions", "integrations/cicd/gitlab", - "integrations/cicd/bitbucket", - "integrations/cloud/teamcity", - { - "group": "View more", - "pages": [ - "integrations/cicd/circleci", - "integrations/cicd/travisci", - "integrations/cicd/rundeck", - "integrations/cicd/codefresh", - "integrations/cloud/checkly", - "integrations/cicd/octopus-deploy" - ] - } + "integrations/cicd/jenkins" ] }, { @@ -884,11 +828,7 @@ "group": "Overview", "pages": [ "api-reference/overview/introduction", - "api-reference/overview/authentication", - { - "group": "Examples", - "pages": ["api-reference/overview/examples/integration"] - } + "api-reference/overview/authentication" ] }, { @@ -2490,20 +2430,6 @@ ] } ] - }, - { - "group": "Integrations", - "pages": [ - "api-reference/endpoints/integrations/create-auth", - "api-reference/endpoints/integrations/list-auth", - "api-reference/endpoints/integrations/find-auth", - "api-reference/endpoints/integrations/delete-auth", - "api-reference/endpoints/integrations/delete-auth-by-id", - "api-reference/endpoints/integrations/create", - "api-reference/endpoints/integrations/update", - "api-reference/endpoints/integrations/delete", - "api-reference/endpoints/integrations/list-project-integrations" - ] } ] }, diff --git a/docs/documentation/guides/nextjs-vercel.mdx b/docs/documentation/guides/nextjs-vercel.mdx index ecefb0f2e..d0cdd639e 100644 --- a/docs/documentation/guides/nextjs-vercel.mdx +++ b/docs/documentation/guides/nextjs-vercel.mdx @@ -183,32 +183,7 @@ At this stage, you know how to use the Infisical CLI to inject secrets into your ## Infisical-Vercel integration for production environment variables -We'll now use the Infisical-Vercel integration send secrets from Infisical to Vercel as production environment variables. - -### Infisical-Vercel integration - -To begin we have to import the Next.js app into Vercel as a project. [Follow these instructions](https://vercel.com/docs/frameworks/nextjs) to deploy the Next.js app to Vercel. - -Next, navigate to your project's integrations tab in Infisical and press on the Vercel tile to grant Infisical access to your Vercel account. - -![integrations](../../images/integrations.png) - -![integrations vercel authorization](../../images/integrations/vercel/integrations-vercel-auth.png) - - - Opting in for the Infisical-Vercel integration will break end-to-end encryption since Infisical will be able to read - your secrets. This is, however, necessary for Infisical to sync the secrets to Vercel. - - Your secrets remain encrypted at rest following our [security guide mechanics](/internals/security). - - -Now select **Production** for (the source) **Environment** and sync it to the **Production Environment** of the (target) application in Vercel. -Lastly, press create integration to start syncing secrets to Vercel. - -![integrations vercel](../../images/integrations/vercel/integrations-vercel-create.png) -![integrations vercel](../../images/integrations/vercel/integrations-vercel.png) - -You should now see your secret from Infisical appear as production environment variables in your Vercel project. +Use our [Vercel Secret Syncs](../../integrations/secret-syncs/vercel) guide to sync secrets from Infisical to Vercel as production environment variables. At this stage, you know how to use the Infisical-Vercel integration to sync production secrets from Infisical to Vercel. @@ -245,4 +220,4 @@ At this stage, you know how to use the Infisical-Vercel integration to sync prod See also: - [Documentation for the Infisical CLI](/cli/overview) -- [Documentation for the Vercel integration](/integrations/cloud/vercel) +- [Documentation for the Vercel Secret Sync](../../integrations/secret-syncs/vercel) diff --git a/docs/documentation/platform/integrations.mdx b/docs/documentation/platform/integrations.mdx deleted file mode 100644 index 2414c5c14..000000000 --- a/docs/documentation/platform/integrations.mdx +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Integrations" -description: "How to sync your secrets among various 3rd-party services with Infisical." ---- - -Integrations allow environment variables to be synced across your entire infrastructure from local development to CI/CD and production. - - - View all available integrations and their guides - - -![integrations](../../images/integrations.png) diff --git a/docs/integrations/app-connections/gitlab.mdx b/docs/integrations/app-connections/gitlab.mdx index c9af952a7..d17322540 100644 --- a/docs/integrations/app-connections/gitlab.mdx +++ b/docs/integrations/app-connections/gitlab.mdx @@ -12,6 +12,8 @@ Infisical supports two methods for connecting to GitLab: **OAuth** and **Access Using the GitLab Connection with OAuth on a self-hosted instance of Infisical requires configuring an OAuth application in GitLab and registering your instance with it. + If you're self-hosting Gitlab with custom certificates, you will have to configure your Infisical instance to trust these certificates. To learn how, please follow [this guide](../../self-hosting/guides/custom-certificates). + **Prerequisites:** - A GitLab account with existing projects - Self-hosted Infisical instance diff --git a/docs/integrations/app-connections/overview.mdx b/docs/integrations/app-connections/overview.mdx index 8b1032e7d..1201ca3ca 100644 --- a/docs/integrations/app-connections/overview.mdx +++ b/docs/integrations/app-connections/overview.mdx @@ -75,10 +75,6 @@ to limit the access of this entity to the minimal permission set required to per 4. Utilize the Connection: Use your App Connection for various features across Infisical such as our Secrets Sync by selecting it via the dropdown menu in the UI or by passing the associated `connectionId` when generating resources via the API. - - Infisical is continuously expanding its third-party application support. If your desired application isn't listed, - you can still use previous methods of connecting to it such as our Native Integrations. - ## Platform Managed Credentials diff --git a/docs/integrations/cloud/aws-amplify.mdx b/docs/integrations/cicd/aws-amplify.mdx similarity index 96% rename from docs/integrations/cloud/aws-amplify.mdx rename to docs/integrations/cicd/aws-amplify.mdx index 6d3123b10..9b4b81ccb 100644 --- a/docs/integrations/cloud/aws-amplify.mdx +++ b/docs/integrations/cicd/aws-amplify.mdx @@ -108,7 +108,7 @@ This approach enables you to fetch secrets from Infisical during Amplify build t - Follow the [Infisical AWS SSM Parameter Store Integration Guide](./aws-parameter-store) to set up the integration. Pause once you reach the step where it asks you to select the path you would like to sync. + Follow the [Infisical AWS SSM Parameter Store Secret Syncs Guide](../secret-syncs/aws-parameter-store) to set up the integration. Pause once you reach the step where it asks you to select the path you would like to sync. ![amplify app id](../../images/integrations/aws/integrations-amplify-app-id.png) diff --git a/docs/integrations/cicd/bitbucket.mdx b/docs/integrations/cicd/bitbucket.mdx index 3c1330308..44893a5b6 100644 --- a/docs/integrations/cicd/bitbucket.mdx +++ b/docs/integrations/cicd/bitbucket.mdx @@ -12,29 +12,7 @@ Prerequisites: - - - Navigate to your project's integrations tab in Infisical. - - ![integrations](/images/integrations.png) - - Press on the Bitbucket tile and grant Infisical access to your Bitbucket account. - - ![integrations bitbucket authorization](/images/integrations/bitbucket/integrations-bitbucket.png) - - - Select which workspace, repository, and optionally, deployment environment, you'd like to sync your secrets - to. - ![integrations configure - bitbucket](/images/integrations/bitbucket/integrations-bitbucket-configuration.png) - - Once created, your integration will begin syncing secrets to the configured repository or deployment - environment. - - ![integrations bitbucket](/images/integrations/bitbucket/integrations-bitbucket.png) - - - + Use our [Bitbucket Secret Syncs](../secret-syncs/bitbucket) diff --git a/docs/integrations/cloud/checkly.mdx b/docs/integrations/cicd/checkly.mdx similarity index 100% rename from docs/integrations/cloud/checkly.mdx rename to docs/integrations/cicd/checkly.mdx diff --git a/docs/integrations/cicd/circleci.mdx b/docs/integrations/cicd/circleci.mdx deleted file mode 100644 index 5bf04822d..000000000 --- a/docs/integrations/cicd/circleci.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "CircleCI" -description: "How to sync secrets from Infisical to CircleCI" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain an API token in User Settings > Personal API Tokens - - ![integrations circleci token](/images/integrations/circleci/integrations-circleci-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](/images/integrations.png) - - Press on the CircleCI tile and input your CircleCI API token to grant Infisical access to your CircleCI account. - - ![integrations circleci authorization](/images/integrations/circleci/integrations-circleci-auth.png) - - - - Select which Infisical environment secrets you want to sync to which CircleCI project or context. - - - ![integrations circle ci project](/images/integrations/circleci/integrations-circleci-create-project.png) - - - ![integrations circle ci project](/images/integrations/circleci/integrations-circleci-create-context.png) - - - - Finally, press create integration to start syncing secrets to CircleCI. - ![integrations circleci](/images/integrations/circleci/integrations-circleci.png) - - - diff --git a/docs/integrations/cicd/codefresh.mdx b/docs/integrations/cicd/codefresh.mdx deleted file mode 100644 index cf69ae04d..000000000 --- a/docs/integrations/cicd/codefresh.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Codefresh" -description: "How to sync secrets from Infisical to Codefresh" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain an API key in User Settings > API Keys - - ![integrations codefresh dashboard](../../images/integrations/codefresh/integrations-codefresh-dashboard.png) - ![integrations codefresh token](../../images/integrations/codefresh/integrations-codefresh-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Codefresh tile and input your Codefresh API key to grant Infisical access to your Codefresh account. - - ![integrations codefresh authorization](../../images/integrations/codefresh/integrations-codefresh-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Codefresh service and press create integration to start syncing secrets to Codefresh. - - ![create integration codefresh](../../images/integrations/codefresh/integrations-codefresh-create.png) - ![integrations codefresh](../../images/integrations/codefresh/integrations-codefresh.png) - - \ No newline at end of file diff --git a/docs/integrations/cicd/githubactions.mdx b/docs/integrations/cicd/githubactions.mdx index 82076874c..fa4387413 100644 --- a/docs/integrations/cicd/githubactions.mdx +++ b/docs/integrations/cicd/githubactions.mdx @@ -4,204 +4,6 @@ description: "How to sync secrets from Infisical to GitHub Actions" --- - Alternatively, you can use Infisical's official GitHub Action - [here](https://github.com/Infisical/secrets-action). - - -Infisical lets you sync secrets to GitHub at the organization-level, repository-level, and repository environment-level. - -## Connecting with GitHub App (Recommended) - - - - - - Navigate to your project's integrations tab in Infisical and press on the GitHub tile. - - ![integrations](../../images/integrations/github/app/integration-overview.png) - - Select GitHub App as the authentication method and click **Connect to GitHub**. - - ![integrations github app auth selection](../../images/integrations/github/app/github-app-method-selection.png) - - You will then be redirected to the GitHub app installation page. - - ![integrations github app installation](../../images/integrations/github/app/github-app-installation.png) - - Install and authorize the GitHub application. This will redirect you back to the Infisical integration page. - - - - Select which Infisical environment secrets you want to sync to which GitHub organization, repository, or repository environment. - - - - ![integrations github](../../images/integrations/github/integrations-github-scope-repo.png) - - - ![integrations github](../../images/integrations/github/integrations-github-scope-org.png) - - When using the organization scope, your secrets will be saved in the top-level of your GitHub Organization. - - You can choose the visibility, which defines which repositories can access the secrets. The options are: - - **All public repositories**: All public repositories in the organization can access the secrets. - - **All private repositories**: All private repositories in the organization can access the secrets. - - **Selected repositories**: Only the selected repositories can access the secrets. This gives a more fine-grained control over which repositories can access the secrets. You can select _both_ private and public repositories with this option. - - - ![integrations github](../../images/integrations/github/integrations-github-scope-env.png) - - - - Finally, press create integration to start syncing secrets to GitHub. - - ![integrations github](../../images/integrations/github/integrations-github.png) - - - - - - Using the GitHub integration with app authentication on a self-hosted instance of Infisical requires configuring an application on GitHub - and registering your instance with it. - - - Navigate to the GitHub app settings [here](https://github.com/settings/apps). Click **New GitHub App**. - - ![integrations github app create](../../images/integrations/github/app/self-hosted-github-app-create.png) - - Give the application a name, a homepage URL (your self-hosted domain i.e. `https://your-domain.com`), and a callback URL (i.e. `https://your-domain.com/integrations/github/oauth2/callback`). - - ![integrations github app basic details](../../images/integrations/github/app/self-hosted-github-app-basic-details.png) - - Enable request user authorization during app installation. - ![integrations github app enable auth](../../images/integrations/github/app/self-hosted-github-app-enable-oauth.png) - - Disable webhook by unchecking the Active checkbox. - ![integrations github app webhook](../../images/integrations/github/app/self-hosted-github-app-webhook.png) - - Set the repository permissions as follows: Metadata: Read-only, Secrets: Read and write, Environments: Read and write, Actions: Read. - ![integrations github app repository](../../images/integrations/github/app/self-hosted-github-app-repository.png) - - Similarly, set the organization permissions as follows: Secrets: Read and write. - ![integrations github app organization](../../images/integrations/github/app/self-hosted-github-app-organization.png) - - Create the Github application. - ![integrations github app create confirm](../../images/integrations/github/app/self-hosted-github-app-create-confirm.png) - - - If you have a GitHub organization, you can create an application under it - in your organization Settings > Developer settings > GitHub Apps > New GitHub App. - - - - Generate a new **Client Secret** for your GitHub application. - ![integrations github app create secret](../../images/integrations/github/app/self-hosted-github-app-secret.png) - - Generate a new **Private Key** for your Github application. - ![integrations github app create private key](../../images/integrations/github/app/self-hosted-github-app-private-key.png) - - Obtain the necessary Github application credentials. This would be the application slug, client ID, app ID, client secret, and private key. - ![integrations github app credentials](../../images/integrations/github/app/self-hosted-github-app-credentials.png) - - Back in your Infisical instance, add the five new environment variables for the credentials of your GitHub application: - - - `CLIENT_ID_GITHUB_APP`: The **Client ID** of your GitHub application. - - `CLIENT_SECRET_GITHUB_APP`: The **Client Secret** of your GitHub application. - - `CLIENT_SLUG_GITHUB_APP`: The **Slug** of your GitHub application. This is the one found in the URL. - - `CLIENT_APP_ID_GITHUB_APP`: The **App ID** of your GitHub application. - - `CLIENT_PRIVATE_KEY_GITHUB_APP`: The **Private Key** of your GitHub application. - - Once added, restart your Infisical instance and use the GitHub integration via app authentication. - - - - - - -## Connecting with GitHub OAuth - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) -- Ensure that you have admin privileges to the repository you want to sync secrets to. - - - - - - Navigate to your project's integrations tab in Infisical and press on the GitHub tile. - ![integrations](../../images/integrations/github/integration-overview.png) - - Select OAuth as the authentication method and click **Connect to GitHub**. - ![integrations github oauth auth selection](../../images/integrations/github/github-oauth-method-selection.png) - - Grant Infisical access to your GitHub account (organization and repo privileges). - ![integrations github authorization](../../images/integrations/github/integrations-github-auth.png) - - - - Select which Infisical environment secrets you want to sync to which GitHub organization, repository, or repository environment. - - - - ![integrations github](../../images/integrations/github/integrations-github-scope-repo.png) - - - ![integrations github](../../images/integrations/github/integrations-github-scope-org.png) - - When using the organization scope, your secrets will be saved in the top-level of your GitHub Organization. - - You can choose the visibility, which defines which repositories can access the secrets. The options are: - - **All public repositories**: All public repositories in the organization can access the secrets. - - **All private repositories**: All private repositories in the organization can access the secrets. - - **Selected repositories**: Only the selected repositories can access the secrets. This gives a more fine-grained control over which repositories can access the secrets. You can select _both_ private and public repositories with this option. - - - ![integrations github](../../images/integrations/github/integrations-github-scope-env.png) - - - - Finally, press create integration to start syncing secrets to GitHub. - - ![integrations github](../../images/integrations/github/integrations-github.png) - - - - - - Using the GitHub integration on a self-hosted instance of Infisical requires configuring an OAuth application in GitHub - and registering your instance with it. - - - Navigate to your user Settings > Developer settings > OAuth Apps to create a new GitHub OAuth application. - - ![integrations github config](../../images/integrations/github/integrations-github-config-settings.png) - ![integrations github config](../../images/integrations/github/integrations-github-config-dev-settings.png) - ![integrations github config](../../images/integrations/github/integrations-github-config-new-app.png) - - Create the OAuth application. As part of the form, set the **Homepage URL** to your self-hosted domain `https://your-domain.com` - and the **Authorization callback URL** to `https://your-domain.com/integrations/github/oauth2/callback`. - - ![integrations github config](../../images/integrations/github/integrations-github-config-new-app-form.png) - - - If you have a GitHub organization, you can create an OAuth application under it - in your organization Settings > Developer settings > OAuth Apps > New Org OAuth App. - - - - Obtain the **Client ID** and generate a new **Client Secret** for your GitHub OAuth application. - - ![integrations github config](../../images/integrations/github/integrations-github-config-credentials.png) - - Back in your Infisical instance, add two new environment variables for the credentials of your GitHub OAuth application: - - - `CLIENT_ID_GITHUB`: The **Client ID** of your GitHub OAuth application. - - `CLIENT_SECRET_GITHUB`: The **Client Secret** of your GitHub OAuth application. - - Once added, restart your Infisical instance and use the GitHub integration. - - - - - + Use our [GitHub Secret Syncs](../secret-syncs/github) to sync secrets to GitHub at the organization-level, repository-level, and repository environment-level. + Alternatively, you can use Infisical's official GitHub Action [here](https://github.com/Infisical/secrets-action). + \ No newline at end of file diff --git a/docs/integrations/cicd/gitlab.mdx b/docs/integrations/cicd/gitlab.mdx index 2da61ef77..7cbf9512e 100644 --- a/docs/integrations/cicd/gitlab.mdx +++ b/docs/integrations/cicd/gitlab.mdx @@ -3,41 +3,13 @@ title: "GitLab" description: "How to sync secrets from Infisical to GitLab" --- - - + Prerequisites: - - Set up and add envars to [Infisical Cloud](https://app.infisical.com) + - Set up and add envars to [Infisical Cloud](https://app.infisical.com). - - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the GitLab tile and grant Infisical access to your GitLab account. - - ![integrations gitlab authorization](../../images/integrations/gitlab/integrations-gitlab-auth.png) - - - - Select which Infisical environment secrets you want to sync to which GitLab repository and press create integration to start syncing secrets to GitLab. - - ![integrations gitlab](../../images/integrations/gitlab/integrations-gitlab-create.png) - - Note that the GitLab integration supports a few options in the **Options** tab: - - - Secret Prefix: If inputted, the prefix is appended to the front of every secret name prior to being synced. - - Secret Suffix: If inputted, the suffix to appended to the back of every name of every secret prior to being synced. - - Setting a secret prefix or suffix ensures that existing secrets in GitLab are not overwritten during the sync. As part of this process, Infisical abstains from mutating any secrets in GitLab without the specified prefix or suffix. - - ![integrations gitlab options](../../images/integrations/gitlab/integrations-gitlab-create-options.png) - - ![integrations gitlab](../../images/integrations/gitlab/integrations-gitlab.png) - - + Use our [GitLab Secret Syncs](../secret-syncs/gitlab) @@ -70,42 +42,4 @@ description: "How to sync secrets from Infisical to GitLab" - - - - - Using the GitLab integration on a self-hosted instance of Infisical requires configuring an application in GitLab - and registering your instance with it. - If you're self-hosting Gitlab with custom certificates, you will have to configure your Infisical instance to trust these certificates. To learn how, please follow [this guide](../../self-hosting/guides/custom-certificates). - - - Navigate to your user Settings > Applications to create a new GitLab application. - - ![integrations gitlab config](../../images/integrations/gitlab/integrations-gitlab-config-edit-profile.png) - ![integrations gitlab config](../../images/integrations/gitlab/integrations-gitlab-config-new-app.png) - - Create the application. As part of the form, set the **Redirect URI** to `https://your-domain.com/integrations/gitlab/oauth2/callback`. - - ![integrations gitlab config](../../images/integrations/gitlab/integrations-gitlab-config-new-app-form.png) - - - If you have a GitLab group, you can create an OAuth application under it - in your group Settings > Applications. - - - - Obtain the **Application ID** and **Secret** for your GitLab application. - - ![integrations gitlab config](../../images/integrations/gitlab/integrations-gitlab-config-credentials.png) - - Back in your Infisical instance, add two new environment variables for the credentials of your GitLab application: - - - `CLIENT_ID_GITLAB`: The **Client ID** of your GitLab application. - - `CLIENT_SECRET_GITLAB`: The **Secret** of your GitLab application. - - Once added, restart your Infisical instance and use the GitLab integration. - - - - - + \ No newline at end of file diff --git a/docs/integrations/cicd/octopus-deploy.mdx b/docs/integrations/cicd/octopus-deploy.mdx deleted file mode 100644 index 90f06e09a..000000000 --- a/docs/integrations/cicd/octopus-deploy.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Octopus Deploy" -description: "Learn how to sync secrets from Infisical to Octopus Deploy" ---- - -Prerequisites: - -- Set up and add secrets to [Infisical Cloud](https://app.infisical.com) - - - - Navigate to **Configuration** > **Users** and click on the **Create Service Account** button. - - ![integrations octopus deploy - users](/images/integrations/octopus-deploy/integrations-octopus-deploy-user-settings.png) - - Fill out the required fields and click on the **Save** button. - ![integrations octopus deploy service - account](/images/integrations/octopus-deploy/integrations-octopus-deploy-create-service-account.png) - - - On the **Service Account** user page, expand the **API Keys** section and click on the **New API Key** button. - - ![integrations octopus deploy - new api key](/images/integrations/octopus-deploy/integrations-octopus-deploy-create-api-key.png) - - Fill out the required fields and click on the **Generate New** button. - - ![integrations octopus deploy - generate api key](/images/integrations/octopus-deploy/integrations-octopus-deploy-generate-api-key.png) - - If you configure your access token to expire, - you will need to generate a new API key for Infisical prior to this date to keep your integration running. - - Copy the generated **API Key** and click on the **Close** button. - - ![integrations octopus deploy - copy api key](/images/integrations/octopus-deploy/integrations-octopus-deploy-copy-api-key.png) - - - You can skip creating a new team if you already have an Octopus Deploy team configured with - the **Project Contributor** role to assign your Service Account to. - - Navigate to **Configuration** > **Teams** and click on the **Add Team** button. - - ![integrations octopus deploy - teams](/images/integrations/octopus-deploy/integrations-octopus-deploy-team-settings.png) - - Create a new team for **Service Accounts** and click on the **Save** button. - ![integrations octopus deploy add - team](/images/integrations/octopus-deploy/integrations-octopus-deploy-create-team.png) - - On the **Members** tab, click on the **Add Member** button, add your **Infisical Service Account** and click on the **Add** button. - ![integrations octopus deploy add service account to team](/images/integrations/octopus-deploy/integrations-octopus-deploy-add-to-team.png) - - On the **User Roles** tab, click on the **Include User Role** button, and add the **Project Contributor** role. Optionally, - click on the **Define Scope** button to further refine what projects your Service Account has access to. Click on the **Apply** button once complete. - ![integrations octopus deploy add user roles to team](/images/integrations/octopus-deploy/integrations-octopus-deploy-add-role.png) - - Save your team changes by clicking on the **Save** button. - ![integrations octopus deploy save team changes](/images/integrations/octopus-deploy/integrations-octopus-deploy-save-team.png) - - - In Infisical, navigate to your **Project** > **Integrations** page and select the **Octopus Deploy** integration. - ![integration octopus deploy](/images/integrations/octopus-deploy/integrations-octopus-deploy-integrations.png) - - Enter your **Instance URL** and **API Key** from **Octopus Deploy** to authorize Infisical. - ![integration octopus deploy](/images/integrations/octopus-deploy/integrations-octopus-deploy-authorize.png) - - Select a **Space** and **Project** from **Octopus Deploy** to sync secrets to; configuring additional **Scope Values** as needed. Click on the **Create Integration** button once configured. - ![integration octopus deploy](/images/integrations/octopus-deploy/integrations-octopus-deploy-create.png) - - Your Infisical secrets will begin to sync to **Octopus Deploy**. - ![integration octopus deploy](/images/integrations/octopus-deploy/integrations-octopus-deploy-sync.png) - - \ No newline at end of file diff --git a/docs/integrations/cicd/rundeck.mdx b/docs/integrations/cicd/rundeck.mdx deleted file mode 100644 index bda7d8162..000000000 --- a/docs/integrations/cicd/rundeck.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Rundeck" -description: "How to sync secrets from Infisical to Rundeck" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a User API Token in the Profile settings of Rundeck - - ![integrations rundeck token](../../images/integrations/rundeck/integrations-rundeck-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Rundeck tile and input your Rundeck instance Base URL and User API token to grant Infisical access to manage Rundeck keys - - ![integrations rundeck authorization](../../images/integrations/rundeck/integrations-rundeck-auth.png) - - - - Select which Infisical environment secrets you want to sync to a Rundeck Key Storage Path and press create integration to start syncing secrets to Rundeck. - - ![create integration rundeck](../../images/integrations/rundeck/integrations-rundeck-create.png) - ![integrations rundeck](../../images/integrations/rundeck/integrations-rundeck.png) - - - diff --git a/docs/integrations/cloud/teamcity.mdx b/docs/integrations/cicd/teamcity.mdx similarity index 100% rename from docs/integrations/cloud/teamcity.mdx rename to docs/integrations/cicd/teamcity.mdx diff --git a/docs/integrations/cicd/travisci.mdx b/docs/integrations/cicd/travisci.mdx deleted file mode 100644 index 873c371b6..000000000 --- a/docs/integrations/cicd/travisci.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Travis CI" -description: "How to sync secrets from Infisical to Travis CI" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain your API token in User Settings > API authentication > Token - - ![integrations travis ci token](../../images/integrations/travis-ci/integrations-travisci-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Travis CI tile and input your Travis CI API token to grant Infisical access to your Travis CI account. - - ![integrations travis ci authorization](../../images/integrations/travis-ci/integrations-travisci-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Travis CI repository and press create integration to start syncing secrets to Travis CI. - - ![create integration travis ci](../../images/integrations/travis-ci/integrations-travisci-create.png) - ![integrations travis ci](../../images/integrations/travis-ci/integrations-travisci.png) - - \ No newline at end of file diff --git a/docs/integrations/cloud/aws-parameter-store.mdx b/docs/integrations/cloud/aws-parameter-store.mdx deleted file mode 100644 index d2bb36a0b..000000000 --- a/docs/integrations/cloud/aws-parameter-store.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "AWS Parameter Store" -description: "Learn how to sync secrets from Infisical to AWS Parameter Store." ---- - - - The AWS Parameter Store Native Integration will be deprecated in 2026. Please migrate to our new [AWS Parameter Store Sync](../secret-syncs/aws-parameter-store). - \ No newline at end of file diff --git a/docs/integrations/cloud/aws-secret-manager.mdx b/docs/integrations/cloud/aws-secret-manager.mdx deleted file mode 100644 index a56461998..000000000 --- a/docs/integrations/cloud/aws-secret-manager.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "AWS Secrets Manager" -description: "Learn how to sync secrets from Infisical to AWS Secrets Manager." ---- - - - The AWS Secrets Manager Native Integration will be deprecated in 2026. Please migrate to our new [AWS Secrets Manager Sync](../secret-syncs/aws-secrets-manager). - \ No newline at end of file diff --git a/docs/integrations/cloud/azure-app-configuration.mdx b/docs/integrations/cloud/azure-app-configuration.mdx deleted file mode 100644 index 4e7dfd94f..000000000 --- a/docs/integrations/cloud/azure-app-configuration.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Azure App Configuration" -description: "How to sync secrets from Infisical to Azure App Configuration" ---- - - - The Azure App Configuration Native Integration will be deprecated in 2026. Please migrate to our new [Azure App Configuration Sync](../secret-syncs/azure-app-configuration). - \ No newline at end of file diff --git a/docs/integrations/cloud/azure-devops.mdx b/docs/integrations/cloud/azure-devops.mdx deleted file mode 100644 index 4eaaf0cc1..000000000 --- a/docs/integrations/cloud/azure-devops.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Azure DevOps" -description: "How to sync secrets from Infisical to Azure DevOps" ---- - -### Usage -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create a new [Azure DevOps](https://dev.azure.com) project if you don't have one already. - - -#### Create a new Azure DevOps personal access token (PAT) -You'll need to create a new personal access token (PAT) in order to authenticate Infisical with Azure DevOps. - - - ![integrations](../../images/integrations/azure-devops/overview-page.png) - - - Make sure the newly created token has Read/Write access to the Release scope. - ![integrations](../../images/integrations/azure-devops/create-new-token.png) - - - Please make sure that the token has access to the following scopes: Variable Groups _(read, create, & manage)_, Release _(read/write)_, Project and Team _(read)_, Service Connections _(read & query)_ - - - - Copy the newly created token as this will be used to authenticate Infisical with Azure DevOps. - ![integrations](../../images/integrations/azure-devops/new-token-created.png) - - - -#### Setup the Infisical Azure DevOps integration -Navigate to your project's integrations tab and select the 'Azure DevOps' integration. -![integrations](../../images/integrations.png) - - - - Enter your credentials that you obtained from the previous step. - - 1. Azure DevOps API token is the personal access token (PAT) you created in the previous step. - 2. Azure DevOps organization name is the name of your Azure DevOps organization. - - ![integrations](../../images/integrations/azure-devops/new-infiscial-integration-step-1.png) - - - Select Infisical project and secret path you want to sync into Azure DevOps. - Finally, press create integration to start syncing secrets to Azure DevOps. - - ![integrations](../../images/integrations/azure-devops/new-infiscial-integration-step-2.png) - - - -Now you have successfully integrated Infisical with Azure DevOps. Your existing and future secret changes will automatically sync to Azure DevOps. -You can view your secrets by navigating to your Azure DevOps project and selecting the 'Library' tab under 'Pipelines' in the 'Library' section. diff --git a/docs/integrations/cloud/azure-key-vault.mdx b/docs/integrations/cloud/azure-key-vault.mdx deleted file mode 100644 index b0bd80c63..000000000 --- a/docs/integrations/cloud/azure-key-vault.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Azure Key Vault" -description: "How to sync secrets from Infisical to Azure Key Vault" ---- - - - The Azure Key Vault Native Integration will be deprecated in 2026. Please migrate to our new [Azure Key Vault Sync](../secret-syncs/azure-key-vault). - \ No newline at end of file diff --git a/docs/integrations/cloud/cloud-66.mdx b/docs/integrations/cloud/cloud-66.mdx deleted file mode 100644 index c087f6564..000000000 --- a/docs/integrations/cloud/cloud-66.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "Cloud 66" -description: "How to sync secrets from Infisical to Cloud 66" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - -## Navigate to your project's integrations tab - -![integrations](../../images/integrations.png) - -## Enter your Cloud 66 Access Token - -In Cloud 66 Dashboard, click on the top right icon > Account Settings > Access Token -![integrations cloud 66 dashboard](../../images/integrations/cloud-66/integrations-cloud-66-dashboard.png) -![integrations cloud 66 access token](../../images/integrations/cloud-66/integrations-cloud-66-access-token.png) - -Create new Personal Access Token. -![integrations cloud 66 personal access token](../../images/integrations/cloud-66/integrations-cloud-66-pat.png) - -Name it **infisical** and check **Public** and **Admin**. Then click "Create Token" -![integrations cloud 66 personal access token setup](../../images/integrations/cloud-66/integrations-cloud-66-pat-setup.png) - -Copy and save your token. -![integrations cloud 66 copy API token](../../images/integrations/cloud-66/integrations-cloud-66-copy-pat.png) - -### Go to Infisical Integration Page - -Click on the Cloud 66 tile and enter your API token to grant Infisical access to your Cloud 66 account. -![integrations cloud 66 tile in infisical dashboard](../../images/integrations/cloud-66/integrations-cloud-66-infisical-dashboard.png) - -Enter your Cloud 66 Personal Access Token here. Then click "Connect to Cloud 66". -![integrations cloud 66 tile in infisical dashboard](../../images/integrations/cloud-66/integrations-cloud-66-paste-pat.png) - - -## Start integration - -Select which Infisical environment secrets you want to sync to which Cloud 66 stacks and press create integration to start syncing secrets to Cloud 66. -![integrations laravel forge](../../images/integrations/cloud-66/integrations-cloud-66-create.png) - - - Any existing environment variables in Cloud 66 will be deleted when you start syncing. Make sure to add all the secrets into the Infisical dashboard first before doing any integrations. - - -Done! -![integrations laravel forge](../../images/integrations/cloud-66/integrations-cloud-66-done.png) diff --git a/docs/integrations/cloud/cloudflare-pages.mdx b/docs/integrations/cloud/cloudflare-pages.mdx deleted file mode 100644 index addba4fcd..000000000 --- a/docs/integrations/cloud/cloudflare-pages.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Cloudflare Pages" -description: "How to sync secrets from Infisical to Cloudflare Pages" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Cloudflare [API token](https://dash.cloudflare.com/profile/api-tokens) and [Account ID](https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/): - - Create a new [API token](https://dash.cloudflare.com/profile/api-tokens) in My Profile > API Tokens - - ![integrations cloudflare credentials 1](../../images/integrations/cloudflare/integrations-cloudflare-credentials-1.png) - ![integrations cloudflare credentials 2](../../images/integrations/cloudflare/integrations-cloudflare-credentials-2.png) - ![integrations cloudflare credentials 3](../../images/integrations/cloudflare/integrations-cloudflare-credentials-3.png) - - Copy your [Account ID](https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/) from Account > Workers & Pages > Overview - - ![integrations cloudflare credentials 4](../../images/integrations/cloudflare/integrations-cloudflare-credentials-4.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Cloudflare Pages tile and input your Cloudflare API token and account ID to grant Infisical access to your Cloudflare Pages. - - ![integrations cloudflare authorization](../../images/integrations/cloudflare/integrations-cloudflare-auth.png) - - - - Select which Infisical environment secrets you want to sync to Cloudflare and press create integration to start syncing secrets. - - ![integrations cloudflare](../../images/integrations/cloudflare/integrations-cloudflare-create.png) - ![integrations cloudflare](../../images/integrations/cloudflare/integrations-cloudflare.png) - - \ No newline at end of file diff --git a/docs/integrations/cloud/cloudflare-workers.mdx b/docs/integrations/cloud/cloudflare-workers.mdx deleted file mode 100644 index 10a579701..000000000 --- a/docs/integrations/cloud/cloudflare-workers.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Cloudflare Workers" -description: "How to sync secrets from Infisical to Cloudflare Workers" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Cloudflare [API token](https://dash.cloudflare.com/profile/api-tokens) and [Account ID](https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/): - - Create a new [API token](https://dash.cloudflare.com/profile/api-tokens) in My Profile > API Tokens - - ![integrations cloudflare credentials 1](../../images/integrations/cloudflare/integrations-cloudflare-credentials-1.png) - ![integrations cloudflare credentials 2](../../images/integrations/cloudflare/integrations-cloudflare-credentials-2.png) - ![integrations cloudflare credentials 3](../../images/integrations/cloudflare/integrations-cloudflare-workers-permission.png) - - Copy your [Account ID](https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/) from Account > Workers & Pages > Overview - - ![integrations cloudflare credentials 4](../../images/integrations/cloudflare/integrations-cloudflare-credentials-4.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Cloudflare Workers tile and input your Cloudflare API token and account ID to grant Infisical access to your Cloudflare Workers. - - ![integrations cloudflare authorization](../../images/integrations/cloudflare/integration-cloudflare-workers-connect.png) - - - - Select which Infisical environment secrets you want to sync to Cloudflare Workers and press create integration to start syncing secrets. - - ![integrations cloudflare](../../images/integrations/cloudflare/integration-cloudflare-workers-create.png) - - - diff --git a/docs/integrations/cloud/databricks.mdx b/docs/integrations/cloud/databricks.mdx deleted file mode 100644 index e5ad22939..000000000 --- a/docs/integrations/cloud/databricks.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Databricks" -description: "Learn how to sync secrets from Infisical to Databricks." ---- - - - The Databricks Native Integration will be deprecated in 2026. Please migrate to our new [Databricks Sync](../secret-syncs/databricks). - \ No newline at end of file diff --git a/docs/integrations/cloud/digital-ocean-app-platform.mdx b/docs/integrations/cloud/digital-ocean-app-platform.mdx deleted file mode 100644 index a0ed545cc..000000000 --- a/docs/integrations/cloud/digital-ocean-app-platform.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Digital Ocean App Platform" -description: "How to sync secrets from Infisical to Digital Ocean App Platform" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - -## Get your Digital Ocean Personal Access Tokens - -On Digital Ocean dashboard, navigate to **API > Tokens** and click on "Generate New Token" -![integrations digital ocean dashboard](../../images/integrations/digital-ocean/integrations-do-dashboard.png) - -Name it **infisical**, choose **No expiry**, and make sure to check **Write (optional)**. Then click on "Generate Token" and copy your API token. -![integrations digital ocean token modal](../../images/integrations/digital-ocean/integrations-do-token-modal.png) - -## Navigate to your project's integrations tab - -Click on the **Digital Ocean App Platform** tile and enter your API token to grant Infisical access to your Digital Ocean account. -![integrations](../../images/integrations.png) - -Then enter your Digital Ocean Personal Access Token here. Then click "Connect to Digital Ocean App Platform". -![integrations infisical dashboard digital ocean integration](../../images/integrations/digital-ocean/integrations-do-enter-token.png) - -## Start integration - -Select which Infisical environment secrets you want to sync to which Digital Ocean App and click "Create Integration". -![integrations digital ocean select projects](../../images/integrations/digital-ocean/integrations-do-select-projects.png) - -Done! -![integrations digital ocean integration success](../../images/integrations/digital-ocean/integrations-do-success.png) diff --git a/docs/integrations/cloud/flyio.mdx b/docs/integrations/cloud/flyio.mdx deleted file mode 100644 index 2aa14a919..000000000 --- a/docs/integrations/cloud/flyio.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Fly.io" -description: "How to sync secrets from Infisical to Fly.io" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Fly.io access token in Access Tokens - - ![integrations fly dashboard](../../images/integrations/flyio/integrations-flyio-dashboard.png) - ![integrations fly token](../../images/integrations/flyio/integrations-flyio-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Fly.io tile and input your Fly.io access token to grant Infisical access to your Fly.io account. - - ![integrations fly authorization](../../images/integrations/flyio/integrations-flyio-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Fly.io app and press create integration to start syncing secrets to Fly.io. - - ![integrations fly](../../images/integrations/flyio/integrations-flyio-create.png) - ![integrations fly](../../images/integrations/flyio/integrations-flyio.png) - - \ No newline at end of file diff --git a/docs/integrations/cloud/gcp-secret-manager.mdx b/docs/integrations/cloud/gcp-secret-manager.mdx deleted file mode 100644 index 22462feef..000000000 --- a/docs/integrations/cloud/gcp-secret-manager.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "GCP Secret Manager" -description: "How to sync secrets from Infisical to GCP Secret Manager" ---- - - - The GCP Secret Manager Native Integration will be deprecated in 2026. Please migrate to our new [GCP Secret Manager Sync](../secret-syncs/gcp-secret-manager). - \ No newline at end of file diff --git a/docs/integrations/cloud/hashicorp-vault.mdx b/docs/integrations/cloud/hashicorp-vault.mdx deleted file mode 100644 index df2542ce7..000000000 --- a/docs/integrations/cloud/hashicorp-vault.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "HashiCorp Vault" -description: "How to sync secrets from Infisical to HashiCorp Vault" ---- - - - The Hashicorp Vault Native Integration will be deprecated in 2026. Please migrate to our new [Hashicorp Vault Sync](../secret-syncs/hashicorp-vault). - diff --git a/docs/integrations/cloud/hasura-cloud.mdx b/docs/integrations/cloud/hasura-cloud.mdx deleted file mode 100644 index f88c1eb50..000000000 --- a/docs/integrations/cloud/hasura-cloud.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Hasura Cloud" -description: "How to sync secrets from Infisical to Hasura Cloud" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Hasura Cloud Access Token in My Account > Access Tokens - - ![integrations hasura cloud tokens](../../images/integrations/hasura-cloud/integrations-hasura-cloud-tokens.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Hasura Cloud tile and input your Hasura Cloud access token to grant Infisical access to your Hasura Cloud account. - - ![integrations hasura cloud authorization](../../images/integrations/hasura-cloud/integrations-hasura-cloud-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Hasura Cloud project and press create integration to start syncing secrets to Hasura Cloud. - - ![integrations hasura cloud](../../images/integrations/hasura-cloud/integrations-hasura-cloud-create.png) - ![integrations hasura cloud](../../images/integrations/hasura-cloud/integrations-hasura-cloud.png) - - \ No newline at end of file diff --git a/docs/integrations/cloud/heroku.mdx b/docs/integrations/cloud/heroku.mdx deleted file mode 100644 index 75cf8c106..000000000 --- a/docs/integrations/cloud/heroku.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: "Heroku" -description: "How to sync secrets from Infisical to Heroku" ---- - - - - Prerequisites: - - - Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Heroku tile and grant Infisical access to your Heroku account. - - ![integrations heroku authorization](../../images/integrations/heroku/integrations-heroku-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Heroku app and press create integration to start syncing secrets to Heroku. - - ![integrations heroku](../../images/integrations/heroku/integrations-heroku-create.png) - - Here's some guidance on each field: - - - Project Environment: The environment in the current Infisical project from which you want to sync secrets from. - - Secrets Path: The path in the current Infisical project from which you want to sync secrets from such as `/` (for secrets that do not reside in a folder) or `/foo/bar` (for secrets nested in a folder, in this case a folder called `bar` in another folder called `foo`). - - Heroku App: The application in Heroku that you want to sync secrets to. - - Initial Sync Behavior (default is **Import - Prefer values from Infisical**): The behavior of the first sync operation triggered after creating the integration. - - **No Import - Overwrite all values in Heroku**: Sync secrets and overwrite any existing secrets in Heroku. - - **Import - Prefer values from Infisical**: Import secrets from Heroku to Infisical; if a secret with the same name already exists in Infisical, do nothing. Afterwards, sync secrets to Heroku. - - **Import - Prefer values from Heroku**: Import secrets from Heroku to Infisical; if a secret with the same name already exists in Infisical, replace its value with the one from Heroku. Afterwards, sync secrets to Heroku. - - ![integrations heroku](../../images/integrations/heroku/integrations-heroku.png) - - - - - Using the Heroku integration on a self-hosted instance of Infisical requires configuring an API client in Heroku - and registering your instance with it. - - - Navigate to your user Account settings > Applications to create a new API client. - - ![integrations Heroku config](../../images/integrations/heroku/integrations-heroku-config-settings.png) - ![integrations Heroku config](../../images/integrations/heroku/integrations-heroku-config-applications.png) - ![integrations Heroku config](../../images/integrations/heroku/integrations-heroku-config-new-app.png) - - Create the API client. As part of the form, set the **OAuth callback URL** to `https://your-domain.com/integrations/heroku/oauth2/callback`. - - ![integrations Heroku config](../../images/integrations/heroku/integrations-heroku-config-new-app-form.png) - - - Obtain the **Client ID** and **Client Secret** for your Heroku API client. - - ![integrations Heroku config](../../images/integrations/heroku/integrations-heroku-config-credentials.png) - - Back in your Infisical instance, add two new environment variables for the credentials of your Heroku API client. - - - `CLIENT_ID_HEROKU`: The **Client ID** of your Heroku API client. - - `CLIENT_SECRET_HEROKU`: The **Client Secret** of your Heroku API client. - - Once added, restart your Infisical instance and use the Heroku integration. - - - - diff --git a/docs/integrations/cloud/laravel-forge.mdx b/docs/integrations/cloud/laravel-forge.mdx deleted file mode 100644 index c58c4a7be..000000000 --- a/docs/integrations/cloud/laravel-forge.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Laravel Forge" -description: "How to sync secrets from Infisical to Laravel Forge" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Laravel Forge access token in API Tokens - - ![integrations laravel forge dashboard](../../images/integrations/laravel-forge/integrations-laravelforge-dashboard.png) - ![integrations laravel forge api tokens](../../images/integrations/laravel-forge/integrations-laravelforge-api.png) - - Obtain your Laravel Forge Server ID in Servers > Server ID - - ![integrations laravel forge server](../../images/integrations/laravel-forge/integrations-laravelforge-servers.png) - ![integrations laravel forge server id](../../images/integrations/laravel-forge/integrations-laravelforge-serverid.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Laravel Forge tile and input your Laravel Forge access token and server ID to grant Infisical access to your Laravel Forge account. - - ![integrations laravel forge authorization](../../images/integrations/laravel-forge/integrations-laravelforge-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Laravel Forge site and press create integration to start syncing secrets to Laravel Forge. - - ![integrations laravel forge](../../images/integrations/laravel-forge/integrations-laravelforge-create.png) - ![integrations laravel forge](../../images/integrations/laravel-forge/integrations-laravelforge.png) - - - diff --git a/docs/integrations/cloud/netlify.mdx b/docs/integrations/cloud/netlify.mdx deleted file mode 100644 index f793aae10..000000000 --- a/docs/integrations/cloud/netlify.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "Netlify" -description: "How to sync secrets from Infisical to Netlify" ---- - - - - - Infisical integrates with Netlify's new environment variable experience. If - your site uses Netlify's old environment variable experience, you'll have to - upgrade it to the new one to use this integration. - - - Prerequisites: - - - Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Netlify tile and grant Infisical access to your Netlify account. - - ![integrations netlify authorization](../../images/integrations/netlify/integrations-netlify-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Netlify app and context. Lastly, press create integration to start syncing secrets to Netlify. - - ![integrations netlify](../../images/integrations/netlify/integrations-netlify-create.png) - ![integrations netlify](../../images/integrations/netlify/integrations-netlify.png) - - - - - Using the Netlify integration on a self-hosted instance of Infisical requires configuring an OAuth application in Netlify - and registering your instance with it. - - - Navigate to your User settings > Applications > OAuth to create a new OAuth application. - - ![integrations Netlify config](../../images/integrations/netlify/integrations-netlify-config-user-settings.png) - ![integrations Netlify config](../../images/integrations/netlify/integrations-netlify-config-new-app.png) - - Create the OAuth application. As part of the form, set the **Redirect URI** to `https://your-domain.com/integrations/netlify/oauth2/callback`. - - ![integrations Netlify config](../../images/integrations/netlify/integrations-netlify-config-new-app-form.png) - - - Obtain the **Client ID** and **Secret** for your Netlify OAuth application. - - ![integrations Netlify config](../../images/integrations/netlify/integrations-netlify-config-credentials.png) - - Back in your Infisical instance, add two new environment variables for the credentials of your Netlify OAuth application. - - - `CLIENT_ID_NETLIFY`: The **Client ID** of your Netlify OAuth application. - - `CLIENT_SECRET_NETLIFY`: The **Secret** of your Netlify OAuth application. - - Once added, restart your Infisical instance and use the Netlify integration. - - - - - diff --git a/docs/integrations/cloud/northflank.mdx b/docs/integrations/cloud/northflank.mdx deleted file mode 100644 index 10dcb288e..000000000 --- a/docs/integrations/cloud/northflank.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Northflank" -description: "How to sync secrets from Infisical to Northflank" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) -- Have a [Northflank](https://northflank.com) project with a secret group ready - - - - Obtain a Northflank API token in Account settings > API > Tokens - - ![integrations northflank dashboard](../../images/integrations/northflank/integrations-northflank-dashboard.png) - ![integrations northflank token](../../images/integrations/northflank/integrations-northflank-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Northflank tile and input your Northflank API token to grant Infisical access to your Northflank account. - - ![integrations northflank authorization](../../images/integrations/northflank/integrations-northflank-auth.png) - - - - Select which Infisical environment secrets you want to sync to which Northflank project and secret group. Finally, press create integration to start syncing secrets to Northflank. - - ![integrations northflank](../../images/integrations/northflank/integrations-northflank-create.png) - ![integrations northflank](../../images/integrations/northflank/integrations-northflank.png) - - \ No newline at end of file diff --git a/docs/integrations/cloud/qovery.mdx b/docs/integrations/cloud/qovery.mdx deleted file mode 100644 index 13aa6af46..000000000 --- a/docs/integrations/cloud/qovery.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Qovery" -description: "How to sync secrets from Infisical to Qovery" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Qovery API Token in Settings > API Token. - - ![integrations qovery api token](../../images/integrations/qovery/integrations-qovery-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Qovery tile and input your Qovery API Token to grant Infisical access to your Qovery account. - - ![integrations qovery authorization](../../images/integrations/qovery/integrations-qovery-auth.png) - - - - Select which Infisical environment secrets you want to sync to Qovery and press create integration to start syncing secrets. - - ![integrations qovery create](../../images/integrations/qovery/integrations-qovery-create-1.png) - - ![integrations qovery create](../../images/integrations/qovery/integrations-qovery-create-2.png) - - - Infisical supports syncing secrets to various Qovery scopes including applications, jobs, or containers. - - - ![integrations qovery settings](../../images/integrations/qovery/integrations-qovery.png) - - diff --git a/docs/integrations/cloud/railway.mdx b/docs/integrations/cloud/railway.mdx deleted file mode 100644 index 77b315517..000000000 --- a/docs/integrations/cloud/railway.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Railway" -description: "How to sync secrets from Infisical to Railway" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Railway API Token in your Railway [Account Settings > Tokens](https://railway.app/account/tokens). - - ![integrations railway dashboard](../../images/integrations/railway/integrations-railway-dashboard.png) - ![integrations railway token](../../images/integrations/railway/integrations-railway-token.png) - - - If this is your first time creating a Railway API token, then you'll be prompted to join - Railway's Private Boarding Beta program on the Railway Account Settings > Tokens page. - - Note that Railway project tokens will not work for this integration since they don't work with - Railway's Public API. - - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Railway tile and input your Railway API Key to grant Infisical access to your Railway account. - - ![integrations railway authorization](../../images/integrations/railway/integrations-railway-authorization.png) - - - - Select which Infisical environment secrets you want to sync to which Railway project and environment (and optionally service). Lastly, press create integration to start syncing secrets to Railway. - - ![integrations create railway](../../images/integrations/railway/integrations-railway-create.png) - - - Infisical integrates with both Railway's [shared variables](https://blog.railway.app/p/shared-variables-release) at the project environment level as well as service variables at the service level. - - To sync secrets to a specific service in a project, you can select a service from the Railway Service dropdown; otherwise, leaving it empty will sync secrets to the shared variables of that project. - - - ![integrations railway](../../images/integrations/railway/integrations-railway.png) - - \ No newline at end of file diff --git a/docs/integrations/cloud/render.mdx b/docs/integrations/cloud/render.mdx deleted file mode 100644 index 1d4860ebd..000000000 --- a/docs/integrations/cloud/render.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Render" -description: "How to sync secrets from Infisical to Render" ---- - - - The Render Native Integration will be deprecated in 2026. Please migrate to - our new [Render Sync](../secret-syncs/render). - diff --git a/docs/integrations/cloud/supabase.mdx b/docs/integrations/cloud/supabase.mdx deleted file mode 100644 index b5179c45f..000000000 --- a/docs/integrations/cloud/supabase.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Supabase" -description: "How to sync secrets from Infisical to Supabase" ---- - - - The Supabase integration is useful if your Supabase project uses sensitive-information such as [environment variables in edge functions](https://supabase.com/docs/guides/functions/secrets). - - Synced envars can be accessed in edge functions using Deno's built-in handler: `Deno.env.get(MY_SECRET_NAME)`. - - -Prerequisites: - -- Have an account and project set up at [Supabase](https://supabase.com/) -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Supabase Access Token in your Supabase [Account > Access Tokens](https://app.supabase.com/account/tokens). - ![integrations supabase dashboard](../../images/integrations/supabase/integrations-supabase-dashboard.png) - ![integrations supabase token](../../images/integrations/supabase/integrations-supabase-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Supabase tile and input your Supabase Access Token to grant Infisical access to your Supabase account. - - ![integrations supabase authorization](../../images/integrations/supabase/integrations-supabase-authorization.png) - - - - Select which Infisical environment secrets you want to sync to which Supabase project. Lastly, press create integration to start syncing secrets to Supabase. - - ![integrations supabase create](../../images/integrations/supabase/integrations-supabase-create.png) - - ![integrations supabase](../../images/integrations/supabase/integrations-supabase.png) - - diff --git a/docs/integrations/cloud/terraform-cloud.mdx b/docs/integrations/cloud/terraform-cloud.mdx deleted file mode 100644 index 63398ef4a..000000000 --- a/docs/integrations/cloud/terraform-cloud.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Terraform Cloud" -description: "How to sync secrets from Infisical to Terraform Cloud" ---- - - - The Terraform Cloud Native Integration will be deprecated in 2026. Please migrate to our new [Terraform Cloud Sync](../secret-syncs/terraform-cloud). - \ No newline at end of file diff --git a/docs/integrations/cloud/vercel.mdx b/docs/integrations/cloud/vercel.mdx deleted file mode 100644 index 7456776bd..000000000 --- a/docs/integrations/cloud/vercel.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Vercel" -description: "How to sync secrets from Infisical to Vercel" ---- - - - The Vercel Native Integration will be deprecated in 2026. Please migrate to our new [Vercel Sync](../secret-syncs/vercel). - \ No newline at end of file diff --git a/docs/integrations/cloud/windmill.mdx b/docs/integrations/cloud/windmill.mdx deleted file mode 100644 index 7d4c2cc82..000000000 --- a/docs/integrations/cloud/windmill.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Windmill" -description: "How to sync secrets from Infisical to Windmill" ---- - - - The Windmill Native Integration will be deprecated in 2026. Please migrate to our new [Windmill Sync](../secret-syncs/windmill). - diff --git a/docs/integrations/overview.mdx b/docs/integrations/overview.mdx deleted file mode 100644 index ed7d47b30..000000000 --- a/docs/integrations/overview.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Overview" -description: "How to use Infisical to inject secrets and configs into various 3-rd party services and frameworks." ---- - -Integrations allow environment variables to be synced from Infisical into your local development workflow, CI/CD pipelines, and production infrastructure. - -Missing an integration? [Throw in a request](https://github.com/Infisical/infisical/issues). - -| Integration | Type | Status | -| ------------------------------------------------------------------------------------- | ---------------------- | ---------------------------------- | -| [Docker](/integrations/platforms/docker) | Platform | Available | -| [Docker-Compose](/integrations/platforms/docker-compose) | Platform | Available | -| [Kubernetes](/integrations/platforms/kubernetes) | Platform | Available | -| [Terraform](https://registry.terraform.io/providers/Infisical/infisical/latest/docs) | Infrastructure as code | Available | -| [PM2](/integrations/platforms/pm2) | Platform | Available | -| [Heroku](/integrations/cloud/heroku) | Cloud | Available | -| [Vercel](/integrations/cloud/vercel) | Cloud | Available | -| [Netlify](/integrations/cloud/netlify) | Cloud | Available | -| [Render](/integrations/cloud/render) | Cloud | Available | -| [Laravel Forge](/integrations/cloud/laravel-forge) | Cloud | Available | -| [Railway](/integrations/cloud/railway) | Cloud | Available | -| [Terraform Cloud](/integrations/cloud/terraform-cloud) | Cloud | Available | -| [TeamCity](/integrations/cloud/teamcity) | Cloud | Available | -| [Fly.io](/integrations/cloud/flyio) | Cloud | Available | -| [Supabase](/integrations/cloud/supabase) | Cloud | Available | -| [Northflank](/integrations/cloud/northflank) | Cloud | Available | -| [Cloudflare Pages](/integrations/cloud/cloudflare-pages) | Cloud | Available | -| [Cloudflare Workers](/integrations/cloud/cloudflare-workers) | Cloud | Available | -| [Checkly](/integrations/cloud/checkly) | Cloud | Available | -| [Qovery](/integrations/cloud/qovery) | Cloud | Available | -| [HashiCorp Vault](/integrations/cloud/hashicorp-vault) | Cloud | Available | -| [AWS Parameter Store](/integrations/cloud/aws-parameter-store) | Cloud | Available | -| [AWS Secrets Manager](/integrations/cloud/aws-secret-manager) | Cloud | Available | -| [Azure Key Vault](/integrations/cloud/azure-key-vault) | Cloud | Available | -| [GCP Secret Manager](/integrations/cloud/gcp-secret-manager) | Cloud | Available | -| [Windmill](/integrations/cloud/windmill) | Cloud | Available | -| [Bitbucket](/integrations/cicd/bitbucket) | CI/CD | Available | -| [Codefresh](/integrations/cicd/codefresh) | CI/CD | Available | -| [GitHub Actions](/integrations/cicd/githubactions) | CI/CD | Available | -| [GitLab](/integrations/cicd/gitlab) | CI/CD | Available | -| [CircleCI](/integrations/cicd/circleci) | CI/CD | Available | -| [Travis CI](/integrations/cicd/travisci) | CI/CD | Available | -| [Rundeck](/integrations/cicd/rundeck) | CI/CD | Available | -| [Octopus Deploy](/integrations/cicd/octopus-deploy) | CI/CD | Available | -| [React](/integrations/frameworks/react) | Framework | Available | -| [Vue](/integrations/frameworks/vue) | Framework | Available | -| [Express](/integrations/frameworks/express) | Framework | Available | -| [Next.js](/integrations/frameworks/nextjs) | Framework | Available | -| [NestJS](/integrations/frameworks/nestjs) | Framework | Available | -| [SvelteKit](/integrations/frameworks/sveltekit) | Framework | Available | -| [Nuxt](/integrations/frameworks/nuxt) | Framework | Available | -| [Gatsby](/integrations/frameworks/gatsby) | Framework | Available | -| [Remix](/integrations/frameworks/remix) | Framework | Available | -| [Vite](/integrations/frameworks/vite) | Framework | Available | -| [Fiber](/integrations/frameworks/fiber) | Framework | Available | -| [Django](/integrations/frameworks/django) | Framework | Available | -| [Flask](/integrations/frameworks/flask) | Framework | Available | -| [Laravel](/integrations/frameworks/laravel) | Framework | Available | -| [Ruby on Rails](/integrations/frameworks/rails) | Framework | Available | -| Jenkins | CI/CD | Available | diff --git a/docs/integrations/secret-syncs/overview.mdx b/docs/integrations/secret-syncs/overview.mdx index 937c8d826..eeadcffa3 100644 --- a/docs/integrations/secret-syncs/overview.mdx +++ b/docs/integrations/secret-syncs/overview.mdx @@ -5,10 +5,6 @@ description: "Learn how to sync secrets to third-party services with Infisical." Secret Syncs enable you to sync secrets from Infisical to third-party services using [App Connections](/integrations/app-connections/overview). - - Secret Syncs will gradually replace Native Integrations as they become available. Native Integrations will be deprecated in the future, so opt for configuring a Secret Sync when available. - - ## Concept Secret Syncs are a project-level resource used to sync secrets, via an [App Connection](/integrations/app-connections/overview), from a particular project environment and folder path (source) @@ -92,7 +88,7 @@ via the UI or API for the third-party service you intend to sync secrets to. Infisical is continuously expanding it's Secret Sync third-party service support. If the service you need isn't available, - you can still use our Native Integrations in the interim, or contact us at team@infisical.com to make a request . + you can contact us at team@infisical.com to make a request . ## Key Schemas diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index edebf1670..669c3aaa3 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -703,110 +703,6 @@ You can configure third-party app connections for re-use across Infisical Projec -## Native Secret Integrations - -To help you sync secrets from Infisical to services such as Github and Gitlab, Infisical provides native integrations out of the box. - - - - OAuth2 client ID for Heroku integration - - - OAuth2 client secret for Heroku integration - - - - - - OAuth2 client ID for Vercel integration - - -{" "} - - - OAuth2 client secret for Vercel integration - - - - OAuth2 slug for Vercel integration - - - - - - OAuth2 client ID for Netlify integration - - - - OAuth2 client secret for Netlify integration - - - - - - OAuth2 client ID for GitHub integration - - - - OAuth2 client secret for GitHub integration - - - - - - OAuth2 client ID for Bitbucket integration - - - - OAuth2 client secret for Bitbucket integration - - - - - - OAuth2 client id for GCP secrets manager integration - - - - OAuth2 client secret for GCP secrets manager integration - - - - - - The AWS IAM User access key for assuming roles. - - - - The AWS IAM User secret key for assuming roles. - - - - - - OAuth2 client id for Azure integration - - - - OAuth2 client secret for Azure integration - - - - - - OAuth2 client id for Gitlab integration - - - - OAuth2 client secret for Gitlab integration - - - ## Secret Scanning From 5bd8fc9ae49d2a638c3cbdb994052260342b8ef0 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Mon, 24 Nov 2025 20:23:30 -0300 Subject: [PATCH 03/26] fix: correct minor typos in GitLab and AWS Amplify documentation --- docs/integrations/app-connections/gitlab.mdx | 2 +- docs/integrations/cicd/aws-amplify.mdx | 2 +- docs/integrations/secret-syncs/overview.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/integrations/app-connections/gitlab.mdx b/docs/integrations/app-connections/gitlab.mdx index d17322540..588a6f990 100644 --- a/docs/integrations/app-connections/gitlab.mdx +++ b/docs/integrations/app-connections/gitlab.mdx @@ -12,7 +12,7 @@ Infisical supports two methods for connecting to GitLab: **OAuth** and **Access Using the GitLab Connection with OAuth on a self-hosted instance of Infisical requires configuring an OAuth application in GitLab and registering your instance with it. - If you're self-hosting Gitlab with custom certificates, you will have to configure your Infisical instance to trust these certificates. To learn how, please follow [this guide](../../self-hosting/guides/custom-certificates). + If you're self-hosting GitLab with custom certificates, you will have to configure your Infisical instance to trust these certificates. To learn how, please follow [this guide](../../self-hosting/guides/custom-certificates). **Prerequisites:** - A GitLab account with existing projects diff --git a/docs/integrations/cicd/aws-amplify.mdx b/docs/integrations/cicd/aws-amplify.mdx index 9b4b81ccb..28de7640c 100644 --- a/docs/integrations/cicd/aws-amplify.mdx +++ b/docs/integrations/cicd/aws-amplify.mdx @@ -19,7 +19,7 @@ This approach enables you to fetch secrets from Infisical during Amplify build t - Create a machine identtiy and connect it to your Infisical project. You can read more about how to use machine identities [here](/documentation/platform/identities/machine-identities). The machine identity will allow you to authenticate and fetch secrets from Infisical. + Create a machine identity and connect it to your Infisical project. You can read more about how to use machine identities [here](/documentation/platform/identities/machine-identities). The machine identity will allow you to authenticate and fetch secrets from Infisical. diff --git a/docs/integrations/secret-syncs/overview.mdx b/docs/integrations/secret-syncs/overview.mdx index eeadcffa3..c341e6ea3 100644 --- a/docs/integrations/secret-syncs/overview.mdx +++ b/docs/integrations/secret-syncs/overview.mdx @@ -88,7 +88,7 @@ via the UI or API for the third-party service you intend to sync secrets to. Infisical is continuously expanding it's Secret Sync third-party service support. If the service you need isn't available, - you can contact us at team@infisical.com to make a request . + you can contact us at team@infisical.com to make a request. ## Key Schemas From 7a3e73ea60d688eb80e88d3250374249522ad713 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Tue, 25 Nov 2025 18:58:24 +0530 Subject: [PATCH 04/26] fix: makes environments optional in project tempalte --- backend/src/ee/routes/v1/project-template-router.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/ee/routes/v1/project-template-router.ts b/backend/src/ee/routes/v1/project-template-router.ts index c157b628b..90343ffb4 100644 --- a/backend/src/ee/routes/v1/project-template-router.ts +++ b/backend/src/ee/routes/v1/project-template-router.ts @@ -72,7 +72,6 @@ const ProjectTemplateEnvironmentsSchema = z position: z.number().min(1) }) .array() - .min(1) .superRefine((environments, ctx) => { if (Buffer.byteLength(JSON.stringify(environments)) > MAX_JSON_SIZE_LIMIT_IN_BYTES) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Size limit exceeded" }); @@ -198,7 +197,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider) description: z.string().max(256).trim().optional().describe(ProjectTemplates.CREATE.description), roles: ProjectTemplateRolesSchema.default([]).describe(ProjectTemplates.CREATE.roles), type: z.nativeEnum(ProjectType).describe(ProjectTemplates.CREATE.type), - environments: ProjectTemplateEnvironmentsSchema.describe(ProjectTemplates.CREATE.environments).optional() + environments: ProjectTemplateEnvironmentsSchema.nullish().describe(ProjectTemplates.CREATE.environments) }), response: { 200: z.object({ From f031339d83d3f58219303196463451a9cf1db18b Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Tue, 25 Nov 2025 20:23:04 +0530 Subject: [PATCH 05/26] fix: default duplicate secret deletion --- .../src/services/secret-v2-bridge/secret-v2-bridge-fns.ts | 6 ++++-- .../services/secret-v2-bridge/secret-v2-bridge-service.ts | 3 ++- frontend/src/helpers/project.ts | 5 ----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index 01a7f6210..d25c9d58e 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -424,8 +424,10 @@ export const fnSecretBulkDelete = async ({ .filter(({ type }) => type === SecretType.Shared) .map(({ id }) => ({ type: CommitType.DELETE, - secretVersionId: secretVersions[id].id - })); + secretVersionId: secretVersions[id]?.id + })) + .filter((el) => el.secretVersionId); + if (changes.length > 0) { if (commitChanges) { commitChanges.push(...changes); diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index 559c86843..d42a26eff 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -2254,7 +2254,8 @@ export const secretV2BridgeServiceFactory = ({ ] } }); - if (secretsToDelete.length !== inputSecrets.length) + const secretsToDeleteSet = new Set(secretsToDelete.map((el) => el.key)); + if (secretsToDeleteSet.size !== inputSecrets.length) throw new NotFoundError({ message: `One or more secrets does not exist: ${secretsToDelete.map((el) => el.key).join(", ")}` }); diff --git a/frontend/src/helpers/project.ts b/frontend/src/helpers/project.ts index 1a3114868..128dd31ce 100644 --- a/frontend/src/helpers/project.ts +++ b/frontend/src/helpers/project.ts @@ -14,11 +14,6 @@ const secretsToBeAdded = [ secretValue: "OVERRIDE_THIS", secretComment: "Override secrets with personal value" }, - { - secretKey: "DB_PASSWORD", - secretValue: "OVERRIDE_THIS", - secretComment: "Another secret override" - }, { secretKey: "DB_PASSWORD", secretValue: "example_password" From 64ba002af6a774878cfc3163d7fd75bcbd6bf8ae Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Wed, 26 Nov 2025 02:56:40 +0530 Subject: [PATCH 06/26] docs: improves cli docs --- docs/cli/commands/login.mdx | 95 +++++++++++++++++++++++--------- docs/cli/usage.mdx | 106 ++++++++++++++++++++++++++++++------ 2 files changed, 156 insertions(+), 45 deletions(-) diff --git a/docs/cli/commands/login.mdx b/docs/cli/commands/login.mdx index c58c13713..1a0db9b4e 100644 --- a/docs/cli/commands/login.mdx +++ b/docs/cli/commands/login.mdx @@ -10,6 +10,7 @@ infisical login ### Description The CLI uses authentication to verify your identity. You can authenticate using: + - **Browser Login** (default): Opens a browser for authentication - **Direct Login**: Provide email and password via flags or environment variables for non-interactive workflows - **Interactive CLI Login**: Use the `--interactive` flag to enter credentials via CLI prompts @@ -24,9 +25,9 @@ If you have added multiple users, you can switch between the users by using the **JWT Token Output:** - For **user authentication** with the `--plain --silent` flags: outputs only the JWT access token (useful for scripting) - For **machine identity authentication**: an access token is always printed to the console - + Use the `--plain` flag to print only the token in plain text and the `--silent` flag to disable update alerts. - + Both flags are ideal for capturing the token in environment variables or CI/CD pipelines. @@ -42,29 +43,34 @@ User authentication is designed for individual developers and supports multiple The User authentication method allows you to log in with your email and password. This method supports three different login flows: - - **Browser Login** (default): Opens a browser for authentication - - **Direct Login**: Provide credentials via flags or environment variables for CI/CD - - **Interactive CLI Login**: Enter credentials via CLI prompts using `--interactive` +- **Browser Login** (default): Opens a browser for authentication +- **Direct Login**: Provide credentials via flags or environment variables for CI/CD +- **Interactive CLI Login**: Enter credentials via CLI prompts using `--interactive` - - - - Your email address. Required for direct login along with `--password` and `--organization-id`. - - - Your password. Required for direct login along with `--email` and `--organization-id`. - - - Your organization id. Required for direct login along with `--password` and `--email`. - - - Force interactive CLI login instead of browser-based authentication. - - - Output only the JWT token (useful for scripting and CI/CD). - - - +{" "} + + + + + Your email address. Required for direct login along with `--password` and + `--organization-id`. + + + Your password. Required for direct login along with `--email` and + `--organization-id`. + + + Your organization id. Required for direct login along with `--password` + and `--email`. + + + Force interactive CLI login instead of browser-based authentication. + + + Output only the JWT token (useful for scripting and CI/CD). + + + @@ -291,6 +297,7 @@ Machine identity authentication methods are designed for automated systems, serv ``` + @@ -316,6 +323,7 @@ Machine identity authentication methods are designed for automated systems, serv ``` + @@ -500,6 +508,27 @@ The login command supports a number of flags that you can use for different auth The `jwt` flag can be substituted with the `INFISICAL_JWT` environment variable. + + + ```bash + infisical login --domain= [other-flags] + ``` + + #### Description + Specifies the Infisical API URL for non-US instances (EU Cloud or self-hosted instances). This flag is required when connecting to any instance other than the US Cloud. + + ```bash + # Example for EU Cloud + infisical login --domain="https://eu.infisical.com" --jwt= --machine-identity-id= + + # Example for self-hosted + infisical login --domain="https://your-self-hosted-infisical.com/api" --email user@example.com --password "password" + ``` + + + **Critical:** If you use `--domain` during login, you must also include it on **all subsequent CLI commands** (e.g., `infisical secrets`, `infisical export`, etc.). Alternatively, set the `INFISICAL_API_URL` environment variable to avoid having to use `--domain` on every command. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. + + @@ -529,8 +558,11 @@ The following examples demonstrate different ways to authenticate as a user with # Basic direct login (defaults to US Cloud) infisical login --email user@example.com --password "your-password" --organization-id "your-organization-id" - # EU Cloud (Custom domain) - infisical login --email user@example.com --password "your-password" --organization-id "your-organization-id" --domain https://eu.infisical.com + # EU Cloud + infisical login --domain https://eu.infisical.com --email user@example.com --password "your-password" --organization-id "your-organization-id" + + # Self-hosted instance + infisical login --domain https://your-self-hosted-infisical.com/api --email user@example.com --password "your-password" --organization-id "your-organization-id" # Output only JWT token for scripting export INFISICAL_TOKEN=$(infisical login --email user@example.com --password "your-password" --organization-id "your-organization-id" --plain --silent) @@ -550,6 +582,11 @@ The following examples demonstrate different ways to authenticate as a user with # Or with plain output for token capture export INFISICAL_TOKEN=$(infisical login --plain --silent) ``` + + + **For non-US instances:** If you're using EU Cloud, or a self-hosted instance, you must set `INFISICAL_API_URL` before login, or use `--domain` on all commands. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. + + @@ -571,7 +608,7 @@ The following examples demonstrate different ways to authenticate as a user with -If you have SSO enabled, we recommend using the default browser login. + If you have SSO enabled, we recommend using the default browser login. ### Machine Identity Authentication Quick Start @@ -584,6 +621,10 @@ In this example we'll be using the `universal-auth` method to login to obtain an export INFISICAL_TOKEN=$(infisical login --method=universal-auth --client-id= --client-secret= --silent --plain) # silent and plain is important to ensure only the token itself is printed, so we can easily set it as an environment variable. ``` + + **For non-US instances:** If you're using EU Cloud, or a self-hosted instance, you must set `INFISICAL_API_URL` before login, or use `--domain` on all commands. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. + + Now that we've set the `INFISICAL_TOKEN` environment variable, we can use the CLI to interact with Infisical. The CLI will automatically check for the presence of the `INFISICAL_TOKEN` environment variable and use it for authentication. diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index bedfda22c..c91ac5736 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -131,6 +131,62 @@ For versions prior to v0.4.0, the CLI defaults to the US Cloud. To connect to th + + ## Domain Configuration + +**Important:** If you're not using interactive login, you must configure the domain for **all CLI commands**. + +The CLI defaults to the US Cloud (https://app.infisical.com). To connect to the **EU Cloud (https://eu.infisical.com)** or a **self-hosted instance**, you can configure the domain in one of the following ways: + +- Use the `INFISICAL_API_URL` environment variable +- Use the `--domain` flag on every command + + + + The easiest way to ensure all CLI commands use the correct domain is to set + the `INFISICAL_API_URL` environment variable. This applies the domain + setting globally to all commands: + + ```bash + # Linux/MacOS + export INFISICAL_API_URL="https://your-domain.infisical.com" + + # Windows PowerShell + setx INFISICAL_API_URL "https://your-domain.infisical.com" + ``` + + Once set, all subsequent CLI commands will automatically use this domain: + + ```bash + # Login with the domain + infisical login --method=universal-auth --client-id= --client-secret= --silent --plain + + # All other commands will also use the same domain automatically + infisical secrets --projectId --env dev + ``` + + + + The `--domain` flag can be used to set the domain for a single command. This + applies the domain setting to the command only: + + ```bash + # Login with domain + infisical login --domain="https://your-domain.infisical.com" --method=universal-auth --client-id= --client-secret= --silent --plain + + # All subsequent commands must also include --domain + infisical secrets --domain="https://your-domain.infisical.com" --projectId --env dev + ``` + + + If you use `--domain` during login but forget to include it on subsequent commands, you may encounter authentication errors. + + + + + + + ## Custom Request Headers @@ -186,51 +242,65 @@ For security and privacy concerns, we recommend you to configure your terminal t ## FAQ - - Yes. The CLI is set to connect to Infisical Cloud by default, but if you're running your own instance of Infisical, you can direct the CLI to it using one of the methods provided below. + + Yes. The CLI is set to connect to Infisical US Cloud by default, but if you're using the EU Cloud, a self-hosted instance, you need to configure the domain for **all CLI commands**. - #### Method 1: Use the updated CLI + #### Method 1:Use the updated CLI (v0.4.0+) - Beginning with CLI version V0.4.0, it is now possible to choose between logging in through the Infisical cloud or your own self-hosted instance. Simply execute the `infisical login` command and follow the on-screen instructions. + Beginning with CLI version V0.4.0, you can choose between logging in through the Infisical US Cloud, EU Cloud, or your own self-hosted instance. Simply execute the `infisical login` command and follow the on-screen instructions. - #### Method 2: Export environment variable + #### Method 2: Export environment variable You can point the CLI to the self-hosted Infisical instance by exporting the environment variable `INFISICAL_API_URL` in your terminal. ```bash - # set backend host - export INFISICAL_API_URL="https://your-self-hosted-infisical.com/api" + # Set the API URL + export INFISICAL_API_URL="https://your-self-hosted-infisical.com" - # remove backend host + # For EU Cloud + export INFISICAL_API_URL="https://eu.infisical.com" + + # Remove the setting unset INFISICAL_API_URL ``` ```bash - # set backend host - setx INFISICAL_API_URL "https://your-self-hosted-infisical.com/api" + # Set the API URL + setx INFISICAL_API_URL "https://your-self-hosted-infisical.com" - # remove backend host + # For EU Cloud + setx INFISICAL_API_URL "https://eu.infisical.com" + + # Remove the setting setx INFISICAL_API_URL "" - # NOTE: Once set or removed, please restart powershell for the change to take effect + # NOTE: Once set, please restart powershell for the change to take effect ``` -#### Method 3: Set manually on every command + #### Method 3: Set manually on every command -Another option to point the CLI to your self-hosted Infisical instance is to set it via a flag on every command you run. + If you prefer not to set the environment variable, you must include the `--domain` flag on **every CLI command** you run: -```bash -# Example -infisical --domain="https://your-self-hosted-infisical.com/api" -``` + ```bash + # Login with domain + infisical login --domain="https://your-domain.infisical.com" --method=oidc-auth --jwt $JWT + + # All subsequent commands must also include --domain + infisical secrets --domain="https://your-self-hosted-infisical.com/api" --projectId --env dev + infisical export --domain="https://your-self-hosted-infisical.com/api" --format=dotenv-export + ``` + + + **Best Practice:** Use `INFISICAL_API_URL` environment variable (Method 2) to avoid having to remember the `--domain` flag on every command. This is especially important in CI/CD pipelines and automation scripts. + From dd37fa311439c691a26055e00791e53835c77489 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Tue, 25 Nov 2025 20:26:18 -0300 Subject: [PATCH 07/26] refactor: deprecate native integrations in favor of secret syncs; update API routes and frontend components accordingly --- .../routes/v1/integration-auth-router.ts | 48 ++- .../server/routes/v1/integration-router.ts | 96 ++--- .../endpoints/integrations/create-auth.mdx | 32 -- .../endpoints/integrations/create.mdx | 40 -- .../integrations/delete-auth-by-id.mdx | 4 - .../endpoints/integrations/delete-auth.mdx | 4 - .../endpoints/integrations/delete.mdx | 4 - .../endpoints/integrations/find-auth.mdx | 4 - .../endpoints/integrations/list-auth.mdx | 4 - .../list-project-integrations.mdx | 4 - .../endpoints/integrations/update.mdx | 4 - .../IntegrationsListPage.tsx | 64 +++- .../IntegrationsListPage.utils.tsx | 352 ------------------ .../CloudIntegrationSection.tsx | 258 ------------- .../CloudIntegrationSection/index.tsx | 1 - .../NativeIntegrationsTab.tsx | 105 +----- 16 files changed, 149 insertions(+), 875 deletions(-) delete mode 100644 docs/api-reference/endpoints/integrations/create-auth.mdx delete mode 100644 docs/api-reference/endpoints/integrations/create.mdx delete mode 100644 docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx delete mode 100644 docs/api-reference/endpoints/integrations/delete-auth.mdx delete mode 100644 docs/api-reference/endpoints/integrations/delete.mdx delete mode 100644 docs/api-reference/endpoints/integrations/find-auth.mdx delete mode 100644 docs/api-reference/endpoints/integrations/list-auth.mdx delete mode 100644 docs/api-reference/endpoints/integrations/list-project-integrations.mdx delete mode 100644 docs/api-reference/endpoints/integrations/update.mdx delete mode 100644 frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx delete mode 100644 frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/index.tsx diff --git a/backend/src/server/routes/v1/integration-auth-router.ts b/backend/src/server/routes/v1/integration-auth-router.ts index e5156724d..40bb8fa13 100644 --- a/backend/src/server/routes/v1/integration-auth-router.ts +++ b/backend/src/server/routes/v1/integration-auth-router.ts @@ -2,6 +2,7 @@ import { z } from "zod"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { ApiDocsTags, INTEGRATION_AUTH } from "@app/lib/api-docs"; +import { ForbiddenRequestError } from "@app/lib/errors"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; @@ -10,6 +11,9 @@ import { Integrations } from "@app/services/integration-auth/integration-list"; import { integrationAuthPubSchema } from "../sanitizedSchemas"; +const NATIVE_INTEGRATION_DEPRECATION_MESSAGE = + "We're moving Native Integrations to Secret Syncs. Check the documentation at https://infisical.com/docs/integrations/secret-syncs/overview. If the integration you need isn't available in the Secret Syncs, please get in touch with us at team@infisical.com."; + export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) => { server.route({ method: "GET", @@ -333,27 +337,33 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) }) } }, - handler: async (req) => { - const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({ - actorId: req.permission.id, - actor: req.permission.type, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - projectId: req.body.workspaceId, - ...req.body + handler: async (_) => { + throw new ForbiddenRequestError({ + message: NATIVE_INTEGRATION_DEPRECATION_MESSAGE }); - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: req.body.workspaceId, - event: { - type: EventType.AUTHORIZE_INTEGRATION, - metadata: { - integration: integrationAuth.integration - } - } - }); - return { integrationAuth }; + // We are keeping the old response commented out for an easy revert on the API if we need to before the full phase out. + + // const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({ + // actorId: req.permission.id, + // actor: req.permission.type, + // actorAuthMethod: req.permission.authMethod, + // actorOrgId: req.permission.orgId, + // projectId: req.body.workspaceId, + // ...req.body + // }); + + // await server.services.auditLog.createAuditLog({ + // ...req.auditLogInfo, + // projectId: req.body.workspaceId, + // event: { + // type: EventType.AUTHORIZE_INTEGRATION, + // metadata: { + // integration: integrationAuth.integration + // } + // } + // }); + // return { integrationAuth }; } }); diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index 95477c341..183c5a38b 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -3,17 +3,19 @@ import { z } from "zod"; import { IntegrationsSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { ApiDocsTags, INTEGRATION } from "@app/lib/api-docs"; +import { ForbiddenRequestError } from "@app/lib/errors"; import { removeTrailingSlash, shake } from "@app/lib/fn"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; -import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; import { IntegrationMetadataSchema } from "@app/services/integration/integration-schema"; import { Integrations } from "@app/services/integration-auth/integration-list"; -import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telemetry/telemetry-types"; import {} from "../sanitizedSchemas"; +const NATIVE_INTEGRATION_DEPRECATION_MESSAGE = + "We're moving Native Integrations to Secret Syncs. Check the documentation at https://infisical.com/docs/integrations/secret-syncs/overview. If the integration you need isn't available in the Secret Syncs, please get in touch with us at team@infisical.com."; + export const registerIntegrationRouter = async (server: FastifyZodProvider) => { server.route({ method: "POST", @@ -66,52 +68,58 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - handler: async (req) => { - const { integration, integrationAuth } = await server.services.integration.createIntegration({ - actorId: req.permission.id, - actor: req.permission.type, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body + handler: async (_) => { + throw new ForbiddenRequestError({ + message: NATIVE_INTEGRATION_DEPRECATION_MESSAGE }); - const createIntegrationEventProperty = shake({ - integrationId: integration.id.toString(), - integration: integration.integration, - environment: req.body.sourceEnvironment, - secretPath: req.body.secretPath, - url: integration.url, - app: integration.app, - appId: integration.appId, - targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId, - targetService: integration.targetService, - targetServiceId: integration.targetServiceId, - path: integration.path, - region: integration.region - }) as TIntegrationCreatedEvent["properties"]; + // We are keeping the old response commented out for an easy revert on the API if we need to before the full phase out. - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: integrationAuth.projectId, - event: { - type: EventType.CREATE_INTEGRATION, - // eslint-disable-next-line - metadata: createIntegrationEventProperty - } - }); + // const { integration, integrationAuth } = await server.services.integration.createIntegration({ + // actorId: req.permission.id, + // actor: req.permission.type, + // actorAuthMethod: req.permission.authMethod, + // actorOrgId: req.permission.orgId, + // ...req.body + // }); - await server.services.telemetry.sendPostHogEvents({ - event: PostHogEventTypes.IntegrationCreated, - organizationId: req.permission.orgId, - distinctId: getTelemetryDistinctId(req), - properties: { - ...createIntegrationEventProperty, - projectId: integrationAuth.projectId, - ...req.auditLogInfo - } - }); - return { integration }; + // const createIntegrationEventProperty = shake({ + // integrationId: integration.id.toString(), + // integration: integration.integration, + // environment: req.body.sourceEnvironment, + // secretPath: req.body.secretPath, + // url: integration.url, + // app: integration.app, + // appId: integration.appId, + // targetEnvironment: integration.targetEnvironment, + // targetEnvironmentId: integration.targetEnvironmentId, + // targetService: integration.targetService, + // targetServiceId: integration.targetServiceId, + // path: integration.path, + // region: integration.region + // }) as TIntegrationCreatedEvent["properties"]; + + // await server.services.auditLog.createAuditLog({ + // ...req.auditLogInfo, + // projectId: integrationAuth.projectId, + // event: { + // type: EventType.CREATE_INTEGRATION, + // // eslint-disable-next-line + // metadata: createIntegrationEventProperty + // } + // }); + + // await server.services.telemetry.sendPostHogEvents({ + // event: PostHogEventTypes.IntegrationCreated, + // organizationId: req.permission.orgId, + // distinctId: getTelemetryDistinctId(req), + // properties: { + // ...createIntegrationEventProperty, + // projectId: integrationAuth.projectId, + // ...req.auditLogInfo + // } + // }); + // return { integration }; } }); diff --git a/docs/api-reference/endpoints/integrations/create-auth.mdx b/docs/api-reference/endpoints/integrations/create-auth.mdx deleted file mode 100644 index 5af7a0f9c..000000000 --- a/docs/api-reference/endpoints/integrations/create-auth.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Create Auth" -openapi: "POST /api/v1/integration-auth/access-token" ---- - -## Integration Authentication Parameters - -The integration authentication endpoint is generic and can be used for all native integrations. -For specific integration parameters for a given service, please review the respective documentation below. - - - - - This value must be **aws-secret-manager**. - - - Infisical project id for the integration. - - - The AWS IAM User Access ID. - - - The AWS IAM User Access Secret Key. - - - - Coming Soon - - - Coming Soon - - diff --git a/docs/api-reference/endpoints/integrations/create.mdx b/docs/api-reference/endpoints/integrations/create.mdx deleted file mode 100644 index 0992e91b9..000000000 --- a/docs/api-reference/endpoints/integrations/create.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Create" -openapi: "POST /api/v1/integration" ---- - -## Integration Parameters - -The integration creation endpoint is generic and can be used for all native integrations. -For specific integration parameters for a given service, please review the respective documentation below. - - - - - The ID of the integration auth object for authentication with AWS. - Refer [Create Integration Auth](./create-auth) for more info - - - Whether the integration should be active or inactive - - - The secret name used when saving secret in AWS SSM. Used for naming and can be arbitrary. - - - The AWS region of the SSM. Example: `us-east-1` - - - The Infisical environment slug from where secrets will be synced from. Example: `dev` - - - The Infisical folder path from where secrets will be synced from. Example: `/some/path`. The root of the environment is `/`. - - - - Coming Soon - - - Coming Soon - - - diff --git a/docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx b/docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx deleted file mode 100644 index 5884363fc..000000000 --- a/docs/api-reference/endpoints/integrations/delete-auth-by-id.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Delete Auth By ID" -openapi: "DELETE /api/v1/integration-auth/{integrationAuthId}" ---- diff --git a/docs/api-reference/endpoints/integrations/delete-auth.mdx b/docs/api-reference/endpoints/integrations/delete-auth.mdx deleted file mode 100644 index 93d957903..000000000 --- a/docs/api-reference/endpoints/integrations/delete-auth.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Delete Auth" -openapi: "DELETE /api/v1/integration-auth" ---- diff --git a/docs/api-reference/endpoints/integrations/delete.mdx b/docs/api-reference/endpoints/integrations/delete.mdx deleted file mode 100644 index 51df56de7..000000000 --- a/docs/api-reference/endpoints/integrations/delete.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Delete" -openapi: "DELETE /api/v1/integration/{integrationId}" ---- diff --git a/docs/api-reference/endpoints/integrations/find-auth.mdx b/docs/api-reference/endpoints/integrations/find-auth.mdx deleted file mode 100644 index 439b82935..000000000 --- a/docs/api-reference/endpoints/integrations/find-auth.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Get Auth By ID" -openapi: "GET /api/v1/integration-auth/{integrationAuthId}" ---- diff --git a/docs/api-reference/endpoints/integrations/list-auth.mdx b/docs/api-reference/endpoints/integrations/list-auth.mdx deleted file mode 100644 index 3ca961d98..000000000 --- a/docs/api-reference/endpoints/integrations/list-auth.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "List Auth" -openapi: "GET /api/v1/workspace/{workspaceId}/authorizations" ---- diff --git a/docs/api-reference/endpoints/integrations/list-project-integrations.mdx b/docs/api-reference/endpoints/integrations/list-project-integrations.mdx deleted file mode 100644 index 24ebbf7d8..000000000 --- a/docs/api-reference/endpoints/integrations/list-project-integrations.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "List Project Integrations" -openapi: "GET /api/v1/workspace/{workspaceId}/integrations" ---- diff --git a/docs/api-reference/endpoints/integrations/update.mdx b/docs/api-reference/endpoints/integrations/update.mdx deleted file mode 100644 index 8567c46ae..000000000 --- a/docs/api-reference/endpoints/integrations/update.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Update" -openapi: "PATCH /api/v1/integration/{integrationId}" ---- diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx index bd6ff70d1..4b2d5f750 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx @@ -3,7 +3,15 @@ import { useTranslation } from "react-i18next"; import { useNavigate, useSearch } from "@tanstack/react-router"; import { ProjectPermissionCan } from "@app/components/permissions"; -import { PageHeader, Tab, TabList, TabPanel, Tabs } from "@app/components/v2"; +import { + Alert, + AlertDescription, + PageHeader, + Tab, + TabList, + TabPanel, + Tabs +} from "@app/components/v2"; import { ROUTE_PATHS } from "@app/const/routes"; import { ProjectPermissionActions, @@ -12,6 +20,7 @@ import { useProject } from "@app/context"; import { ProjectPermissionSecretSyncActions } from "@app/context/ProjectPermissionContext/types"; +import { useGetWorkspaceIntegrations } from "@app/hooks/api"; import { ProjectType } from "@app/hooks/api/projects/types"; import { IntegrationsListPageTabs } from "@app/types/integrations"; @@ -32,6 +41,9 @@ export const IntegrationsListPage = () => { from: ROUTE_PATHS.SecretManager.IntegrationsListPage.id }); + const { data: integrations } = useGetWorkspaceIntegrations(currentProject.id); + const hasNativeIntegrations = Boolean(integrations?.length); + const updateSelectedTab = (tab: string) => { navigate({ to: ROUTE_PATHS.SecretManager.IntegrationsListPage.path, @@ -65,9 +77,11 @@ export const IntegrationsListPage = () => { Secret Syncs - - Native Integrations - + {hasNativeIntegrations && ( + + Native Integrations + + )} Framework Integrations @@ -84,15 +98,39 @@ export const IntegrationsListPage = () => { - - - - - + {hasNativeIntegrations && ( + + + + We're moving Native Integrations to{" "} + + Secret Syncs + + . If the integration you need isn't available in the Secret Syncs menu, + please get in touch with us at{" "} + + team@infisical.com + + . + + + + + + + )} diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.utils.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.utils.tsx index 9332023f5..bb9d02d3d 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.utils.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.utils.tsx @@ -1,10 +1,4 @@ -import crypto from "crypto"; - -import { NavigateFn } from "@tanstack/react-router"; - import { createNotification } from "@app/components/notifications"; -import { localStorageService } from "@app/helpers/localStorage"; -import { TCloudIntegration } from "@app/hooks/api/types"; export const createIntegrationMissingEnvVarsNotification = ( slug: string, @@ -27,349 +21,3 @@ export const createIntegrationMissingEnvVarsNotification = ( ), title: "Missing Environment Variables" }); - -export const redirectForProviderAuth = ( - orgId: string, - projectId: string, - navigate: NavigateFn, - integrationOption: TCloudIntegration -) => { - try { - // generate CSRF token for OAuth2 code-token exchange integrations - const state = crypto.randomBytes(16).toString("hex"); - localStorage.setItem("latestCSRFToken", state); - localStorageService.setIntegrationProjectId(projectId); - - switch (integrationOption.slug) { - case "gcp-secret-manager": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/gcp-secret-manager/authorize", - params: { - orgId, - projectId - } - }); - break; - case "azure-key-vault": { - if (!integrationOption.clientId) { - createIntegrationMissingEnvVarsNotification(integrationOption.slug); - return; - } - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-key-vault/authorize", - params: { - orgId, - projectId - }, - search: { - clientId: integrationOption.clientId, - state - } - }); - break; - } - case "azure-app-configuration": { - if (!integrationOption.clientId) { - createIntegrationMissingEnvVarsNotification(integrationOption.slug); - return; - } - const link = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${window.location.origin}/integrations/azure-app-configuration/oauth2/callback&response_mode=query&scope=https://azconfig.io/.default openid offline_access&state=${state}`; - window.location.assign(link); - break; - } - case "aws-parameter-store": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/aws-parameter-store/authorize", - params: { - orgId, - projectId - } - }); - break; - case "aws-secret-manager": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/aws-secret-manager/authorize", - params: { - orgId, - projectId - } - }); - break; - case "heroku": { - if (!integrationOption.clientId) { - createIntegrationMissingEnvVarsNotification(integrationOption.slug); - return; - } - const link = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`; - window.location.assign(link); - break; - } - case "vercel": { - if (!integrationOption.clientSlug) { - createIntegrationMissingEnvVarsNotification(integrationOption.slug); - return; - } - const link = `https://vercel.com/integrations/${integrationOption.clientSlug}/new?state=${state}`; - window.location.assign(link); - break; - } - case "netlify": { - if (!integrationOption.clientId) { - createIntegrationMissingEnvVarsNotification(integrationOption.slug); - return; - } - const link = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/integrations/netlify/oauth2/callback`; - - window.location.assign(link); - break; - } - case "github": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/github/auth-mode-selection", - params: { - orgId, - projectId - } - }); - break; - case "gitlab": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/gitlab/authorize", - params: { - orgId, - projectId - } - }); - break; - case "render": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/render/authorize", - params: { - orgId, - projectId - } - }); - break; - case "flyio": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/flyio/authorize", - params: { - orgId, - projectId - } - }); - break; - case "circleci": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/circleci/authorize", - params: { - orgId, - projectId - } - }); - break; - case "databricks": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/databricks/authorize", - params: { - orgId, - projectId - } - }); - break; - case "laravel-forge": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/laravel-forge/authorize", - params: { - orgId, - projectId - } - }); - break; - case "travisci": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/travisci/authorize", - params: { - orgId, - projectId - } - }); - break; - case "supabase": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/supabase/authorize", - params: { - orgId, - projectId - } - }); - break; - case "checkly": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/checkly/authorize", - params: { - orgId, - projectId - } - }); - break; - case "qovery": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/qovery/authorize", - params: { - orgId, - projectId - } - }); - break; - case "railway": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/railway/authorize", - params: { - orgId, - projectId - } - }); - break; - case "terraform-cloud": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/terraform-cloud/authorize", - params: { - orgId, - projectId - } - }); - break; - case "hashicorp-vault": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/hashicorp-vault/authorize", - params: { - orgId, - projectId - } - }); - break; - case "cloudflare-pages": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/cloudflare-pages/authorize", - params: { - orgId, - projectId - } - }); - break; - case "cloudflare-workers": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/cloudflare-workers/authorize", - params: { - orgId, - projectId - } - }); - break; - case "bitbucket": { - if (!integrationOption.clientId) { - createIntegrationMissingEnvVarsNotification(integrationOption.slug, "cicd"); - return; - } - const link = `https://bitbucket.org/site/oauth2/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${window.location.origin}/integrations/bitbucket/oauth2/callback&state=${state}`; - window.location.assign(link); - break; - } - case "codefresh": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/codefresh/authorize", - params: { - orgId, - projectId - } - }); - break; - case "digital-ocean-app-platform": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/digital-ocean-app-platform/authorize", - params: { - orgId, - projectId - } - }); - break; - case "cloud-66": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/cloud-66/authorize", - params: { - orgId, - projectId - } - }); - break; - case "northflank": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/northflank/authorize", - params: { - orgId, - projectId - } - }); - break; - case "windmill": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/windmill/authorize", - params: { - orgId, - projectId - } - }); - break; - case "teamcity": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/teamcity/authorize", - params: { - orgId, - projectId - } - }); - break; - case "hasura-cloud": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/hasura-cloud/authorize", - params: { - orgId, - projectId - } - }); - break; - case "rundeck": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/rundeck/authorize", - params: { - orgId, - projectId - } - }); - break; - case "azure-devops": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-devops/authorize", - params: { - orgId, - projectId - } - }); - break; - case "octopus-deploy": - navigate({ - to: "/organizations/$orgId/projects/secret-management/$projectId/integrations/octopus-deploy/authorize", - params: { - orgId, - projectId - } - }); - break; - default: - break; - } - } catch (err) { - console.error(err); - } -}; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx deleted file mode 100644 index ff92f9f41..000000000 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import { useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { - faCheck, - faChevronLeft, - faMagnifyingGlass, - faSearch, - faXmark -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { useNavigate } from "@tanstack/react-router"; - -import { NoEnvironmentsBanner } from "@app/components/integrations/NoEnvironmentsBanner"; -import { createNotification } from "@app/components/notifications"; -import { - Button, - DeleteActionModal, - EmptyState, - Input, - Skeleton, - Tooltip -} from "@app/components/v2"; -import { ROUTE_PATHS } from "@app/const/routes"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - useOrganization, - useProject, - useProjectPermission -} from "@app/context"; -import { usePopUp } from "@app/hooks"; -import { SecretSync } from "@app/hooks/api/secretSyncs"; -import { IntegrationAuth, TCloudIntegration } from "@app/hooks/api/types"; -import { IntegrationsListPageTabs } from "@app/types/integrations"; - -type Props = { - isLoading?: boolean; - integrationAuths?: Record; - cloudIntegrations?: TCloudIntegration[]; - onIntegrationStart: (slug: string) => void; - // cb: handle popUpClose child->parent communication pattern - onIntegrationRevoke: (slug: string, cb: () => void) => void; - onViewActiveIntegrations?: () => void; -}; - -type TRevokeIntegrationPopUp = { provider: string }; - -const SECRET_SYNCS = Object.values(SecretSync) as string[]; -const isSecretSyncAvailable = (type: string) => SECRET_SYNCS.includes(type); - -export const CloudIntegrationSection = ({ - isLoading, - cloudIntegrations = [], - integrationAuths = {}, - onIntegrationStart, - onIntegrationRevoke, - onViewActiveIntegrations -}: Props) => { - const { t } = useTranslation(); - const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ - "deleteConfirmation" - ] as const); - const { permission } = useProjectPermission(); - const { currentOrg } = useOrganization(); - const { currentProject } = useProject(); - const navigate = useNavigate(); - - const isEmpty = !isLoading && !cloudIntegrations?.length; - - const sortedCloudIntegrations = useMemo(() => { - const sortedIntegrations = cloudIntegrations.sort((a, b) => a.name.localeCompare(b.name)); - - if (currentProject?.environments.length === 0) { - return sortedIntegrations.map((integration) => ({ ...integration, isAvailable: false })); - } - - return sortedIntegrations; - }, [cloudIntegrations, currentProject?.environments]); - - const [search, setSearch] = useState(""); - - const filteredIntegrations = sortedCloudIntegrations?.filter((cloudIntegration) => - cloudIntegration.name.toLowerCase().includes(search.toLowerCase().trim()) - ); - - return ( -
- {currentProject?.environments.length === 0 && ( -
- -
- )} -
- {onViewActiveIntegrations && ( - - )} -
-
-

{t("integrations.cloud-integrations")}

-

{t("integrations.click-to-start")}

-
- setSearch(e.target.value)} - leftIcon={} - placeholder="Search cloud integrations..." - containerClassName="flex-1 h-min text-base" - /> -
-
-
- {isLoading && - Array.from({ length: 12 }).map((_, index) => ( - - ))} - - {!isLoading && filteredIntegrations.length ? ( - filteredIntegrations.map((cloudIntegration) => { - const syncSlug = cloudIntegration.syncSlug ?? cloudIntegration.slug; - const isSyncAvailable = isSecretSyncAvailable(syncSlug); - - return ( -
null} - role="button" - tabIndex={0} - className={`group relative ${ - cloudIntegration.isAvailable - ? "cursor-pointer duration-200 hover:bg-mineshaft-700" - : "opacity-50" - } flex h-36 flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-800 p-3`} - onClick={() => { - if (isSyncAvailable) { - navigate({ - to: ROUTE_PATHS.SecretManager.IntegrationsListPage.path, - params: { - orgId: currentOrg.id, - projectId: currentProject.id - }, - search: { - selectedTab: IntegrationsListPageTabs.SecretSyncs, - addSync: syncSlug as SecretSync - } - }); - return; - } - if (!cloudIntegration.isAvailable) return; - if ( - permission.cannot( - ProjectPermissionActions.Create, - ProjectPermissionSub.Integrations - ) - ) { - createNotification({ - type: "error", - text: "You do not have permission to create an integration" - }); - return; - } - onIntegrationStart(cloudIntegration.slug); - }} - key={cloudIntegration.slug} - > -
- integration logo -
- {cloudIntegration.name} -
-
- {cloudIntegration.isAvailable && - Boolean(integrationAuths?.[cloudIntegration.slug]) && ( -
-
-
- - Authorized -
- -
null} - role="button" - tabIndex={0} - onClick={async (event) => { - event.stopPropagation(); - handlePopUpOpen("deleteConfirmation", { - provider: cloudIntegration.slug - }); - }} - className="absolute top-0 right-0 flex h-0 w-12 cursor-pointer items-center justify-center overflow-hidden rounded-r-md bg-red text-xs opacity-50 transition-all duration-300 group-hover:h-full hover:opacity-100" - > - -
-
-
-
- )} - {isSyncAvailable && ( -
-
-
- Secret Sync Available -
-
-
- )} -
- ); - }) - ) : ( - - )} -
- {isEmpty && ( -
- {Array.from({ length: 16 }).map((_, index) => ( -
- ))} -
- )} - handlePopUpToggle("deleteConfirmation", isOpen)} - deleteKey={(popUp?.deleteConfirmation?.data as TRevokeIntegrationPopUp)?.provider || ""} - onDeleteApproved={async () => { - onIntegrationRevoke( - (popUp.deleteConfirmation.data as TRevokeIntegrationPopUp)?.provider, - () => handlePopUpClose("deleteConfirmation") - ); - }} - /> -
- ); -}; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/index.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/index.tsx deleted file mode 100644 index 62f7a006c..000000000 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/CloudIntegrationSection/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { CloudIntegrationSection } from "./CloudIntegrationSection"; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx index 967027857..b51c06df4 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/NativeIntegrationsTab/NativeIntegrationsTab.tsx @@ -1,11 +1,8 @@ -import { useCallback, useEffect, useState } from "react"; -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { useNavigate } from "@tanstack/react-router"; +import { useCallback, useEffect } from "react"; import { createNotification } from "@app/components/notifications"; -import { Button, Checkbox, DeleteActionModal, Spinner } from "@app/components/v2"; -import { useOrganization, useProject } from "@app/context"; +import { Checkbox, DeleteActionModal, Spinner } from "@app/components/v2"; +import { useProject } from "@app/context"; import { usePopUp, useToggle } from "@app/hooks"; import { useDeleteIntegration, @@ -17,38 +14,26 @@ import { import { IntegrationAuth } from "@app/hooks/api/integrationAuth/types"; import { TIntegration } from "@app/hooks/api/integrations/types"; -import { redirectForProviderAuth } from "../../IntegrationsListPage.utils"; -import { CloudIntegrationSection } from "../CloudIntegrationSection"; import { IntegrationsTable } from "./IntegrationsTable"; -enum IntegrationView { - List = "list", - New = "new" -} - export const NativeIntegrationsTab = () => { - const { currentOrg } = useOrganization(); const { currentProject } = useProject(); const { environments, id: workspaceId } = currentProject; - const navigate = useNavigate(); const { data: cloudIntegrations, isPending: isCloudIntegrationsLoading } = useGetCloudIntegrations(); - const { - data: integrationAuths, - isPending: isIntegrationAuthLoading, - isFetching: isIntegrationAuthFetching - } = useGetWorkspaceAuthorizations( - workspaceId, - useCallback((data: IntegrationAuth[]) => { - const groupBy: Record = {}; - data.forEach((el) => { - groupBy[el.integration] = el; - }); - return groupBy; - }, []) - ); + const { data: integrationAuths, isFetching: isIntegrationAuthFetching } = + useGetWorkspaceAuthorizations( + workspaceId, + useCallback((data: IntegrationAuth[]) => { + const groupBy: Record = {}; + data.forEach((el) => { + groupBy[el.integration] = el; + }); + return groupBy; + }, []) + ); // mutation const { @@ -58,11 +43,8 @@ export const NativeIntegrationsTab = () => { } = useGetWorkspaceIntegrations(workspaceId); const { mutateAsync: deleteIntegration } = useDeleteIntegration(); - const { - mutateAsync: deleteIntegrationAuths, - isSuccess: isDeleteIntegrationAuthSuccess, - reset: resetDeleteIntegrationAuths - } = useDeleteIntegrationAuths(); + + const { reset: resetDeleteIntegrationAuths } = useDeleteIntegrationAuths(); const isIntegrationsAuthorizedEmpty = !Object.keys(integrationAuths || {}).length; const isIntegrationsEmpty = !integrations?.length; @@ -71,7 +53,6 @@ export const NativeIntegrationsTab = () => { // After the refetch is completed check if its empty. Then set bot active and reset the submit hook for isSuccess to go back to false useEffect(() => { if ( - isDeleteIntegrationAuthSuccess && !isIntegrationFetching && !isIntegrationAuthFetching && isIntegrationsAuthorizedEmpty && @@ -81,29 +62,11 @@ export const NativeIntegrationsTab = () => { } }, [ isIntegrationFetching, - isDeleteIntegrationAuthSuccess, isIntegrationAuthFetching, isIntegrationsAuthorizedEmpty, isIntegrationsEmpty ]); - const handleProviderIntegration = async (provider: string) => { - const selectedCloudIntegration = cloudIntegrations?.find(({ slug }) => provider === slug); - if (!selectedCloudIntegration) return; - - try { - redirectForProviderAuth(currentOrg.id, currentProject.id, navigate, selectedCloudIntegration); - } catch (error) { - console.error(error); - } - }; - - // function to strat integration for a provider - // confirmation to user passing the bot key for provider to get secret access - const handleProviderIntegrationStart = (provider: string) => { - handleProviderIntegration(provider); - }; - const handleIntegrationDelete = async ( integrationId: string, shouldDeleteIntegrationSecrets: boolean, @@ -117,28 +80,11 @@ export const NativeIntegrationsTab = () => { }); }; - const handleIntegrationAuthRevoke = async (provider: string, cb?: () => void) => { - const integrationAuthForProvider = integrationAuths?.[provider]; - if (!integrationAuthForProvider) return; - - await deleteIntegrationAuths({ - integration: provider, - workspaceId - }); - if (cb) cb(); - createNotification({ - type: "success", - text: "Revoked provider authentication" - }); - }; - const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ "deleteConfirmation", "deleteSecretsConfirmation" ] as const); - const [view, setView] = useState(IntegrationView.List); - const [shouldDeleteSecrets, setShouldDeleteSecrets] = useToggle(false); if (isIntegrationLoading || isCloudIntegrationsLoading) @@ -150,18 +96,10 @@ export const NativeIntegrationsTab = () => { return ( <> - {view === IntegrationView.List ? ( + {integrations?.length && (

Native Integrations

-
{ }} />
- ) : ( - setView(IntegrationView.List)} - /> )} Date: Tue, 25 Nov 2025 20:42:29 -0300 Subject: [PATCH 08/26] refactor: restore native integrations tab and reorganize tab panels in IntegrationsListPage --- .../IntegrationsListPage.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx index 4b2d5f750..77b4213b0 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx @@ -77,17 +77,17 @@ export const IntegrationsListPage = () => { Secret Syncs - {hasNativeIntegrations && ( - - Native Integrations - - )} Framework Integrations Infrastructure Integrations + {hasNativeIntegrations && ( + + Native Integrations + + )} { + + + + + + {hasNativeIntegrations && ( @@ -131,12 +137,6 @@ export const IntegrationsListPage = () => { )} - - - - - -
From e22369ec4d773eac3a6ceab806a8750d976bc431 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Wed, 26 Nov 2025 18:17:35 +0530 Subject: [PATCH 09/26] fix: review comments --- docs/cli/commands/login.mdx | 72 ++++++++++++++++++------------------- docs/cli/usage.mdx | 20 +++++------ 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/docs/cli/commands/login.mdx b/docs/cli/commands/login.mdx index 1a0db9b4e..a670c03aa 100644 --- a/docs/cli/commands/login.mdx +++ b/docs/cli/commands/login.mdx @@ -43,34 +43,29 @@ User authentication is designed for individual developers and supports multiple The User authentication method allows you to log in with your email and password. This method supports three different login flows: -- **Browser Login** (default): Opens a browser for authentication -- **Direct Login**: Provide credentials via flags or environment variables for CI/CD -- **Interactive CLI Login**: Enter credentials via CLI prompts using `--interactive` + - **Browser Login** (default): Opens a browser for authentication + - **Direct Login**: Provide credentials via flags or environment variables for CI/CD + - **Interactive CLI Login**: Enter credentials via CLI prompts using `--interactive` -{" "} - - - - - Your email address. Required for direct login along with `--password` and - `--organization-id`. - - - Your password. Required for direct login along with `--email` and - `--organization-id`. - - - Your organization id. Required for direct login along with `--password` - and `--email`. - - - Force interactive CLI login instead of browser-based authentication. - - - Output only the JWT token (useful for scripting and CI/CD). - - - + + + + Your email address. Required for direct login along with `--password` and `--organization-id`. + + + Your password. Required for direct login along with `--email` and `--organization-id`. + + + Your organization id. Required for direct login along with `--password` and `--email`. + + + Force interactive CLI login instead of browser-based authentication. + + + Output only the JWT token (useful for scripting and CI/CD). + + + @@ -297,7 +292,6 @@ Machine identity authentication methods are designed for automated systems, serv ``` - @@ -323,7 +317,6 @@ Machine identity authentication methods are designed for automated systems, serv ``` - @@ -511,18 +504,21 @@ The login command supports a number of flags that you can use for different auth ```bash - infisical login --domain= [other-flags] + infisical login --domain= ``` #### Description - Specifies the Infisical API URL for non-US instances (EU Cloud or self-hosted instances). This flag is required when connecting to any instance other than the US Cloud. + Specifies the Infisical API URL for non-US Cloud instances. This flag is required when connecting to any instance other than US Cloud (e.g. EU Cloud or self-hosted). ```bash # Example for EU Cloud - infisical login --domain="https://eu.infisical.com" --jwt= --machine-identity-id= + infisical login --domain="https://eu.infisical.com" + + # Example for localhost + infisical login --domain="http://localhost:8080" # Example for self-hosted - infisical login --domain="https://your-self-hosted-infisical.com/api" --email user@example.com --password "password" + infisical login --domain="https://your-self-hosted-infisical.com" ``` @@ -558,11 +554,11 @@ The following examples demonstrate different ways to authenticate as a user with # Basic direct login (defaults to US Cloud) infisical login --email user@example.com --password "your-password" --organization-id "your-organization-id" - # EU Cloud + # Basic direct login (EU Cloud) infisical login --domain https://eu.infisical.com --email user@example.com --password "your-password" --organization-id "your-organization-id" - # Self-hosted instance - infisical login --domain https://your-self-hosted-infisical.com/api --email user@example.com --password "your-password" --organization-id "your-organization-id" + # Basic direct login (Self-hosted Instance) + infisical login --domain https://your-self-hosted-infisical.com --email user@example.com --password "your-password" --organization-id "your-organization-id" # Output only JWT token for scripting export INFISICAL_TOKEN=$(infisical login --email user@example.com --password "your-password" --organization-id "your-organization-id" --plain --silent) @@ -584,7 +580,7 @@ The following examples demonstrate different ways to authenticate as a user with ``` - **For non-US instances:** If you're using EU Cloud, or a self-hosted instance, you must set `INFISICAL_API_URL` before login, or use `--domain` on all commands. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. + **For non-US Cloud instances:** If you're using EU Cloud or a self-hosted instance, you must set `INFISICAL_API_URL` before login or use `--domain` on all commands. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. @@ -622,7 +618,7 @@ In this example we'll be using the `universal-auth` method to login to obtain an ``` - **For non-US instances:** If you're using EU Cloud, or a self-hosted instance, you must set `INFISICAL_API_URL` before login, or use `--domain` on all commands. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. + **For non-US Cloud instances:** If you're using EU Cloud or a self-hosted instance, you must set `INFISICAL_API_URL` before login or use `--domain` on all commands. Refer to the [Domain Configuration](/cli/usage#domain-configuration) section for more details. Now that we've set the `INFISICAL_TOKEN` environment variable, we can use the CLI to interact with Infisical. The CLI will automatically check for the presence of the `INFISICAL_TOKEN` environment variable and use it for authentication. diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index c91ac5736..e158539db 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -127,7 +127,7 @@ The CLI is designed for a variety of secret management applications ranging from Starting with CLI version v0.4.0, you can now choose to log in via Infisical Cloud (US/EU) or your own self-hosted instance by simply running `infisical login` and following the on-screen instructions — no need to manually set the `INFISICAL_API_URL` environment variable. -For versions prior to v0.4.0, the CLI defaults to the US Cloud. To connect to the EU Cloud or a self-hosted instance, set the `INFISICAL_API_URL` environment variable to `https://eu.infisical.com` or your custom URL. +For versions prior to v0.4.0, the CLI defaults to US Cloud. To connect to EU Cloud or a self-hosted instance, set the `INFISICAL_API_URL` environment variable to `https://eu.infisical.com` or your custom URL. @@ -136,7 +136,7 @@ For versions prior to v0.4.0, the CLI defaults to the US Cloud. To connect to th **Important:** If you're not using interactive login, you must configure the domain for **all CLI commands**. -The CLI defaults to the US Cloud (https://app.infisical.com). To connect to the **EU Cloud (https://eu.infisical.com)** or a **self-hosted instance**, you can configure the domain in one of the following ways: +The CLI defaults to US Cloud (https://app.infisical.com). To connect to **EU Cloud (https://eu.infisical.com)** or a **self-hosted instance**, you MUST configure the domain in one of the following ways: - Use the `INFISICAL_API_URL` environment variable - Use the `--domain` flag on every command @@ -175,7 +175,7 @@ The CLI defaults to the US Cloud (https://app.infisical.com). To connect to the infisical login --domain="https://your-domain.infisical.com" --method=universal-auth --client-id= --client-secret= --silent --plain # All subsequent commands must also include --domain - infisical secrets --domain="https://your-domain.infisical.com" --projectId --env dev + infisical secrets --domain="https://your-domain.infisical.com" --projectId= --env=dev ``` @@ -242,12 +242,12 @@ For security and privacy concerns, we recommend you to configure your terminal t ## FAQ - - Yes. The CLI is set to connect to Infisical US Cloud by default, but if you're using the EU Cloud, a self-hosted instance, you need to configure the domain for **all CLI commands**. + + Yes. The CLI is set to connect to Infisical US Cloud by default, but if you're using EU Cloud or a self-hosted instance you can to configure the domain for **all CLI commands**. - #### Method 1:Use the updated CLI (v0.4.0+) + #### Method 1: Use the updated CLI (v0.4.0+) - Beginning with CLI version V0.4.0, you can choose between logging in through the Infisical US Cloud, EU Cloud, or your own self-hosted instance. Simply execute the `infisical login` command and follow the on-screen instructions. + Beginning with CLI version V0.4.0, you can choose between logging in through Infisical US Cloud, EU Cloud, or your own self-hosted instance. Simply execute the `infisical login` command and follow the on-screen instructions. #### Method 2: Export environment variable @@ -287,15 +287,15 @@ For security and privacy concerns, we recommend you to configure your terminal t #### Method 3: Set manually on every command - If you prefer not to set the environment variable, you must include the `--domain` flag on **every CLI command** you run: + If you prefer not to use an environment variable, you must include the `--domain` flag on **every CLI command** you run: ```bash # Login with domain infisical login --domain="https://your-domain.infisical.com" --method=oidc-auth --jwt $JWT # All subsequent commands must also include --domain - infisical secrets --domain="https://your-self-hosted-infisical.com/api" --projectId --env dev - infisical export --domain="https://your-self-hosted-infisical.com/api" --format=dotenv-export + infisical secrets --domain="https://your-self-hosted-infisical.com" --projectId --env dev + infisical export --domain="https://your-self-hosted-infisical.com" --format=dotenv-export ``` From 448d8186ec01b53df6c4c49a5646e972ac3a544f Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Wed, 26 Nov 2025 18:48:41 +0530 Subject: [PATCH 10/26] fix: review comments --- .../src/services/secret-v2-bridge/secret-v2-bridge-fns.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index d25c9d58e..c18a51ea4 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -421,12 +421,11 @@ export const fnSecretBulkDelete = async ({ ); const changes = deletedSecrets - .filter(({ type }) => type === SecretType.Shared) + .filter(({ type, id }) => type === SecretType.Shared && secretVersions[id]) .map(({ id }) => ({ type: CommitType.DELETE, secretVersionId: secretVersions[id]?.id - })) - .filter((el) => el.secretVersionId); + })); if (changes.length > 0) { if (commitChanges) { From 79960aa1aea5329a79bf454c088003d0b828030a Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Wed, 26 Nov 2025 18:55:10 +0530 Subject: [PATCH 11/26] fix: greptile review --- .../components/SecretListView/SecretItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx index 27f180ee9..95fe6edd1 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretItem.tsx @@ -398,7 +398,7 @@ export const SecretItem = memo( const data = await fetchValue(); if (!data) return; - navigator.clipboard.writeText((data.valueOverride ?? data.value) as string); + navigator.clipboard.writeText(data.valueOverride ?? data.value); setIsSecValueCopied.on(); }; From 40c80f4b6829568055ecaea0200613c9becc5732 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Wed, 26 Nov 2025 10:49:05 -0300 Subject: [PATCH 12/26] refactor: remove deprecated native integration error handling and streamline integration token saving process in API routes --- .../routes/v1/integration-auth-router.ts | 48 ++++------ .../server/routes/v1/integration-router.ts | 96 +++++++++---------- 2 files changed, 63 insertions(+), 81 deletions(-) diff --git a/backend/src/server/routes/v1/integration-auth-router.ts b/backend/src/server/routes/v1/integration-auth-router.ts index 40bb8fa13..e5156724d 100644 --- a/backend/src/server/routes/v1/integration-auth-router.ts +++ b/backend/src/server/routes/v1/integration-auth-router.ts @@ -2,7 +2,6 @@ import { z } from "zod"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { ApiDocsTags, INTEGRATION_AUTH } from "@app/lib/api-docs"; -import { ForbiddenRequestError } from "@app/lib/errors"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; @@ -11,9 +10,6 @@ import { Integrations } from "@app/services/integration-auth/integration-list"; import { integrationAuthPubSchema } from "../sanitizedSchemas"; -const NATIVE_INTEGRATION_DEPRECATION_MESSAGE = - "We're moving Native Integrations to Secret Syncs. Check the documentation at https://infisical.com/docs/integrations/secret-syncs/overview. If the integration you need isn't available in the Secret Syncs, please get in touch with us at team@infisical.com."; - export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) => { server.route({ method: "GET", @@ -337,33 +333,27 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) }) } }, - handler: async (_) => { - throw new ForbiddenRequestError({ - message: NATIVE_INTEGRATION_DEPRECATION_MESSAGE + handler: async (req) => { + const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({ + actorId: req.permission.id, + actor: req.permission.type, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + projectId: req.body.workspaceId, + ...req.body }); - // We are keeping the old response commented out for an easy revert on the API if we need to before the full phase out. - - // const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({ - // actorId: req.permission.id, - // actor: req.permission.type, - // actorAuthMethod: req.permission.authMethod, - // actorOrgId: req.permission.orgId, - // projectId: req.body.workspaceId, - // ...req.body - // }); - - // await server.services.auditLog.createAuditLog({ - // ...req.auditLogInfo, - // projectId: req.body.workspaceId, - // event: { - // type: EventType.AUTHORIZE_INTEGRATION, - // metadata: { - // integration: integrationAuth.integration - // } - // } - // }); - // return { integrationAuth }; + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: req.body.workspaceId, + event: { + type: EventType.AUTHORIZE_INTEGRATION, + metadata: { + integration: integrationAuth.integration + } + } + }); + return { integrationAuth }; } }); diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index 183c5a38b..95477c341 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -3,19 +3,17 @@ import { z } from "zod"; import { IntegrationsSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { ApiDocsTags, INTEGRATION } from "@app/lib/api-docs"; -import { ForbiddenRequestError } from "@app/lib/errors"; import { removeTrailingSlash, shake } from "@app/lib/fn"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; +import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; import { IntegrationMetadataSchema } from "@app/services/integration/integration-schema"; import { Integrations } from "@app/services/integration-auth/integration-list"; +import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telemetry/telemetry-types"; import {} from "../sanitizedSchemas"; -const NATIVE_INTEGRATION_DEPRECATION_MESSAGE = - "We're moving Native Integrations to Secret Syncs. Check the documentation at https://infisical.com/docs/integrations/secret-syncs/overview. If the integration you need isn't available in the Secret Syncs, please get in touch with us at team@infisical.com."; - export const registerIntegrationRouter = async (server: FastifyZodProvider) => { server.route({ method: "POST", @@ -68,58 +66,52 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - handler: async (_) => { - throw new ForbiddenRequestError({ - message: NATIVE_INTEGRATION_DEPRECATION_MESSAGE + handler: async (req) => { + const { integration, integrationAuth } = await server.services.integration.createIntegration({ + actorId: req.permission.id, + actor: req.permission.type, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body }); - // We are keeping the old response commented out for an easy revert on the API if we need to before the full phase out. + const createIntegrationEventProperty = shake({ + integrationId: integration.id.toString(), + integration: integration.integration, + environment: req.body.sourceEnvironment, + secretPath: req.body.secretPath, + url: integration.url, + app: integration.app, + appId: integration.appId, + targetEnvironment: integration.targetEnvironment, + targetEnvironmentId: integration.targetEnvironmentId, + targetService: integration.targetService, + targetServiceId: integration.targetServiceId, + path: integration.path, + region: integration.region + }) as TIntegrationCreatedEvent["properties"]; - // const { integration, integrationAuth } = await server.services.integration.createIntegration({ - // actorId: req.permission.id, - // actor: req.permission.type, - // actorAuthMethod: req.permission.authMethod, - // actorOrgId: req.permission.orgId, - // ...req.body - // }); + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: integrationAuth.projectId, + event: { + type: EventType.CREATE_INTEGRATION, + // eslint-disable-next-line + metadata: createIntegrationEventProperty + } + }); - // const createIntegrationEventProperty = shake({ - // integrationId: integration.id.toString(), - // integration: integration.integration, - // environment: req.body.sourceEnvironment, - // secretPath: req.body.secretPath, - // url: integration.url, - // app: integration.app, - // appId: integration.appId, - // targetEnvironment: integration.targetEnvironment, - // targetEnvironmentId: integration.targetEnvironmentId, - // targetService: integration.targetService, - // targetServiceId: integration.targetServiceId, - // path: integration.path, - // region: integration.region - // }) as TIntegrationCreatedEvent["properties"]; - - // await server.services.auditLog.createAuditLog({ - // ...req.auditLogInfo, - // projectId: integrationAuth.projectId, - // event: { - // type: EventType.CREATE_INTEGRATION, - // // eslint-disable-next-line - // metadata: createIntegrationEventProperty - // } - // }); - - // await server.services.telemetry.sendPostHogEvents({ - // event: PostHogEventTypes.IntegrationCreated, - // organizationId: req.permission.orgId, - // distinctId: getTelemetryDistinctId(req), - // properties: { - // ...createIntegrationEventProperty, - // projectId: integrationAuth.projectId, - // ...req.auditLogInfo - // } - // }); - // return { integration }; + await server.services.telemetry.sendPostHogEvents({ + event: PostHogEventTypes.IntegrationCreated, + organizationId: req.permission.orgId, + distinctId: getTelemetryDistinctId(req), + properties: { + ...createIntegrationEventProperty, + projectId: integrationAuth.projectId, + ...req.auditLogInfo + } + }); + return { integration }; } }); From 0e49aaf1e605f5764a872b0a24bfdcc16faab96c Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Wed, 26 Nov 2025 11:44:54 -0300 Subject: [PATCH 13/26] feat: add telemetry events for integration deletion and synchronization, including new event types and properties --- .../server/routes/v1/integration-router.ts | 99 ++++++++++++------- .../src/services/telemetry/telemetry-types.ts | 45 +++++++++ 2 files changed, 111 insertions(+), 33 deletions(-) diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index 95477c341..5670edf77 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -10,7 +10,12 @@ import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; import { IntegrationMetadataSchema } from "@app/services/integration/integration-schema"; import { Integrations } from "@app/services/integration-auth/integration-list"; -import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telemetry/telemetry-types"; +import { + PostHogEventTypes, + TIntegrationCreatedEvent, + TIntegrationDeletedEvent, + TIntegrationSyncedEvent +} from "@app/services/telemetry/telemetry-types"; import {} from "../sanitizedSchemas"; @@ -288,31 +293,46 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { shouldDeleteIntegrationSecrets: req.query.shouldDeleteIntegrationSecrets }); + const deleteIntegrationEventProperty = shake({ + integrationId: integration.id, + integration: integration.integration, + environment: integration.environment.slug, + secretPath: integration.secretPath, + url: integration.url, + app: integration.app, + appId: integration.appId, + targetEnvironment: integration.targetEnvironment, + targetEnvironmentId: integration.targetEnvironmentId, + targetService: integration.targetService, + targetServiceId: integration.targetServiceId, + path: integration.path, + region: integration.region + }) as TIntegrationDeletedEvent["properties"]; + await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, projectId: integration.projectId, event: { type: EventType.DELETE_INTEGRATION, // eslint-disable-next-line - metadata: shake({ - integrationId: integration.id, - integration: integration.integration, - environment: integration.environment.slug, - secretPath: integration.secretPath, - url: integration.url, - app: integration.app, - appId: integration.appId, - targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId, - targetService: integration.targetService, - targetServiceId: integration.targetServiceId, - path: integration.path, - region: integration.region, + metadata: { + ...deleteIntegrationEventProperty, shouldDeleteIntegrationSecrets: req.query.shouldDeleteIntegrationSecrets - // eslint-disable-next-line - }) as any + } as any } }); + + await server.services.telemetry.sendPostHogEvents({ + event: PostHogEventTypes.IntegrationDeleted, + organizationId: req.permission.orgId, + distinctId: getTelemetryDistinctId(req), + properties: { + ...deleteIntegrationEventProperty, + projectId: integration.projectId, + ...req.auditLogInfo + } + }); + return { integration }; } }); @@ -351,28 +371,41 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { id: req.params.integrationId }); + const syncIntegrationEventProperty = shake({ + integrationId: integration.id, + integration: integration.integration, + environment: integration.environment.slug, + secretPath: integration.secretPath, + url: integration.url, + app: integration.app, + appId: integration.appId, + targetEnvironment: integration.targetEnvironment, + targetEnvironmentId: integration.targetEnvironmentId, + targetService: integration.targetService, + targetServiceId: integration.targetServiceId, + path: integration.path, + region: integration.region + }) as TIntegrationSyncedEvent["properties"]; + await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, projectId: integration.projectId, event: { type: EventType.MANUAL_SYNC_INTEGRATION, // eslint-disable-next-line - metadata: shake({ - integrationId: integration.id, - integration: integration.integration, - environment: integration.environment.slug, - secretPath: integration.secretPath, - url: integration.url, - app: integration.app, - appId: integration.appId, - targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId, - targetService: integration.targetService, - targetServiceId: integration.targetServiceId, - path: integration.path, - region: integration.region - // eslint-disable-next-line - }) as any + metadata: syncIntegrationEventProperty as any + } + }); + + await server.services.telemetry.sendPostHogEvents({ + event: PostHogEventTypes.IntegrationSynced, + organizationId: req.permission.orgId, + distinctId: getTelemetryDistinctId(req), + properties: { + ...syncIntegrationEventProperty, + projectId: integration.projectId, + isManualSync: true, + ...req.auditLogInfo } }); diff --git a/backend/src/services/telemetry/telemetry-types.ts b/backend/src/services/telemetry/telemetry-types.ts index de466614a..d2e977605 100644 --- a/backend/src/services/telemetry/telemetry-types.ts +++ b/backend/src/services/telemetry/telemetry-types.ts @@ -21,6 +21,8 @@ export enum PostHogEventTypes { SecretScannerPush = "cloud secret scan", ProjectCreated = "Project Created", IntegrationCreated = "Integration Created", + IntegrationSynced = "Integration Synced", + IntegrationDeleted = "Integration Deleted", MachineIdentityCreated = "Machine Identity Created", UserOrgInvitation = "User Org Invitation", TelemetryInstanceStats = "Self Hosted Instance Stats", @@ -126,6 +128,47 @@ export type TIntegrationCreatedEvent = { }; }; +export type TIntegrationSyncedEvent = { + event: PostHogEventTypes.IntegrationSynced; + properties: { + projectId: string; + integrationId: string; + integration: string; + environment: string; + secretPath: string; + isManualSync: boolean; + url?: string; + app?: string; + appId?: string; + targetEnvironment?: string; + targetEnvironmentId?: string; + targetService?: string; + targetServiceId?: string; + path?: string; + region?: string; + }; +}; + +export type TIntegrationDeletedEvent = { + event: PostHogEventTypes.IntegrationDeleted; + properties: { + projectId: string; + integrationId: string; + integration: string; + environment: string; + secretPath: string; + url?: string; + app?: string; + appId?: string; + targetEnvironment?: string; + targetEnvironmentId?: string; + targetService?: string; + targetServiceId?: string; + path?: string; + region?: string; + }; +}; + export type TUserOrgInvitedEvent = { event: PostHogEventTypes.UserOrgInvitation; properties: { @@ -249,6 +292,8 @@ export type TPostHogEvent = { distinctId: string; organizationId?: string } & ( | TUserOrgInvitedEvent | TMachineIdentityCreatedEvent | TIntegrationCreatedEvent + | TIntegrationSyncedEvent + | TIntegrationDeletedEvent | TProjectCreateEvent | TTelemetryInstanceStatsEvent | TSecretRequestCreatedEvent From ffe866efb05637fbd3524f7abfb5603b47d9de06 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Wed, 26 Nov 2025 12:02:23 -0300 Subject: [PATCH 14/26] fix: add missing eslint-disable comments for metadata in integration deletion event --- backend/src/server/routes/v1/integration-router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index 5670edf77..1d3a6a8b0 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -314,10 +314,10 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { projectId: integration.projectId, event: { type: EventType.DELETE_INTEGRATION, - // eslint-disable-next-line metadata: { ...deleteIntegrationEventProperty, shouldDeleteIntegrationSecrets: req.query.shouldDeleteIntegrationSecrets + // eslint-disable-next-line } as any } }); From f98b803e76c0dca6263838cec3d0c3bbc1e0ab21 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Wed, 26 Nov 2025 12:05:08 -0300 Subject: [PATCH 15/26] fix: add eslint-disable comment for shouldDeleteIntegrationSecrets in integration deletion event metadata --- backend/src/server/routes/v1/integration-router.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index 1d3a6a8b0..7a3b84c5a 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -314,6 +314,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { projectId: integration.projectId, event: { type: EventType.DELETE_INTEGRATION, + // eslint-disable-next-line metadata: { ...deleteIntegrationEventProperty, shouldDeleteIntegrationSecrets: req.query.shouldDeleteIntegrationSecrets From ceb87616bf985c1753404b1cef00910e1e7ee3d1 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Wed, 26 Nov 2025 23:44:43 +0530 Subject: [PATCH 16/26] fix: review comments --- backend/src/ee/routes/v1/project-template-router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/ee/routes/v1/project-template-router.ts b/backend/src/ee/routes/v1/project-template-router.ts index 90343ffb4..6a022bad7 100644 --- a/backend/src/ee/routes/v1/project-template-router.ts +++ b/backend/src/ee/routes/v1/project-template-router.ts @@ -197,7 +197,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider) description: z.string().max(256).trim().optional().describe(ProjectTemplates.CREATE.description), roles: ProjectTemplateRolesSchema.default([]).describe(ProjectTemplates.CREATE.roles), type: z.nativeEnum(ProjectType).describe(ProjectTemplates.CREATE.type), - environments: ProjectTemplateEnvironmentsSchema.nullish().describe(ProjectTemplates.CREATE.environments) + environments: ProjectTemplateEnvironmentsSchema.optional().describe(ProjectTemplates.CREATE.environments) }), response: { 200: z.object({ From 9ffb4406391db7df0324b7cca047a5a4b4506ae4 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Wed, 26 Nov 2025 16:52:12 -0300 Subject: [PATCH 17/26] feat: integrate telemetry service for secret synchronization events and update project role permissions to reflect workspace integrations --- backend/src/server/routes/index.ts | 3 +- backend/src/services/secret/secret-queue.ts | 29 ++++++++- docs/docs.json | 1 - docs/integrations/cicd/checkly.mdx | 45 -------------- .../components/PolicySelectionModal.tsx | 13 +++- .../components/RolePermissionsSection.tsx | 13 +++- .../IntegrationsListPage.tsx | 61 +++++++++---------- 7 files changed, 84 insertions(+), 81 deletions(-) delete mode 100644 docs/integrations/cicd/checkly.mdx diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 00771168c..0d7999957 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -1329,7 +1329,8 @@ export const registerRoutes = async ( eventBusService, licenseService, membershipRoleDAL, - membershipUserDAL + membershipUserDAL, + telemetryService }); const projectService = projectServiceFactory({ diff --git a/backend/src/services/secret/secret-queue.ts b/backend/src/services/secret/secret-queue.ts index eefa0764f..5246aa8d1 100644 --- a/backend/src/services/secret/secret-queue.ts +++ b/backend/src/services/secret/secret-queue.ts @@ -64,6 +64,8 @@ import { expandSecretReferencesFactory, getAllSecretReferences } from "../secret import { TSecretVersionV2DALFactory } from "../secret-v2-bridge/secret-version-dal"; import { TSecretVersionV2TagDALFactory } from "../secret-v2-bridge/secret-version-tag-dal"; import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service"; +import { TTelemetryServiceFactory } from "../telemetry/telemetry-service"; +import { PostHogEventTypes } from "../telemetry/telemetry-types"; import { TUserDALFactory } from "../user/user-dal"; import { TWebhookDALFactory } from "../webhook/webhook-dal"; import { fnTriggerWebhook } from "../webhook/webhook-fns"; @@ -120,6 +122,7 @@ type TSecretQueueFactoryDep = { reminderService: Pick; eventBusService: TEventBusService; licenseService: Pick; + telemetryService: Pick; }; export type TGetSecrets = { @@ -184,7 +187,8 @@ export const secretQueueFactory = ({ eventBusService, licenseService, membershipUserDAL, - membershipRoleDAL + membershipRoleDAL, + telemetryService }: TSecretQueueFactoryDep) => { const integrationMeter = opentelemetry.metrics.getMeter("Integrations"); const errorHistogram = integrationMeter.createHistogram("integration_secret_sync_errors", { @@ -1029,6 +1033,29 @@ export const secretQueueFactory = ({ isSynced: response?.isSynced ?? true }); + await telemetryService.sendPostHogEvents({ + event: PostHogEventTypes.IntegrationSynced, + distinctId: `project/${projectId}`, + organizationId: project.orgId, + properties: { + integrationId: integration.id, + integration: integration.integration, + environment, + secretPath, + projectId, + url: integration.url ?? undefined, + app: integration.app ?? undefined, + appId: integration.appId ?? undefined, + targetEnvironment: integration.targetEnvironment ?? undefined, + targetEnvironmentId: integration.targetEnvironmentId ?? undefined, + targetService: integration.targetService ?? undefined, + targetServiceId: integration.targetServiceId ?? undefined, + path: integration.path ?? undefined, + region: integration.region ?? undefined, + isManualSync: isManual ?? false + } + }); + // May be undefined, if it's undefined we assume the sync was successful, hence the strict equality type check. if (response?.isSynced === false) { integrationsFailedToSync.push({ diff --git a/docs/docs.json b/docs/docs.json index 27d93b2c8..68ac594fb 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -574,7 +574,6 @@ "pages": [ "integrations/cicd/aws-amplify", "integrations/cicd/bitbucket", - "integrations/cicd/checkly", "integrations/cicd/githubactions", "integrations/cicd/gitlab", "integrations/cicd/jenkins" diff --git a/docs/integrations/cicd/checkly.mdx b/docs/integrations/cicd/checkly.mdx deleted file mode 100644 index 00ec38d2f..000000000 --- a/docs/integrations/cicd/checkly.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: "Checkly" -description: "How to sync secrets from Infisical to Checkly" ---- - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) - - - - Obtain a Checkly API Key in User Settings > API Keys. - - ![integrations checkly dashboard](../../images/integrations/checkly/integrations-checkly-dashboard.png) - ![integrations checkly token](../../images/integrations/checkly/integrations-checkly-token.png) - - Navigate to your project's integrations tab in Infisical. - - ![integrations](../../images/integrations.png) - - Press on the Checkly tile and input your Checkly API Key to grant Infisical access to your Checkly account. - - ![integrations checkly authorization](../../images/integrations/checkly/integrations-checkly-auth.png) - - - - Select which Infisical environment secrets you want to sync to Checkly and press create integration to start syncing secrets. - - ![integrations checkly](../../images/integrations/checkly/integrations-checkly-create.png) - - - Infisical integrates with Checkly's environment variables at the **global** and **group** levels. - - To sync secrets to a specific group, you can select a group from the Checkly Group dropdown; otherwise, leaving it empty will sync secrets globally. - - - ![integrations checkly](../../images/integrations/checkly/integrations-checkly.png) - - - In the new version of the Checkly integration, you are able to specify suffixes that depend on the secrets' environment and path. - If you choose to do so, you should utilize such suffixes for ALL Checkly integrations – otherwise the integration system - might run into issues with deleting secrets from the wrong environments. - - - \ No newline at end of file diff --git a/frontend/src/pages/project/RoleDetailsBySlugPage/components/PolicySelectionModal.tsx b/frontend/src/pages/project/RoleDetailsBySlugPage/components/PolicySelectionModal.tsx index 63853ad51..3505722bc 100644 --- a/frontend/src/pages/project/RoleDetailsBySlugPage/components/PolicySelectionModal.tsx +++ b/frontend/src/pages/project/RoleDetailsBySlugPage/components/PolicySelectionModal.tsx @@ -18,7 +18,8 @@ import { Tooltip, Tr } from "@app/components/v2"; -import { ProjectPermissionSub } from "@app/context"; +import { ProjectPermissionSub, useProject } from "@app/context"; +import { useGetWorkspaceIntegrations } from "@app/hooks/api"; import { ProjectType } from "@app/hooks/api/projects/types"; import { @@ -46,6 +47,9 @@ type TForm = { permissions: Record }; const Content = ({ onClose, type: projectType }: ContentProps) => { const rootForm = useFormContext(); const [search, setSearch] = useState(""); + const { currentProject } = useProject(); + const { data: integrations = [] } = useGetWorkspaceIntegrations(currentProject?.id ?? ""); + const { control, handleSubmit, @@ -60,6 +64,8 @@ const Content = ({ onClose, type: projectType }: ContentProps) => { } }); + const hasNativeIntegrations = integrations.length > 0; + const filteredPolicies = Object.entries(PROJECT_PERMISSION_OBJECT) .filter( ([subject, { title }]) => @@ -68,6 +74,11 @@ const Content = ({ onClose, type: projectType }: ContentProps) => { ] && (search ? title.toLowerCase().includes(search.toLowerCase()) : true) ) .filter(([subject]) => !EXCLUDED_PERMISSION_SUBS.includes(subject as ProjectPermissionSub)) + .filter( + ([subject]) => + // Hide Native Integrations policy if project has no integrations + subject !== ProjectPermissionSub.Integrations || hasNativeIntegrations + ) .sort((a, b) => a[1].title.localeCompare(b[1].title)) .map(([subject]) => subject); diff --git a/frontend/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx b/frontend/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx index c93cea534..f50b39a92 100644 --- a/frontend/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx +++ b/frontend/src/pages/project/RoleDetailsBySlugPage/components/RolePermissionsSection.tsx @@ -11,7 +11,11 @@ import { Button } from "@app/components/v2"; import { ProjectPermissionSub, useProject } from "@app/context"; import { ProjectPermissionSet } from "@app/context/ProjectPermissionContext"; import { evaluatePermissionsAbility } from "@app/helpers/permissions"; -import { useGetProjectRoleBySlug, useUpdateProjectRole } from "@app/hooks/api"; +import { + useGetProjectRoleBySlug, + useGetWorkspaceIntegrations, + useUpdateProjectRole +} from "@app/hooks/api"; import { ProjectType } from "@app/hooks/api/projects/types"; import { ProjectMembershipRole } from "@app/hooks/api/roles/types"; @@ -105,6 +109,8 @@ export const RolePermissionsSection = ({ roleSlug, isDisabled }: Props) => { currentProject?.id ?? "", roleSlug as string ); + const { data: integrations = [] } = useGetWorkspaceIntegrations(projectId); + const hasNativeIntegrations = integrations.length > 0; const [showAccessTree, setShowAccessTree] = useState(null); @@ -198,6 +204,11 @@ export const RolePermissionsSection = ({ roleSlug, isDisabled }: Props) => { {!isPending && } {(Object.keys(PROJECT_PERMISSION_OBJECT) as ProjectPermissionSub[]) .filter((subject) => !EXCLUDED_PERMISSION_SUBS.includes(subject)) + .filter( + (subject) => + // Hide Native Integrations policy if project has no integrations + subject !== ProjectPermissionSub.Integrations || hasNativeIntegrations + ) .map((subject) => ( { {hasNativeIntegrations && ( - - - We're moving Native Integrations to{" "} - - Secret Syncs - - . If the integration you need isn't available in the Secret Syncs menu, - please get in touch with us at{" "} - - team@infisical.com - - . - - +
+
+ +
+

+ We're moving Native Integrations to{" "} + + Secret Syncs + + . If the integration you need isn't available in the Secret Syncs menu, + please get in touch with us at{" "} + + team@infisical.com + + . +

+
+
+
Date: Thu, 27 Nov 2025 01:49:33 +0530 Subject: [PATCH 18/26] feat: adds expiring scim token notification --- ...143442_add-notification-flag-scim-token.ts | 21 ++++++ backend/src/db/schemas/scim-tokens.ts | 3 +- backend/src/ee/services/scim/scim-dal.ts | 65 +++++++++++++++++-- backend/src/ee/services/scim/scim-service.ts | 65 ++++++++++++++++++- backend/src/ee/services/scim/scim-types.ts | 11 ++++ backend/src/server/routes/index.ts | 1 + .../resource-cleanup-queue.ts | 4 ++ .../service-token/service-token-service.ts | 10 ++- .../emails/ScimTokenExpiryNoticeTemplate.tsx | 54 +++++++++++++++ backend/src/services/smtp/emails/index.ts | 1 + backend/src/services/smtp/smtp-service.ts | 3 + 11 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 backend/src/db/migrations/20251126143442_add-notification-flag-scim-token.ts create mode 100644 backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx diff --git a/backend/src/db/migrations/20251126143442_add-notification-flag-scim-token.ts b/backend/src/db/migrations/20251126143442_add-notification-flag-scim-token.ts new file mode 100644 index 000000000..00dcf7902 --- /dev/null +++ b/backend/src/db/migrations/20251126143442_add-notification-flag-scim-token.ts @@ -0,0 +1,21 @@ +import { Knex } from "knex"; + +import { TableName } from "../schemas"; + +export async function up(knex: Knex): Promise { + const hasCol = await knex.schema.hasColumn(TableName.ScimToken, "expiryNotificationSent"); + if (!hasCol) { + await knex.schema.alterTable(TableName.ScimToken, (t) => { + t.boolean("expiryNotificationSent").defaultTo(false); + }); + } +} + +export async function down(knex: Knex): Promise { + const hasCol = await knex.schema.hasColumn(TableName.ScimToken, "expiryNotificationSent"); + if (hasCol) { + await knex.schema.alterTable(TableName.ScimToken, (t) => { + t.dropColumn("expiryNotificationSent"); + }); + } +} diff --git a/backend/src/db/schemas/scim-tokens.ts b/backend/src/db/schemas/scim-tokens.ts index ab6e10d27..6774b6bfd 100644 --- a/backend/src/db/schemas/scim-tokens.ts +++ b/backend/src/db/schemas/scim-tokens.ts @@ -13,7 +13,8 @@ export const ScimTokensSchema = z.object({ description: z.string(), orgId: z.string().uuid(), createdAt: z.date(), - updatedAt: z.date() + updatedAt: z.date(), + expiryNotificationSent: z.boolean().default(false).nullable().optional() }); export type TScimTokens = z.infer; diff --git a/backend/src/ee/services/scim/scim-dal.ts b/backend/src/ee/services/scim/scim-dal.ts index 77a19d4d2..580ae2747 100644 --- a/backend/src/ee/services/scim/scim-dal.ts +++ b/backend/src/ee/services/scim/scim-dal.ts @@ -1,10 +1,65 @@ +import { Knex } from "knex"; + import { TDbClient } from "@app/db"; -import { TableName } from "@app/db/schemas"; -import { ormify, TOrmify } from "@app/lib/knex"; +import { AccessScope, OrgMembershipRole, OrgMembershipStatus, TableName } from "@app/db/schemas"; +import { DatabaseError } from "@app/lib/errors"; +import { ormify } from "@app/lib/knex"; -export type TScimDALFactory = TOrmify; +import { TExpiringScimToken } from "./scim-types"; -export const scimDALFactory = (db: TDbClient): TScimDALFactory => { +export type TScimDALFactory = ReturnType; + +export const scimDALFactory = (db: TDbClient) => { const scimTokenOrm = ormify(db, TableName.ScimToken); - return scimTokenOrm; + + const findExpiringTokens = async (tx?: Knex, batchSize = 500, offset = 0): Promise => { + try { + const conn = tx || db.replicaNode(); + + const batch = await conn(TableName.ScimToken) + .join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.ScimToken}.orgId`) + .whereRaw( + ` + (${TableName.ScimToken}."ttlDays" > 0 AND + (${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") < NOW() + INTERVAL '1 day' AND + (${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") > NOW()) + ` + ) + .where(`${TableName.ScimToken}.expiryNotificationSent`, false) + .select( + conn.ref("id").withSchema(TableName.ScimToken), + conn.ref("ttlDays").withSchema(TableName.ScimToken), + conn.ref("description").withSchema(TableName.ScimToken), + conn.ref("orgId").withSchema(TableName.ScimToken), + conn.ref("createdAt").withSchema(TableName.ScimToken), + conn.ref("name").withSchema(TableName.Organization).as("orgName"), + conn.raw(` + COALESCE( + ( + SELECT array_agg(${TableName.Users}.email) + FROM ${TableName.Membership} + JOIN ${TableName.MembershipRole} ON ${TableName.Membership}.id = ${TableName.MembershipRole}."membershipId" + JOIN ${TableName.Users} ON ${TableName.Membership}."actorUserId" = ${TableName.Users}.id + WHERE ${TableName.Membership}."scopeOrgId" = ${TableName.ScimToken}."orgId" + AND ${TableName.Membership}.scope = '${AccessScope.Organization}' + AND ${TableName.MembershipRole}.role = '${OrgMembershipRole.Admin}' + AND ${TableName.Membership}.status != '${OrgMembershipStatus.Invited}' + AND ${TableName.Membership}."actorUserId" IS NOT NULL + AND ${TableName.Users}."isGhost" = false + AND ${TableName.Users}.email IS NOT NULL + ), + ARRAY[]::text[] + ) as "adminEmails" + `) + ) + .limit(batchSize) + .offset(offset); + + return batch; + } catch (err) { + throw new DatabaseError({ error: err, name: "FindExpiringTokens" }); + } + }; + + return { ...scimTokenOrm, findExpiringTokens }; }; diff --git a/backend/src/ee/services/scim/scim-service.ts b/backend/src/ee/services/scim/scim-service.ts index 8b9256023..0f71dd185 100644 --- a/backend/src/ee/services/scim/scim-service.ts +++ b/backend/src/ee/services/scim/scim-service.ts @@ -19,6 +19,7 @@ import { TScimDALFactory } from "@app/ee/services/scim/scim-dal"; import { getConfig } from "@app/lib/config/env"; import { crypto } from "@app/lib/crypto"; import { BadRequestError, NotFoundError, ScimRequestError, UnauthorizedError } from "@app/lib/errors"; +import { logger } from "@app/lib/logger"; import { alphaNumericNanoId } from "@app/lib/nanoid"; import { TAdditionalPrivilegeDALFactory } from "@app/services/additional-privilege/additional-privilege-dal"; import { AuthTokenType } from "@app/services/auth/auth-type"; @@ -47,7 +48,7 @@ import { buildScimGroup, buildScimGroupList, buildScimUser, buildScimUserList, p import { TScimGroup, TScimServiceFactory } from "./scim-types"; type TScimServiceFactoryDep = { - scimDAL: Pick; + scimDAL: Pick; userDAL: Pick< TUserDALFactory, "find" | "findOne" | "create" | "transaction" | "findUserEncKeyByUserIdsBatch" | "findById" | "updateById" @@ -1237,6 +1238,65 @@ export const scimServiceFactory = ({ return { scimTokenId: scimToken.id, orgId: scimToken.orgId }; }; + const notifyExpiringTokens: TScimServiceFactory["notifyExpiringTokens"] = async () => { + const appCfg = getConfig(); + let processedCount = 0; + let hasMoreRecords = true; + let offset = 0; + const batchSize = 500; + + while (hasMoreRecords) { + // eslint-disable-next-line no-await-in-loop + const expiringTokens = await scimDAL.findExpiringTokens(undefined, batchSize, offset); + + if (expiringTokens.length === 0) { + hasMoreRecords = false; + break; + } + + const successfullyNotifiedTokenIds: string[] = []; + + // eslint-disable-next-line no-await-in-loop + await Promise.all( + expiringTokens.map(async (token) => { + try { + if (token.adminEmails.length === 0) { + // Still mark as notified to avoid repeated checks + successfullyNotifiedTokenIds.push(token.id); + return; + } + + await smtpService.sendMail({ + recipients: token.adminEmails, + subjectLine: "SCIM Token Expiry Notice", + template: SmtpTemplates.ScimTokenExpired, + substitutions: { + tokenDescription: token.description, + orgName: token.orgName, + url: `${appCfg.SITE_URL}/organizations/${token.orgId}/settings?selectedTab=provisioning-settings` + } + }); + + successfullyNotifiedTokenIds.push(token.id); + } catch (error) { + logger.error(error, `Failed to send expiration notification for SCIM token ${token.id}:`); + } + }) + ); + + // Batch update all successfully notified tokens in a single query + if (successfullyNotifiedTokenIds.length > 0) { + // eslint-disable-next-line no-await-in-loop + await scimDAL.update({ $in: { id: successfullyNotifiedTokenIds } }, { expiryNotificationSent: true }); + } + + processedCount += expiringTokens.length; + offset += batchSize; + } + + return processedCount; + }; + return { createScimToken, listScimTokens, @@ -1253,6 +1313,7 @@ export const scimServiceFactory = ({ deleteScimGroup, replaceScimGroup, updateScimGroup, - fnValidateScimToken + fnValidateScimToken, + notifyExpiringTokens }; }; diff --git a/backend/src/ee/services/scim/scim-types.ts b/backend/src/ee/services/scim/scim-types.ts index 8bdea39e1..1275ef283 100644 --- a/backend/src/ee/services/scim/scim-types.ts +++ b/backend/src/ee/services/scim/scim-types.ts @@ -158,6 +158,16 @@ export type TScimGroup = { }; }; +export type TExpiringScimToken = { + id: string; + ttlDays: number; + description: string; + orgId: string; + createdAt: Date; + orgName: string; + adminEmails: string[]; +}; + export type TScimServiceFactory = { createScimToken: (arg: TCreateScimTokenDTO) => Promise<{ scimToken: string; @@ -200,4 +210,5 @@ export type TScimServiceFactory = { scimTokenId: string; orgId: string; }>; + notifyExpiringTokens: () => Promise; }; diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 00771168c..c6bd7bbaa 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -1907,6 +1907,7 @@ export const registerRoutes = async ( // DAILY const dailyResourceCleanUp = dailyResourceCleanUpQueueServiceFactory({ + scimService, auditLogDAL, queueService, secretVersionDAL, diff --git a/backend/src/services/resource-cleanup/resource-cleanup-queue.ts b/backend/src/services/resource-cleanup/resource-cleanup-queue.ts index 185ab5e94..60310765b 100644 --- a/backend/src/services/resource-cleanup/resource-cleanup-queue.ts +++ b/backend/src/services/resource-cleanup/resource-cleanup-queue.ts @@ -1,4 +1,5 @@ import { TAuditLogDALFactory } from "@app/ee/services/audit-log/audit-log-dal"; +import { TScimServiceFactory } from "@app/ee/services/scim/scim-types"; import { TSnapshotDALFactory } from "@app/ee/services/secret-snapshot/snapshot-dal"; import { TKeyValueStoreDALFactory } from "@app/keystore/key-value-store-dal"; import { getConfig } from "@app/lib/config/env"; @@ -29,6 +30,7 @@ type TDailyResourceCleanUpQueueServiceFactoryDep = { orgService: TOrgServiceFactory; userNotificationDAL: Pick; keyValueStoreDAL: Pick; + scimService: Pick; }; export type TDailyResourceCleanUpQueueServiceFactory = ReturnType; @@ -44,6 +46,7 @@ export const dailyResourceCleanUpQueueServiceFactory = ({ secretVersionV2DAL, identityUniversalAuthClientSecretDAL, serviceTokenService, + scimService, orgService, userNotificationDAL, keyValueStoreDAL @@ -86,6 +89,7 @@ export const dailyResourceCleanUpQueueServiceFactory = ({ await secretVersionV2DAL.pruneExcessVersions(); await secretFolderVersionDAL.pruneExcessVersions(); await serviceTokenService.notifyExpiringTokens(); + await scimService.notifyExpiringTokens(); await orgService.notifyInvitedUsers(); await auditLogDAL.pruneAuditLog(); await userNotificationDAL.pruneNotifications(); diff --git a/backend/src/services/service-token/service-token-service.ts b/backend/src/services/service-token/service-token-service.ts index de759eb9a..8f7b0a1b7 100644 --- a/backend/src/services/service-token/service-token-service.ts +++ b/backend/src/services/service-token/service-token-service.ts @@ -214,6 +214,8 @@ export const serviceTokenServiceFactory = ({ break; } + const successfullyNotifiedTokenIds: string[] = []; + // eslint-disable-next-line no-await-in-loop await Promise.all( expiringTokens.map(async (token) => { @@ -228,13 +230,19 @@ export const serviceTokenServiceFactory = ({ url: `${appCfg.SITE_URL}/organizations/${token.orgId}/projects/secret-management/${token.projectId}/access-management?selectedTab=service-tokens` } }); - await serviceTokenDAL.update({ id: token.id }, { expiryNotificationSent: true }); + successfullyNotifiedTokenIds.push(token.id); } catch (error) { logger.error(error, `Failed to send expiration notification for token ${token.id}:`); } }) ); + // Batch update all successfully notified tokens in a single query + if (successfullyNotifiedTokenIds.length > 0) { + // eslint-disable-next-line no-await-in-loop + await serviceTokenDAL.update({ $in: { id: successfullyNotifiedTokenIds } }, { expiryNotificationSent: true }); + } + processedCount += expiringTokens.length; offset += batchSize; } diff --git a/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx b/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx new file mode 100644 index 000000000..afc4bc90c --- /dev/null +++ b/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx @@ -0,0 +1,54 @@ +import { Heading, Section, Text } from "@react-email/components"; +import React from "react"; + +import { BaseButton } from "./BaseButton"; +import { BaseEmailWrapper, BaseEmailWrapperProps } from "./BaseEmailWrapper"; + +interface ScimTokenExpiryNoticeTemplateProps extends Omit { + tokenDescription?: string; + orgName: string; + url: string; +} + +export const ScimTokenExpiryNoticeTemplate = ({ + tokenDescription, + siteUrl, + orgName, + url +}: ScimTokenExpiryNoticeTemplateProps) => { + return ( + + + SCIM token expiry notice + +
+ + {tokenDescription ? ( + <> + Your SCIM token {tokenDescription} + + ) : ( + "One of your SCIM tokens" + )}{" "} + for the organization {orgName} will expire within 24 hours. + + + If this token is still needed for your external platform sync, please create a new one before it expires to + avoid disruption to your workflow. + +
+
+ Manage SCIM Tokens +
+
+ ); +}; + +export default ScimTokenExpiryNoticeTemplate; + +ScimTokenExpiryNoticeTemplate.PreviewProps = { + orgName: "Example Organization", + siteUrl: "https://infisical.com", + url: "https://infisical.com", + tokenDescription: "Example SCIM Token" +} as ScimTokenExpiryNoticeTemplateProps; diff --git a/backend/src/services/smtp/emails/index.ts b/backend/src/services/smtp/emails/index.ts index 692cacbaf..376f6780e 100644 --- a/backend/src/services/smtp/emails/index.ts +++ b/backend/src/services/smtp/emails/index.ts @@ -19,6 +19,7 @@ export * from "./PasswordSetupTemplate"; export * from "./PkiExpirationAlertTemplate"; export * from "./ProjectAccessRequestTemplate"; export * from "./ProjectInvitationTemplate"; +export * from "./ScimTokenExpiryNoticeTemplate"; export * from "./ScimUserProvisionedTemplate"; export * from "./SecretApprovalRequestBypassedTemplate"; export * from "./SecretApprovalRequestNeedsReviewTemplate"; diff --git a/backend/src/services/smtp/smtp-service.ts b/backend/src/services/smtp/smtp-service.ts index cef22009a..a30cecd30 100644 --- a/backend/src/services/smtp/smtp-service.ts +++ b/backend/src/services/smtp/smtp-service.ts @@ -28,6 +28,7 @@ import { PkiExpirationAlertTemplate, ProjectAccessRequestTemplate, ProjectInvitationTemplate, + ScimTokenExpiryNoticeTemplate, ScimUserProvisionedTemplate, SecretApprovalRequestBypassedTemplate, SecretApprovalRequestNeedsReviewTemplate, @@ -74,6 +75,7 @@ export enum SmtpTemplates { SecretLeakIncident = "secretLeakIncident", WorkspaceInvite = "workspaceInvitation", ScimUserProvisioned = "scimUserProvisioned", + ScimTokenExpired = "scimTokenExpired", PkiExpirationAlert = "pkiExpirationAlert", IntegrationSyncFailed = "integrationSyncFailed", SecretSyncFailed = "secretSyncFailed", @@ -121,6 +123,7 @@ const EmailTemplateMap: Record> = { [SmtpTemplates.SecretLeakIncident]: SecretLeakIncidentTemplate, [SmtpTemplates.WorkspaceInvite]: ProjectInvitationTemplate, [SmtpTemplates.ScimUserProvisioned]: ScimUserProvisionedTemplate, + [SmtpTemplates.ScimTokenExpired]: ScimTokenExpiryNoticeTemplate, [SmtpTemplates.SecretRequestCompleted]: SecretRequestCompletedTemplate, [SmtpTemplates.UnlockAccount]: UnlockAccountTemplate, [SmtpTemplates.ServiceTokenExpired]: ServiceTokenExpiryNoticeTemplate, From 0186f250068ba290430fea72198c5a09a4a05713 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Wed, 26 Nov 2025 14:45:53 -0800 Subject: [PATCH 19/26] style: minor banner adjustments --- .../IntegrationsListPage/IntegrationsListPage.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx index 4d371c299..9d5774d5d 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/IntegrationsListPage.tsx @@ -100,11 +100,11 @@ export const IntegrationsListPage = () => {
{hasNativeIntegrations && ( -
+
-

+

We're moving Native Integrations to{" "} { > Secret Syncs - . If the integration you need isn't available in the Secret Syncs menu, + . +

+

+ If the integration you need isn't available in the Secret Syncs menu, please get in touch with us at{" "} Date: Wed, 26 Nov 2025 20:28:55 -0300 Subject: [PATCH 20/26] fix(identity-oidc-auth): handle errors when fetching OIDC discovery document and validate jwks_uri --- .../identity-oidc-auth-service.ts | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts index a253c1e95..a5178f36d 100644 --- a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts +++ b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts @@ -99,13 +99,28 @@ export const identityOidcAuthServiceFactory = ({ } const requestAgent = new https.Agent({ ca: caCert, rejectUnauthorized: !!caCert }); - const { data: discoveryDoc } = await axios.get<{ jwks_uri: string }>( - `${identityOidcAuth.oidcDiscoveryUrl}/.well-known/openid-configuration`, - { - httpsAgent: identityOidcAuth.oidcDiscoveryUrl.includes("https") ? requestAgent : undefined - } - ); + + let discoveryDoc: { jwks_uri: string }; + try { + const response = await axios.get<{ jwks_uri: string }>( + `${identityOidcAuth.oidcDiscoveryUrl}/.well-known/openid-configuration`, + { + httpsAgent: identityOidcAuth.oidcDiscoveryUrl.includes("https") ? requestAgent : undefined + } + ); + discoveryDoc = response.data; + } catch (error) { + throw new UnauthorizedError({ + message: `Access denied: Failed to fetch OIDC discovery document from ${identityOidcAuth.oidcDiscoveryUrl}. ${error instanceof Error ? error.message : String(error)}` + }); + } + const jwksUri = discoveryDoc.jwks_uri; + if (!jwksUri) { + throw new UnauthorizedError({ + message: `Access denied: OIDC discovery document does not contain a jwks_uri. The identity provider may be misconfigured.` + }); + } const decodedToken = crypto.jwt().decode(oidcJwt, { complete: true }); if (!decodedToken) { From dbf9d8c57d11ab682abab285ffc9fa3367b03f36 Mon Sep 17 00:00:00 2001 From: x032205 Date: Wed, 26 Nov 2025 19:23:16 -0500 Subject: [PATCH 21/26] make MUST lowercase --- docs/cli/usage.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index e158539db..16c35b3b6 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -136,7 +136,7 @@ For versions prior to v0.4.0, the CLI defaults to US Cloud. To connect to EU Clo **Important:** If you're not using interactive login, you must configure the domain for **all CLI commands**. -The CLI defaults to US Cloud (https://app.infisical.com). To connect to **EU Cloud (https://eu.infisical.com)** or a **self-hosted instance**, you MUST configure the domain in one of the following ways: +The CLI defaults to US Cloud (https://app.infisical.com). To connect to **EU Cloud (https://eu.infisical.com)** or a **self-hosted instance**, you must configure the domain in one of the following ways: - Use the `INFISICAL_API_URL` environment variable - Use the `--domain` flag on every command From af2c1b31bce15c922d63c4053ae1b373af43f308 Mon Sep 17 00:00:00 2001 From: x032205 Date: Wed, 26 Nov 2025 19:25:25 -0500 Subject: [PATCH 22/26] remove unnecessary "to" --- docs/cli/usage.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index 16c35b3b6..04a7cb025 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -243,7 +243,7 @@ For security and privacy concerns, we recommend you to configure your terminal t - Yes. The CLI is set to connect to Infisical US Cloud by default, but if you're using EU Cloud or a self-hosted instance you can to configure the domain for **all CLI commands**. + Yes. The CLI is set to connect to Infisical US Cloud by default, but if you're using EU Cloud or a self-hosted instance you can configure the domain for **all CLI commands**. #### Method 1: Use the updated CLI (v0.4.0+) From b2586e9c3089bed6b813eaee8723c49452eabf03 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Thu, 27 Nov 2025 19:28:41 +0530 Subject: [PATCH 23/26] fix: update project template environment handling to use nullish instead of optional --- backend/src/ee/routes/v1/project-template-router.ts | 4 ++-- .../services/project-template/project-template-service.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/src/ee/routes/v1/project-template-router.ts b/backend/src/ee/routes/v1/project-template-router.ts index 6a022bad7..81fd79c82 100644 --- a/backend/src/ee/routes/v1/project-template-router.ts +++ b/backend/src/ee/routes/v1/project-template-router.ts @@ -197,7 +197,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider) description: z.string().max(256).trim().optional().describe(ProjectTemplates.CREATE.description), roles: ProjectTemplateRolesSchema.default([]).describe(ProjectTemplates.CREATE.roles), type: z.nativeEnum(ProjectType).describe(ProjectTemplates.CREATE.type), - environments: ProjectTemplateEnvironmentsSchema.optional().describe(ProjectTemplates.CREATE.environments) + environments: ProjectTemplateEnvironmentsSchema.nullish().describe(ProjectTemplates.CREATE.environments) }), response: { 200: z.object({ @@ -242,7 +242,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider) .describe(ProjectTemplates.UPDATE.name), description: z.string().max(256).trim().optional().describe(ProjectTemplates.UPDATE.description), roles: ProjectTemplateRolesSchema.optional().describe(ProjectTemplates.UPDATE.roles), - environments: ProjectTemplateEnvironmentsSchema.optional().describe(ProjectTemplates.UPDATE.environments) + environments: ProjectTemplateEnvironmentsSchema.nullish().describe(ProjectTemplates.UPDATE.environments) }), response: { 200: z.object({ diff --git a/backend/src/ee/services/project-template/project-template-service.ts b/backend/src/ee/services/project-template/project-template-service.ts index 5a9f04d8d..1ba21873a 100644 --- a/backend/src/ee/services/project-template/project-template-service.ts +++ b/backend/src/ee/services/project-template/project-template-service.ts @@ -189,11 +189,15 @@ export const projectTemplateServiceFactory = ({ message: `A project template with the name "${params.name}" already exists.` }); + const projectTemplateEnvironments = + type === ProjectType.SecretManager && environments === undefined + ? ProjectTemplateDefaultEnvironments + : environments; + const projectTemplate = await projectTemplateDAL.create({ ...params, roles: JSON.stringify(roles.map((role) => ({ ...role, permissions: packRules(role.permissions) }))), - environments: - type === ProjectType.SecretManager ? JSON.stringify(environments ?? ProjectTemplateDefaultEnvironments) : null, + environments: JSON.stringify(projectTemplateEnvironments), orgId: actor.orgId, type }); From e09b763e50aca6f298618fd887e379a25dfa2cf4 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Thu, 27 Nov 2025 20:42:56 +0530 Subject: [PATCH 24/26] fix: review comments --- backend/src/ee/services/scim/scim-dal.ts | 55 ++++++++----------- backend/src/ee/services/scim/scim-service.ts | 7 ++- .../emails/ScimTokenExpiryNoticeTemplate.tsx | 23 +++++++- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/backend/src/ee/services/scim/scim-dal.ts b/backend/src/ee/services/scim/scim-dal.ts index 580ae2747..e856070e1 100644 --- a/backend/src/ee/services/scim/scim-dal.ts +++ b/backend/src/ee/services/scim/scim-dal.ts @@ -14,44 +14,35 @@ export const scimDALFactory = (db: TDbClient) => { const findExpiringTokens = async (tx?: Knex, batchSize = 500, offset = 0): Promise => { try { - const conn = tx || db.replicaNode(); - - const batch = await conn(TableName.ScimToken) - .join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.ScimToken}.orgId`) + const batch = await (tx || db.replicaNode())(TableName.ScimToken) + .leftJoin(TableName.Organization, `${TableName.Organization}.id`, `${TableName.ScimToken}.orgId`) + .leftJoin(TableName.Membership, `${TableName.Membership}.scopeOrgId`, `${TableName.ScimToken}.orgId`) + .leftJoin(TableName.MembershipRole, `${TableName.MembershipRole}.membershipId`, `${TableName.Membership}.id`) + .leftJoin(TableName.Users, `${TableName.Users}.id`, `${TableName.Membership}.actorUserId`) .whereRaw( ` (${TableName.ScimToken}."ttlDays" > 0 AND - (${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") < NOW() + INTERVAL '1 day' AND - (${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") > NOW()) + (${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") < NOW() + INTERVAL '7 days' AND + (${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") > NOW()) ` ) .where(`${TableName.ScimToken}.expiryNotificationSent`, false) - .select( - conn.ref("id").withSchema(TableName.ScimToken), - conn.ref("ttlDays").withSchema(TableName.ScimToken), - conn.ref("description").withSchema(TableName.ScimToken), - conn.ref("orgId").withSchema(TableName.ScimToken), - conn.ref("createdAt").withSchema(TableName.ScimToken), - conn.ref("name").withSchema(TableName.Organization).as("orgName"), - conn.raw(` - COALESCE( - ( - SELECT array_agg(${TableName.Users}.email) - FROM ${TableName.Membership} - JOIN ${TableName.MembershipRole} ON ${TableName.Membership}.id = ${TableName.MembershipRole}."membershipId" - JOIN ${TableName.Users} ON ${TableName.Membership}."actorUserId" = ${TableName.Users}.id - WHERE ${TableName.Membership}."scopeOrgId" = ${TableName.ScimToken}."orgId" - AND ${TableName.Membership}.scope = '${AccessScope.Organization}' - AND ${TableName.MembershipRole}.role = '${OrgMembershipRole.Admin}' - AND ${TableName.Membership}.status != '${OrgMembershipStatus.Invited}' - AND ${TableName.Membership}."actorUserId" IS NOT NULL - AND ${TableName.Users}."isGhost" = false - AND ${TableName.Users}.email IS NOT NULL - ), - ARRAY[]::text[] - ) as "adminEmails" - `) - ) + .where(`${TableName.Membership}.scope`, AccessScope.Organization) + .where(`${TableName.MembershipRole}.role`, OrgMembershipRole.Admin) + .whereNot(`${TableName.Membership}.status`, OrgMembershipStatus.Invited) + .whereNotNull(`${TableName.Membership}.actorUserId`) + .where(`${TableName.Users}.isGhost`, false) + .whereNotNull(`${TableName.Users}.email`) + .groupBy([`${TableName.ScimToken}.id`, `${TableName.Organization}.name`]) + .select([ + db.ref("id").withSchema(TableName.ScimToken), + db.ref("ttlDays").withSchema(TableName.ScimToken), + db.ref("description").withSchema(TableName.ScimToken), + db.ref("orgId").withSchema(TableName.ScimToken), + db.ref("createdAt").withSchema(TableName.ScimToken), + db.ref("name").withSchema(TableName.Organization).as("orgName"), + db.raw(`array_agg(${TableName.Users}."email") as "adminEmails"`) + ]) .limit(batchSize) .offset(offset); diff --git a/backend/src/ee/services/scim/scim-service.ts b/backend/src/ee/services/scim/scim-service.ts index 0f71dd185..0542bc911 100644 --- a/backend/src/ee/services/scim/scim-service.ts +++ b/backend/src/ee/services/scim/scim-service.ts @@ -1266,6 +1266,9 @@ export const scimServiceFactory = ({ return; } + const createdOn = new Date(token.createdAt); + const expiringOn = new Date(createdOn.getTime() + Number(token.ttlDays) * 86400 * 1000); + await smtpService.sendMail({ recipients: token.adminEmails, subjectLine: "SCIM Token Expiry Notice", @@ -1273,7 +1276,9 @@ export const scimServiceFactory = ({ substitutions: { tokenDescription: token.description, orgName: token.orgName, - url: `${appCfg.SITE_URL}/organizations/${token.orgId}/settings?selectedTab=provisioning-settings` + url: `${appCfg.SITE_URL}/organizations/${token.orgId}/settings?selectedTab=provisioning-settings`, + createdOn, + expiringOn } }); diff --git a/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx b/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx index afc4bc90c..84b9395b2 100644 --- a/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx +++ b/backend/src/services/smtp/emails/ScimTokenExpiryNoticeTemplate.tsx @@ -7,6 +7,8 @@ import { BaseEmailWrapper, BaseEmailWrapperProps } from "./BaseEmailWrapper"; interface ScimTokenExpiryNoticeTemplateProps extends Omit { tokenDescription?: string; orgName: string; + createdOn: Date; + expiringOn: Date; url: string; } @@ -14,8 +16,20 @@ export const ScimTokenExpiryNoticeTemplate = ({ tokenDescription, siteUrl, orgName, - url + url, + createdOn, + expiringOn }: ScimTokenExpiryNoticeTemplateProps) => { + const formatDate = (date: Date) => + date.toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric" + }); + + const createdOnDisplay = formatDate(createdOn); + const expiringOnDisplay = formatDate(expiringOn); + return ( @@ -30,7 +44,8 @@ export const ScimTokenExpiryNoticeTemplate = ({ ) : ( "One of your SCIM tokens" )}{" "} - for the organization {orgName} will expire within 24 hours. + for {orgName}, created on {createdOnDisplay}, is scheduled to expire on{" "} + {expiringOnDisplay}. If this token is still needed for your external platform sync, please create a new one before it expires to @@ -50,5 +65,7 @@ ScimTokenExpiryNoticeTemplate.PreviewProps = { orgName: "Example Organization", siteUrl: "https://infisical.com", url: "https://infisical.com", - tokenDescription: "Example SCIM Token" + tokenDescription: "Example SCIM Token", + createdOn: new Date("2025-11-27T00:00:00Z"), + expiringOn: new Date("2025-12-27T00:00:00Z") } as ScimTokenExpiryNoticeTemplateProps; From a292a3e56cb079c58648c120872e147e35273974 Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Thu, 27 Nov 2025 16:02:22 -0300 Subject: [PATCH 25/26] docs: enhance Ansible and Python SDK authentication sections to include Token Auth details --- docs/integrations/platforms/ansible.mdx | 22 +++++++++++++++++++++- docs/sdks/languages/python.mdx | 9 +++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/integrations/platforms/ansible.mdx b/docs/integrations/platforms/ansible.mdx index 85f63079f..7db74f20d 100644 --- a/docs/integrations/platforms/ansible.mdx +++ b/docs/integrations/platforms/ansible.mdx @@ -36,7 +36,7 @@ You can either call modules by their Fully Qualified Collection Name (FQCN), suc ### Authentication -The Infisical Ansible Collection supports [Universal Auth](/documentation/platform/identities/universal-auth) and [OIDC](/documentation/platform/identities/oidc-auth/general) for authenticating against Infisical. +The Infisical Ansible Collection supports [Universal Auth](/documentation/platform/identities/universal-auth), [OIDC Auth](/documentation/platform/identities/oidc-auth/general), and [Token Auth](/documentation/platform/identities/token-auth) for authenticating against Infisical. @@ -77,6 +77,26 @@ The Infisical Ansible Collection supports [Universal Auth](/documentation/platfo | jwt | `INFISICAL_JWT` | + + + Token Auth is the simplest authentication method that allows you to authenticate directly with an access token. This can be either a [Machine Identity Token Auth](/documentation/platform/identities/token-auth) token or a User JWT token. + + + Please note that in order to use Token Auth, you must have `1.1.4` or newer of the `infisicalsdk` package installed. + + + ```yaml + lookup('infisical.vault.read_secrets', auth_method="token_auth", token='' ...rest) + ``` + + You can also provide the `auth_method` and `token` parameters through environment variables: + + | Parameter Name | Environment Variable Name | + | -------------- | ------------------------- | + | auth_method | `INFISICAL_AUTH_METHOD` | + | token | `INFISICAL_TOKEN` | + + ### Examples diff --git a/docs/sdks/languages/python.mdx b/docs/sdks/languages/python.mdx index 670e0975a..d69f19173 100644 --- a/docs/sdks/languages/python.mdx +++ b/docs/sdks/languages/python.mdx @@ -108,6 +108,15 @@ response = client.auth.oidc_auth.login( This authentication method is useful when integrating with OIDC-compliant identity providers like Okta, Auth0, or any service that issues OIDC tokens. +#### Token Auth + +```python +response = client.auth.token_auth.login(token="") +``` + +**Parameters:** +- `token` (str): The access token to authenticate with. This can be a [machine identity token](/documentation/platform/identities/token-auth) or a user access token. + ### `secrets` This sub-class handles operations related to secrets: From a7b733ca917a9c95ca57ea2b4692d61286ead80c Mon Sep 17 00:00:00 2001 From: Victor Santos Date: Thu, 27 Nov 2025 16:29:02 -0300 Subject: [PATCH 26/26] docs: update minimum required version for infisicalsdk in Token Auth section of Ansible documentation --- docs/integrations/platforms/ansible.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/platforms/ansible.mdx b/docs/integrations/platforms/ansible.mdx index 7db74f20d..3eed68f05 100644 --- a/docs/integrations/platforms/ansible.mdx +++ b/docs/integrations/platforms/ansible.mdx @@ -82,7 +82,7 @@ The Infisical Ansible Collection supports [Universal Auth](/documentation/platfo Token Auth is the simplest authentication method that allows you to authenticate directly with an access token. This can be either a [Machine Identity Token Auth](/documentation/platform/identities/token-auth) token or a User JWT token. - Please note that in order to use Token Auth, you must have `1.1.4` or newer of the `infisicalsdk` package installed. + Please note that in order to use Token Auth, you must have `1.0.13` or newer of the `infisicalsdk` package installed. ```yaml