fix: addressed requested changes

This commit is contained in:
Daniel Hougaard
2025-05-08 23:13:46 +04:00
parent a4b648ad95
commit a3b7df4e6b
12 changed files with 166 additions and 146 deletions

View File

@@ -152,7 +152,7 @@ declare module "fastify" {
identityId: string; identityId: string;
user: { user: {
uid: string; uid: string;
mail: string; mail?: string;
}; };
}; };
kmipUser: { kmipUser: {

View File

@@ -23,7 +23,6 @@ export async function up(knex: Knex): Promise<void> {
t.string("url").notNullable(); t.string("url").notNullable();
t.string("searchBase").notNullable(); t.string("searchBase").notNullable();
t.string("searchFilter").notNullable(); t.string("searchFilter").notNullable();
t.string("uniqueAttribute").notNullable();
t.jsonb("allowedFields").nullable(); t.jsonb("allowedFields").nullable();

View File

@@ -22,7 +22,6 @@ export const IdentityLdapAuthsSchema = z.object({
url: z.string(), url: z.string(),
searchBase: z.string(), searchBase: z.string(),
searchFilter: z.string(), searchFilter: z.string(),
uniqueAttribute: z.string(),
allowedFields: z.unknown().nullable().optional(), allowedFields: z.unknown().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date() updatedAt: z.date()

View File

@@ -1056,7 +1056,7 @@ interface LoginIdentityLdapAuthEvent {
metadata: { metadata: {
identityId: string; identityId: string;
ldapUsername: string; ldapUsername: string;
ldapEmail: string; ldapEmail?: string;
}; };
} }

View File

@@ -185,6 +185,49 @@ export const UNIVERSAL_AUTH = {
} }
} as const; } as const;
export const LDAP_AUTH = {
LOGIN: {
identityId: "The ID of the identity to login.",
username: "The username of the LDAP user to login.",
password: "The password of the LDAP user to login."
},
ATTACH: {
identityId: "The ID of the identity to attach the configuration onto.",
url: "The URL of the LDAP server.",
allowedFields:
"The comma-separated array of key/value pairs of required fields that the LDAP entry must have in order to authenticate.",
searchBase: "The base DN to search for the LDAP user.",
searchFilter: "The filter to use to search for the LDAP user.",
bindDN: "The DN of the user to bind to the LDAP server.",
bindPass: "The password of the user to bind to the LDAP server.",
ldapCaCertificate: "The PEM-encoded CA certificate for the LDAP server.",
accessTokenTTL: "The lifetime for an access token in seconds.",
accessTokenMaxTTL: "The maximum lifetime for an access token in seconds.",
accessTokenNumUsesLimit: "The maximum number of times that an access token can be used.",
accessTokenTrustedIps: "The IPs or CIDR ranges that access tokens can be used from."
},
UPDATE: {
identityId: "The ID of the identity to update the configuration for.",
url: "The new URL of the LDAP server.",
allowedFields: "The comma-separated list of allowed fields to return from the LDAP user.",
searchBase: "The new base DN to search for the LDAP user.",
searchFilter: "The new filter to use to search for the LDAP user.",
bindDN: "The new DN of the user to bind to the LDAP server.",
bindPass: "The new password of the user to bind to the LDAP server.",
ldapCaCertificate: "The new PEM-encoded CA certificate for the LDAP server.",
accessTokenTTL: "The new lifetime for an access token in seconds.",
accessTokenMaxTTL: "The new maximum lifetime for an access token in seconds.",
accessTokenNumUsesLimit: "The new maximum number of times that an access token can be used.",
accessTokenTrustedIps: "The new IPs or CIDR ranges that access tokens can be used from."
},
RETRIEVE: {
identityId: "The ID of the identity to retrieve the configuration for."
},
REVOKE: {
identityId: "The ID of the identity to revoke the configuration for."
}
} as const;
export const AWS_AUTH = { export const AWS_AUTH = {
LOGIN: { LOGIN: {
identityId: "The ID of the identity to login.", identityId: "The ID of the identity to login.",

View File

@@ -15,7 +15,7 @@ import { z } from "zod";
import { IdentityLdapAuthsSchema } from "@app/db/schemas/identity-ldap-auths"; import { IdentityLdapAuthsSchema } from "@app/db/schemas/identity-ldap-auths";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags } from "@app/lib/api-docs"; import { ApiDocsTags, LDAP_AUTH } from "@app/lib/api-docs";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { UnauthorizedError } from "@app/lib/errors"; import { UnauthorizedError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
@@ -45,6 +45,7 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
...ldapConfig, ...ldapConfig,
isActive: true, isActive: true,
groupSearchBase: "", groupSearchBase: "",
uniqueUserAttribute: "",
groupSearchFilter: "" groupSearchFilter: ""
}; };
@@ -120,9 +121,9 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
tags: [ApiDocsTags.LdapAuth], tags: [ApiDocsTags.LdapAuth],
description: "Login with LDAP Auth", description: "Login with LDAP Auth",
body: z.object({ body: z.object({
identityId: z.string().trim(), identityId: z.string().trim().describe(LDAP_AUTH.LOGIN.identityId),
username: z.string(), username: z.string().describe(LDAP_AUTH.LOGIN.username),
password: z.string() password: z.string().describe(LDAP_AUTH.LOGIN.password)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -147,11 +148,7 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
}, },
handler: async (req) => { handler: async (req) => {
if ( if (!req.passportMachineIdentity?.identityId || !req.passportMachineIdentity.user.uid) {
!req.passportMachineIdentity?.identityId ||
!req.passportMachineIdentity.user.mail ||
!req.passportMachineIdentity.user.uid
) {
throw new UnauthorizedError({ message: "Invalid request. Missing identity ID or LDAP entry details." }); throw new UnauthorizedError({ message: "Invalid request. Missing identity ID or LDAP entry details." });
} }
@@ -200,29 +197,40 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
} }
], ],
params: z.object({ params: z.object({
identityId: z.string().trim() identityId: z.string().trim().describe(LDAP_AUTH.ATTACH.identityId)
}), }),
body: z body: z
.object({ .object({
url: z.string().trim().min(1), url: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.url),
bindDN: z.string().trim().min(1), bindDN: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.bindDN),
bindPass: z.string().trim().min(1), bindPass: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.bindPass),
searchBase: z.string().trim().min(1), searchBase: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.searchBase),
uniqueAttribute: z.string().trim().min(1).default("uidNumber"), searchFilter: z.string().trim().min(1).default("(uid={{username}})").describe(LDAP_AUTH.ATTACH.searchFilter),
searchFilter: z.string().trim().min(1).default("(uid={{username}})"), allowedFields: AllowedFieldsSchema.array().optional().describe(LDAP_AUTH.ATTACH.allowedFields),
allowedFields: AllowedFieldsSchema.array().optional(), ldapCaCertificate: z.string().trim().optional().describe(LDAP_AUTH.ATTACH.ldapCaCertificate),
ldapCaCertificate: z.string().trim().optional(),
accessTokenTrustedIps: z accessTokenTrustedIps: z
.object({ .object({
ipAddress: z.string().trim() ipAddress: z.string().trim()
}) })
.array() .array()
.min(1) .min(1)
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]), .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
accessTokenTTL: z.number().int().min(0).max(315360000).default(2592000), .describe(LDAP_AUTH.ATTACH.accessTokenTrustedIps),
accessTokenMaxTTL: z.number().int().min(1).max(315360000).default(2592000), accessTokenTTL: z
accessTokenNumUsesLimit: z.number().int().min(0).default(0) .number()
.int()
.min(0)
.max(315360000)
.default(2592000)
.describe(LDAP_AUTH.ATTACH.accessTokenTTL),
accessTokenMaxTTL: z
.number()
.int()
.min(1)
.max(315360000)
.default(2592000)
.describe(LDAP_AUTH.ATTACH.accessTokenMaxTTL),
accessTokenNumUsesLimit: z.number().int().min(0).default(0).describe(LDAP_AUTH.ATTACH.accessTokenNumUsesLimit)
}) })
.refine( .refine(
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL, (val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
@@ -286,27 +294,38 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
} }
], ],
params: z.object({ params: z.object({
identityId: z.string() identityId: z.string().trim().describe(LDAP_AUTH.UPDATE.identityId)
}), }),
body: z body: z
.object({ .object({
url: z.string().trim().min(1), url: z.string().trim().min(1).describe(LDAP_AUTH.UPDATE.url),
bindDN: z.string().trim().min(1), bindDN: z.string().trim().min(1).describe(LDAP_AUTH.UPDATE.bindDN),
bindPass: z.string().trim().min(1), bindPass: z.string().trim().min(1).describe(LDAP_AUTH.UPDATE.bindPass),
searchBase: z.string().trim().min(1), searchBase: z.string().trim().min(1).describe(LDAP_AUTH.UPDATE.searchBase),
uniqueAttribute: z.string().trim().min(1).default("uidNumber"), searchFilter: z.string().trim().min(1).default("(uid={{username}})").describe(LDAP_AUTH.UPDATE.searchFilter),
searchFilter: z.string().trim().min(1).default("(uid={{username}})"), allowedFields: AllowedFieldsSchema.array().optional().describe(LDAP_AUTH.UPDATE.allowedFields),
allowedFields: AllowedFieldsSchema.array().optional(),
accessTokenTrustedIps: z accessTokenTrustedIps: z
.object({ .object({
ipAddress: z.string().trim() ipAddress: z.string().trim()
}) })
.array() .array()
.min(1) .min(1)
.optional(), .optional()
accessTokenTTL: z.number().int().min(0).max(315360000).optional(), .describe(LDAP_AUTH.UPDATE.accessTokenTrustedIps),
accessTokenNumUsesLimit: z.number().int().min(0).optional(), accessTokenTTL: z.number().int().min(0).max(315360000).optional().describe(LDAP_AUTH.UPDATE.accessTokenTTL),
accessTokenMaxTTL: z.number().int().max(315360000).min(0).optional() accessTokenNumUsesLimit: z
.number()
.int()
.min(0)
.optional()
.describe(LDAP_AUTH.UPDATE.accessTokenNumUsesLimit),
accessTokenMaxTTL: z
.number()
.int()
.max(315360000)
.min(0)
.optional()
.describe(LDAP_AUTH.UPDATE.accessTokenMaxTTL)
}) })
.refine( .refine(
(val) => (val.accessTokenMaxTTL && val.accessTokenTTL ? val.accessTokenTTL <= val.accessTokenMaxTTL : true), (val) => (val.accessTokenMaxTTL && val.accessTokenTTL ? val.accessTokenTTL <= val.accessTokenMaxTTL : true),
@@ -370,7 +389,7 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
} }
], ],
params: z.object({ params: z.object({
identityId: z.string() identityId: z.string().trim().describe(LDAP_AUTH.RETRIEVE.identityId)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -427,7 +446,7 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
} }
], ],
params: z.object({ params: z.object({
identityId: z.string() identityId: z.string().trim().describe(LDAP_AUTH.REVOKE.identityId)
}), }),
response: { response: {
200: z.object({ 200: z.object({

View File

@@ -88,7 +88,6 @@ export const identityLdapAuthServiceFactory = ({
url: ldapAuth.url, url: ldapAuth.url,
bindDN, bindDN,
bindPass, bindPass,
uniqueUserAttribute: ldapAuth.uniqueAttribute,
searchBase: ldapAuth.searchBase, searchBase: ldapAuth.searchBase,
searchFilter: ldapAuth.searchFilter, searchFilter: ldapAuth.searchFilter,
caCert: ldapCaCertificate || "", caCert: ldapCaCertificate || "",
@@ -100,9 +99,8 @@ export const identityLdapAuthServiceFactory = ({
url: ldapAuth.url, url: ldapAuth.url,
bindDN, bindDN,
bindCredentials: bindPass, bindCredentials: bindPass,
uniqueUserAttribute: ldapAuth.uniqueAttribute,
searchBase: ldapAuth.searchBase, searchBase: ldapAuth.searchBase,
searchFilter: ldapAuth.searchFilter || "(uid={{username}})", searchFilter: ldapAuth.searchFilter,
...(ldapCaCertificate ...(ldapCaCertificate
? { ? {
tlsOptions: { tlsOptions: {
@@ -178,7 +176,6 @@ export const identityLdapAuthServiceFactory = ({
url, url,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
bindDN, bindDN,
bindPass, bindPass,
ldapCaCertificate, ldapCaCertificate,
@@ -287,7 +284,6 @@ export const identityLdapAuthServiceFactory = ({
encryptedBindPass, encryptedBindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
url, url,
encryptedLdapCaCertificate, encryptedLdapCaCertificate,
accessTokenMaxTTL, accessTokenMaxTTL,
@@ -308,7 +304,6 @@ export const identityLdapAuthServiceFactory = ({
url, url,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
bindDN, bindDN,
bindPass, bindPass,
ldapCaCertificate, ldapCaCertificate,
@@ -428,7 +423,6 @@ export const identityLdapAuthServiceFactory = ({
url, url,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
encryptedBindDN, encryptedBindDN,
encryptedBindPass, encryptedBindPass,
encryptedLdapCaCertificate, encryptedLdapCaCertificate,

View File

@@ -17,7 +17,6 @@ export type TAttachLdapAuthDTO = {
url: string; url: string;
searchBase: string; searchBase: string;
searchFilter: string; searchFilter: string;
uniqueAttribute: string;
bindDN: string; bindDN: string;
bindPass: string; bindPass: string;
ldapCaCertificate?: string; ldapCaCertificate?: string;
@@ -34,7 +33,6 @@ export type TUpdateLdapAuthDTO = {
url?: string; url?: string;
searchBase?: string; searchBase?: string;
searchFilter?: string; searchFilter?: string;
uniqueAttribute?: string;
bindDN?: string; bindDN?: string;
bindPass?: string; bindPass?: string;
allowedFields?: TAllowedFields[]; allowedFields?: TAllowedFields[];

View File

@@ -1064,7 +1064,6 @@ export const useAddIdentityLdapAuth = () => {
bindPass, bindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
accessTokenTTL, accessTokenTTL,
@@ -1080,7 +1079,6 @@ export const useAddIdentityLdapAuth = () => {
bindPass, bindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
accessTokenTTL, accessTokenTTL,
@@ -1113,7 +1111,6 @@ export const useUpdateIdentityLdapAuth = () => {
bindPass, bindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
accessTokenTTL, accessTokenTTL,
@@ -1129,7 +1126,6 @@ export const useUpdateIdentityLdapAuth = () => {
bindPass, bindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
accessTokenTTL, accessTokenTTL,

View File

@@ -433,7 +433,6 @@ export type AddIdentityLdapAuthDTO = {
bindPass: string; bindPass: string;
searchBase: string; searchBase: string;
searchFilter: string; searchFilter: string;
uniqueAttribute: string;
ldapCaCertificate?: string; ldapCaCertificate?: string;
allowedFields?: { allowedFields?: {
key: string; key: string;
@@ -455,7 +454,6 @@ export type UpdateIdentityLdapAuthDTO = {
bindPass?: string; bindPass?: string;
searchBase?: string; searchBase?: string;
searchFilter?: string; searchFilter?: string;
uniqueAttribute?: string;
ldapCaCertificate?: string; ldapCaCertificate?: string;
allowedFields?: { allowedFields?: {
key: string; key: string;
@@ -480,7 +478,6 @@ export type IdentityLdapAuth = {
bindPass: string; bindPass: string;
searchBase: string; searchBase: string;
searchFilter: string; searchFilter: string;
uniqueAttribute: string;
ldapCaCertificate?: string; ldapCaCertificate?: string;
allowedFields?: { allowedFields?: {
key: string; key: string;

View File

@@ -35,7 +35,6 @@ const schema = z
bindDN: z.string(), bindDN: z.string(),
bindPass: z.string(), bindPass: z.string(),
searchBase: z.string(), searchBase: z.string(),
uniqueAttribute: z.string(), // defaults to uidNumber
searchFilter: z.string(), // defaults to (uid={{username}}) searchFilter: z.string(), // defaults to (uid={{username}})
ldapCaCertificate: z ldapCaCertificate: z
.string() .string()
@@ -112,7 +111,6 @@ export const IdentityLdapAuthForm = ({
bindDN: "", bindDN: "",
bindPass: "", bindPass: "",
searchBase: "", searchBase: "",
uniqueAttribute: "uidNumber",
searchFilter: "(uid={{username}})", searchFilter: "(uid={{username}})",
accessTokenTTL: "2592000", accessTokenTTL: "2592000",
accessTokenMaxTTL: "2592000", accessTokenMaxTTL: "2592000",
@@ -140,7 +138,6 @@ export const IdentityLdapAuthForm = ({
bindDN: data.bindDN, bindDN: data.bindDN,
bindPass: data.bindPass, bindPass: data.bindPass,
searchBase: data.searchBase, searchBase: data.searchBase,
uniqueAttribute: data.uniqueAttribute,
searchFilter: data.searchFilter, searchFilter: data.searchFilter,
ldapCaCertificate: data.ldapCaCertificate || undefined, ldapCaCertificate: data.ldapCaCertificate || undefined,
allowedFields: data.allowedFields, allowedFields: data.allowedFields,
@@ -161,7 +158,6 @@ export const IdentityLdapAuthForm = ({
bindDN: "", bindDN: "",
bindPass: "", bindPass: "",
searchBase: "", searchBase: "",
uniqueAttribute: "uidNumber",
searchFilter: "(uid={{username}})", searchFilter: "(uid={{username}})",
ldapCaCertificate: undefined, ldapCaCertificate: undefined,
allowedFields: [], allowedFields: [],
@@ -185,7 +181,6 @@ export const IdentityLdapAuthForm = ({
bindDN, bindDN,
bindPass, bindPass,
searchBase, searchBase,
uniqueAttribute,
searchFilter, searchFilter,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
@@ -206,7 +201,6 @@ export const IdentityLdapAuthForm = ({
bindPass, bindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
accessTokenTTL: Number(accessTokenTTL), accessTokenTTL: Number(accessTokenTTL),
@@ -223,7 +217,6 @@ export const IdentityLdapAuthForm = ({
bindPass, bindPass,
searchBase, searchBase,
searchFilter, searchFilter,
uniqueAttribute,
ldapCaCertificate, ldapCaCertificate,
allowedFields, allowedFields,
accessTokenTTL: Number(accessTokenTTL), accessTokenTTL: Number(accessTokenTTL),
@@ -259,8 +252,8 @@ export const IdentityLdapAuthForm = ({
"bindPass", "bindPass",
"searchBase", "searchBase",
"searchFilter", "searchFilter",
"uniqueAttribute",
"accessTokenTTL", "accessTokenTTL",
"allowedFields",
"accessTokenMaxTTL", "accessTokenMaxTTL",
"accessTokenNumUsesLimit" "accessTokenNumUsesLimit"
].includes(Object.keys(fields)[0]) ].includes(Object.keys(fields)[0])
@@ -334,21 +327,6 @@ export const IdentityLdapAuthForm = ({
)} )}
/> />
<Controller
control={control}
name="uniqueAttribute"
render={({ field, fieldState: { error } }) => (
<FormControl
isRequired
label="Unique User Attribute"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="uidNumber" />
</FormControl>
)}
/>
<Controller <Controller
control={control} control={control}
name="searchFilter" name="searchFilter"
@@ -364,69 +342,6 @@ export const IdentityLdapAuthForm = ({
)} )}
/> />
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
tooltipText="The lifetime for an acccess token in seconds. This value will be referenced at renewal time."
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="0" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum lifetime for an access token in seconds. This value will be referenced at renewal time."
>
<Input {...field} placeholder="2592000" type="number" min="0" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses."
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
</TabPanel>
<TabPanel value={IdentityFormTab.Advanced}>
<Controller
control={control}
name="ldapCaCertificate"
render={({ field, fieldState: { error } }) => (
<FormControl
label="CA Certificate"
isOptional
errorText={error?.message}
isError={Boolean(error)}
tooltipText="An optional PEM-encoded CA cert for the LDAP server. This is used by the TLS client for secure communication with the LDAP server."
>
<TextArea {...field} placeholder="-----BEGIN CERTIFICATE----- ..." />
</FormControl>
)}
/>
{allowedFieldsFields.map(({ id }, index) => ( {allowedFieldsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}> <div className="mb-3 flex items-end space-x-2" key={id}>
<Controller <Controller
@@ -535,6 +450,69 @@ export const IdentityLdapAuthForm = ({
</Button> </Button>
</div> </div>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
tooltipText="The lifetime for an acccess token in seconds. This value will be referenced at renewal time."
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="0" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum lifetime for an access token in seconds. This value will be referenced at renewal time."
>
<Input {...field} placeholder="2592000" type="number" min="0" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses."
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
</TabPanel>
<TabPanel value={IdentityFormTab.Advanced}>
<Controller
control={control}
name="ldapCaCertificate"
render={({ field, fieldState: { error } }) => (
<FormControl
label="CA Certificate"
isOptional
errorText={error?.message}
isError={Boolean(error)}
tooltipText="An optional PEM-encoded CA cert for the LDAP server. This is used by the TLS client for secure communication with the LDAP server."
>
<TextArea {...field} placeholder="-----BEGIN CERTIFICATE----- ..." />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => ( {accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}> <div className="mb-3 flex items-end space-x-2" key={id}>
<Controller <Controller

View File

@@ -79,9 +79,6 @@ export const ViewIdentityLdapAuthContent = ({
<IdentityAuthFieldDisplay label="Search Base / DN"> <IdentityAuthFieldDisplay label="Search Base / DN">
{data.searchBase} {data.searchBase}
</IdentityAuthFieldDisplay> </IdentityAuthFieldDisplay>
<IdentityAuthFieldDisplay label="Unique Attribute">
{data.uniqueAttribute}
</IdentityAuthFieldDisplay>
<IdentityAuthFieldDisplay label="Search Filter">{data.searchFilter}</IdentityAuthFieldDisplay> <IdentityAuthFieldDisplay label="Search Filter">{data.searchFilter}</IdentityAuthFieldDisplay>
<IdentityAuthFieldDisplay label="CA Certificate"> <IdentityAuthFieldDisplay label="CA Certificate">
{data.ldapCaCertificate && ( {data.ldapCaCertificate && (