Merge pull request #2528 from Infisical/meet/fix-mustache-import-error

fix: change mustache import
This commit is contained in:
Daniel Hougaard
2024-10-03 23:30:18 +04:00
committed by GitHub
2 changed files with 52 additions and 27 deletions

4
backend/src/@types/ldif.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module "ldif" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Untyped, the function returns `any`.
function parse(input: string, ...args: any[]): any;
}

View File

@@ -1,15 +1,13 @@
/* eslint-disable */
import ldapjs from "ldapjs"; import ldapjs from "ldapjs";
import { render } from "mustache"; import ldif from "ldif";
import mustache from "mustache";
import { customAlphabet } from "nanoid"; import { customAlphabet } from "nanoid";
import { z } from "zod"; import { z } from "zod";
import { BadRequestError } from "@app/lib/errors";
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 generatePassword = () => { const generatePassword = () => {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*$#"; const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*$#";
@@ -21,7 +19,7 @@ const encodePassword = (password?: string) => {
const utf16lePassword = Buffer.from(quotedPassword, "utf16le"); const utf16lePassword = Buffer.from(quotedPassword, "utf16le");
const base64Password = utf16lePassword.toString("base64"); const base64Password = utf16lePassword.toString("base64");
return base64Password; return base64Password;
} };
const generateUsername = () => { const generateUsername = () => {
return alphaNumericNanoId(20); return alphaNumericNanoId(20);
@@ -36,16 +34,15 @@ 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) EncodedPassword: encodePassword(password)
}; };
const ldif = render(ldifTemplate, data); const renderedLdif = mustache.render(ldifTemplate, data);
return ldif; return renderedLdif;
}; };
export const LdapProvider = (): TDynamicProviderFns => { export const LdapProvider = (): TDynamicProviderFns => {
@@ -64,10 +61,10 @@ export const LdapProvider = (): TDynamicProviderFns => {
}, },
reconnect: true, reconnect: true,
bindDN: providerInputs.binddn, bindDN: providerInputs.binddn,
bindCredentials: providerInputs.bindpass, bindCredentials: providerInputs.bindpass
}); });
client.on("error", (err) => { client.on("error", (err: Error) => {
client.unbind(); client.unbind();
reject(new BadRequestError({ message: err.message })); reject(new BadRequestError({ message: err.message }));
}); });
@@ -90,30 +87,53 @@ export const LdapProvider = (): TDynamicProviderFns => {
}; };
const executeLdif = async (client: ldapjs.Client, ldif_file: string) => { const executeLdif = async (client: ldapjs.Client, ldif_file: string) => {
let parsedEntries; type TEntry = {
dn: string;
type: string;
changes: {
operation?: string;
attribute: {
attribute: string;
};
value: {
value: string;
};
values: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Untyped, can be any for ldapjs.Change.modification.values
value: any;
}[];
}[];
};
let parsedEntries: TEntry[];
try { try {
parsedEntries = ldif.parse(ldif_file).entries as any[]; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
parsedEntries = ldif.parse(ldif_file).entries as TEntry[];
} catch (err) { } catch (err) {
throw new BadRequestError({ message: "Invalid LDIF format, refer to the documentation at Dynamic secrets > LDAP > LDIF Entries." }); throw new BadRequestError({
message: "Invalid LDIF format, refer to the documentation at Dynamic secrets > LDAP > LDIF Entries."
});
} }
const dnArray: string[] = []; const dnArray: string[] = [];
for (const entry of parsedEntries) { for await (const entry of parsedEntries) {
const { dn } = entry; const { dn } = entry;
let response_dn: string; let responseDn: string;
if (entry.type === "add") { if (entry.type === "add") {
const attributes: any = {}; const attributes: Record<string, string | string[]> = {};
entry.changes.forEach((change: any) => { entry.changes.forEach((change) => {
const attrName = change.attribute.attribute; const attrName = change.attribute.attribute;
const attrValue = change.value.value; const attrValue = change.value.value;
attributes[attrName] = Array.isArray(attrValue) ? attrValue : [attrValue]; attributes[attrName] = Array.isArray(attrValue) ? attrValue : [attrValue];
}); });
response_dn = await new Promise((resolve, reject) => { responseDn = await new Promise((resolve, reject) => {
client.add(dn, attributes, (err) => { client.add(dn, attributes, (err) => {
if (err) { if (err) {
reject(new BadRequestError({ message: err.message })); reject(new BadRequestError({ message: err.message }));
@@ -123,21 +143,22 @@ export const LdapProvider = (): TDynamicProviderFns => {
}); });
}); });
} else if (entry.type === "modify") { } else if (entry.type === "modify") {
const changes: any = []; const changes: ldapjs.Change[] = [];
entry.changes.forEach((change: any) => { entry.changes.forEach((change) => {
changes.push( changes.push(
new ldapjs.Change({ new ldapjs.Change({
operation: change.operation || "replace", operation: change.operation || "replace",
modification: { modification: {
type: change.attribute.attribute, type: change.attribute.attribute,
values: change.values.map((value: any) => value.value) // eslint-disable-next-line @typescript-eslint/no-unsafe-return
values: change.values.map((value) => value.value)
} }
}) })
); );
}); });
response_dn = await new Promise((resolve, reject) => { responseDn = await new Promise((resolve, reject) => {
client.modify(dn, changes, (err) => { client.modify(dn, changes, (err) => {
if (err) { if (err) {
reject(new BadRequestError({ message: err.message })); reject(new BadRequestError({ message: err.message }));
@@ -147,7 +168,7 @@ export const LdapProvider = (): TDynamicProviderFns => {
}); });
}); });
} else if (entry.type === "delete") { } else if (entry.type === "delete") {
response_dn = await new Promise((resolve, reject) => { responseDn = await new Promise((resolve, reject) => {
client.del(dn, (err) => { client.del(dn, (err) => {
if (err) { if (err) {
reject(new BadRequestError({ message: err.message })); reject(new BadRequestError({ message: err.message }));
@@ -161,7 +182,7 @@ export const LdapProvider = (): TDynamicProviderFns => {
throw new BadRequestError({ message: `Unsupported operation type ${entry.type}` }); throw new BadRequestError({ message: `Unsupported operation type ${entry.type}` });
} }
dnArray.push(response_dn); dnArray.push(responseDn);
} }
client.unbind(); client.unbind();
return dnArray; return dnArray;
@@ -173,10 +194,10 @@ export const LdapProvider = (): TDynamicProviderFns => {
const username = generateUsername(); const username = generateUsername();
const password = generatePassword(); const password = generatePassword();
const ldif = generateLDIF({ username, password, ldifTemplate: providerInputs.creationLdif }); const generatedLdif = generateLDIF({ username, password, ldifTemplate: providerInputs.creationLdif });
try { try {
const dnArray = await executeLdif(client, ldif); const dnArray = await executeLdif(client, generatedLdif);
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) {