fix: refactor and handle modify

This commit is contained in:
Meet
2024-10-02 20:51:02 +05:30
parent 27afad583b
commit e0199084ad
5 changed files with 434 additions and 444 deletions
@@ -5,11 +5,10 @@ import { render } from "mustache";
import { customAlphabet } from "nanoid"; import { customAlphabet } from "nanoid";
import { z } from "zod"; import { z } from "zod";
import { logger } from "@app/lib/logger";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { LdapSchema, TDynamicProviderFns } from "./models"; import { LdapSchema, TDynamicProviderFns } from "./models";
import { BadRequestError } from "@app/lib/errors";
const ldif = require("ldif"); const ldif = require("ldif");
const generatePassword = () => { const generatePassword = () => {
@@ -17,8 +16,15 @@ const generatePassword = () => {
return customAlphabet(charset, 64)(); return customAlphabet(charset, 64)();
}; };
const encodePassword = (password?: string) => {
const quotedPassword = `"${password}"`;
const utf16lePassword = Buffer.from(quotedPassword, "utf16le");
const base64Password = utf16lePassword.toString("base64");
return base64Password;
}
const generateUsername = () => { const generateUsername = () => {
return alphaNumericNanoId(32); return alphaNumericNanoId(20);
}; };
const generateLDIF = ({ const generateLDIF = ({
@@ -30,9 +36,11 @@ const generateLDIF = ({
password?: string; password?: string;
ldifTemplate: string; ldifTemplate: string;
}): string => { }): string => {
const data = { const data = {
Username: username, Username: username,
Password: password Password: password,
EncodedPassword: encodePassword(password)
}; };
const ldif = render(ldifTemplate, data); const ldif = render(ldifTemplate, data);
@@ -47,7 +55,7 @@ export const LdapProvider = (): TDynamicProviderFns => {
}; };
const getClient = async (providerInputs: z.infer<typeof LdapSchema>): Promise<ldapjs.Client> => { const getClient = async (providerInputs: z.infer<typeof LdapSchema>): Promise<ldapjs.Client> => {
return new Promise((resolve) => { return new Promise((resolve, reject) => {
const client = ldapjs.createClient({ const client = ldapjs.createClient({
url: providerInputs.url, url: providerInputs.url,
tlsOptions: { tlsOptions: {
@@ -57,18 +65,17 @@ export const LdapProvider = (): TDynamicProviderFns => {
reconnect: true, reconnect: true,
bindDN: providerInputs.binddn, bindDN: providerInputs.binddn,
bindCredentials: providerInputs.bindpass, bindCredentials: providerInputs.bindpass,
log: logger
}); });
client.on("error", (err) => { client.on("error", (err) => {
client.unbind(); client.unbind();
throw new Error(err.message); reject(new BadRequestError({ message: err.message }));
}); });
client.bind(providerInputs.binddn, providerInputs.bindpass, (err) => { client.bind(providerInputs.binddn, providerInputs.bindpass, (err) => {
if (err) { if (err) {
client.unbind(); client.unbind();
throw new Error(err.message); reject(new BadRequestError({ message: err.message }));
} else { } else {
resolve(client); resolve(client);
} }
@@ -100,10 +107,10 @@ export const LdapProvider = (): TDynamicProviderFns => {
attributes[attrName] = Array.isArray(attrValue) ? attrValue : [attrValue]; attributes[attrName] = Array.isArray(attrValue) ? attrValue : [attrValue];
}); });
response_dn = await new Promise((resolve) => { response_dn = await new Promise((resolve, reject) => {
client.add(dn, attributes, (err) => { client.add(dn, attributes, (err) => {
if (err) { if (err) {
throw new Error(err.message); reject(new BadRequestError({ message: err.message }));
} else { } else {
resolve(dn); resolve(dn);
} }
@@ -117,28 +124,27 @@ export const LdapProvider = (): TDynamicProviderFns => {
new ldapjs.Change({ new ldapjs.Change({
operation: change.operation || "replace", operation: change.operation || "replace",
modification: { modification: {
[change.attribute.attribute]: Array.isArray(change.value.value) type: change.attribute.attribute,
? change.value.value values: change.values.map((value: any) => value.value)
: [change.value.value]
} }
}) })
); );
}); });
response_dn = await new Promise((resolve) => { response_dn = await new Promise((resolve, reject) => {
client.modify(dn, changes, (err) => { client.modify(dn, changes, (err) => {
if (err) { if (err) {
throw new Error(err.message); reject(new BadRequestError({ message: err.message }));
} else { } else {
resolve(dn); resolve(dn);
} }
}); });
}); });
} else if (entry.type === "delete") { } else if (entry.type === "delete") {
response_dn = await new Promise((resolve) => { response_dn = await new Promise((resolve, reject) => {
client.del(dn, (err) => { client.del(dn, (err) => {
if (err) { if (err) {
throw new Error(err.message); reject(new BadRequestError({ message: err.message }));
} else { } else {
resolve(dn); resolve(dn);
} }
@@ -168,11 +174,11 @@ export const LdapProvider = (): TDynamicProviderFns => {
return { entityId: username, data: { DN_ARRAY: dnArray, USERNAME: username, PASSWORD: password } }; return { entityId: username, data: { DN_ARRAY: dnArray, USERNAME: username, PASSWORD: password } };
} catch (err) { } catch (err) {
if (providerInputs.rollbackLdif) {
const rollbackLdif = generateLDIF({ username, password, ldifTemplate: providerInputs.rollbackLdif }); const rollbackLdif = generateLDIF({ username, password, ldifTemplate: providerInputs.rollbackLdif });
await executeLdif(client, rollbackLdif); await executeLdif(client, rollbackLdif);
}
throw new Error((err as Error).message); throw new BadRequestError({ message: (err as Error).message });
} }
}; };
@@ -180,9 +180,9 @@ export const LdapSchema = z.object({
bindpass: z.string().trim().min(1), bindpass: z.string().trim().min(1),
ca: z.string().optional(), ca: z.string().optional(),
creationLdif: z.string().trim().min(1), creationLdif: z.string().min(1),
revocationLdif: z.string().trim().min(1), revocationLdif: z.string().min(1),
rollbackLdif: z.string().trim().min(1) rollbackLdif: z.string().optional()
}); });
export enum DynamicSecretProviders { export enum DynamicSecretProviders {
@@ -199,7 +199,7 @@ export type TDynamicSecretProvider =
ca?: string | undefined; ca?: string | undefined;
creationLdif: string; creationLdif: string;
revocationLdif: string; revocationLdif: string;
rollbackLdif: string; rollbackLdif?: string;
}; };
}; };
; ;
@@ -16,9 +16,9 @@ const formSchema = z.object({
bindpass: z.string().trim().min(1), bindpass: z.string().trim().min(1),
ca: z.string().optional(), ca: z.string().optional(),
creationLdif: z.string().trim().min(1), creationLdif: z.string().min(1),
revocationLdif: z.string().trim().min(1), revocationLdif: z.string().min(1),
rollbackLdif: z.string().trim().min(1), rollbackLdif: z.string().optional()
}), }),
defaultTTL: z.string().superRefine((val, ctx) => { defaultTTL: z.string().superRefine((val, ctx) => {
@@ -54,15 +54,13 @@ type Props = {
environment: string; environment: string;
}; };
export const LdapInputForm = ( export const LdapInputForm = ({
{
onCompleted, onCompleted,
onCancel, onCancel,
secretPath, secretPath,
projectSlug, projectSlug,
environment, environment
}: Props }: Props) => {
) => {
const { const {
control, control,
formState: { isSubmitting }, formState: { isSubmitting },
@@ -78,7 +76,7 @@ export const LdapInputForm = (
creationLdif: "", creationLdif: "",
revocationLdif: "", revocationLdif: "",
rollbackLdif: "" rollbackLdif: ""
}, }
} }
}); });
@@ -203,7 +201,7 @@ export const LdapInputForm = (
isError={Boolean(error?.message)} isError={Boolean(error?.message)}
errorText={error?.message} errorText={error?.message}
> >
<Input {...field} /> <Input {...field} type="password" />
</FormControl> </FormControl>
)} )}
/> />
@@ -263,8 +261,6 @@ export const LdapInputForm = (
</FormControl> </FormControl>
)} )}
/> />
</div> </div>
</div> </div>
</div> </div>
@@ -279,5 +275,5 @@ export const LdapInputForm = (
</Button> </Button>
</div> </div>
</form> </form>
) );
}; };
@@ -16,9 +16,9 @@ const formSchema = z.object({
binddn: z.string().trim().min(1), binddn: z.string().trim().min(1),
bindpass: z.string().trim().min(1), bindpass: z.string().trim().min(1),
ca: z.string().optional(), ca: z.string().optional(),
creationLdif: z.string().trim().min(1), creationLdif: z.string().min(1),
revocationLdif: z.string().trim().min(1), revocationLdif: z.string().min(1),
rollbackLdif: z.string().trim().min(1), rollbackLdif: z.string().optional()
}) })
.partial(), .partial(),
defaultTTL: z.string().superRefine((val, ctx) => { defaultTTL: z.string().superRefine((val, ctx) => {
@@ -63,7 +63,7 @@ export const EditDynamicSecretLdapForm = ({
environment, environment,
secretPath, secretPath,
projectSlug projectSlug
}: Props) => { }: Props) => {
const { const {
control, control,
formState: { isSubmitting }, formState: { isSubmitting },
@@ -166,11 +166,7 @@ export const EditDynamicSecretLdapForm = ({
control={control} control={control}
name="inputs.url" name="inputs.url"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl label="URL" isError={Boolean(error)} errorText={error?.message}>
label="URL"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} /> <Input {...field} />
</FormControl> </FormControl>
)} )}
@@ -179,11 +175,7 @@ export const EditDynamicSecretLdapForm = ({
control={control} control={control}
name="inputs.binddn" name="inputs.binddn"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl label="Bind DN" isError={Boolean(error)} errorText={error?.message}>
label="Bind DN"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} /> <Input {...field} />
</FormControl> </FormControl>
)} )}
@@ -197,7 +189,7 @@ export const EditDynamicSecretLdapForm = ({
isError={Boolean(error)} isError={Boolean(error)}
errorText={error?.message} errorText={error?.message}
> >
<Input {...field} /> <Input {...field} type="password" />
</FormControl> </FormControl>
)} )}
/> />
@@ -205,11 +197,7 @@ export const EditDynamicSecretLdapForm = ({
control={control} control={control}
name="inputs.ca" name="inputs.ca"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl label="CA" isError={Boolean(error)} errorText={error?.message}>
label="CA"
isError={Boolean(error)}
errorText={error?.message}
>
<TextArea {...field} /> <TextArea {...field} />
</FormControl> </FormControl>
)} )}
@@ -264,5 +252,5 @@ export const EditDynamicSecretLdapForm = ({
</div> </div>
</form> </form>
</div> </div>
) );
} };