diff --git a/ui/components/providers/workflow/forms/connect-account-form.tsx b/ui/components/providers/workflow/forms/connect-account-form.tsx
index 90e3cba642..4a0b73ccdf 100644
--- a/ui/components/providers/workflow/forms/connect-account-form.tsx
+++ b/ui/components/providers/workflow/forms/connect-account-form.tsx
@@ -8,6 +8,8 @@ import { useForm } from "react-hook-form";
import { z } from "zod";
import { addProvider } from "@/actions/providers/providers";
+import { AwsMethodSelector } from "@/components/providers/organizations/aws-method-selector";
+import { OrgWizardModal } from "@/components/providers/organizations/org-wizard-modal";
import { ProviderTitleDocs } from "@/components/providers/workflow/provider-title-docs";
import { Button } from "@/components/shadcn";
import { useToast } from "@/components/ui";
@@ -83,6 +85,8 @@ const getProviderFieldDetails = (providerType?: ProviderType) => {
export const ConnectAccountForm = () => {
const { toast } = useToast();
const [prevStep, setPrevStep] = useState(1);
+ const [awsMethod, setAwsMethod] = useState<"single" | null>(null);
+ const [isOrgModalOpen, setIsOrgModalOpen] = useState(false);
const router = useRouter();
const formSchema = addProviderFormSchema;
@@ -170,10 +174,19 @@ export const ConnectAccountForm = () => {
};
const handleBackStep = () => {
+ // If in UID form after choosing single, go back to method selector
+ if (prevStep === 2 && awsMethod === "single") {
+ setAwsMethod(null);
+ form.setValue("providerUid", "");
+ form.setValue("providerAlias", "");
+ return;
+ }
+
setPrevStep((prev) => prev - 1);
- //Deselect the providerType if the user is going back to the first step
+ // Deselect the providerType if the user is going back to the first step
if (prevStep === 2) {
form.setValue("providerType", undefined as unknown as ProviderType);
+ setAwsMethod(null);
}
// Reset the providerUid and providerAlias fields when going back
form.setValue("providerUid", "");
@@ -200,35 +213,50 @@ export const ConnectAccountForm = () => {
errorMessage={form.formState.errors.providerType?.message}
/>
)}
- {/* Step 2: UID, alias, and credentials (if AWS) */}
- {prevStep === 2 && (
+ {/* Step 2: AWS method selector (only for AWS, before choosing method) */}
+ {prevStep === 2 && providerType === "aws" && awsMethod === null && (
<>
-
setAwsMethod("single")}
+ onSelectOrganizations={() => setIsOrgModalOpen(true)}
/>
-
>
)}
+ {/* Step 2: UID, alias form (non-AWS or AWS single account) */}
+ {prevStep === 2 &&
+ (providerType !== "aws" || awsMethod === "single") && (
+ <>
+
+
+
+ >
+ )}
{/* Navigation buttons */}
- {/* Show "Back" button only in Step 2 */}
+ {/* Show "Back" button in Step 2 (skip when on AWS method selector) */}
{prevStep === 2 && (
)}
- {/* Show "Next" button in Step 2 */}
- {prevStep === 2 && (
-
- )}
+ {/* Show "Next" button in Step 2 (only when UID form is visible) */}
+ {prevStep === 2 &&
+ (providerType !== "aws" || awsMethod === "single") && (
+
+ )}
diff --git a/ui/components/providers/workflow/index.ts b/ui/components/providers/workflow/index.ts
index 65cabc53ce..fa64a01884 100644
--- a/ui/components/providers/workflow/index.ts
+++ b/ui/components/providers/workflow/index.ts
@@ -1,5 +1,4 @@
export * from "./credentials-role-helper";
export * from "./provider-title-docs";
export * from "./skeleton-provider-workflow";
-export * from "./vertical-steps";
export * from "./workflow-add-provider";
diff --git a/ui/components/providers/workflow/workflow-add-provider.tsx b/ui/components/providers/workflow/workflow-add-provider.tsx
index fbb5a3e393..46ca13e9bb 100644
--- a/ui/components/providers/workflow/workflow-add-provider.tsx
+++ b/ui/components/providers/workflow/workflow-add-provider.tsx
@@ -1,97 +1,149 @@
"use client";
-import { Progress } from "@heroui/progress";
-import { Spacer } from "@heroui/spacer";
+import { FolderGit2, KeyRound, Shield } from "lucide-react";
import { usePathname } from "next/navigation";
-import React from "react";
-import { VerticalSteps } from "./vertical-steps";
+import { ProwlerShort } from "@/components/icons/prowler/ProwlerIcons";
+import { cn } from "@/lib/utils";
+import { IconComponent, IconSvgProps } from "@/types/components";
-const steps = [
+interface StepConfig {
+ label: string;
+ description: string;
+ icon: IconComponent;
+}
+
+const STEPS: StepConfig[] = [
{
- title: "Choose your Cloud Provider",
+ label: "Link a Cloud Provider",
description:
- "Select the cloud provider you wish to connect and specify your preferred authentication method from the supported options.",
- href: "/providers/connect-account",
+ "Enter the provider details you would like to add in Prowler.",
+ icon: FolderGit2,
},
{
- title: "Enter Authentication Details",
+ label: "Authenticate Credentials",
description:
- "Provide the necessary credentials to establish a secure connection to your selected cloud provider.",
- href: "/providers/add-credentials",
+ "Authorize a secure connection between Prowler and your provider.",
+ icon: KeyRound,
},
{
- title: "Verify Connection & Start Scan",
+ label: "Validate Connection",
description:
- "Ensure your credentials are correct and start scanning your cloud environment.",
- href: "/providers/test-connection",
+ "Review provider resources and test the connection to Prowler.",
+ icon: Shield,
+ },
+ {
+ label: "Launch Scan",
+ description: "Scan newly connected resources.",
+ icon: ProwlerShort,
},
];
-const ROUTE_CONFIG: Record<
- string,
- {
- stepIndex: number;
- stepOverride?: { index: number; title: string; description: string };
- }
-> = {
- "/providers/connect-account": { stepIndex: 0 },
- "/providers/add-credentials": { stepIndex: 1 },
- "/providers/test-connection": { stepIndex: 2 },
- "/providers/update-credentials": {
- stepIndex: 1,
- stepOverride: {
- index: 2,
- title: "Make sure the new credentials are valid",
- description: "Valid credentials will take you back to the providers page",
- },
- },
+const ROUTE_TO_STEP: Record = {
+ "/providers/connect-account": 0,
+ "/providers/add-credentials": 1,
+ "/providers/test-connection": 2,
+ "/providers/update-credentials": 1,
};
export const WorkflowAddProvider = () => {
const pathname = usePathname();
-
- const config = ROUTE_CONFIG[pathname] || { stepIndex: 0 };
- const currentStep = config.stepIndex;
-
- const updatedSteps = steps.map((step, index) => {
- if (config.stepOverride && index === config.stepOverride.index) {
- return { ...step, ...config.stepOverride };
- }
- return step;
- });
+ const currentStep = ROUTE_TO_STEP[pathname] ?? 0;
return (
-
-
- Add a Cloud Provider
-
-
- Complete these steps to configure your cloud provider and initiate your
- first scan.
-
-
-
-
-
+
);
};
+
+interface StepCircleProps {
+ isComplete: boolean;
+ isActive: boolean;
+ icon: IconComponent;
+}
+
+function StepCircle({ isComplete, isActive, icon: Icon }: StepCircleProps) {
+ const borderColor =
+ isComplete || isActive ? "border-primary" : "border-[#202020]";
+ const iconColor = isComplete || isActive ? "text-primary" : "text-[#525252]";
+
+ return (
+
+
+
+ );
+}
+
+/**
+ * Renders either a Lucide icon (className-based) or a custom SVG icon
+ * (size-prop-based like ProwlerShort) with consistent sizing.
+ */
+function StepIcon({
+ icon: Icon,
+ className,
+}: {
+ icon: IconComponent;
+ className: string;
+}) {
+ if (isCustomSvgIcon(Icon)) {
+ return ;
+ }
+ return ;
+}
+
+/**
+ * Type guard: Lucide icons have a `displayName` property set by lucide-react.
+ * Custom SVG icons (React.FC) accept a `size` number prop.
+ */
+function isCustomSvgIcon(icon: IconComponent): icon is React.FC {
+ return !("displayName" in icon && typeof icon.displayName === "string");
+}