Com 20 gcp - #215
Com 20 gcp#215
Conversation
# Conflicts: # apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
|
WalkthroughThis pull request makes systematic changes to update the handling of severity across the codebase. The modifications replace the use of the Changes
Sequence Diagram(s)sequenceDiagram
participant GCP_Client as GCP Integration Client
participant Auth as Google OAuth2 Endpoint
participant SCC as GCP Security Command Center API
GCP_Client->>GCP_Client: Generate JWT using service account key
GCP_Client->>Auth: POST JWT to obtain an access token
Auth-->>GCP_Client: Return access token
GCP_Client->>SCC: Request findings with access token (handle pagination)
SCC-->>GCP_Client: Return a page of findings
GCP_Client->>GCP_Client: Process findings and iterate if nextPageToken exists
sequenceDiagram
participant User as End User
participant NoTests as NoTests Component
participant Action as refreshTestsAction
participant DB as Database
User->>NoTests: Click "Refresh Tests" button
NoTests->>Action: Execute refreshTestsClick function
Action->>DB: Update or insert test records with new severity and remediation
DB-->>Action: Return update status
Action->>NoTests: Show toast notification and trigger page reload
Possibly related PRs
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (14)
packages/integrations/src/index.ts (1)
4-4: Export GCPCredentials type for consistencyGood addition of the GCP integration. However, for consistency with other integrations, consider exporting the GCPCredentials type alongside AWSCredentials and AzureCredentials.
export type { AWSCredentials, AzureCredentials, + GCPCredentials, DecryptFunction, EncryptedData, } from "./factory";Also applies to: 6-6
packages/docs/integrations/gcp.mdx (1)
93-93: Added organization ID verification to troubleshooting.Good addition of organization ID verification to the troubleshooting section.
Consider expanding the troubleshooting section with more details about the new fields (
severity,description,remediation) and how they might impact results:**Issue**: Failed to connect GCP project -**Solution**: Verify organization id and service account key and IAM permissions +**Solution**: Verify organization id and service account key and IAM permissions. Ensure that your service account has sufficient permissions to retrieve finding details including severity, descriptions, and remediation steps.packages/integrations/src/aws/src/index.ts (2)
54-68: Consider extracting the transformation logic to avoid duplicationThe transformation logic for findings is duplicated in two places (here and again at lines 83-91). This violates the DRY principle and could lead to maintenance issues.
+function transformFinding(finding: any): AWSFinding { + return { + title: finding.Title || "Untitled Finding", + description: finding.Description || "No description available", + remediation: finding.Remediation?.Recommendation?.Text || "No remediation available", + status: finding.Compliance?.Status || "unknown", + severity: finding.Severity?.Label || "INFO", + resultDetails: finding + }; +} async function fetch(credentials: AWSCredentials): Promise<AWSFinding[]> { console.log("Fetching AWS Security Hub findings"); try { // ... let response: GetFindingsCommandOutput = await securityHubClient.send(command); const allFindings: AWSFinding[] = []; // Process initial response if (response.Findings) { - const transformedFindings = response.Findings.map(finding => ({ - title: finding.Title || "Untitled Finding", - description: finding.Description || "No description available", - remediation: finding.Remediation?.Recommendation?.Text || "No remediation available", - status: finding.Compliance?.Status || "unknown", - severity: finding.Severity?.Label || "INFO", - resultDetails: finding - })); + const transformedFindings = response.Findings.map(transformFinding); allFindings.push(...transformedFindings); }
83-91: Use the extracted transformation function hereThis is the second occurrence of the same transformation logic.
if (response.Findings) { - const transformedFindings = response.Findings.map(finding => ({ - title: finding.Title || "Untitled Finding", - description: finding.Description || "No description available", - remediation: finding.Remediation?.Recommendation?.Text || "No remediation available", - status: finding.Compliance?.Status || "unknown", - severity: finding.Severity?.Label || "INFO", - resultDetails: finding - })); + const transformedFindings = response.Findings.map(transformFinding); allFindings.push(...transformedFindings); }packages/integrations/src/gcp/src/test.ts (2)
69-96: Remove commented-out code before productionThere's a large block of commented code related to
controlDetails. If this is development code, it should be removed before production deployment, or if it's intended to be used later, it should be properly documented.if (findings.length > 0) { console.log(`\n📄 Page ${page} - ${findings.length} findings:\n`); for (const finding of findings) { console.log(finding); - /* let controlDetails: any[] = { - Id: finding.name, - name: finding.category, - standard: finding.sourceProperties?.Recommendation || finding.sourceProperties?.Explanation || '—', - Title: finding.sourceProperties?.Recommendation || finding.sourceProperties?.Explanation || '—', - description: finding.description || '', - state: finding.state, - Compliance: { - Status: finding.state === "ACTIVE" ? "FAILED" : "PASSED", - }, - Severity: { - Label: "INFO", - }, - Description: controlDetail.properties.description, - Remediation: { - Recommendation: { - Text: controlDetail.properties.description, - Url: "", - }, - }, - }; */ }
28-42: Add token caching to avoid unnecessary JWT generationThe current implementation generates a new JWT and exchanges it for an access token every time
getAccessToken()is called. Consider implementing token caching with expiration checking to avoid unnecessary token generation, especially since tokens are valid for 1 hour (as set in line 22).+let cachedToken: { token: string; expiresAt: number } | null = null; async function getAccessToken(): Promise<string> { + // Check if we have a valid cached token + if (cachedToken && Date.now() < cachedToken.expiresAt) { + console.log('Using cached token'); + return cachedToken.token; + } const jwtToken = generateJWT(); const res = await fetch(TOKEN_URI, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: jwtToken, }), }); if (!res.ok) throw new Error(`Token exchange failed: ${await res.text()}`); const data = await res.json(); + + // Cache the token with expiration time (slightly before the actual expiration) + cachedToken = { + token: data.access_token, + expiresAt: Date.now() + (data.expires_in || 3600) * 1000 - 300000 // 5 minutes buffer + }; + return data.access_token; }packages/integrations/src/factory.ts (1)
30-30: Consider using a more specific type for resultDetailsThe
resultDetailsproperty is typed asany, which loses type safety. Consider creating more specific types for each integration's result details.export interface IntegrationFinding { title: string; description: string; remediation: string; status: string; severity: string; - resultDetails: any; + resultDetails: Record<string, unknown>; }packages/db/prisma/migrations/20250327203613_rename_organization_integration_results/migration.sql (1)
49-58: Consider limiting cascade operations for better controlAll foreign key constraints are set with CASCADE for both DELETE and UPDATE operations. This might lead to unintended data loss in certain scenarios. Consider using more restrictive options where appropriate.
For example, you might want to restrict cascade operations for
assignedUserId:-ALTER TABLE "OrganizationIntegrationResults" ADD CONSTRAINT "OrganizationIntegrationResults_assignedUserId_fkey" FOREIGN KEY ("assignedUserId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE "OrganizationIntegrationResults" ADD CONSTRAINT "OrganizationIntegrationResults_assignedUserId_fkey" FOREIGN KEY ("assignedUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;This would set the
assignedUserIdto NULL when a user is deleted, rather than deleting all their assigned integration results.packages/integrations/src/gcp/src/index.ts (3)
1-2: Consider using Node.js's built-in fetch in newer Node versions
Since Node.js 18, a globalfetchimplementation is available. If your environment supports it, you can remove thenode-fetchdependency.
25-31: Consider using a stricter type forresultDetails
Relying onanycan reduce type safety and make debugging more difficult. If possible, define a more specific type or interface for this property.
76-76: Function name may cause confusion
Consider renamingfetchto avoid shadowing the common globalfetchmethod in newer Node.js environments and browsers.packages/integrations/src/azure/src/index.ts (2)
13-20: Consider using a more specific type for resultDetailsThe new
AzureFindinginterface provides a good standardized structure for Azure findings. However,resultDetails: anybypasses TypeScript's type checking. Consider using a more specific type or at leastunknownfor better type safety.interface AzureFinding { title: string; description: string; remediation: string; status: string; severity: string; - resultDetails: any; + resultDetails: unknown; }
73-73: Remove unused complianceData arrayThe function initializes a
complianceDataarray at line 108 that isn't used after changing the return type toPromise<AzureFinding[]>. This is likely a leftover from the previous implementation.async function fetchComplianceData( credentials: AzureCredentials, ): Promise<AzureFinding[]> { try { const BASE_URL = `https://management.azure.com/subscriptions/${credentials.AZURE_SUBSCRIPTION_ID}/providers/Microsoft.Security`; // Set environment variables for DefaultAzureCredential process.env.AZURE_CLIENT_ID = credentials.AZURE_CLIENT_ID; process.env.AZURE_TENANT_ID = credentials.AZURE_TENANT_ID; process.env.AZURE_CLIENT_SECRET = credentials.AZURE_CLIENT_SECRET; // Get access token const credential = new DefaultAzureCredential(); const tokenResponse = await credential.getToken( "https://management.azure.com/.default", ); const token = tokenResponse.token; // Fetch all compliance standards const standardsUrl = `${BASE_URL}/regulatoryComplianceStandards?api-version=${API_VERSION}`; const standardsResponse = await nodeFetch(standardsUrl, { headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, }); if (!standardsResponse.ok) { throw new Error( `Failed to fetch standards: ${standardsResponse.statusText}`, ); } const standardsData = (await standardsResponse.json()) as AzureResponse; const standards = standardsData.value.map((standard) => standard.name); // Fetch controls for each standard - const complianceData: ComplianceStandard[] = []; // Fetch details for each control const findings: AzureFinding[] = [];Also applies to: 110-112, 163-163
packages/integrations/package.json (1)
21-21: Include @types/jsonwebtoken for better TypeScript supportAdding the
jsonwebtokenpackage for JWT-based authentication is appropriate. Consider also adding the corresponding TypeScript type definitions for better development experience."devDependencies": { "@types/node": "^22.13.2", "@types/node-fetch": "^2.6.2", + "@types/jsonwebtoken": "^9.0.5", "typescript": "^5.7.3" },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
bun.lockis excluded by!**/*.lockyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (22)
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/overview/data/getComplianceScores.ts(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/actions/getTest.ts(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/components/TestDetails.tsx(2 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/getTests.ts(3 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/refreshTests.ts(2 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/components/table/empty-states.tsx(2 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/types/index.ts(1 hunks)apps/app/src/jobs/tasks/integration/integration-results.ts(2 hunks)packages/db/package.json(1 hunks)packages/db/prisma/migrations/20250327203613_rename_organization_integration_results/migration.sql(1 hunks)packages/db/prisma/schema/cloud.prisma(1 hunks)packages/docs/integrations/azure.mdx(0 hunks)packages/docs/integrations/gcp.mdx(3 hunks)packages/integrations/package.json(1 hunks)packages/integrations/src/aws/src/index.ts(4 hunks)packages/integrations/src/azure/src/index.ts(4 hunks)packages/integrations/src/factory.ts(4 hunks)packages/integrations/src/gcp/config.ts(1 hunks)packages/integrations/src/gcp/src/index.ts(1 hunks)packages/integrations/src/gcp/src/test.ts(1 hunks)packages/integrations/src/index.ts(1 hunks)
💤 Files with no reviewable changes (1)
- packages/docs/integrations/azure.mdx
🧰 Additional context used
🧬 Code Definitions (1)
packages/integrations/src/factory.ts (2)
packages/integrations/src/index.ts (3)
DecryptFunction(13-13)EncryptedData(14-14)IntegrationHandler(9-9)packages/integrations/src/gcp/src/index.ts (1)
GCPCredentials(129-129)
🔇 Additional comments (48)
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/overview/data/getComplianceScores.ts (1)
117-117: Property changed fromlabeltoseverityThe change from
result.labeltoresult.severitymakes the property name more explicit and aligns with the broader updates across the codebase where the classification of test results is now uniformly referred to as "severity" rather than "label".apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx (1)
65-65: Property changed fromlabeltoseverityin database queriesThese changes consistently update all five severity level queries (
INFO,LOW,MEDIUM,HIGH,CRITICAL) to use the property nameseverityinstead oflabel. This aligns with the schema changes and maintains consistency across the codebase.Also applies to: 71-71, 77-77, 83-83, 89-89
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/components/TestDetails.tsx (2)
131-131: Simplified access to description propertyChanged from accessing the nested
cloudTest.resultDetails?.Descriptionto the directcloudTest.descriptionproperty, aligning with the data structure refactoring in thegetTestfunction.
152-152: Simplified access to remediation propertyChanged from a complex nested access pattern (likely
cloudTest.resultDetails?.Remediation?.Recommendation?.Textbased on the AI summary) to the directcloudTest.remediationproperty. This simplification makes the code more readable and maintainable.packages/integrations/src/gcp/config.ts (2)
36-42: Improved configuration parameter clarityUpdated parameter from "region" to "organization_id" which better reflects GCP's organization structure. This change aligns with the actual GCP terminology and requirements.
44-50:Details
✅ Verification successful
Enhanced authentication method for GCP
Good update from AWS-style credentials to GCP service account key authentication. This change is more appropriate for GCP Security Center access.
Verify that the service account key is properly handled as sensitive information in the application:
🏁 Script executed:
#!/bin/bash # Check for proper handling of service account key in code rg -i "service_account_key" --type ts -A 3 -B 3Length of output: 2712
GCP Authentication & Sensitive Data Handling Verified
The service account key is now consistently handled as sensitive data:
- In packages/integrations/src/factory.ts, the key is decrypted via
decryptSettingsand passed securely.- In packages/integrations/src/gcp/src/index.ts, the key is subsequently processed using
parseServiceAccountKey, with no evidence of logging or plain-text exposure.- The configuration (in packages/integrations/src/gcp/config.ts) appropriately sets an empty default value, reducing the risk of accidental exposure.
Overall, the updated handling meets the security criteria for sensitive information.
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/components/table/empty-states.tsx (4)
7-9: Added required imports for test refresh functionalityClean addition of the necessary imports for implementing the test refresh functionality.
14-22: Well-implemented refresh tests action with user feedbackThe implementation of the refresh tests action includes proper success and error handling with user feedback through toast notifications, and page reload on success to show updated data.
24-26: Clean handler function for refresh buttonGood separation of concerns with a dedicated click handler.
38-38:Details
❓ Verification inconclusive
Added UI element for refreshing tests
New button enables users to manually refresh tests, replacing the previous employee invite functionality.
Let's check if the translation key exists:
🏁 Script executed:
#!/bin/bash # Check if the translation key for refresh tests exists rg -i "tests\.actions\.refresh" --type jsonLength of output: 45
Refresh Tests Button – Verify Translation Key
The new UI element for refreshing tests is correctly added, replacing the previous employee invite functionality. However, the search for the translation key
"tests.actions.refresh"in JSON files returned no results. Please verify manually whether this key exists in the relevant translation files. If it’s missing, add the key to ensure proper localization.apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/types/index.ts (2)
9-9: Added new 'remediation' field to test schemaGood addition of a remediation field which will improve documentation of findings and allow providing actionable steps to users.
13-13:Details
❓ Verification inconclusive
Renamed 'label' to 'severity' in test schema
This change improves clarity by using more descriptive field names. The 'severity' field name better communicates the purpose of this value compared to the generic 'label'.
Let's verify that the database schema has been updated accordingly with a migration:
🏁 Script executed:
#!/bin/bash # Look for migration files that might have updated the schema fd -g "*.ts" -p "migration" --exec grep -l "severity\|remediation" {} \;Length of output: 172
Action: Please verify the migration for the schema update
The change from using the generic field name
"label"to the more descriptive"severity"in the test schema atapps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/types/index.tsappears correct. However, our initial attempt to automatically verify that a corresponding database migration exists failed due to an incorrect search path (the script error indicated that “migration” is not a directory).
- Next Steps:
- Manually review your migrations (typically stored in a
migrationsor similarly named directory) to confirm that a migration updating the database schema with the renamed field exists.- If no such migration is present, please add one to ensure that the production schema remains in sync with the test schema changes.
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/getTests.ts (3)
62-62: Updated property name in query filterChanged property name from 'label' to 'severity' in the filter condition, consistent with the schema changes.
107-107: Updated property name in count queryChanged property name from 'label' to 'severity' in the count query, ensuring consistency with the main query.
116-116:Details
✅ Verification successful
Updated property name in results transformation
Changed the property name from 'label' to 'severity' when transforming the results, maintaining consistency throughout the data flow.
Let's check if the property name has been consistently updated across the codebase:
🏁 Script executed:
#!/bin/bash # Check for any remaining instances of label that might need to be updated to severity rg -g "*.ts" -g "*.tsx" "\blabel\b" --type-add "tsx:*.tsx" -A 2 -B 2 | grep -v "label.*:" | grep -v "label=.*"Length of output: 77911
Confirmed: The results transformation update is consistent.
The change in the file
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/getTests.ts
(where the property was renamed fromlabeltoseverityat line 116) has been verified. In our targeted search, we found no instances of a lingeringresult.labelin this context. The many remaining occurrences oflabelin the codebase belong to UI components and other unrelated contexts, so they are unaffected by this change.apps/app/src/jobs/tasks/integration/integration-results.ts (4)
74-88: Update on existing result data structure.The code is now updating more fields in existing results, including the new
description,remediation, andseverityfields, which provides more comprehensive information.
90-101: Update on new result data structure.The code now creates new results with additional fields (
description,remediation,severity) that replace the previouslabelfield, making the results more informative.
115-119: Error handling now includes additional fields.Good addition of
descriptionandremediationfields to error records, withseverityreplacinglabel. This ensures consistent error information.
65-72:Details
❓ Verification inconclusive
Change from using a nested ID path to title as unique identifier.
This change uses
titleas a unique identifier instead of a nested ID. While this simplifies the query, it assumes titles are always unique within the scope of an integration.Verify the uniqueness of titles by running this script:
🏁 Script executed:
#!/bin/bash # Check if any duplicate titles exist within the same integration echo "Checking for duplicate titles within the same integration..." cat << 'EOF' > check_duplicate_titles.js const { db } = require("@bubba/db"); async function checkForDuplicateTitles() { // Get all integration results const allResults = await db.organizationIntegrationResults.findMany({ select: { title: true, organizationIntegrationId: true } }); // Group by integration and title const titleCounts = {}; allResults.forEach(result => { if (!result.title) return; // Skip null titles const key = `${result.organizationIntegrationId}:${result.title}`; titleCounts[key] = (titleCounts[key] || 0) + 1; }); // Find duplicates const duplicates = Object.entries(titleCounts) .filter(([_, count]) => count > 1) .map(([key, count]) => { const [integrationId, title] = key.split(':'); return { integrationId, title, count }; }); if (duplicates.length > 0) { console.log("WARNING: Found duplicate titles within the same integration!"); console.table(duplicates); return false; } else { console.log("No duplicate titles found within the same integration."); return true; } } checkForDuplicateTitles() .then(process.exit) .catch(err => { console.error("Error checking for duplicate titles:", err); process.exit(1); }); EOF npx tsx check_duplicate_titles.jsLength of output: 267
Action Required: Verify Title Uniqueness via Node
The change to use
titleas a unique identifier simplifies the query, but its correctness hinges on ensuring that titles remain unique within each integration. The initial verification attempt usingnpx tsxfailed due to an unavailablenpxcommand. Please re-run the duplicate check using Node directly (see below) to confirm that no duplicate titles exist within the same integration scope.
- File under review:
apps/app/src/jobs/tasks/integration/integration-results.ts(lines 65–72)- Concern: Verification that titles are unique in each integration.
To help with verification, try running the following script with Node:
#!/bin/bash # Re-run duplicate title check using node instead of npx echo "Running duplicate title check using node..." node check_duplicate_titles.jsOnce you confirm that the script reports no duplicates (or address any found issues), this change can be considered validated.
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/refreshTests.ts (3)
74-81: Switched from ID-based to title-based result matching.Similar to the changes in integration-results.ts, this function now uses
titleas the unique identifier for matching existing results.Consider adding a compound filter to further ensure uniqueness:
const existingResult = await db.organizationIntegrationResults.findFirst({ where: { title: result.title, organizationIntegrationId: existingIntegration.id, + // Consider adding a secondary condition if available + // For example: status: result.status, }, });
87-94: Enhanced data structure for result updates.The update operation now includes additional fields like
description,remediation, and usesseverityinstead oflabel, which aligns with the schema changes.
101-107: Enhanced data structure for new results.The create operation now includes the same additional fields as the update operation, maintaining consistency.
packages/db/prisma/schema/cloud.prisma (1)
4-7:Details
❓ Verification inconclusive
Schema updated with new fields and severity replacing label.
The schema now includes
description,remediation, andseverityfields, withstatusrepositioned. This aligns with the code changes in the other files.Make sure you've created and run the necessary database migrations for these schema changes:
Also, consider validating that the migration strategy handles existing data properly:
🏁 Script executed:
#!/bin/bash # Check if a migration exists for these schema changes echo "Checking for migration files related to the schema changes..." fd -t f -e sql --glob "*.sql" -x grep -l "OrganizationIntegrationResults" {} \;Length of output: 423
🏁 Script executed:
#!/bin/bash # Check if existing data is handled in migrations echo "Checking how existing data is migrated..." fd -t f -e sql --glob "*.sql" -x grep -l "label.*severity" {} \;Length of output: 162
Attention: Verify the new migration strategy for existing data changes
The schema update in
packages/db/prisma/schema/cloud.prisma(lines 4–7) now introduces the new fieldsdescription,remediation, andseverity(withseverityreplacinglabel), and repositionsstatus. Our initial check confirms that migration files exist—specifically, for example,./packages/db/prisma/migrations/20250327203613_rename_organization_integration_results/migration.sqland another adding comments.However, the automated search for explicit handling of existing data (converting or migrating data from
labeltoseverity) returned no findings. Please manually verify that your migration strategy or the relevant migration file explicitly handles existing data when renaming or converting the column (for instance, by reviewing the migration steps in the rename migration file).
- File to review:
packages/db/prisma/migrations/20250327203613_rename_organization_integration_results/migration.sql- Action required: Confirm that the transformation from
labeltoseverityis properly implemented for existing records.packages/docs/integrations/gcp.mdx (2)
8-8: Updated integration description.Focusing on "automated compliance monitoring and risk assessment" instead of "security testing" better aligns with the product's current capabilities.
22-40: Greatly improved GCP configuration steps.The configuration steps have been significantly enhanced with detailed instructions for:
- Creating a service account
- Assigning specific roles
- Enabling required APIs
- Managing and using the service account key
This will make it much easier for users to set up the integration correctly.
packages/integrations/src/aws/src/index.ts (3)
17-24: LGTM: Well-structured interface for AWS findingsThe
AWSFindinginterface defines a clear structure for AWS security findings, which will improve type safety throughout the codebase.
30-30: Good type safety improvementUpdating the return type from
Promise<any[]>toPromise<AWSFinding[]>provides better type safety and documentation for consumers of this API.
107-107: Good export of the new typeProperly exporting the
AWSFindingtype makes it available for consumers of this module.packages/integrations/src/factory.ts (4)
24-31: LGTM: Good standardization of findings interfaceCreating a common
IntegrationFindinginterface standardizes the structure across all integrations, which will make the codebase more maintainable and consistent.
39-39: Type enhancement improves API clarityUpdating the return type from
Promise<any[]>toPromise<IntegrationFinding[]>provides better type safety and documentation for the API consumers.
109-120: LGTM: Well-structured GCP integration handlerThe GCP handler follows the same pattern as the other integration handlers, correctly implementing the required interface methods.
126-126: Updated Deel integration to use new return typeThe Deel handler's fetch method has been properly updated to use the new
IntegrationFinding[]return type, maintaining consistency with other integrations.packages/db/prisma/migrations/20250327203613_rename_organization_integration_results/migration.sql (3)
23-37: LGTM: Well-structured table definitionThe new table includes all necessary fields including the new
remediationandseverityfields that align with theIntegrationFindinginterface. The primary key is properly defined.
39-46: LGTM: Proper indexes for performanceCreating indexes on foreign key columns (
assignedUserId,organizationIntegrationId, andorganizationId) will improve query performance.
4-6:Details
❓ Verification inconclusive
Warning: Data loss during migration
The migration drops the
Organization_integration_resultstable and creates a new one. This will result in data loss if the table contains data. Ensure you have a data migration strategy.
🏁 Script executed:
#!/bin/bash # Check if the table contains data before running the migration echo "Checking if Organization_integration_results table has data..." psql -c "SELECT COUNT(*) FROM \"Organization_integration_results\";" 2>/dev/null || echo "Table does not exist or cannot be accessed" # Suggest a data migration approach echo "If the table contains data, consider this migration approach:" echo "1. Create new table" echo "2. Copy data with transformed schema" echo "3. Rename tables" echo "4. Update foreign keys"Length of output: 661
Data Loss Warning: Confirm Production Environment State
The migration drops the
Organization_integration_resultstable and creates a new one. Our verification script indicates that the table is either non-existent or inaccessible in the current environment. However, please verify that this holds true in all target environments—especially production—to ensure there’s no unexpected data. If legacy data might exist, ensure a proper backup and migration strategy is in place (for example, by creating the new table, copying data with necessary schema transformations, renaming tables, and updating foreign keys).packages/integrations/src/gcp/src/index.ts (11)
4-5: Looks good
Encoding the filter for GCP Security Command Center is correct, and the string ensures both ACTIVE and INACTIVE findings are fetched.
7-10: No concerns
TheGCPCredentialsinterface is straightforward and accurately represents the organization ID and serialized key.
12-22: No issues
ThisServiceAccountKeyinterface closely matches standard GCP service account keys.
34-40: No concerns
TheparseServiceAccountKeyfunction cleanly handles potential JSON parsing errors with a helpful message.
42-54: JWT generation looks correct
The algorithm, scope, and expiration window of one hour meet common best practices when authenticating with GCP.
56-70: Implements GCP token exchange correctly
Fetching the OAuth token with a POST and throwing on error ensures robust error handling.
78-79: No further comments
This step of parsing the service account key and retrieving the access token is straightforward.
80-80: No further comments
The base URL construction with the organization ID and filter is straightforward.
121-122: No issues
The final array of findings is returned correctly.
129-129: No issues
Exporting both theGCPCredentialsandGCPFindingtypes clearly indicates their usage outside this module.
82-119:Details
❓ Verification inconclusive
Verify alignment of “description” and “title” fields
The code mapsfinding.descriptiontotitleand usesfinding.sourceProperties.Explanationas the main description. Confirm that this matches the desired structure and naming in GCP.
🏁 Script executed:
#!/bin/bash # Description: Search for references to 'finding.title' or 'finding.name' that might be relevant. # This helps verify if we should use them instead or in addition to 'finding.description'. rg -A 3 'finding(\.title|\.name)'Length of output: 482
Verify GCP finding field mappings for consistency
It appears that inpackages/integrations/src/gcp/src/index.tsthe finding’stitleis derived fromfinding.descriptionwhile the test file (packages/integrations/src/gcp/src/test.ts) referencesfinding.name(e.g., using it for theId) and builds itsTitlefromfinding.sourceProperties.Recommendationorfinding.sourceProperties.Explanation. Please confirm that the intended structure for a GCP finding is to usefinding.nameas the primary identifier for the title and whetherfinding.descriptionshould be used as a fallback. Adjust the mapping in production or update tests as needed to ensure consistency with GCP’s expected field naming.packages/integrations/src/azure/src/index.ts (1)
152-159:Details
❓ Verification inconclusive
Use available data for severity and remediation instead of hardcoded values
The code currently uses hardcoded values for
severityandremediation. Looking at theComplianceControlinterface, there are appropriate properties available in the source data that could be used instead.findings.push({ title: controlDetail.properties.description || "Untitled Control", description: controlDetail.properties.description || "No description available", - remediation: "No remediation available", // Azure API doesn't provide remediation in this endpoint + remediation: controlDetail.Remediation?.Recommendation?.Text || "No remediation available", status: controlDetail.properties.state.toUpperCase(), - severity: "INFO", + severity: controlDetail.Severity?.Label || "INFO", resultDetails: controlDetail });I'm assuming
controlDetailhas the same structure as theComplianceControlinterface, but this might need verification. If the structure is different, you'll need to adjust the property access accordingly.
🏁 Script executed:
#!/bin/bash # Check the actual structure of controlDetail rg -A 5 -B 5 "const controlDetail" "packages/integrations/src/azure/src/index.ts"Length of output: 550
Update remediation and severity fields to use dynamic values
The current implementation uses hardcoded strings for both remediation and severity. Assuming that the underlying data (i.e., the ComplianceControl interface as represented by the AzureControlResponse) actually exposes remediation and severity details, please update the values as follows:
- Remediation: Instead of always displaying "No remediation available", use the available remediation text from the API.
- Severity: Instead of "INFO", use the provided severity label.
If the ComplianceControl (or AzureControlResponse) interface indeed defines a remediation object with a Recommendation text and a severity object with a Label, then the refactor would look like this:
findings.push({ title: controlDetail.properties.description || "Untitled Control", description: controlDetail.properties.description || "No description available", - remediation: "No remediation available", // Azure API doesn't provide remediation in this endpoint + remediation: controlDetail.Remediation?.Recommendation?.Text || "No remediation available", status: controlDetail.properties.state.toUpperCase(), - severity: "INFO", + severity: controlDetail.Severity?.Label || "INFO", resultDetails: controlDetail });If the structure of
controlDetaildoes not already include these properties or if the API does not provide such values for remediation and severity, please adjust the property paths accordingly. Also, ensure a review of the ComplianceControl interface to confirm these fields exist.packages/db/package.json (1)
9-9: Good addition of the migration scriptAdding the
db:migratescript is appropriate given the database schema changes in this PR. This script will help ensure consistent database migrations across development environments.
Summary by CodeRabbit