diff --git a/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx b/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx index b867e919d0..31e1640a7e 100644 --- a/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx +++ b/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx @@ -9,6 +9,7 @@ import { AddViaServiceAccountForm, SelectViaGCP, } from "@/components/providers/workflow/forms/select-credentials-type/gcp"; +import { SelectViaGitHub } from "@/components/providers/workflow/forms/select-credentials-type/github"; import { ProviderType } from "@/types/providers"; interface Props { @@ -26,9 +27,20 @@ export default function AddCredentialsPage({ searchParams }: Props) { )} + {searchParams.type === "github" && !searchParams.via && ( + + )} + {((searchParams.type === "aws" && searchParams.via === "credentials") || (searchParams.type === "gcp" && searchParams.via === "credentials") || - (searchParams.type !== "aws" && searchParams.type !== "gcp")) && ( + (searchParams.type === "github" && + searchParams.via === "personal_access_token") || + (searchParams.type === "github" && + searchParams.via === "oauth_app_token") || + (searchParams.type === "github" && searchParams.via === "github_app") || + (searchParams.type !== "aws" && + searchParams.type !== "gcp" && + searchParams.type !== "github")) && ( )} diff --git a/ui/app/(prowler)/providers/(set-up-provider)/update-credentials/page.tsx b/ui/app/(prowler)/providers/(set-up-provider)/update-credentials/page.tsx index 185a107244..7f0470b134 100644 --- a/ui/app/(prowler)/providers/(set-up-provider)/update-credentials/page.tsx +++ b/ui/app/(prowler)/providers/(set-up-provider)/update-credentials/page.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { CredentialsUpdateInfo } from "@/components/providers"; +import { CredentialsUpdateInfo } from "@/components/providers/credentials-update-info"; import { UpdateViaCredentialsForm, UpdateViaRoleForm, @@ -20,7 +20,9 @@ interface Props { export default function UpdateCredentialsPage({ searchParams }: Props) { return ( <> - {(searchParams.type === "aws" || searchParams.type === "gcp") && + {(searchParams.type === "aws" || + searchParams.type === "gcp" || + searchParams.type === "github") && !searchParams.via && ( )} diff --git a/ui/components/icons/providers-badge/github-provider-badge.tsx b/ui/components/icons/providers-badge/github-provider-badge.tsx new file mode 100644 index 0000000000..3e2fad413c --- /dev/null +++ b/ui/components/icons/providers-badge/github-provider-badge.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; + +import { IconSvgProps } from "@/types"; + +export const GitHubProviderBadge: 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 86641d82ad..07b45d3cb0 100644 --- a/ui/components/icons/providers-badge/index.ts +++ b/ui/components/icons/providers-badge/index.ts @@ -1,5 +1,6 @@ export * from "./aws-provider-badge"; export * from "./azure-provider-badge"; export * from "./gcp-provider-badge"; +export * from "./github-provider-badge"; export * from "./ks8-provider-badge"; export * from "./m365-provider-badge"; diff --git a/ui/components/providers/credentials-update-info.tsx b/ui/components/providers/credentials-update-info.tsx index 2715a1ea6b..0fe75f0cb2 100644 --- a/ui/components/providers/credentials-update-info.tsx +++ b/ui/components/providers/credentials-update-info.tsx @@ -2,6 +2,7 @@ import { SelectViaAWS } from "@/components/providers/workflow/forms/select-credentials-type/aws"; import { SelectViaGCP } from "@/components/providers/workflow/forms/select-credentials-type/gcp"; +import { SelectViaGitHub } from "@/components/providers/workflow/forms/select-credentials-type/github"; import { ProviderType } from "@/types/providers"; interface UpdateCredentialsInfoProps { @@ -20,6 +21,9 @@ export const CredentialsUpdateInfo = ({ if (providerType === "gcp") { return ; } + if (providerType === "github") { + return ; + } return null; }; diff --git a/ui/components/providers/radio-group-provider.tsx b/ui/components/providers/radio-group-provider.tsx index ec77a148db..fa5021a8ad 100644 --- a/ui/components/providers/radio-group-provider.tsx +++ b/ui/components/providers/radio-group-provider.tsx @@ -11,6 +11,7 @@ import { AWSProviderBadge, AzureProviderBadge, GCPProviderBadge, + GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, } from "../icons/providers-badge"; @@ -71,6 +72,12 @@ export const RadioGroupProvider: React.FC = ({ Kubernetes + +
+ + GitHub +
+
{errorMessage && ( diff --git a/ui/components/providers/workflow/forms/base-credentials-form.tsx b/ui/components/providers/workflow/forms/base-credentials-form.tsx index 39ab8ff6b3..1959a609a3 100644 --- a/ui/components/providers/workflow/forms/base-credentials-form.tsx +++ b/ui/components/providers/workflow/forms/base-credentials-form.tsx @@ -14,6 +14,7 @@ import { AzureCredentials, GCPDefaultCredentials, GCPServiceAccountKey, + GitHubCredentials, KubernetesCredentials, M365Credentials, ProviderType, @@ -25,6 +26,7 @@ import { AWSRoleCredentialsForm } from "./select-credentials-type/aws/credential import { GCPDefaultCredentialsForm } from "./select-credentials-type/gcp/credentials-type"; 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 { KubernetesCredentialsForm } from "./via-credentials/k8s-credentials-form"; import { M365CredentialsForm } from "./via-credentials/m365-credentials-form"; @@ -121,6 +123,12 @@ export const BaseCredentialsForm = ({ control={form.control as unknown as Control} /> )} + {providerType === "github" && ( + } + via={searchParamsObj.get("via") || undefined} + /> + )}
{showBackButton && diff --git a/ui/components/providers/workflow/forms/connect-account-form.tsx b/ui/components/providers/workflow/forms/connect-account-form.tsx index fa1d48abd4..9bd498bb59 100644 --- a/ui/components/providers/workflow/forms/connect-account-form.tsx +++ b/ui/components/providers/workflow/forms/connect-account-form.tsx @@ -45,6 +45,11 @@ const getProviderFieldDetails = (providerType?: string) => { label: "Domain ID", placeholder: "e.g. your-domain.onmicrosoft.com", }; + case "github": + return { + label: "Username", + placeholder: "e.g. your-github-username", + }; default: return { label: "Provider UID", diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-app-form.tsx b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-app-form.tsx new file mode 100644 index 0000000000..39537b78bc --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-app-form.tsx @@ -0,0 +1,51 @@ +import { Control } from "react-hook-form"; + +import { CustomInput, CustomTextarea } from "@/components/ui/custom"; +import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; +import { GitHubCredentials } from "@/types"; + +export const GitHubAppForm = ({ + control, +}: { + control: Control; +}) => { + return ( + <> +
+
+ GitHub App +
+
+ Use GitHub App credentials for advanced integration. This requires + both the App ID and Private Key. +
+
+ + + + ); +}; diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-oauth-app-token-form.tsx b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-oauth-app-token-form.tsx new file mode 100644 index 0000000000..eb526b97e0 --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-oauth-app-token-form.tsx @@ -0,0 +1,38 @@ +import { Control } from "react-hook-form"; + +import { CustomInput } from "@/components/ui/custom"; +import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; +import { GitHubCredentials } from "@/types"; + +export const GitHubOAuthAppTokenForm = ({ + control, +}: { + control: Control; +}) => { + return ( + <> +
+
+ OAuth App Token +
+
+ Use an OAuth app token for application-level authentication. This is + suitable for applications that need broader access. +
+
+ + + ); +}; diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-personal-access-token-form.tsx b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-personal-access-token-form.tsx new file mode 100644 index 0000000000..42842134cb --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/github-personal-access-token-form.tsx @@ -0,0 +1,40 @@ +import { Control } from "react-hook-form"; + +import { CustomInput } from "@/components/ui/custom"; +import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; +import { GitHubCredentials } from "@/types"; + +export const GitHubPersonalAccessTokenForm = ({ + control, +}: { + control: Control; +}) => { + return ( + <> +
+
+ Personal Access Token +
+
+ Use a personal access token for individual user authentication. This + is the simplest method for personal use. +
+
+ + + ); +}; diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/index.ts b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/index.ts new file mode 100644 index 0000000000..5b5efd0ba6 --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/credentials-type/index.ts @@ -0,0 +1,3 @@ +export * from "./github-app-form"; +export * from "./github-oauth-app-token-form"; +export * from "./github-personal-access-token-form"; diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/index.ts b/ui/components/providers/workflow/forms/select-credentials-type/github/index.ts new file mode 100644 index 0000000000..af2ab44833 --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/index.ts @@ -0,0 +1,2 @@ +export * from "./radio-group-github-via-credentials-type-form"; +export * from "./select-via-github"; diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/radio-group-github-via-credentials-type-form.tsx b/ui/components/providers/workflow/forms/select-credentials-type/github/radio-group-github-via-credentials-type-form.tsx new file mode 100644 index 0000000000..4c94a02a2b --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/radio-group-github-via-credentials-type-form.tsx @@ -0,0 +1,80 @@ +"use client"; + +import { RadioGroup } from "@nextui-org/react"; +import React from "react"; +import { Control, Controller } from "react-hook-form"; + +import { CustomRadio } from "@/components/ui/custom"; +import { FormMessage } from "@/components/ui/form"; + +type RadioGroupGitHubViaCredentialsFormProps = { + control: Control; + isInvalid: boolean; + errorMessage?: string; + onChange?: (value: string) => void; +}; + +export const RadioGroupGitHubViaCredentialsTypeForm = ({ + control, + isInvalid, + errorMessage, + onChange, +}: RadioGroupGitHubViaCredentialsFormProps) => { + return ( + ( + <> + { + field.onChange(value); + if (onChange) { + onChange(value); + } + }} + > +
+ + Authentication Methods + + +
+ Personal Access Token +
+
+ +
+ OAuth App Token +
+
+ +
+ GitHub App +
+
+
+
+ {errorMessage && ( + + {errorMessage} + + )} + + )} + /> + ); +}; diff --git a/ui/components/providers/workflow/forms/select-credentials-type/github/select-via-github.tsx b/ui/components/providers/workflow/forms/select-credentials-type/github/select-via-github.tsx new file mode 100644 index 0000000000..9fe491f4ca --- /dev/null +++ b/ui/components/providers/workflow/forms/select-credentials-type/github/select-via-github.tsx @@ -0,0 +1,38 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import { useForm } from "react-hook-form"; + +import { Form } from "@/components/ui/form"; + +import { RadioGroupGitHubViaCredentialsTypeForm } from "./radio-group-github-via-credentials-type-form"; + +interface SelectViaGitHubProps { + initialVia?: string; +} + +export const SelectViaGitHub = ({ initialVia }: SelectViaGitHubProps) => { + const router = useRouter(); + const form = useForm({ + defaultValues: { + githubCredentialsType: initialVia || "", + }, + }); + + const handleSelectionChange = (value: string) => { + const url = new URL(window.location.href); + url.searchParams.set("via", value); + router.push(url.toString()); + }; + + return ( +
+ + + ); +}; diff --git a/ui/components/providers/workflow/forms/via-credentials/github-credentials-form.tsx b/ui/components/providers/workflow/forms/via-credentials/github-credentials-form.tsx new file mode 100644 index 0000000000..2e3771cb97 --- /dev/null +++ b/ui/components/providers/workflow/forms/via-credentials/github-credentials-form.tsx @@ -0,0 +1,239 @@ +import { Control } from "react-hook-form"; + +import { CustomInput, CustomTextarea } from "@/components/ui/custom"; +import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; +import { GitHubCredentials } from "@/types"; + +export const GitHubCredentialsForm = ({ + control, + via, +}: { + control: Control; + via?: string; +}) => { + const renderPersonalAccessTokenFields = () => ( +
+
+

+ Personal Access Token +

+

+ Use a personal access token for individual user authentication +

+
+ +
+ ); + + const renderOAuthAppTokenFields = () => ( +
+
+

+ OAuth App Token +

+

+ Use an OAuth app token for application-level authentication +

+
+ +
+ ); + + const renderGitHubAppFields = () => ( +
+
+

+ GitHub App +

+

+ Use GitHub App credentials (both App ID and Private Key are + required) +

+
+ + +
+ ); + + const renderAllOptions = () => ( + <> +
+
+ Connect via Credentials +
+
+ Choose one of the following authentication methods for your GitHub + credentials: +
+
+ + {/* Option 1: Personal Access Token */} +
+
+

+ Option 1: Personal Access Token +

+

+ Use a personal access token for individual user authentication +

+
+ +
+ + {/* Option 2: OAuth App Token */} +
+
+

+ Option 2: OAuth App Token +

+

+ Use an OAuth app token for application-level authentication +

+
+ +
+ + {/* Option 3: GitHub App */} +
+
+

+ Option 3: GitHub App +

+

+ Use GitHub App credentials (both App ID and Private Key are + required) +

+
+ + +
+ + ); + + // If via parameter is provided, show only the selected method + if (via) { + return ( + <> +
+
+ Connect via Credentials +
+
+ Enter your GitHub credentials for the selected authentication method. +
+
+ + {via === "personal_access_token" && renderPersonalAccessTokenFields()} + {via === "oauth_app_token" && renderOAuthAppTokenFields()} + {via === "github_app" && renderGitHubAppFields()} + + ); + } + + // If no via parameter, show all options (fallback behavior) + return renderAllOptions(); +}; diff --git a/ui/components/scans/launch-workflow/select-scan-provider.tsx b/ui/components/scans/launch-workflow/select-scan-provider.tsx index 10a21d2b10..deb7c43106 100644 --- a/ui/components/scans/launch-workflow/select-scan-provider.tsx +++ b/ui/components/scans/launch-workflow/select-scan-provider.tsx @@ -66,6 +66,7 @@ export const SelectScanProvider = < | "azure" | "gcp" | "kubernetes" + | "github" } entityAlias={selectedItem.alias} entityId={selectedItem.uid} @@ -91,6 +92,7 @@ export const SelectScanProvider = < | "azure" | "gcp" | "kubernetes" + | "github" } entityAlias={item.alias} entityId={item.uid} diff --git a/ui/components/ui/custom/custom-input.tsx b/ui/components/ui/custom/custom-input.tsx index 5b76ef6fda..3ba577e7ee 100644 --- a/ui/components/ui/custom/custom-input.tsx +++ b/ui/components/ui/custom/custom-input.tsx @@ -94,36 +94,53 @@ export const CustomInput = ({ ( - <> - - - - {showFormMessage && ( - - )} - - )} + render={({ field }) => { + // Handle number type conversion + const handleChange = (e: React.ChangeEvent) => { + const value = e.target.value; + if (type === "number") { + // Convert empty string to undefined, otherwise convert to number + const numValue = value === "" ? undefined : Number(value); + field.onChange(numValue); + } else { + field.onChange(value); + } + }; + + return ( + <> + + + + {showFormMessage && ( + + )} + + ); + }} /> ); }; diff --git a/ui/components/ui/entities/get-provider-logo.tsx b/ui/components/ui/entities/get-provider-logo.tsx index 17ab559988..047652ffdc 100644 --- a/ui/components/ui/entities/get-provider-logo.tsx +++ b/ui/components/ui/entities/get-provider-logo.tsx @@ -4,6 +4,7 @@ import { AWSProviderBadge, AzureProviderBadge, GCPProviderBadge, + GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, } from "@/components/icons/providers-badge"; @@ -21,6 +22,8 @@ export const getProviderLogo = (provider: ProviderType) => { return ; case "m365": return ; + case "github": + return ; default: return null; } @@ -38,6 +41,8 @@ export const getProviderName = (provider: ProviderType): string => { return "Kubernetes"; case "m365": return "Microsoft 365"; + case "github": + return "GitHub"; default: return "Unknown Provider"; } diff --git a/ui/lib/error-mappings.ts b/ui/lib/error-mappings.ts index 582dfd5696..e30b54975a 100644 --- a/ui/lib/error-mappings.ts +++ b/ui/lib/error-mappings.ts @@ -28,4 +28,9 @@ export const PROVIDER_CREDENTIALS_ERROR_MAPPING: Record = { [ErrorPointers.ROLE_SESSION_NAME]: ProviderCredentialFields.ROLE_SESSION_NAME, [ErrorPointers.SERVICE_ACCOUNT_KEY]: ProviderCredentialFields.SERVICE_ACCOUNT_KEY, + [ErrorPointers.PERSONAL_ACCESS_TOKEN]: + ProviderCredentialFields.PERSONAL_ACCESS_TOKEN, + [ErrorPointers.OAUTH_APP_TOKEN]: ProviderCredentialFields.OAUTH_APP_TOKEN, + [ErrorPointers.GITHUB_APP_ID]: ProviderCredentialFields.GITHUB_APP_ID, + [ErrorPointers.GITHUB_APP_KEY]: ProviderCredentialFields.GITHUB_APP_KEY, }; diff --git a/ui/lib/external-urls.ts b/ui/lib/external-urls.ts index cea7a694ae..1e8210a116 100644 --- a/ui/lib/external-urls.ts +++ b/ui/lib/external-urls.ts @@ -25,6 +25,11 @@ export const getProviderHelpText = (provider: string) => { text: "Need help connecting your Kubernetes cluster?", link: "https://goto.prowler.com/provider-k8s", }; + case "github": + return { + text: "Need help connecting your GitHub account?", + link: "https://goto.prowler.com/provider-github", + }; default: return { text: "How to setup a provider?", diff --git a/ui/lib/lighthouse/prompts.ts b/ui/lib/lighthouse/prompts.ts index 925640aa7f..6b1bb53e8f 100644 --- a/ui/lib/lighthouse/prompts.ts +++ b/ui/lib/lighthouse/prompts.ts @@ -10,7 +10,7 @@ You use Prowler tool's capabilities to answer the user's query. ## Prowler Capabilities - Prowler is an Open Cloud Security tool -- Prowler scans misconfigurations in AWS, Azure, Microsoft 365, GCP, and Kubernetes +- Prowler scans misconfigurations in AWS, Azure, Microsoft 365, GCP, GitHub, and Kubernetes - Prowler helps with continuous monitoring, security assessments and audits, incident response, compliance, hardening, and forensics readiness - Supports multiple compliance frameworks including CIS, NIST 800, NIST CSF, CISA, FedRAMP, PCI-DSS, GDPR, HIPAA, FFIEC, SOC2, GXP, Well-Architected Security, ENS, and more. These compliance frameworks are not available for all providers. @@ -279,7 +279,7 @@ const userInfoAgentPrompt = `You are Prowler's User Info Agent, specializing in - Mentioning all keys in the function call is mandatory. Don't skip any keys. - Don't add empty filters in the function call.`; -const providerAgentPrompt = `You are Prowler's Provider Agent, specializing in provider information within the Prowler tool. Prowler supports the following provider types: AWS, GCP, Azure, and other cloud platforms. +const providerAgentPrompt = `You are Prowler's Provider Agent, specializing in provider information within the Prowler tool. Prowler supports the following provider types: AWS, GCP, Azure, GitHub, and other cloud platforms. ## Available Tools diff --git a/ui/lib/lighthouse/tools/checks.ts b/ui/lib/lighthouse/tools/checks.ts index dbb1cccf6f..b54edadc18 100644 --- a/ui/lib/lighthouse/tools/checks.ts +++ b/ui/lib/lighthouse/tools/checks.ts @@ -19,7 +19,7 @@ export const getProviderChecksTool = tool( { name: "getProviderChecks", description: - "Returns a list of available checks for a specific provider (aws, gcp, azure, kubernetes). Allows filtering by service, severity, and compliance framework ID. If no filters are provided, all checks will be returned.", + "Returns a list of available checks for a specific provider (aws, gcp, azure, kubernetes, github). Allows filtering by service, severity, and compliance framework ID. If no filters are provided, all checks will be returned.", schema: checkSchema, }, ); diff --git a/ui/lib/provider-credentials/build-crendentials.ts b/ui/lib/provider-credentials/build-crendentials.ts index 791a209c8c..b46dc793c6 100644 --- a/ui/lib/provider-credentials/build-crendentials.ts +++ b/ui/lib/provider-credentials/build-crendentials.ts @@ -147,6 +147,28 @@ export const buildKubernetesSecret = (formData: FormData) => { return filterEmptyValues(secret); }; +export const buildGitHubSecret = (formData: FormData) => { + const secret = { + [ProviderCredentialFields.PERSONAL_ACCESS_TOKEN]: getFormValue( + formData, + ProviderCredentialFields.PERSONAL_ACCESS_TOKEN, + ), + [ProviderCredentialFields.OAUTH_APP_TOKEN]: getFormValue( + formData, + ProviderCredentialFields.OAUTH_APP_TOKEN, + ), + [ProviderCredentialFields.GITHUB_APP_ID]: getFormValue( + formData, + ProviderCredentialFields.GITHUB_APP_ID, + ), + [ProviderCredentialFields.GITHUB_APP_KEY]: getFormValue( + formData, + ProviderCredentialFields.GITHUB_APP_KEY, + ), + }; + return filterEmptyValues(secret); +}; + // Main function to build secret configuration export const buildSecretConfig = ( formData: FormData, @@ -177,6 +199,10 @@ export const buildSecretConfig = ( secretType: "static", secret: buildKubernetesSecret(formData), }), + github: () => ({ + secretType: "static", + secret: buildGitHubSecret(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 5cbd6605b9..47b210b029 100644 --- a/ui/lib/provider-credentials/provider-credential-fields.ts +++ b/ui/lib/provider-credentials/provider-credential-fields.ts @@ -35,6 +35,12 @@ export const ProviderCredentialFields = { // Kubernetes fields KUBECONFIG_CONTENT: "kubeconfig_content", + + // GitHub fields + PERSONAL_ACCESS_TOKEN: "personal_access_token", + OAUTH_APP_TOKEN: "oauth_app_token", + GITHUB_APP_ID: "github_app_id", + GITHUB_APP_KEY: "github_app_key_content", } as const; // Type for credential field values @@ -59,6 +65,10 @@ export const ErrorPointers = { SESSION_DURATION: "/data/attributes/secret/session_duration", ROLE_SESSION_NAME: "/data/attributes/secret/role_session_name", SERVICE_ACCOUNT_KEY: "/data/attributes/secret/service_account_key", + PERSONAL_ACCESS_TOKEN: "/data/attributes/secret/personal_access_token", + 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", } as const; export type ErrorPointer = (typeof ErrorPointers)[keyof typeof ErrorPointers]; diff --git a/ui/types/components.ts b/ui/types/components.ts index 82dd41083b..7c15bac4a2 100644 --- a/ui/types/components.ts +++ b/ui/types/components.ts @@ -235,13 +235,22 @@ export type KubernetesCredentials = { [ProviderCredentialFields.PROVIDER_ID]: string; }; +export type GitHubCredentials = { + [ProviderCredentialFields.PERSONAL_ACCESS_TOKEN]?: string; + [ProviderCredentialFields.OAUTH_APP_TOKEN]?: string; + [ProviderCredentialFields.GITHUB_APP_ID]?: number; + [ProviderCredentialFields.GITHUB_APP_KEY]?: string; + [ProviderCredentialFields.PROVIDER_ID]: string; +}; + export type CredentialsFormSchema = | AWSCredentials | AzureCredentials | GCPDefaultCredentials | GCPServiceAccountKey | KubernetesCredentials - | M365Credentials; + | M365Credentials + | GitHubCredentials; export interface SearchParamsProps { [key: string]: string | string[] | undefined; diff --git a/ui/types/formSchemas.ts b/ui/types/formSchemas.ts index b79c55e077..d789baddf7 100644 --- a/ui/types/formSchemas.ts +++ b/ui/types/formSchemas.ts @@ -68,9 +68,12 @@ export const awsCredentialsTypeSchema = z.object({ export const addProviderFormSchema = z .object({ - providerType: z.enum(["aws", "azure", "gcp", "kubernetes", "m365"], { - required_error: "Please select a provider type", - }), + providerType: z.enum( + ["aws", "azure", "gcp", "kubernetes", "m365", "github"], + { + required_error: "Please select a provider type", + }, + ), }) .and( z.discriminatedUnion("providerType", [ @@ -102,6 +105,11 @@ export const addProviderFormSchema = z providerUid: z.string(), awsCredentialsType: z.string().optional(), }), + z.object({ + providerType: z.literal("github"), + [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), + providerUid: z.string(), + }), ]), ); @@ -164,7 +172,22 @@ export const addCredentialsFormSchema = (providerType: string) => [ProviderCredentialFields.USER]: z.string().optional(), [ProviderCredentialFields.PASSWORD]: z.string().optional(), } - : {}), + : providerType === "github" + ? { + [ProviderCredentialFields.PERSONAL_ACCESS_TOKEN]: z + .string() + .optional(), + [ProviderCredentialFields.OAUTH_APP_TOKEN]: z + .string() + .optional(), + [ProviderCredentialFields.GITHUB_APP_ID]: z + .number() + .optional(), + [ProviderCredentialFields.GITHUB_APP_KEY]: z + .string() + .optional(), + } + : {}), }) .superRefine((data: Record, ctx) => { if (providerType === "m365") { diff --git a/ui/types/lighthouse/checks.ts b/ui/types/lighthouse/checks.ts index 186eb6cae6..206e19a5d3 100644 --- a/ui/types/lighthouse/checks.ts +++ b/ui/types/lighthouse/checks.ts @@ -1,7 +1,7 @@ import { z } from "zod"; export const checkSchema = z.object({ - providerType: z.enum(["aws", "gcp", "azure", "kubernetes", "m365"]), + providerType: z.enum(["aws", "gcp", "azure", "kubernetes", "m365", "github"]), service: z.array(z.string()).optional(), severity: z .array(z.enum(["informational", "low", "medium", "high", "critical"])) diff --git a/ui/types/lighthouse/compliances.ts b/ui/types/lighthouse/compliances.ts index e8983e5626..d9f6c4debc 100644 --- a/ui/types/lighthouse/compliances.ts +++ b/ui/types/lighthouse/compliances.ts @@ -89,7 +89,7 @@ export const getCompliancesOverviewSchema = z.object({ export const getComplianceFrameworksSchema = z.object({ providerType: z - .enum(["aws", "azure", "gcp", "kubernetes", "m365"]) + .enum(["aws", "azure", "gcp", "kubernetes", "m365", "github"]) .describe("The provider type to get the compliance frameworks for."), }); diff --git a/ui/types/lighthouse/providers.ts b/ui/types/lighthouse/providers.ts index c4ffcd07a4..a1ddea8bbb 100644 --- a/ui/types/lighthouse/providers.ts +++ b/ui/types/lighthouse/providers.ts @@ -2,7 +2,14 @@ import { z } from "zod"; // Get Providers Schema -const providerEnum = z.enum(["", "aws", "azure", "gcp", "kubernetes"]); +const providerEnum = z.enum([ + "", + "aws", + "azure", + "gcp", + "kubernetes", + "github", +]); const sortFieldsEnum = z.enum([ "", diff --git a/ui/types/lighthouse/resources.ts b/ui/types/lighthouse/resources.ts index 7b70dfe96b..e953d6461b 100644 --- a/ui/types/lighthouse/resources.ts +++ b/ui/types/lighthouse/resources.ts @@ -37,7 +37,14 @@ const resourceSortEnum = z.enum([ "-updated_at", ]); -const providerTypeEnum = z.enum(["", "aws", "gcp", "azure", "kubernetes"]); +const providerTypeEnum = z.enum([ + "", + "aws", + "gcp", + "azure", + "kubernetes", + "github", +]); export const getResourcesSchema = z.object({ page: z.number().optional().describe("The page number to fetch."), diff --git a/ui/types/lighthouse/scans.ts b/ui/types/lighthouse/scans.ts index 00aff8f251..9906026138 100644 --- a/ui/types/lighthouse/scans.ts +++ b/ui/types/lighthouse/scans.ts @@ -1,6 +1,13 @@ import { z } from "zod"; -const providerTypeEnum = z.enum(["", "aws", "azure", "gcp", "kubernetes"]); +const providerTypeEnum = z.enum([ + "", + "aws", + "azure", + "gcp", + "kubernetes", + "github", +]); const stateEnum = z.enum([ "", "available", diff --git a/ui/types/providers.ts b/ui/types/providers.ts index b7aae5b944..15f20e6978 100644 --- a/ui/types/providers.ts +++ b/ui/types/providers.ts @@ -1,4 +1,10 @@ -export type ProviderType = "aws" | "azure" | "m365" | "gcp" | "kubernetes"; +export type ProviderType = + | "aws" + | "azure" + | "m365" + | "gcp" + | "kubernetes" + | "github"; export interface ProviderProps { id: string;