Review fixes

This commit is contained in:
x032205
2025-07-04 01:50:41 -04:00
parent 456107fbf3
commit 218338e5d2
15 changed files with 46 additions and 35 deletions
@@ -58,7 +58,7 @@ export const BitbucketSecretScanningFactory = () => {
const authHeader = `Basic ${Buffer.from(`${email}:${apiToken}`).toString("base64")}`; const authHeader = `Basic ${Buffer.from(`${email}:${apiToken}`).toString("base64")}`;
const { data } = await request.post<{ uuid: string }>( const { data } = await request.post<{ uuid: string }>(
`${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${payload.config.workspaceSlug}/hooks`, `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${encodeURIComponent(payload.config.workspaceSlug)}/hooks`,
{ {
description: "Infisical webhook for push events", description: "Infisical webhook for push events",
url: `${cfg.SITE_URL}/secret-scanning/webhooks/bitbucket`, url: `${cfg.SITE_URL}/secret-scanning/webhooks/bitbucket`,
@@ -92,7 +92,7 @@ export const BitbucketSecretScanningFactory = () => {
const newWebhookUrl = `${cfg.SITE_URL}/secret-scanning/webhooks/bitbucket?dataSourceId=${dataSourceId}`; const newWebhookUrl = `${cfg.SITE_URL}/secret-scanning/webhooks/bitbucket?dataSourceId=${dataSourceId}`;
await request.put( await request.put(
`${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${payload.config.workspaceSlug}/hooks/${webhookId}`, `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${encodeURIComponent(payload.config.workspaceSlug)}/hooks/${webhookId}`,
{ {
description: "Infisical webhook for push events", description: "Infisical webhook for push events",
url: newWebhookUrl, url: newWebhookUrl,
@@ -5,7 +5,7 @@ import { logger } from "@app/lib/logger";
import { TBitbucketDataSource, TBitbucketPushEvent } from "./bitbucket-secret-scanning-types"; import { TBitbucketDataSource, TBitbucketPushEvent } from "./bitbucket-secret-scanning-types";
export const bitBucketSecretScanningService = ( export const bitbucketSecretScanningService = (
secretScanningV2DAL: TSecretScanningV2DALFactory, secretScanningV2DAL: TSecretScanningV2DALFactory,
secretScanningV2Queue: Pick<TSecretScanningV2QueueServiceFactory, "queueResourceDiffScan"> secretScanningV2Queue: Pick<TSecretScanningV2QueueServiceFactory, "queueResourceDiffScan">
) => { ) => {
@@ -51,7 +51,7 @@ import { TAppConnection } from "@app/services/app-connection/app-connection-type
import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { KmsDataKey } from "@app/services/kms/kms-types"; import { KmsDataKey } from "@app/services/kms/kms-types";
import { bitBucketSecretScanningService } from "./bitbucket/bitbucket-secret-scanning-service"; import { bitbucketSecretScanningService } from "./bitbucket/bitbucket-secret-scanning-service";
import { TSecretScanningV2DALFactory } from "./secret-scanning-v2-dal"; import { TSecretScanningV2DALFactory } from "./secret-scanning-v2-dal";
import { TSecretScanningV2QueueServiceFactory } from "./secret-scanning-v2-queue"; import { TSecretScanningV2QueueServiceFactory } from "./secret-scanning-v2-queue";
@@ -901,6 +901,6 @@ export const secretScanningV2ServiceFactory = ({
findSecretScanningConfigByProjectId, findSecretScanningConfigByProjectId,
upsertSecretScanningConfig, upsertSecretScanningConfig,
github: githubSecretScanningService(secretScanningV2DAL, secretScanningV2Queue), github: githubSecretScanningService(secretScanningV2DAL, secretScanningV2Queue),
bitbucket: bitBucketSecretScanningService(secretScanningV2DAL, secretScanningV2Queue) bitbucket: bitbucketSecretScanningService(secretScanningV2DAL, secretScanningV2Queue)
}; };
}; };
@@ -1,14 +1,14 @@
import type { EmitterWebhookEventName } from "@octokit/webhooks/dist-types/types"; import type { EmitterWebhookEventName } from "@octokit/webhooks/dist-types/types";
import { PushEvent } from "@octokit/webhooks-types"; import { PushEvent } from "@octokit/webhooks-types";
import crypto from "crypto";
import { Probot } from "probot"; import { Probot } from "probot";
import { z } from "zod"; import { z } from "zod";
import { generateBitbucketWebhookSecret } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory";
import { TBitbucketPushEvent } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-types"; import { TBitbucketPushEvent } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { writeLimit } from "@app/server/config/rateLimiter"; import { writeLimit } from "@app/server/config/rateLimiter";
import crypto from "crypto";
import { generateBitbucketWebhookSecret } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory";
export const registerSecretScanningV2Webhooks = async (server: FastifyZodProvider) => { export const registerSecretScanningV2Webhooks = async (server: FastifyZodProvider) => {
const probotApp = (app: Probot) => { const probotApp = (app: Probot) => {
@@ -62,7 +62,7 @@ export const registerBitbucketConnectionRouter = async (server: FastifyZodProvid
connectionId: z.string().uuid() connectionId: z.string().uuid()
}), }),
querystring: z.object({ querystring: z.object({
workspaceSlug: z.string() workspaceSlug: z.string().min(1).max(255)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -46,7 +46,7 @@ import { ValidateAzureDevOpsConnectionCredentialsSchema } from "./azure-devops/a
import { azureDevOpsConnectionService } from "./azure-devops/azure-devops-service"; import { azureDevOpsConnectionService } from "./azure-devops/azure-devops-service";
import { ValidateAzureKeyVaultConnectionCredentialsSchema } from "./azure-key-vault"; import { ValidateAzureKeyVaultConnectionCredentialsSchema } from "./azure-key-vault";
import { ValidateBitbucketConnectionCredentialsSchema } from "./bitbucket"; import { ValidateBitbucketConnectionCredentialsSchema } from "./bitbucket";
import { bitBucketConnectionService } from "./bitbucket/bitbucket-connection-service"; import { bitbucketConnectionService } from "./bitbucket/bitbucket-connection-service";
import { ValidateCamundaConnectionCredentialsSchema } from "./camunda"; import { ValidateCamundaConnectionCredentialsSchema } from "./camunda";
import { camundaConnectionService } from "./camunda/camunda-connection-service"; import { camundaConnectionService } from "./camunda/camunda-connection-service";
import { ValidateCloudflareConnectionCredentialsSchema } from "./cloudflare/cloudflare-connection-schema"; import { ValidateCloudflareConnectionCredentialsSchema } from "./cloudflare/cloudflare-connection-schema";
@@ -536,7 +536,7 @@ export const appConnectionServiceFactory = ({
flyio: flyioConnectionService(connectAppConnectionById), flyio: flyioConnectionService(connectAppConnectionById),
gitlab: gitlabConnectionService(connectAppConnectionById, appConnectionDAL, kmsService), gitlab: gitlabConnectionService(connectAppConnectionById, appConnectionDAL, kmsService),
cloudflare: cloudflareConnectionService(connectAppConnectionById), cloudflare: cloudflareConnectionService(connectAppConnectionById),
bitbucket: bitBucketConnectionService(connectAppConnectionById), bitbucket: bitbucketConnectionService(connectAppConnectionById),
zabbix: zabbixConnectionService(connectAppConnectionById) zabbix: zabbixConnectionService(connectAppConnectionById)
}; };
}; };
@@ -95,7 +95,7 @@ export const listBitbucketRepositories = async (appConnection: TBitbucketConnect
let allRepos: TBitbucketRepo[] = []; let allRepos: TBitbucketRepo[] = [];
let nextUrl: string | undefined = let nextUrl: string | undefined =
`${IntegrationUrls.BITBUCKET_API_URL}/2.0/repositories/${workspaceSlug}?pagelen=100`; `${IntegrationUrls.BITBUCKET_API_URL}/2.0/repositories/${encodeURIComponent(workspaceSlug)}?pagelen=100`;
let iterationCount = 0; let iterationCount = 0;
// Limit to 10 iterations, fetching at most 10 * 100 = 1000 repositories // Limit to 10 iterations, fetching at most 10 * 100 = 1000 repositories
@@ -11,8 +11,19 @@ import {
import { BitbucketConnectionMethod } from "./bitbucket-connection-enums"; import { BitbucketConnectionMethod } from "./bitbucket-connection-enums";
export const BitbucketConnectionAccessTokenCredentialsSchema = z.object({ export const BitbucketConnectionAccessTokenCredentialsSchema = z.object({
apiToken: z.string().trim().min(1, "API Token required").describe(AppConnections.CREDENTIALS.BITBUCKET.apiToken), apiToken: z
email: z.string().email().trim().min(1, "Email required").describe(AppConnections.CREDENTIALS.BITBUCKET.email) .string()
.trim()
.min(1, "API Token required")
.max(255)
.describe(AppConnections.CREDENTIALS.BITBUCKET.apiToken),
email: z
.string()
.email()
.trim()
.min(1, "Email required")
.max(255)
.describe(AppConnections.CREDENTIALS.BITBUCKET.email)
}); });
const BaseBitbucketConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.Bitbucket) }); const BaseBitbucketConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.Bitbucket) });
@@ -10,7 +10,7 @@ type TGetAppConnectionFunc = (
actor: OrgServiceActor actor: OrgServiceActor
) => Promise<TBitbucketConnection>; ) => Promise<TBitbucketConnection>;
export const bitBucketConnectionService = (getAppConnection: TGetAppConnectionFunc) => { export const bitbucketConnectionService = (getAppConnection: TGetAppConnectionFunc) => {
const listWorkspaces = async (connectionId: string, actor: OrgServiceActor) => { const listWorkspaces = async (connectionId: string, actor: OrgServiceActor) => {
const appConnection = await getAppConnection(AppConnection.Bitbucket, connectionId, actor); const appConnection = await getAppConnection(AppConnection.Bitbucket, connectionId, actor);
const workspaces = await listBitbucketWorkspaces(appConnection); const workspaces = await listBitbucketWorkspaces(appConnection);
@@ -20,7 +20,7 @@ description: "Learn how to configure secret scanning for Bitbucket."
3. Configure which workspace and repositories you would like to scan. Then click **Next**. 3. Configure which workspace and repositories you would like to scan. Then click **Next**.
![Data Source Configuration](/images/platform/secret-scanning/bitbucket/step-3.png) ![Data Source Configuration](/images/platform/secret-scanning/bitbucket/step-3.png)
- **Bitbucket Radar Connection** - the connection that has access to the repositories you want to scan. - **Bitbucket Connection** - the connection that has access to the repositories you want to scan.
- **Workspace** - the Bitbucket workspace to scan secrets in. - **Workspace** - the Bitbucket workspace to scan secrets in.
- **Scan Repositories** - select which repositories you would like to scan. - **Scan Repositories** - select which repositories you would like to scan.
- **All Repositories** - Infisical will scan all repositories associated with your connection. - **All Repositories** - Infisical will scan all repositories associated with your connection.
@@ -92,7 +92,7 @@ Infisical supports the use of [Service Accounts](https://developer.1password.com
"method": "api-token", "method": "api-token",
"credentials": { "credentials": {
"instanceUrl": "https://1pass.example.com", "instanceUrl": "https://1pass.example.com",
"apiToken": "[PRIVATE TOKEN]" "apiToken": "<YOUR-API-TOKEN>"
} }
}' }'
``` ```
@@ -93,7 +93,7 @@ Infisical supports the use of [API Tokens](https://support.atlassian.com/bitbuck
"method": "api-token", "method": "api-token",
"credentials": { "credentials": {
"email": "[email protected]", "email": "[email protected]",
"apiToken": "[PRIVATE TOKEN]" "apiToken": "<YOUR-API-TOKEN>"
} }
}' }'
``` ```
@@ -120,7 +120,7 @@ export const OCIVaultSyncFields = () => {
menuPlacement="top" menuPlacement="top"
isLoading={isVaultsLoading && Boolean(connectionId)} isLoading={isVaultsLoading && Boolean(connectionId)}
isDisabled={!connectionId || !selectedCompartment} isDisabled={!connectionId || !selectedCompartment}
value={vaults?.find((v) => v.id === value) ?? null} value={vaults?.find((v) => v.id === value) || null}
onChange={(option) => { onChange={(option) => {
onChange((option as SingleValue<{ id: string }>)?.id ?? null); onChange((option as SingleValue<{ id: string }>)?.id ?? null);
setValue("destinationConfig.keyOcid", ""); setValue("destinationConfig.keyOcid", "");
@@ -10,12 +10,12 @@ import {
TBitbucketWorkspace TBitbucketWorkspace
} from "./types"; } from "./types";
const bitBucketConnectionKeys = { const bitbucketConnectionKeys = {
all: [...appConnectionKeys.all, "bitbucket"] as const, all: [...appConnectionKeys.all, "bitbucket"] as const,
listRepos: (connectionId: string, workspaceSlug: string) => listRepos: (connectionId: string, workspaceSlug: string) =>
[...bitBucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const, [...bitbucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const,
listWorkspaces: (connectionId: string) => listWorkspaces: (connectionId: string) =>
[...bitBucketConnectionKeys.all, "workspaces", connectionId] as const [...bitbucketConnectionKeys.all, "workspaces", connectionId] as const
}; };
export const useBitbucketConnectionListWorkspaces = ( export const useBitbucketConnectionListWorkspaces = (
@@ -25,13 +25,13 @@ export const useBitbucketConnectionListWorkspaces = (
TBitbucketWorkspace[], TBitbucketWorkspace[],
unknown, unknown,
TBitbucketWorkspace[], TBitbucketWorkspace[],
ReturnType<typeof bitBucketConnectionKeys.listWorkspaces> ReturnType<typeof bitbucketConnectionKeys.listWorkspaces>
>, >,
"queryKey" | "queryFn" "queryKey" | "queryFn"
> >
) => { ) => {
return useQuery({ return useQuery({
queryKey: bitBucketConnectionKeys.listWorkspaces(connectionId), queryKey: bitbucketConnectionKeys.listWorkspaces(connectionId),
queryFn: async () => { queryFn: async () => {
const { data } = await apiRequest.get<TBitbucketConnectionListWorkspacesResponse>( const { data } = await apiRequest.get<TBitbucketConnectionListWorkspacesResponse>(
`/api/v1/app-connections/bitbucket/${connectionId}/workspaces` `/api/v1/app-connections/bitbucket/${connectionId}/workspaces`
@@ -52,18 +52,18 @@ export const useBitbucketConnectionListRepositories = (
unknown, unknown,
TBitbucketRepo[], TBitbucketRepo[],
// The ReturnType here will be a supertype of the actual queryKey, which is acceptable // The ReturnType here will be a supertype of the actual queryKey, which is acceptable
ReturnType<typeof bitBucketConnectionKeys.listRepos> ReturnType<typeof bitbucketConnectionKeys.listRepos>
>, >,
"queryKey" | "queryFn" "queryKey" | "queryFn"
> >
) => { ) => {
return useQuery({ return useQuery({
// Append workspaceSlug to the existing query key for unique caching // Append workspaceSlug to the existing query key for unique caching
queryKey: bitBucketConnectionKeys.listRepos(connectionId, workspaceSlug), queryKey: bitbucketConnectionKeys.listRepos(connectionId, workspaceSlug),
queryFn: async () => { queryFn: async () => {
const { data } = await apiRequest.get<TBitbucketConnectionListRepositoriesResponse>( const { data } = await apiRequest.get<TBitbucketConnectionListRepositoriesResponse>(
// Include workspaceSlug in the API endpoint path // Include workspaceSlug in the API endpoint path
`/api/v1/app-connections/bitbucket/${connectionId}/repositories?workspaceSlug=${workspaceSlug}` `/api/v1/app-connections/bitbucket/${connectionId}/repositories?workspaceSlug=${encodeURIComponent(workspaceSlug)}`
); );
return data.repositories; return data.repositories;
@@ -89,8 +89,8 @@ export const BitbucketConfigurePage = () => {
} }
}); });
const bitBucketWorkspace = watch("targetWorkspace"); const bitbucketWorkspace = watch("targetWorkspace");
const bitBucketRepo = watch("targetRepo"); const bitbucketRepo = watch("targetRepo");
const integrationAuthId = useSearch({ const integrationAuthId = useSearch({
from: ROUTE_PATHS.SecretManager.Integratons.BitbucketConfigurePage.id, from: ROUTE_PATHS.SecretManager.Integratons.BitbucketConfigurePage.id,
@@ -103,17 +103,17 @@ export const BitbucketConfigurePage = () => {
const { data: bitbucketRepos, isPending: isBitbucketReposLoading } = useGetIntegrationAuthApps({ const { data: bitbucketRepos, isPending: isBitbucketReposLoading } = useGetIntegrationAuthApps({
integrationAuthId: (integrationAuthId as string) ?? "", integrationAuthId: (integrationAuthId as string) ?? "",
workspaceSlug: bitBucketWorkspace?.slug workspaceSlug: bitbucketWorkspace?.slug
}); });
const { data: bitbucketEnvironments, isPending: isBitbucketEnvironmentsLoading } = const { data: bitbucketEnvironments, isPending: isBitbucketEnvironmentsLoading } =
useGetIntegrationAuthBitbucketEnvironments( useGetIntegrationAuthBitbucketEnvironments(
{ {
integrationAuthId: (integrationAuthId as string) ?? "", integrationAuthId: (integrationAuthId as string) ?? "",
workspaceSlug: bitBucketWorkspace?.slug ?? "", workspaceSlug: bitbucketWorkspace?.slug ?? "",
repoSlug: bitBucketRepo?.appId ?? "" repoSlug: bitbucketRepo?.appId ?? ""
}, },
{ enabled: Boolean(bitBucketWorkspace?.slug && bitBucketRepo?.appId) } { enabled: Boolean(bitbucketWorkspace?.slug && bitbucketRepo?.appId) }
); );
const onSubmit = async ({ const onSubmit = async ({
@@ -167,8 +167,8 @@ export const BitbucketConfigurePage = () => {
useEffect(() => { useEffect(() => {
if ( if (
bitBucketWorkspace || bitbucketWorkspace ||
bitBucketRepo || bitbucketRepo ||
!bitbucketRepos || !bitbucketRepos ||
!bitbucketWorkspaces || !bitbucketWorkspaces ||
!currentWorkspace !currentWorkspace
@@ -325,7 +325,7 @@ export const BitbucketConfigurePage = () => {
? "Select an environment..." ? "Select an environment..."
: "No environments found..." : "No environments found..."
} }
isLoading={isBitbucketEnvironmentsLoading && Boolean(bitBucketRepo)} isLoading={isBitbucketEnvironmentsLoading && Boolean(bitbucketRepo)}
isDisabled={!bitbucketEnvironments?.length || isBitbucketEnvironmentsLoading} isDisabled={!bitbucketEnvironments?.length || isBitbucketEnvironmentsLoading}
/> />
</FormControl> </FormControl>