Skip to content

Com 20 gcp - #215

Merged
7yntax merged 9 commits into
mainfrom
COM-20-gcp
Mar 28, 2025
Merged

7yntax merged 9 commits into
mainfrom
COM-20-gcp

Conversation

@7yntax

@7yntax 7yntax commented Mar 28, 2025 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Introduced a dashboard button to refresh tests with interactive notifications.
    • Expanded cloud integration support to include streamlined connectivity for Google Cloud Platform.
  • Improvements
    • Standardized the presentation of test and compliance results by using consistent severity ratings.
    • Enhanced test information with clear remediation details.
  • Documentation
    • Updated integration guides for Azure and GCP to provide clearer configuration and troubleshooting steps.
  • Chores
    • Refined database structures to support enhanced integration results handling.

@linear

linear Bot commented Mar 28, 2025

Copy link
Copy Markdown

COM-20 Cloud Tests

@vercel

vercel Bot commented Mar 28, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 28, 2025 2:25pm
comp-portal ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 28, 2025 2:25pm

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Mar 28, 2025 •

Copy link
Copy Markdown

Walkthrough

This pull request makes systematic changes to update the handling of severity across the codebase. The modifications replace the use of the label property with severity in data mappings, database queries, and schema definitions. In addition, the integration modules now include new fields such as remediation and refined logic for processing findings. Updates also cover a new database migration, JWT-based authentication for GCP integration, refreshed UI actions for test updates, and modifications to documentation and dependency management.

Changes

File(s) Change Summary
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/overview/data/getComplianceScores.ts
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/actions/getTest.ts
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/components/TestDetails.tsx
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/getTests.ts
Updated mapping logic: replaced use of label with severity, simplified extraction of description, added remediation, and adjusted query conditions.
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/actions/refreshTests.ts
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/components/table/empty-states.tsx
Revised logic for refreshing test data: changed duplicate lookups from Id to title, expanded update/creation fields, added action methods, and replaced previous button actions.
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/types/index.ts Updated test schema: removed label, added severity (nullable) and introduced remediation field.
apps/app/src/jobs/tasks/integration/integration-results.ts Modified integration result handling: shifted from using label to severity, updated update/create logic to include description, remediation, and expanded result fields.
packages/db/package.json
packages/db/prisma/migrations/.../migration.sql
packages/db/prisma/schema/cloud.prisma
Added new DB migration script and command (db:migrate), dropped the old table, created a new OrganizationIntegrationResults table with additional fields, and updated the Prisma model (removed label, added description, remediation, severity).
packages/docs/integrations/azure.mdx
packages/docs/integrations/gcp.mdx
Streamlined documentation: removed redundant and obsolete troubleshooting entries in Azure docs and restructured the configuration guide for GCP integration.
packages/integrations/package.json Added a new dependency: "jsonwebtoken": "^9.0.2".
packages/integrations/src/aws/src/index.ts
packages/integrations/src/azure/src/index.ts
packages/integrations/src/factory.ts
packages/integrations/src/gcp/config.ts
packages/integrations/src/gcp/src/index.ts
packages/integrations/src/gcp/src/test.ts
packages/integrations/src/index.ts
Enhanced integration modules: introduced new interfaces (AWSFinding, AzureFinding, IntegrationFinding), updated fetch method return types, added a new GCP handler with JWT-based authentication and token retrieval, refined data mapping, and included GCP in the global integrations export.

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
Loading
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
Loading

Possibly related PRs

Poem

I'm just a rabbit, hopping through the code,
Replacing old labels with severity to ease the load.
With JWTs and migrations, our path's cleared and bright,
I nibble on updates, from morning 'til night.
Carrots and commits, in every byte they gleam—
Cheers to these changes, a coder's dream!

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (14)
packages/integrations/src/index.ts (1)

4-4: Export GCPCredentials type for consistency

Good 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 duplication

The 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 here

This 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 production

There'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 generation

The 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 resultDetails

The resultDetails property is typed as any, 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 control

All 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 assignedUserId to 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 global fetch implementation is available. If your environment supports it, you can remove the node-fetch dependency.


25-31: Consider using a stricter type for resultDetails
Relying on any can 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 renaming fetch to avoid shadowing the common global fetch method in newer Node.js environments and browsers.

packages/integrations/src/azure/src/index.ts (2)

13-20: Consider using a more specific type for resultDetails

The new AzureFinding interface provides a good standardized structure for Azure findings. However, resultDetails: any bypasses TypeScript's type checking. Consider using a more specific type or at least unknown for better type safety.

interface AzureFinding {
  title: string;
  description: string;
  remediation: string;
  status: string;
  severity: string;
-  resultDetails: any;
+  resultDetails: unknown;
}

73-73: Remove unused complianceData array

The function initializes a complianceData array at line 108 that isn't used after changing the return type to Promise<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 support

Adding the jsonwebtoken package 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3c454a2 and 485b3ab.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • yarn.lock is 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 from label to severity

The change from result.label to result.severity makes 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 from label to severity in database queries

