Add user search filter field for LDAP and validation for search filters

This commit is contained in:
Tuan Dang
2024-04-24 20:58:16 -07:00
parent 99d59a38d5
commit 8d5ef5f4d9
12 changed files with 132 additions and 14 deletions

View File

@@ -0,0 +1,15 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.LdapConfig, (t) => {
t.string("searchFilter").notNullable().defaultTo("");
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.LdapConfig, (t) => {
t.dropColumn("searchFilter");
});
}

View File

@@ -25,7 +25,8 @@ export const LdapConfigsSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
groupSearchBase: z.string().default(""), groupSearchBase: z.string().default(""),
groupSearchFilter: z.string().default("") groupSearchFilter: z.string().default(""),
searchFilter: z.string().default("")
}); });
export type TLdapConfigs = z.infer<typeof LdapConfigsSchema>; export type TLdapConfigs = z.infer<typeof LdapConfigsSchema>;

View File

@@ -16,7 +16,7 @@ import { z } from "zod";
import { LdapConfigsSchema, LdapGroupMapsSchema } from "@app/db/schemas"; import { LdapConfigsSchema, LdapGroupMapsSchema } from "@app/db/schemas";
import { TLDAPConfig } from "@app/ee/services/ldap-config/ldap-config-types"; import { TLDAPConfig } from "@app/ee/services/ldap-config/ldap-config-types";
import { searchGroups } from "@app/ee/services/ldap-config/ldap-fns"; import { isValidLdapFilter, searchGroups } from "@app/ee/services/ldap-config/ldap-fns";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
@@ -55,10 +55,14 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
const ldapConfig = (req as unknown as FastifyRequest).ldapConfig as TLDAPConfig; const ldapConfig = (req as unknown as FastifyRequest).ldapConfig as TLDAPConfig;
const groupFilter = "(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))"; const groupFilter = "(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))";
const searchFilter = (ldapConfig.groupSearchFilter || groupFilter) const groupSearchFilter = (ldapConfig.groupSearchFilter || groupFilter)
.replace(/{{\.Username}}/g, user.uid) .replace(/{{\.Username}}/g, user.uid)
.replace(/{{\.UserDN}}/g, user.dn); .replace(/{{\.UserDN}}/g, user.dn);
if (!isValidLdapFilter(groupSearchFilter)) {
throw new Error("Generated LDAP search filter is invalid.");
}
const { isUserCompleted, providerAuthToken } = await server.services.ldap.ldapLogin({ const { isUserCompleted, providerAuthToken } = await server.services.ldap.ldapLogin({
ldapConfigId: ldapConfig.id, ldapConfigId: ldapConfig.id,
externalId: user.uidNumber, externalId: user.uidNumber,
@@ -67,7 +71,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
lastName: user.sn ?? "", lastName: user.sn ?? "",
emails: user.mail ? [user.mail] : [], emails: user.mail ? [user.mail] : [],
groups: ldapConfig.groupSearchBase groups: ldapConfig.groupSearchBase
? await searchGroups(ldapConfig, searchFilter, ldapConfig.groupSearchBase) ? await searchGroups(ldapConfig, groupSearchFilter, ldapConfig.groupSearchBase)
: undefined, : undefined,
relayState: ((req as unknown as FastifyRequest).body as { RelayState?: string }).RelayState, relayState: ((req as unknown as FastifyRequest).body as { RelayState?: string }).RelayState,
orgId: (req as unknown as FastifyRequest).ldapConfig.organization orgId: (req as unknown as FastifyRequest).ldapConfig.organization
@@ -130,6 +134,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
bindDN: z.string(), bindDN: z.string(),
bindPass: z.string(), bindPass: z.string(),
searchBase: z.string(), searchBase: z.string(),
searchFilter: z.string(),
groupSearchBase: z.string(), groupSearchBase: z.string(),
groupSearchFilter: z.string(), groupSearchFilter: z.string(),
caCert: z.string() caCert: z.string()
@@ -163,8 +168,12 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
bindDN: z.string().trim(), bindDN: z.string().trim(),
bindPass: z.string().trim(), bindPass: z.string().trim(),
searchBase: z.string().trim(), searchBase: z.string().trim(),
groupSearchBase: z.string().trim().default(""), searchFilter: z.string().trim().default("(uid={{username}})"),
groupSearchFilter: z.string().trim().default(""), groupSearchBase: z.string().trim(),
groupSearchFilter: z
.string()
.trim()
.default("(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))"),
caCert: z.string().trim().default("") caCert: z.string().trim().default("")
}), }),
response: { response: {
@@ -200,6 +209,7 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
bindDN: z.string().trim(), bindDN: z.string().trim(),
bindPass: z.string().trim(), bindPass: z.string().trim(),
searchBase: z.string().trim(), searchBase: z.string().trim(),
searchFilter: z.string().trim(),
groupSearchBase: z.string().trim(), groupSearchBase: z.string().trim(),
groupSearchFilter: z.string().trim(), groupSearchFilter: z.string().trim(),
caCert: z.string().trim() caCert: z.string().trim()

View File

@@ -40,7 +40,7 @@ import {
TTestLdapConnectionDTO, TTestLdapConnectionDTO,
TUpdateLdapCfgDTO TUpdateLdapCfgDTO
} from "./ldap-config-types"; } from "./ldap-config-types";
import { testLDAPConfig } from "./ldap-fns"; import { isValidLdapFilter, testLDAPConfig } from "./ldap-fns";
import { TLdapGroupMapDALFactory } from "./ldap-group-map-dal"; import { TLdapGroupMapDALFactory } from "./ldap-group-map-dal";
type TLdapConfigServiceFactoryDep = { type TLdapConfigServiceFactoryDep = {
@@ -98,6 +98,7 @@ export const ldapConfigServiceFactory = ({
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -112,6 +113,18 @@ export const ldapConfigServiceFactory = ({
"Failed to create LDAP configuration due to plan restriction. Upgrade plan to create LDAP configuration." "Failed to create LDAP configuration due to plan restriction. Upgrade plan to create LDAP configuration."
}); });
const isSearchFilterValid = isValidLdapFilter(searchFilter);
if (!isSearchFilterValid)
throw new BadRequestError({
message: "Failed to create LDAP configuration due to invalid search filter."
});
const isGroupSearchFilterValid = isValidLdapFilter(groupSearchFilter);
if (!isGroupSearchFilterValid)
throw new BadRequestError({
message: "Failed to create LDAP configuration due to invalid group search filter."
});
const orgBot = await orgBotDAL.transaction(async (tx) => { const orgBot = await orgBotDAL.transaction(async (tx) => {
const doc = await orgBotDAL.findOne({ orgId }, tx); const doc = await orgBotDAL.findOne({ orgId }, tx);
if (doc) return doc; if (doc) return doc;
@@ -175,6 +188,7 @@ export const ldapConfigServiceFactory = ({
bindPassIV, bindPassIV,
bindPassTag, bindPassTag,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
encryptedCACert, encryptedCACert,
@@ -196,6 +210,7 @@ export const ldapConfigServiceFactory = ({
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -210,10 +225,27 @@ export const ldapConfigServiceFactory = ({
"Failed to update LDAP configuration due to plan restriction. Upgrade plan to update LDAP configuration." "Failed to update LDAP configuration due to plan restriction. Upgrade plan to update LDAP configuration."
}); });
if (searchFilter) {
const isSearchFilterValid = isValidLdapFilter(searchFilter);
if (!isSearchFilterValid)
throw new BadRequestError({
message: "Failed to update LDAP configuration due to invalid search filter."
});
}
if (groupSearchFilter) {
const isGroupSearchFilterValid = isValidLdapFilter(groupSearchFilter);
if (!isGroupSearchFilterValid)
throw new BadRequestError({
message: "Failed to update LDAP configuration due to invalid group search filter."
});
}
const updateQuery: TLdapConfigsUpdate = { const updateQuery: TLdapConfigsUpdate = {
isActive, isActive,
url, url,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter groupSearchFilter
}; };
@@ -317,6 +349,7 @@ export const ldapConfigServiceFactory = ({
bindDN, bindDN,
bindPass, bindPass,
searchBase: ldapConfig.searchBase, searchBase: ldapConfig.searchBase,
searchFilter: ldapConfig.searchFilter,
groupSearchBase: ldapConfig.groupSearchBase, groupSearchBase: ldapConfig.groupSearchBase,
groupSearchFilter: ldapConfig.groupSearchFilter, groupSearchFilter: ldapConfig.groupSearchFilter,
caCert caCert
@@ -352,7 +385,7 @@ export const ldapConfigServiceFactory = ({
bindDN: ldapConfig.bindDN, bindDN: ldapConfig.bindDN,
bindCredentials: ldapConfig.bindPass, bindCredentials: ldapConfig.bindPass,
searchBase: ldapConfig.searchBase, searchBase: ldapConfig.searchBase,
searchFilter: "(uid={{username}})", searchFilter: ldapConfig.searchFilter || "(uid={{username}})",
// searchAttributes: ["uid", "uidNumber", "givenName", "sn", "mail"], // searchAttributes: ["uid", "uidNumber", "givenName", "sn", "mail"],
...(ldapConfig.caCert !== "" ...(ldapConfig.caCert !== ""
? { ? {

View File

@@ -20,6 +20,7 @@ export type TCreateLdapCfgDTO = {
bindDN: string; bindDN: string;
bindPass: string; bindPass: string;
searchBase: string; searchBase: string;
searchFilter: string;
groupSearchBase: string; groupSearchBase: string;
groupSearchFilter: string; groupSearchFilter: string;
caCert: string; caCert: string;
@@ -33,6 +34,7 @@ export type TUpdateLdapCfgDTO = {
bindDN: string; bindDN: string;
bindPass: string; bindPass: string;
searchBase: string; searchBase: string;
searchFilter: string;
groupSearchBase: string; groupSearchBase: string;
groupSearchFilter: string; groupSearchFilter: string;
caCert: string; caCert: string;

View File

@@ -4,6 +4,17 @@ import { logger } from "@app/lib/logger";
import { TLDAPConfig } from "./ldap-config-types"; import { TLDAPConfig } from "./ldap-config-types";
export const isValidLdapFilter = (filter: string) => {
try {
ldapjs.parseFilter(filter);
return true;
} catch (error) {
logger.error("Invalid LDAP filter");
logger.error(error);
return false;
}
};
/** /**
* Test the LDAP configuration by attempting to bind to the LDAP server * Test the LDAP configuration by attempting to bind to the LDAP server
* @param ldapConfig - The LDAP configuration to test * @param ldapConfig - The LDAP configuration to test

View File

@@ -25,7 +25,8 @@ You can configure your organization in Infisical to have members authenticate wi
- URL: The LDAP server to connect to such as `ldap://ldap.your-org.com`, `ldaps://ldap.myorg.com:636` (for connection over SSL/TLS), etc. - URL: The LDAP server to connect to such as `ldap://ldap.your-org.com`, `ldaps://ldap.myorg.com:636` (for connection over SSL/TLS), etc.
- Bind DN: The distinguished name of object to bind when performing the user search such as `cn=infisical,ou=Users,dc=acme,dc=com`. - Bind DN: The distinguished name of object to bind when performing the user search such as `cn=infisical,ou=Users,dc=acme,dc=com`.
- Bind Pass: The password to use along with `Bind DN` when performing the user search. - Bind Pass: The password to use along with `Bind DN` when performing the user search.
- Search Base / User DN: Base DN under which to perform user search such as `ou=Users,dc=acme,dc=com` - User Search Base / User DN: Base DN under which to perform user search such as `ou=Users,dc=acme,dc=com`.
- User Search Filter (optional): Template used to construct the LDAP user search filter such as `(uid={{username}})`; use literal `{{username}}` to have the given username used in the search. The default is `(uid={{username}})` which is compatible with several common directory schemas.
- Group Search Base / Group DN (optional): LDAP search base to use for group membership search such as `ou=Groups,dc=acme,dc=com`. - Group Search Base / Group DN (optional): LDAP search base to use for group membership search such as `ou=Groups,dc=acme,dc=com`.
- Group Filter (optional): Template used when constructing the group membership query such as `(&(objectClass=posixGroup)(memberUid={{.Username}}))`. The template can access the following context variables: [`UserDN`, `UserName`]. The default is `(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))` which is compatible with several common directory schemas. - Group Filter (optional): Template used when constructing the group membership query such as `(&(objectClass=posixGroup)(memberUid={{.Username}}))`. The template can access the following context variables: [`UserDN`, `UserName`]. The default is `(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))` which is compatible with several common directory schemas.
- CA Certificate: The CA certificate to use when verifying the LDAP server certificate. - CA Certificate: The CA certificate to use when verifying the LDAP server certificate.
@@ -35,6 +36,14 @@ You can configure your organization in Infisical to have members authenticate wi
</Note> </Note>
</Step> </Step>
<Step title="Test the LDAP connection">
Once you've filled out the LDAP configuration, you can test that part of the configuration is correct by pressing the **Test Connection** button.
Infisical will attempt to bind to the LDAP server using the provided **URL**, **Bind DN**, and **Bind Pass**. If the operation is successful, then Infisical will display a success message; if not, then Infisical will display an error message and provide a fuller error in the server logs.
![LDAP test connection](/images/platform/ldap/ldap-test-connection.png)
</Step>
<Step title="Define mappings from LDAP groups to groups in Infisical"> <Step title="Define mappings from LDAP groups to groups in Infisical">
In order to sync LDAP groups to Infisical, head to the **LDAP Group Mappings** section to define mappings from LDAP groups to groups in Infisical. In order to sync LDAP groups to Infisical, head to the **LDAP Group Mappings** section to define mappings from LDAP groups to groups in Infisical.

View File

@@ -21,7 +21,6 @@ description: "Learn how to configure JumpCloud LDAP for authenticating into Infi
Next, under User Security Settings and Permissions > Permission Settings, check the box next to **Enable as LDAP Bind DN**. Next, under User Security Settings and Permissions > Permission Settings, check the box next to **Enable as LDAP Bind DN**.
![LDAP JumpCloud](/images/platform/ldap/jumpcloud/ldap-jumpcloud-enable-bind-dn.png) ![LDAP JumpCloud](/images/platform/ldap/jumpcloud/ldap-jumpcloud-enable-bind-dn.png)
</Step> </Step>
<Step title="Prepare the LDAP configuration in Infisical"> <Step title="Prepare the LDAP configuration in Infisical">
In Infisical, head to your Organization Settings > Security > LDAP and select **Manage**. In Infisical, head to your Organization Settings > Security > LDAP and select **Manage**.
@@ -35,7 +34,8 @@ description: "Learn how to configure JumpCloud LDAP for authenticating into Infi
- URL: The LDAP server to connect to (`ldaps://ldap.jumpcloud.com:636`). - URL: The LDAP server to connect to (`ldaps://ldap.jumpcloud.com:636`).
- Bind DN: The distinguished name of object to bind when performing the user search (`uid=<ldap-user-username>,ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com`). - Bind DN: The distinguished name of object to bind when performing the user search (`uid=<ldap-user-username>,ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com`).
- Bind Pass: The password to use along with `Bind DN` when performing the user search. - Bind Pass: The password to use along with `Bind DN` when performing the user search.
- Search Base / User DN: Base DN under which to perform user search (`ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com`). - User Search Base / User DN: Base DN under which to perform user search (`ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com`).
- User Search Filter (optional): Template used to construct the LDAP user search filter (`(uid={{username}})`).
- Group Search Base / Group DN (optional): LDAP search base to use for group membership search (`ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com`). - Group Search Base / Group DN (optional): LDAP search base to use for group membership search (`ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com`).
- Group Filter (optional): Template used when constructing the group membership query (`(&(objectClass=groupOfNames)(member=uid={{.Username}},ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com))`) - Group Filter (optional): Template used when constructing the group membership query (`(&(objectClass=groupOfNames)(member=uid={{.Username}},ou=Users,o=<your-org-id>,dc=jumpcloud,dc=com))`)
- CA Certificate: The CA certificate to use when verifying the LDAP server certificate (instructions to obtain the certificate for JumpCloud [here](https://jumpcloud.com/support/connect-to-ldap-with-tls-ssl)). - CA Certificate: The CA certificate to use when verifying the LDAP server certificate (instructions to obtain the certificate for JumpCloud [here](https://jumpcloud.com/support/connect-to-ldap-with-tls-ssl)).
@@ -47,6 +47,13 @@ description: "Learn how to configure JumpCloud LDAP for authenticating into Infi
in your LDAP instance **ORG DN**. in your LDAP instance **ORG DN**.
</Tip> </Tip>
</Step> </Step>
<Step title="Test the LDAP connection">
Once you've filled out the LDAP configuration, you can test that part of the configuration is correct by pressing the **Test Connection** button.
Infisical will attempt to bind to the LDAP server using the provided **URL**, **Bind DN**, and **Bind Pass**. If the operation is successful, then Infisical will display a success message; if not, then Infisical will display an error message and provide a fuller error in the server logs.
![LDAP test connection](/images/platform/ldap/ldap-test-connection.png)
</Step>
<Step title="Define mappings from LDAP groups to groups in Infisical"> <Step title="Define mappings from LDAP groups to groups in Infisical">
In order to sync LDAP groups to Infisical, head to the **LDAP Group Mappings** section to define mappings from LDAP groups to groups in Infisical. In order to sync LDAP groups to Infisical, head to the **LDAP Group Mappings** section to define mappings from LDAP groups to groups in Infisical.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 KiB

View File

@@ -14,6 +14,7 @@ export const useCreateLDAPConfig = () => {
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -24,6 +25,7 @@ export const useCreateLDAPConfig = () => {
bindDN: string; bindDN: string;
bindPass: string; bindPass: string;
searchBase: string; searchBase: string;
searchFilter: string;
groupSearchBase: string; groupSearchBase: string;
groupSearchFilter: string; groupSearchFilter: string;
caCert?: string; caCert?: string;
@@ -35,6 +37,7 @@ export const useCreateLDAPConfig = () => {
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -58,6 +61,7 @@ export const useUpdateLDAPConfig = () => {
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -68,6 +72,7 @@ export const useUpdateLDAPConfig = () => {
bindDN?: string; bindDN?: string;
bindPass?: string; bindPass?: string;
searchBase?: string; searchBase?: string;
searchFilter?: string;
groupSearchBase?: string; groupSearchBase?: string;
groupSearchFilter?: string; groupSearchFilter?: string;
caCert?: string; caCert?: string;
@@ -79,6 +84,7 @@ export const useUpdateLDAPConfig = () => {
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert

View File

@@ -10,7 +10,8 @@ import {
useCreateLDAPConfig, useCreateLDAPConfig,
useGetLDAPConfig, useGetLDAPConfig,
useTestLDAPConnection, useTestLDAPConnection,
useUpdateLDAPConfig} from "@app/hooks/api"; useUpdateLDAPConfig
} from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp"; import { UsePopUpState } from "@app/hooks/usePopUp";
const LDAPFormSchema = z.object({ const LDAPFormSchema = z.object({
@@ -18,6 +19,7 @@ const LDAPFormSchema = z.object({
bindDN: z.string().default(""), bindDN: z.string().default(""),
bindPass: z.string().default(""), bindPass: z.string().default(""),
searchBase: z.string().default(""), searchBase: z.string().default(""),
searchFilter: z.string().default(""),
groupSearchBase: z.string().default(""), groupSearchBase: z.string().default(""),
groupSearchFilter: z.string().default(""), groupSearchFilter: z.string().default(""),
caCert: z.string().optional() caCert: z.string().optional()
@@ -47,6 +49,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
const watchBindDN = watch("bindDN"); const watchBindDN = watch("bindDN");
const watchBindPass = watch("bindPass"); const watchBindPass = watch("bindPass");
const watchSearchBase = watch("searchBase"); const watchSearchBase = watch("searchBase");
const watchSearchFilter = watch("searchFilter");
const watchGroupSearchBase = watch("groupSearchBase"); const watchGroupSearchBase = watch("groupSearchBase");
const watchGroupSearchFilter = watch("groupSearchFilter"); const watchGroupSearchFilter = watch("groupSearchFilter");
const watchCaCert = watch("caCert"); const watchCaCert = watch("caCert");
@@ -58,6 +61,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
bindDN: data?.bindDN ?? "", bindDN: data?.bindDN ?? "",
bindPass: data?.bindPass ?? "", bindPass: data?.bindPass ?? "",
searchBase: data?.searchBase ?? "", searchBase: data?.searchBase ?? "",
searchFilter: data?.searchFilter ?? "",
groupSearchBase: data?.groupSearchBase ?? "", groupSearchBase: data?.groupSearchBase ?? "",
groupSearchFilter: data?.groupSearchFilter ?? "", groupSearchFilter: data?.groupSearchFilter ?? "",
caCert: data?.caCert ?? "" caCert: data?.caCert ?? ""
@@ -70,6 +74,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert, caCert,
@@ -86,6 +91,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -98,6 +104,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
searchFilter,
groupSearchBase, groupSearchBase,
groupSearchFilter, groupSearchFilter,
caCert caCert
@@ -128,6 +135,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
bindDN: watchBindDN, bindDN: watchBindDN,
bindPass: watchBindPass, bindPass: watchBindPass,
searchBase: watchSearchBase, searchBase: watchSearchBase,
searchFilter: watchSearchFilter,
groupSearchBase: watchGroupSearchBase, groupSearchBase: watchGroupSearchBase,
groupSearchFilter: watchGroupSearchFilter, groupSearchFilter: watchGroupSearchFilter,
caCert: watchCaCert, caCert: watchCaCert,
@@ -201,7 +209,7 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
name="searchBase" name="searchBase"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl <FormControl
label="Search Base / User DN" label="User Search Base / User DN"
errorText={error?.message} errorText={error?.message}
isError={Boolean(error)} isError={Boolean(error)}
> >
@@ -209,6 +217,19 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
</FormControl> </FormControl>
)} )}
/> />
<Controller
control={control}
name="searchFilter"
render={({ field, fieldState: { error } }) => (
<FormControl
label="User Search Filter (Optional)"
errorText={error?.message}
isError={Boolean(error)}
>
<Input {...field} placeholder="(uid={{username}})" />
</FormControl>
)}
/>
<Controller <Controller
control={control} control={control}
name="groupSearchBase" name="groupSearchBase"
@@ -231,7 +252,10 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
errorText={error?.message} errorText={error?.message}
isError={Boolean(error)} isError={Boolean(error)}
> >
<Input {...field} placeholder="(objectClass=posixGroup)" /> <Input
{...field}
placeholder="(&(objectClass=posixGroup)(memberUid={{.Username}}))"
/>
</FormControl> </FormControl>
)} )}
/> />