From 7e75a27f68c253be95b591b912dfd72ce5105296 Mon Sep 17 00:00:00 2001 From: Vault Automation Date: Wed, 15 Apr 2026 15:15:59 -0400 Subject: [PATCH] [UI][Bugfix] VAULT-43725 Add validations for LDAP roles create / edit forms (#13757) (#13863) (#13964) * LDAP create role name field should only contain lowercase and alphanumeric characters * Add changelog.. * Fix controller issue Co-authored-by: Kianna <30884335+kiannaquach@users.noreply.github.com> --- changelog/_13757.txt | 3 +++ ui/app/forms/secrets/ldap/roles/dynamic.ts | 13 ++++++++++++- ui/app/forms/secrets/ldap/roles/static.ts | 17 ++++++++++++++--- ui/lib/ldap/addon/routes/error.ts | 8 +++++--- 4 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 changelog/_13757.txt diff --git a/changelog/_13757.txt b/changelog/_13757.txt new file mode 100644 index 0000000000..ce698a493b --- /dev/null +++ b/changelog/_13757.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: Add name field validation to LDAP create and edit roles forms. +``` \ No newline at end of file diff --git a/ui/app/forms/secrets/ldap/roles/dynamic.ts b/ui/app/forms/secrets/ldap/roles/dynamic.ts index 7021832646..226743c24b 100644 --- a/ui/app/forms/secrets/ldap/roles/dynamic.ts +++ b/ui/app/forms/secrets/ldap/roles/dynamic.ts @@ -84,7 +84,18 @@ export default class LdapDynamicRoleForm extends Form { ]; validations: Validations = { - name: [{ type: 'presence', message: 'Name is required' }], + name: [ + { type: 'presence', message: 'Name is required' }, + { + validator: ({ name }: LdapDynamicRoleFormData) => { + // Allow alphanumeric, hyphens, underscores, periods, and forward slashes + const validPattern = /^[a-z0-9\-_./]+$/; + return validPattern.test(name); + }, + message: + 'Name must be lowercase and can only contain alphanumeric characters, hyphens, underscores, periods, and forward slashes.', + }, + ], creation_ldif: [{ type: 'presence', message: 'Creation LDIF is required.' }], deletion_ldif: [{ type: 'presence', message: 'Deletion LDIF is required.' }], }; diff --git a/ui/app/forms/secrets/ldap/roles/static.ts b/ui/app/forms/secrets/ldap/roles/static.ts index 33c6b36372..ad46ae055d 100644 --- a/ui/app/forms/secrets/ldap/roles/static.ts +++ b/ui/app/forms/secrets/ldap/roles/static.ts @@ -8,11 +8,11 @@ import FormField from 'vault/utils/forms/field'; import type { Validations } from 'vault/app-types'; import type { LdapWriteStaticRoleRequest } from '@hashicorp/vault-client-typescript'; -type LdapDynamicRoleFormData = LdapWriteStaticRoleRequest & { +type LdapStaticRoleFormData = LdapWriteStaticRoleRequest & { name: string; }; -export default class LdapStaticRoleForm extends Form { +export default class LdapStaticRoleForm extends Form { formFields = [ new FormField('name', 'string', { label: 'Role name', @@ -38,7 +38,18 @@ export default class LdapStaticRoleForm extends Form { ]; validations: Validations = { - name: [{ type: 'presence', message: 'Name is required' }], + name: [ + { type: 'presence', message: 'Name is required' }, + { + validator: ({ name }: LdapStaticRoleFormData) => { + // Allow alphanumeric, hyphens, underscores, periods, and forward slashes + const validPattern = /^[a-z0-9\-_./]+$/; + return validPattern.test(name); + }, + message: + 'Name must be lowercase and can only contain alphanumeric characters, hyphens, underscores, periods, and forward slashes.', + }, + ], username: [{ type: 'presence', message: 'Username is required.' }], rotation_period: [{ type: 'presence', message: 'Rotation Period is required.' }], }; diff --git a/ui/lib/ldap/addon/routes/error.ts b/ui/lib/ldap/addon/routes/error.ts index 59fac854c5..9cd1cc79c3 100644 --- a/ui/lib/ldap/addon/routes/error.ts +++ b/ui/lib/ldap/addon/routes/error.ts @@ -8,14 +8,15 @@ import { service } from '@ember/service'; import type Transition from '@ember/routing/transition'; import type AdapterError from '@ember-data/adapter/error'; -import type SecretEngineModel from 'vault/models/secret-engine'; +import type SecretsEngineResource from 'vault/resources/secrets/engine'; import type { Breadcrumb } from 'vault/vault/app-types'; import type Controller from '@ember/controller'; import type SecretMountPath from 'vault/services/secret-mount-path'; +import type { LdapApplicationModel } from './application'; interface LdapErrorController extends Controller { breadcrumbs: Array; - backend: SecretEngineModel; + backend: SecretsEngineResource; } export default class LdapErrorRoute extends Route { @@ -28,6 +29,7 @@ export default class LdapErrorRoute extends Route { { label: 'Secrets engines', route: 'secrets', linkExternal: true }, { label: this.secretMountPath.currentPath, route: 'overview' }, ]; - controller.backend = this.modelFor('application') as SecretEngineModel; + const { secretsEngine } = this.modelFor('application') as LdapApplicationModel; + controller.backend = secretsEngine; } }