These changes consistently update all five severity level queries (INFO, LOW, MEDIUM, HIGH, CRITICAL) to use the property name severity instead of label. 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 property

Changed from accessing the nested cloudTest.resultDetails?.Description to the direct cloudTest.description property, aligning with the data structure refactoring in the getTest function.


152-152: Simplified access to remediation property

Changed from a complex nested access pattern (likely cloudTest.resultDetails?.Remediation?.Recommendation?.Text based on the AI summary) to the direct cloudTest.remediation property. This simplification makes the code more readable and maintainable.

packages/integrations/src/gcp/config.ts (2)

36-42: Improved configuration parameter clarity

Updated 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 3

Length 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 decryptSettings and 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 functionality

Clean addition of the necessary imports for implementing the test refresh functionality.


14-22: Well-implemented refresh tests action with user feedback

The 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 button

Good 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 json

Length 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 schema

Good 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 at apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/types/index.ts appears 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 migrations or 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 filter

Changed property name from 'label' to 'severity' in the filter condition, consistent with the schema changes.


107-107: Updated property name in count query

Changed 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 from label to severity at line 116) has been verified. In our targeted search, we found no instances of a lingering result.label in this context. The many remaining occurrences of label in 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, and severity fields, 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 previous label field, making the results more informative.


115-119: Error handling now includes additional fields.

Good addition of description and remediation fields to error records, with severity replacing label. 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 title as 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.js

Length of output: 267


Action Required: Verify Title Uniqueness via Node

The change to use title as a unique identifier simplifies the query, but its correctness hinges on ensuring that titles remain unique within each integration. The initial verification attempt using npx tsx failed due to an unavailable npx command. 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.js

Once 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 title as 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 uses severity instead of label, 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, and severity fields, with status repositioned. 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 fields description, remediation, and severity (with severity replacing label), and repositions status. Our initial check confirms that migration files exist—specifically, for example, ./packages/db/prisma/migrations/20250327203613_rename_organization_integration_results/migration.sql and another adding comments.

However, the automated search for explicit handling of existing data (converting or migrating data from label to severity) 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 label to severity is 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 findings

The AWSFinding interface defines a clear structure for AWS security findings, which will improve type safety throughout the codebase.


30-30: Good type safety improvement

Updating the return type from Promise<any[]> to Promise<AWSFinding[]> provides better type safety and documentation for consumers of this API.


107-107: Good export of the new type

Properly exporting the AWSFinding type makes it available for consumers of this module.

packages/integrations/src/factory.ts (4)

24-31: LGTM: Good standardization of findings interface

Creating a common IntegrationFinding interface standardizes the structure across all integrations, which will make the codebase more maintainable and consistent.


39-39: Type enhancement improves API clarity

Updating the return type from Promise<any[]> to Promise<IntegrationFinding[]> provides better type safety and documentation for the API consumers.


109-120: LGTM: Well-structured GCP integration handler

The 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 type

The 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 definition

The new table includes all necessary fields including the new remediation and severity fields that align with the IntegrationFinding interface. The primary key is properly defined.


39-46: LGTM: Proper indexes for performance

Creating indexes on foreign key columns (assignedUserId, organizationIntegrationId, and organizationId) will improve query performance.


4-6:

Details

❓ Verification inconclusive

Warning: Data loss during migration

The migration drops the Organization_integration_results table 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_results table 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
The GCPCredentials interface is straightforward and accurately represents the organization ID and serialized key.


12-22: No issues
This ServiceAccountKey interface closely matches standard GCP service account keys.


34-40: No concerns
The parseServiceAccountKey function 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 the GCPCredentials and GCPFinding types clearly indicates their usage outside this module.


82-119:

Details

❓ Verification inconclusive

Verify alignment of “description” and “title” fields
The code maps finding.description to title and uses finding.sourceProperties.Explanation as 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 in packages/integrations/src/gcp/src/index.ts the finding’s title is derived from finding.description while the test file (packages/integrations/src/gcp/src/test.ts) references finding.name (e.g., using it for the Id) and builds its Title from finding.sourceProperties.Recommendation or finding.sourceProperties.Explanation. Please confirm that the intended structure for a GCP finding is to use finding.name as the primary identifier for the title and whether finding.description should 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 severity and remediation. Looking at the ComplianceControl interface, 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 controlDetail has the same structure as the ComplianceControl interface, 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 controlDetail does 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 script

Adding the db:migrate script is appropriate given the database schema changes in this PR. This script will help ensure consistent database migrations across development environments.

Comment thread packages/integrations/src/gcp/src/test.ts
Comment thread packages/integrations/src/gcp/src/test.ts
Comment thread packages/integrations/src/gcp/src/test.ts
@7yntax
7yntax merged commit bfb6190 into main Mar 28, 2025

This branch was successfully deployed

2 active deployments
Preview – app — 485b3ab1 Deployed Mar 28, 2025 by vercel[bot]
Preview – comp-portal — 485b3ab1 Deployed Mar 28, 2025 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants