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];