From 75390c097960662d7447391e5e314cf5d0ce024f Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Fri, 12 Sep 2025 10:37:49 +0200 Subject: [PATCH] wip: add IaC to UI --- ui/CHANGELOG.md | 10 +++++ .../filters/custom-provider-inputs.tsx | 10 +++++ .../filters/custom-select-provider.tsx | 5 +++ .../providers-badge/iac-provider-badge.tsx | 44 +++++++++++++++++++ ui/components/icons/providers-badge/index.ts | 1 + .../provider-overview/provider-overview.tsx | 1 + .../providers/enhanced-provider-selector.tsx | 1 + .../providers/radio-group-provider.tsx | 7 +++ .../workflow/forms/base-credentials-form.tsx | 7 +++ .../workflow/forms/connect-account-form.tsx | 5 +++ .../via-credentials/iac-credentials-form.tsx | 44 +++++++++++++++++++ .../workflow/forms/via-credentials/index.ts | 1 + .../ui/entities/get-provider-logo.tsx | 5 +++ ui/lib/external-urls.ts | 5 +++ .../build-crendentials.ts | 18 ++++++++ .../provider-credential-fields.ts | 6 +++ ui/types/components.ts | 7 +++ ui/types/formSchemas.ts | 16 ++++++- ui/types/providers.ts | 1 + 19 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 ui/components/icons/providers-badge/iac-provider-badge.tsx create mode 100644 ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 6b599c24ed..b97abf0925 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to the **Prowler UI** are documented in this file. +## [Unreleased] + +### 🚀 Added + +- IaC (Infrastructure as Code) provider support for scanning remote repositories [(#TBD)](https://github.com/prowler-cloud/prowler/pull/TBD) + +--- + ## [1.12.1] (Prowler v5.12.1) ### 🚀 Added @@ -14,6 +22,8 @@ All notable changes to the **Prowler UI** are documented in this file. - Field-level email validation message [(#8698)] (https://github.com/prowler-cloud/prowler/pull/8698) - POST method on auth form [(#8699)] (https://github.com/prowler-cloud/prowler/pull/8699) +--- + ## [1.12.0] (Prowler v5.12.0) ### 🚀 Added diff --git a/ui/components/filters/custom-provider-inputs.tsx b/ui/components/filters/custom-provider-inputs.tsx index 77f56c2946..eb42b8934e 100644 --- a/ui/components/filters/custom-provider-inputs.tsx +++ b/ui/components/filters/custom-provider-inputs.tsx @@ -5,6 +5,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, } from "../icons/providers-badge"; @@ -62,3 +63,12 @@ export const CustomProviderInputGitHub = () => { ); }; + +export const CustomProviderInputIac = () => { + return ( +
+ +

Infrastructure as Code

+
+ ); +}; diff --git a/ui/components/filters/custom-select-provider.tsx b/ui/components/filters/custom-select-provider.tsx index 0d56c3b27d..bfbbc959bf 100644 --- a/ui/components/filters/custom-select-provider.tsx +++ b/ui/components/filters/custom-select-provider.tsx @@ -11,6 +11,7 @@ import { CustomProviderInputAzure, CustomProviderInputGCP, CustomProviderInputGitHub, + CustomProviderInputIac, CustomProviderInputKubernetes, CustomProviderInputM365, } from "./custom-provider-inputs"; @@ -43,6 +44,10 @@ const providerDisplayData: Record< label: "GitHub", component: , }, + iac: { + label: "Infrastructure as Code", + component: , + }, }; const dataInputsProvider = PROVIDER_TYPES.map((providerType) => ({ diff --git a/ui/components/icons/providers-badge/iac-provider-badge.tsx b/ui/components/icons/providers-badge/iac-provider-badge.tsx new file mode 100644 index 0000000000..9a701606ed --- /dev/null +++ b/ui/components/icons/providers-badge/iac-provider-badge.tsx @@ -0,0 +1,44 @@ +import * as React from "react"; + +import { IconSvgProps } from "@/types"; + +export const IacProviderBadge: React.FC = ({ + size, + width, + height, + ...props +}) => ( + +); diff --git a/ui/components/icons/providers-badge/index.ts b/ui/components/icons/providers-badge/index.ts index 07b45d3cb0..1a04a7fa1c 100644 --- a/ui/components/icons/providers-badge/index.ts +++ b/ui/components/icons/providers-badge/index.ts @@ -2,5 +2,6 @@ export * from "./aws-provider-badge"; export * from "./azure-provider-badge"; export * from "./gcp-provider-badge"; export * from "./github-provider-badge"; +export * from "./iac-provider-badge"; export * from "./ks8-provider-badge"; export * from "./m365-provider-badge"; diff --git a/ui/components/overview/provider-overview/provider-overview.tsx b/ui/components/overview/provider-overview/provider-overview.tsx index 5fe8a07070..7405b81052 100644 --- a/ui/components/overview/provider-overview/provider-overview.tsx +++ b/ui/components/overview/provider-overview/provider-overview.tsx @@ -49,6 +49,7 @@ export const ProvidersOverview = ({ gcp: "GCP", kubernetes: "Kubernetes", github: "GitHub", + iac: "IaC", }; const providers = PROVIDER_TYPES.map((providerType) => ({ diff --git a/ui/components/providers/enhanced-provider-selector.tsx b/ui/components/providers/enhanced-provider-selector.tsx index 39779382be..bc6e6d3388 100644 --- a/ui/components/providers/enhanced-provider-selector.tsx +++ b/ui/components/providers/enhanced-provider-selector.tsx @@ -15,6 +15,7 @@ const providerTypeLabels: Record = { m365: "Microsoft 365", kubernetes: "Kubernetes", github: "GitHub", + iac: "Infrastructure as Code", }; interface EnhancedProviderSelectorProps { diff --git a/ui/components/providers/radio-group-provider.tsx b/ui/components/providers/radio-group-provider.tsx index fa5021a8ad..1494a66779 100644 --- a/ui/components/providers/radio-group-provider.tsx +++ b/ui/components/providers/radio-group-provider.tsx @@ -12,6 +12,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, } from "../icons/providers-badge"; @@ -78,6 +79,12 @@ export const RadioGroupProvider: React.FC = ({ GitHub + +
+ + Infrastructure as Code +
+
{errorMessage && ( diff --git a/ui/components/providers/workflow/forms/base-credentials-form.tsx b/ui/components/providers/workflow/forms/base-credentials-form.tsx index 94a2965c1a..1c7421a1e0 100644 --- a/ui/components/providers/workflow/forms/base-credentials-form.tsx +++ b/ui/components/providers/workflow/forms/base-credentials-form.tsx @@ -16,6 +16,7 @@ import { AzureCredentials, GCPDefaultCredentials, GCPServiceAccountKey, + IacCredentials, KubernetesCredentials, M365Credentials, ProviderType, @@ -28,6 +29,7 @@ import { GCPDefaultCredentialsForm } from "./select-credentials-type/gcp/credent import { GCPServiceAccountKeyForm } from "./select-credentials-type/gcp/credentials-type/gcp-service-account-key-form"; import { AzureCredentialsForm } from "./via-credentials/azure-credentials-form"; import { GitHubCredentialsForm } from "./via-credentials/github-credentials-form"; +import { IacCredentialsForm } from "./via-credentials/iac-credentials-form"; import { KubernetesCredentialsForm } from "./via-credentials/k8s-credentials-form"; import { M365CredentialsForm } from "./via-credentials/m365-credentials-form"; @@ -133,6 +135,11 @@ export const BaseCredentialsForm = ({ credentialsType={searchParamsObj.get("via") || undefined} /> )} + {providerType === "iac" && ( + } + /> + )}
{showBackButton && requiresBackButton(searchParamsObj.get("via")) && ( diff --git a/ui/components/providers/workflow/forms/connect-account-form.tsx b/ui/components/providers/workflow/forms/connect-account-form.tsx index aa3136a78d..418f0e492d 100644 --- a/ui/components/providers/workflow/forms/connect-account-form.tsx +++ b/ui/components/providers/workflow/forms/connect-account-form.tsx @@ -51,6 +51,11 @@ const getProviderFieldDetails = (providerType?: ProviderType) => { label: "Username", placeholder: "e.g. your-github-username", }; + case "iac": + return { + label: "Repository URL", + placeholder: "e.g. https://github.com/user/repo", + }; default: return { label: "Provider UID", diff --git a/ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx b/ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx new file mode 100644 index 0000000000..a11f2efa9a --- /dev/null +++ b/ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx @@ -0,0 +1,44 @@ +import { Control } from "react-hook-form"; + +import { CustomInput } from "@/components/ui/custom"; +import { IacCredentials } from "@/types"; + +export const IacCredentialsForm = ({ + control, +}: { + control: Control; +}) => { + return ( + <> +
+
+ Connect via Repository +
+
+ Please provide the repository URL to scan for Infrastructure as Code + files. +
+
+ + + + ); +}; diff --git a/ui/components/providers/workflow/forms/via-credentials/index.ts b/ui/components/providers/workflow/forms/via-credentials/index.ts index d020b9715f..de795e93d0 100644 --- a/ui/components/providers/workflow/forms/via-credentials/index.ts +++ b/ui/components/providers/workflow/forms/via-credentials/index.ts @@ -1,4 +1,5 @@ export * from "./azure-credentials-form"; export * from "./github-credentials-form"; +export * from "./iac-credentials-form"; export * from "./k8s-credentials-form"; export * from "./m365-credentials-form"; diff --git a/ui/components/ui/entities/get-provider-logo.tsx b/ui/components/ui/entities/get-provider-logo.tsx index 047652ffdc..1d9d6d0fd9 100644 --- a/ui/components/ui/entities/get-provider-logo.tsx +++ b/ui/components/ui/entities/get-provider-logo.tsx @@ -5,6 +5,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, } from "@/components/icons/providers-badge"; @@ -24,6 +25,8 @@ export const getProviderLogo = (provider: ProviderType) => { return ; case "github": return ; + case "iac": + return ; default: return null; } @@ -43,6 +46,8 @@ export const getProviderName = (provider: ProviderType): string => { return "Microsoft 365"; case "github": return "GitHub"; + case "iac": + return "Infrastructure as Code"; default: return "Unknown Provider"; } diff --git a/ui/lib/external-urls.ts b/ui/lib/external-urls.ts index 6ec84ef46c..2fea554972 100644 --- a/ui/lib/external-urls.ts +++ b/ui/lib/external-urls.ts @@ -32,6 +32,11 @@ export const getProviderHelpText = (provider: string) => { text: "Need help connecting your GitHub account?", link: "https://goto.prowler.com/provider-github", }; + case "iac": + return { + text: "Need help scanning your Infrastructure as Code repository?", + link: "https://goto.prowler.com/provider-iac", + }; default: return { text: "How to setup a provider?", diff --git a/ui/lib/provider-credentials/build-crendentials.ts b/ui/lib/provider-credentials/build-crendentials.ts index 475702db0c..d23e1812f1 100644 --- a/ui/lib/provider-credentials/build-crendentials.ts +++ b/ui/lib/provider-credentials/build-crendentials.ts @@ -190,6 +190,20 @@ export const buildGitHubSecret = (formData: FormData) => { return {}; }; +export const buildIacSecret = (formData: FormData) => { + const secret = { + [ProviderCredentialFields.REPOSITORY_URL]: getFormValue( + formData, + ProviderCredentialFields.REPOSITORY_URL, + ), + [ProviderCredentialFields.ACCESS_TOKEN]: getFormValue( + formData, + ProviderCredentialFields.ACCESS_TOKEN, + ), + }; + return filterEmptyValues(secret); +}; + // Main function to build secret configuration export const buildSecretConfig = ( formData: FormData, @@ -224,6 +238,10 @@ export const buildSecretConfig = ( secretType: "static", secret: buildGitHubSecret(formData), }), + iac: () => ({ + secretType: "static", + secret: buildIacSecret(formData), + }), }; const builder = secretBuilders[providerType]; diff --git a/ui/lib/provider-credentials/provider-credential-fields.ts b/ui/lib/provider-credentials/provider-credential-fields.ts index 32dc184292..b702225868 100644 --- a/ui/lib/provider-credentials/provider-credential-fields.ts +++ b/ui/lib/provider-credentials/provider-credential-fields.ts @@ -42,6 +42,10 @@ export const ProviderCredentialFields = { OAUTH_APP_TOKEN: "oauth_app_token", GITHUB_APP_ID: "github_app_id", GITHUB_APP_KEY: "github_app_key_content", + + // IaC fields + REPOSITORY_URL: "repository_url", + ACCESS_TOKEN: "access_token", } as const; // Type for credential field values @@ -70,6 +74,8 @@ export const ErrorPointers = { OAUTH_APP_TOKEN: "/data/attributes/secret/oauth_app_token", GITHUB_APP_ID: "/data/attributes/secret/github_app_id", GITHUB_APP_KEY: "/data/attributes/secret/github_app_key_content", + REPOSITORY_URL: "/data/attributes/secret/repository_url", + ACCESS_TOKEN: "/data/attributes/secret/access_token", } as const; export type ErrorPointer = (typeof ErrorPointers)[keyof typeof ErrorPointers]; diff --git a/ui/types/components.ts b/ui/types/components.ts index fa6e10859c..f78321af7e 100644 --- a/ui/types/components.ts +++ b/ui/types/components.ts @@ -239,12 +239,19 @@ export type KubernetesCredentials = { [ProviderCredentialFields.PROVIDER_ID]: string; }; +export type IacCredentials = { + [ProviderCredentialFields.REPOSITORY_URL]: string; + [ProviderCredentialFields.ACCESS_TOKEN]?: string; + [ProviderCredentialFields.PROVIDER_ID]: string; +}; + export type CredentialsFormSchema = | AWSCredentials | AzureCredentials | GCPDefaultCredentials | GCPServiceAccountKey | KubernetesCredentials + | IacCredentials | M365Credentials; export interface SearchParamsProps { diff --git a/ui/types/formSchemas.ts b/ui/types/formSchemas.ts index 5b1891379f..143e4cb05c 100644 --- a/ui/types/formSchemas.ts +++ b/ui/types/formSchemas.ts @@ -110,6 +110,11 @@ export const addProviderFormSchema = z [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), providerUid: z.string(), }), + z.object({ + providerType: z.literal("iac"), + [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), + providerUid: z.string(), + }), ]), ); @@ -190,7 +195,16 @@ export const addCredentialsFormSchema = ( .string() .optional(), } - : {}), + : providerType === "iac" + ? { + [ProviderCredentialFields.REPOSITORY_URL]: z + .string() + .nonempty("Repository URL is required"), + [ProviderCredentialFields.ACCESS_TOKEN]: z + .string() + .optional(), + } + : {}), }) .superRefine((data: Record, ctx) => { if (providerType === "m365") { diff --git a/ui/types/providers.ts b/ui/types/providers.ts index 86f4e90533..c6d9331d0d 100644 --- a/ui/types/providers.ts +++ b/ui/types/providers.ts @@ -5,6 +5,7 @@ export const PROVIDER_TYPES = [ "kubernetes", "m365", "github", + "iac", ] as const; export type ProviderType = (typeof PROVIDER_TYPES)[number];