diff --git a/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts b/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts index 6840548c5..74418d02f 100644 --- a/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts +++ b/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts @@ -17,7 +17,8 @@ import { TSecretScanningFactoryGetFullScanPath, TSecretScanningFactoryInitialize, TSecretScanningFactoryListRawResources, - TSecretScanningFactoryPostInitialization + TSecretScanningFactoryPostInitialization, + TSecretScanningFactoryTeardown } from "@app/ee/services/secret-scanning-v2/secret-scanning-v2-types"; import { getConfig } from "@app/lib/config/env"; import { request } from "@app/lib/config/request"; @@ -30,13 +31,19 @@ import { } from "@app/services/app-connection/bitbucket"; import { IntegrationUrls } from "@app/services/integration-auth/integration-list"; -import { TBitbucketDataSourceWithConnection, TQueueBitbucketResourceDiffScan } from "./bitbucket-secret-scanning-types"; +import { + TBitbucketDataSourceCredentials, + TBitbucketDataSourceInput, + TBitbucketDataSourceWithConnection, + TQueueBitbucketResourceDiffScan +} from "./bitbucket-secret-scanning-types"; export const BitbucketSecretScanningFactory = () => { - const initialize: TSecretScanningFactoryInitialize = async ( - { connection, payload }, - callback - ) => { + const initialize: TSecretScanningFactoryInitialize< + TBitbucketDataSourceInput, + TBitbucketConnection, + TBitbucketDataSourceCredentials + > = async ({ connection, payload }, callback) => { const { email, apiToken } = connection.credentials; const authHeader = `Basic ${Buffer.from(`${email}:${apiToken}`).toString("base64")}`; @@ -61,12 +68,11 @@ export const BitbucketSecretScanningFactory = () => { }); }; - const postInitialization: TSecretScanningFactoryPostInitialization = async ({ - dataSourceId, - credentials, - connection, - payload - }) => { + const postInitialization: TSecretScanningFactoryPostInitialization< + TBitbucketDataSourceInput, + TBitbucketConnection, + TBitbucketDataSourceCredentials + > = async ({ dataSourceId, credentials, connection, payload }) => { const { email, apiToken } = connection.credentials; const { webhookId } = credentials; @@ -92,15 +98,22 @@ export const BitbucketSecretScanningFactory = () => { ); }; - // TODO(andrey): Hook this up - const postDeletion: any = async ({ credentials, connection, payload }) => { - const { email, apiToken } = connection.credentials; + const teardown: TSecretScanningFactoryTeardown< + TBitbucketDataSourceWithConnection, + TBitbucketDataSourceCredentials + > = async ({ credentials, dataSource }) => { + const { + connection: { + credentials: { email, apiToken } + }, + config + } = dataSource; const { webhookId } = credentials; const authHeader = `Basic ${Buffer.from(`${email}:${apiToken}`).toString("base64")}`; await request.delete( - `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${payload.config.workspaceSlug}/hooks/${webhookId}`, + `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${config.workspaceSlug}/hooks/${webhookId}`, { headers: { Authorization: authHeader, @@ -286,6 +299,7 @@ export const BitbucketSecretScanningFactory = () => { listRawResources, getFullScanPath, getDiffScanResourcePayload, - getDiffScanFindingsPayload + getDiffScanFindingsPayload, + teardown }; }; diff --git a/backend/src/ee/services/secret-scanning-v2/github/github-secret-scanning-factory.ts b/backend/src/ee/services/secret-scanning-v2/github/github-secret-scanning-factory.ts index 2dde97d7c..8d86c755a 100644 --- a/backend/src/ee/services/secret-scanning-v2/github/github-secret-scanning-factory.ts +++ b/backend/src/ee/services/secret-scanning-v2/github/github-secret-scanning-factory.ts @@ -19,7 +19,8 @@ import { TSecretScanningFactoryGetFullScanPath, TSecretScanningFactoryInitialize, TSecretScanningFactoryListRawResources, - TSecretScanningFactoryPostInitialization + TSecretScanningFactoryPostInitialization, + TSecretScanningFactoryTeardown } from "@app/ee/services/secret-scanning-v2/secret-scanning-v2-types"; import { getConfig } from "@app/lib/config/env"; import { BadRequestError } from "@app/lib/errors"; @@ -27,10 +28,14 @@ import { titleCaseToCamelCase } from "@app/lib/fn"; import { GitHubRepositoryRegex } from "@app/lib/regex"; import { listGitHubRadarRepositories, TGitHubRadarConnection } from "@app/services/app-connection/github-radar"; -import { TGitHubDataSourceWithConnection, TQueueGitHubResourceDiffScan } from "./github-secret-scanning-types"; +import { + TGitHubDataSourceInput, + TGitHubDataSourceWithConnection, + TQueueGitHubResourceDiffScan +} from "./github-secret-scanning-types"; export const GitHubSecretScanningFactory = () => { - const initialize: TSecretScanningFactoryInitialize = async ( + const initialize: TSecretScanningFactoryInitialize = async ( { connection, secretScanningV2DAL }, callback ) => { @@ -51,10 +56,17 @@ export const GitHubSecretScanningFactory = () => { }); }; - const postInitialization: TSecretScanningFactoryPostInitialization = async () => { + const postInitialization: TSecretScanningFactoryPostInitialization< + TGitHubDataSourceInput, + TGitHubRadarConnection + > = async () => { // no post-initialization required }; + const teardown: TSecretScanningFactoryTeardown = async () => { + // no termination required + }; + const listRawResources: TSecretScanningFactoryListRawResources = async ( dataSource ) => { @@ -225,6 +237,7 @@ export const GitHubSecretScanningFactory = () => { listRawResources, getFullScanPath, getDiffScanResourcePayload, - getDiffScanFindingsPayload + getDiffScanFindingsPayload, + teardown }; }; diff --git a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-factory.ts b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-factory.ts index 76e72ab77..2ca1f4882 100644 --- a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-factory.ts +++ b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-factory.ts @@ -5,14 +5,16 @@ import { SecretScanningDataSource } from "./secret-scanning-v2-enums"; import { TQueueSecretScanningResourceDiffScan, TSecretScanningDataSourceCredentials, + TSecretScanningDataSourceInput, TSecretScanningDataSourceWithConnection, TSecretScanningFactory } from "./secret-scanning-v2-types"; type TSecretScanningFactoryImplementation = TSecretScanningFactory< TSecretScanningDataSourceWithConnection, - TSecretScanningDataSourceCredentials, - TQueueSecretScanningResourceDiffScan["payload"] + TQueueSecretScanningResourceDiffScan["payload"], + TSecretScanningDataSourceInput, + TSecretScanningDataSourceCredentials >; export const SECRET_SCANNING_FACTORY_MAP: Record = { diff --git a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts index f84254a50..fbba667b7 100644 --- a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts +++ b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts @@ -30,6 +30,8 @@ import { TFindSecretScanningDataSourceByNameDTO, TListSecretScanningDataSourcesByProjectId, TSecretScanningDataSource, + TSecretScanningDataSourceCredentials, + TSecretScanningDataSourceInput, TSecretScanningDataSourceWithConnection, TSecretScanningDataSourceWithDetails, TSecretScanningFinding, @@ -257,7 +259,7 @@ export const secretScanningV2ServiceFactory = ({ try { const createdDataSource = await factory.initialize( { - payload, + payload: payload as TSecretScanningDataSourceInput, connection: connection as TSecretScanningDataSourceWithConnection["connection"], secretScanningV2DAL }, @@ -288,7 +290,7 @@ export const secretScanningV2ServiceFactory = ({ ); await factory.postInitialization({ - payload, + payload: payload as TSecretScanningDataSourceInput, connection: connection as TSecretScanningDataSourceWithConnection["connection"], dataSourceId: dataSource.id, credentials @@ -399,7 +401,6 @@ export const secretScanningV2ServiceFactory = ({ actorId: actor.id, actorAuthMethod: actor.authMethod, actorOrgId: actor.orgId, - projectId: dataSource.projectId }); @@ -413,7 +414,36 @@ export const secretScanningV2ServiceFactory = ({ message: `Secret Scanning Data Source with ID "${dataSourceId}" is not configured for ${SECRET_SCANNING_DATA_SOURCE_NAME_MAP[type]}` }); - // TODO: clean up webhooks + const factory = SECRET_SCANNING_FACTORY_MAP[type](); + + let connection: TAppConnection | null = null; + if (dataSource.connection) { + connection = await decryptAppConnection(dataSource.connection, kmsService); + } + + let credentials: TSecretScanningDataSourceCredentials | undefined; + + if (dataSource.encryptedCredentials) { + const { decryptor } = await kmsService.createCipherPairWithDataKey({ + type: KmsDataKey.SecretManager, + projectId: dataSource.projectId + }); + + credentials = JSON.parse( + decryptor({ + cipherTextBlob: dataSource.encryptedCredentials + }).toString() + ) as TSecretScanningDataSourceCredentials; + } + + await factory.teardown({ + dataSource: { + ...dataSource, + // @ts-expect-error currently we don't have a null connection data source + connection + }, + credentials + }); await secretScanningV2DAL.dataSources.deleteById(dataSourceId); diff --git a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-types.ts b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-types.ts index 5c11a8ffb..35486bd59 100644 --- a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-types.ts +++ b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-types.ts @@ -58,7 +58,7 @@ export type TSecretScanningDataSourceInput = TGitHubDataSourceInput | TBitbucket export type TSecretScanningDataSourceListItem = TGitHubDataSourceListItem | TBitbucketDataSourceListItem; -export type TDataSourceCredentialsSchema = TBitbucketDataSourceCredentials | undefined; +export type TSecretScanningDataSourceCredentials = TBitbucketDataSourceCredentials | undefined; export type TSecretScanningFinding = TGitHubFinding | TBitbucketFinding; @@ -151,11 +151,12 @@ export type TSecretScanningDataSourceRaw = NonNullable< >; export type TSecretScanningFactoryInitialize< + P extends TSecretScanningDataSourceInput, T extends TSecretScanningDataSourceWithConnection["connection"] | undefined = undefined, - C extends TSecretScanningDataSourceCredentials = TDataSourceCredentialsSchema + C extends TSecretScanningDataSourceCredentials = undefined > = ( params: { - payload: TCreateSecretScanningDataSourceDTO; + payload: P; connection: T; secretScanningV2DAL: TSecretScanningV2DALFactory; }, @@ -163,24 +164,27 @@ export type TSecretScanningFactoryInitialize< ) => Promise; export type TSecretScanningFactoryPostInitialization< + P extends TSecretScanningDataSourceInput, T extends TSecretScanningDataSourceWithConnection["connection"] | undefined = undefined, - C extends TSecretScanningDataSourceCredentials = TDataSourceCredentialsSchema -> = (params: { - payload: TCreateSecretScanningDataSourceDTO; - connection: T; - credentials: C; - dataSourceId: string; -}) => Promise; + C extends TSecretScanningDataSourceCredentials = undefined +> = (params: { payload: P; connection: T; credentials: C; dataSourceId: string }) => Promise; + +export type TSecretScanningFactoryTeardown< + T extends TSecretScanningDataSourceWithConnection, + C extends TSecretScanningDataSourceCredentials = undefined +> = (params: { dataSource: T; credentials: C }) => Promise; export type TSecretScanningFactory< T extends TSecretScanningDataSourceWithConnection, - C extends TSecretScanningDataSourceCredentials, - P extends TQueueSecretScanningResourceDiffScan["payload"] + P extends TQueueSecretScanningResourceDiffScan["payload"], + I extends TSecretScanningDataSourceInput, + C extends TSecretScanningDataSourceCredentials | undefined = undefined > = () => { listRawResources: TSecretScanningFactoryListRawResources; getFullScanPath: TSecretScanningFactoryGetFullScanPath; - initialize: TSecretScanningFactoryInitialize; - postInitialization: TSecretScanningFactoryPostInitialization; + initialize: TSecretScanningFactoryInitialize; + postInitialization: TSecretScanningFactoryPostInitialization; + teardown: TSecretScanningFactoryTeardown; getDiffScanResourcePayload: TSecretScanningFactoryGetDiffScanResourcePayload

; getDiffScanFindingsPayload: TSecretScanningFactoryGetDiffScanFindingsPayload; }; @@ -198,5 +202,3 @@ export type TUpsertSecretScanningConfigDTO = { projectId: string; content: string | null; }; - -export type TSecretScanningDataSourceCredentials = TDataSourceCredentialsSchema;