From e034aa381ae93a6670c4620bb7451079430c12d5 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 24 Oct 2024 00:29:41 +0800 Subject: [PATCH 1/4] feat: initial schema setup --- .../dynamic-secret/providers/models.ts | 35 +++- frontend/src/hooks/api/dynamicSecret/types.ts | 10 +- .../CreateDynamicSecretForm/LdapInputForm.tsx | 173 +++++++++++++----- 3 files changed, 162 insertions(+), 56 deletions(-) diff --git a/backend/src/ee/services/dynamic-secret/providers/models.ts b/backend/src/ee/services/dynamic-secret/providers/models.ts index c204333ce..1020ace13 100644 --- a/backend/src/ee/services/dynamic-secret/providers/models.ts +++ b/backend/src/ee/services/dynamic-secret/providers/models.ts @@ -12,6 +12,11 @@ export enum ElasticSearchAuthTypes { ApiKey = "api-key" } +export enum LdapCredentialType { + Dynamic = "dynamic", + Static = "static" +} + export const DynamicSecretRedisDBSchema = z.object({ host: z.string().trim().toLowerCase(), port: z.number(), @@ -174,16 +179,26 @@ export const AzureEntraIDSchema = z.object({ clientSecret: z.string().trim().min(1) }); -export const LdapSchema = z.object({ - url: z.string().trim().min(1), - binddn: z.string().trim().min(1), - bindpass: z.string().trim().min(1), - ca: z.string().optional(), - - creationLdif: z.string().min(1), - revocationLdif: z.string().min(1), - rollbackLdif: z.string().optional() -}); +export const LdapSchema = z.union([ + z.object({ + url: z.string().trim().min(1), + binddn: z.string().trim().min(1), + bindpass: z.string().trim().min(1), + ca: z.string().optional(), + credentialType: z.literal(LdapCredentialType.Dynamic).optional().default(LdapCredentialType.Dynamic), + creationLdif: z.string().min(1), + revocationLdif: z.string().min(1), + rollbackLdif: z.string().optional() + }), + z.object({ + url: z.string().trim().min(1), + binddn: z.string().trim().min(1), + bindpass: z.string().trim().min(1), + ca: z.string().optional(), + credentialType: z.literal(LdapCredentialType.Static), + rotationLdif: z.string().min(1) + }) +]); export enum DynamicSecretProviders { SqlDatabase = "sql-database", diff --git a/frontend/src/hooks/api/dynamicSecret/types.ts b/frontend/src/hooks/api/dynamicSecret/types.ts index 792fad8d3..08513c05d 100644 --- a/frontend/src/hooks/api/dynamicSecret/types.ts +++ b/frontend/src/hooks/api/dynamicSecret/types.ts @@ -189,7 +189,7 @@ export type TDynamicSecretProvider = applicationId: string; clientSecret: string; }; - } + } | { type: DynamicSecretProviders.Ldap; inputs: { @@ -197,13 +197,13 @@ export type TDynamicSecretProvider = binddn: string; bindpass: string; ca?: string | undefined; - creationLdif: string; - revocationLdif: string; + credentialType: string; + creationLdif?: string; + revocationLdif?: string; rollbackLdif?: string; + rotationLdif?: string; }; }; - ; - export type TCreateDynamicSecretDTO = { projectSlug: string; provider: TDynamicSecretProvider; diff --git a/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx b/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx index b78161aa5..b4720e9cf 100644 --- a/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx +++ b/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx @@ -8,21 +8,47 @@ import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; import { createNotification } from "@app/components/notifications"; -import { Button, FormControl, Input, TextArea } from "@app/components/v2"; +import { Button, FormControl, Input, Select, SelectItem, TextArea } from "@app/components/v2"; import { useCreateDynamicSecret } from "@app/hooks/api"; import { DynamicSecretProviders } from "@app/hooks/api/dynamicSecret/types"; -const formSchema = z.object({ - provider: z.object({ - url: z.string().trim().min(1), - binddn: z.string().trim().min(1), - bindpass: z.string().trim().min(1), - ca: z.string().optional(), +enum CredentialType { + Dynamic = "dynamic", + Static = "static" +} - creationLdif: z.string().min(1), - revocationLdif: z.string().min(1), - rollbackLdif: z.string().optional() - }), +const credentialTypes = [ + { + label: "Dynamic", + value: CredentialType.Dynamic + }, + { + label: "Static", + value: CredentialType.Static + } +] as const; + +const formSchema = z.object({ + provider: z.discriminatedUnion("credentialType", [ + z.object({ + url: z.string().trim().min(1), + binddn: z.string().trim().min(1), + bindpass: z.string().trim().min(1), + ca: z.string().optional(), + credentialType: z.literal(CredentialType.Dynamic), + creationLdif: z.string().min(1), + revocationLdif: z.string().min(1), + rollbackLdif: z.string().optional() + }), + z.object({ + url: z.string().trim().min(1), + binddn: z.string().trim().min(1), + bindpass: z.string().trim().min(1), + ca: z.string().optional(), + credentialType: z.literal(CredentialType.Static), + rotationLdif: z.string().min(1) + }) + ]), defaultTTL: z.string().superRefine((val, ctx) => { const valMs = ms(val); @@ -67,6 +93,8 @@ export const LdapInputForm = ({ const { control, formState: { isSubmitting }, + setValue, + watch, handleSubmit } = useForm({ resolver: zodResolver(formSchema), @@ -78,11 +106,14 @@ export const LdapInputForm = ({ ca: "", creationLdif: "", revocationLdif: "", - rollbackLdif: "" + rollbackLdif: "", + credentialType: CredentialType.Dynamic } } }); + const selectedCredentialType = watch("provider.credentialType"); + const createDynamicSecret = useCreateDynamicSecret(); const handleCreateDynamicSecret = async ({ name, maxTTL, provider, defaultTTL }: TForm) => { @@ -240,45 +271,105 @@ export const LdapInputForm = ({ ( -