mirror of
https://github.com/taylanbakircioglu/haproxy-openmanager.git
synced 2026-09-21 01:53:24 +00:00
fix: allow dot character in entity names for UI and backend validation
Bulk import accepted dots in frontend/backend/server names but UI and backend validators rejected them with ^[a-zA-Z0-9_-]+$. After import, entities with dots could not be edited. HAProxy itself allows dots in section names, so the regex is expanded to ^[a-zA-Z0-9_.-]+$ across all 12 validation points (5 React form rules, 1 ACL char-strip, 3 Pydantic validators, 1 WAF validator, 2 config-validator warnings).
This commit is contained in:
@@ -108,8 +108,8 @@ class FrontendConfig(BaseModel):
|
||||
raise ValueError('Frontend name cannot be empty')
|
||||
|
||||
# HAProxy names cannot contain spaces or special characters
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+$', v.strip()):
|
||||
raise ValueError('Frontend name can only contain letters, numbers, underscore (_) and dash (-). Spaces and special characters are not allowed.')
|
||||
if not re.match(r'^[a-zA-Z0-9_.-]+$', v.strip()):
|
||||
raise ValueError('Frontend name can only contain letters, numbers, dot (.), underscore (_) and dash (-). Spaces and special characters are not allowed.')
|
||||
|
||||
if len(v.strip()) > 50:
|
||||
raise ValueError('Frontend name cannot exceed 50 characters')
|
||||
@@ -147,8 +147,8 @@ class FrontendConfig(BaseModel):
|
||||
|
||||
@validator('default_backend')
|
||||
def validate_default_backend(cls, v):
|
||||
if v and not re.match(r'^[a-zA-Z0-9_-]+$', v.strip()):
|
||||
raise ValueError('Default backend name can only contain letters, numbers, underscore (_) and dash (-)')
|
||||
if v and not re.match(r'^[a-zA-Z0-9_.-]+$', v.strip()):
|
||||
raise ValueError('Default backend name can only contain letters, numbers, dot (.), underscore (_) and dash (-)')
|
||||
return v.strip() if v else None
|
||||
|
||||
@validator('ssl_certificate_id')
|
||||
@@ -288,7 +288,7 @@ class FrontendConfig(BaseModel):
|
||||
continue
|
||||
|
||||
# Basic ACL syntax validation
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+\s+', rule):
|
||||
if not re.match(r'^[a-zA-Z0-9_.-]+\s+', rule):
|
||||
raise ValueError(f'Invalid ACL rule syntax: "{rule}". Must start with ACL name followed by condition.')
|
||||
|
||||
# Check for dangerous patterns
|
||||
|
||||
@@ -22,8 +22,8 @@ class WAFRule(BaseModel):
|
||||
raise ValueError('WAF rule name cannot be empty')
|
||||
|
||||
# HAProxy ACL names cannot contain spaces or special characters
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+$', v.strip()):
|
||||
raise ValueError('WAF rule name can only contain letters, numbers, underscore (_) and dash (-). Spaces and special characters are not allowed.')
|
||||
if not re.match(r'^[a-zA-Z0-9_.-]+$', v.strip()):
|
||||
raise ValueError('WAF rule name can only contain letters, numbers, dot (.), underscore (_) and dash (-). Spaces and special characters are not allowed.')
|
||||
|
||||
if len(v.strip()) > 50:
|
||||
raise ValueError('WAF rule name cannot exceed 50 characters')
|
||||
|
||||
@@ -156,11 +156,11 @@ class HAProxyConfigValidator:
|
||||
section_name = parts[1]
|
||||
|
||||
# Check name format
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+$', section_name):
|
||||
if not re.match(r'^[a-zA-Z0-9_.-]+$', section_name):
|
||||
self._add_result(
|
||||
ValidationLevel.WARNING,
|
||||
f"Section name '{section_name}' contains invalid characters",
|
||||
suggestion="Use only letters, numbers, underscore and hyphen"
|
||||
suggestion="Use only letters, numbers, dot, underscore and hyphen"
|
||||
)
|
||||
|
||||
# Set current section for validation
|
||||
@@ -265,12 +265,12 @@ class HAProxyConfigValidator:
|
||||
server_addr = args[1]
|
||||
|
||||
# Check server name format
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+$', server_name):
|
||||
if not re.match(r'^[a-zA-Z0-9_.-]+$', server_name):
|
||||
self._add_result(
|
||||
ValidationLevel.WARNING,
|
||||
f"Server name '{server_name}' contains invalid characters",
|
||||
directive="server",
|
||||
suggestion="Use only letters, numbers, underscore and hyphen"
|
||||
suggestion="Use only letters, numbers, dot, underscore and hyphen"
|
||||
)
|
||||
|
||||
# Check address format
|
||||
|
||||
@@ -313,7 +313,7 @@ function ACLDefinitionCard({ rule, index, onChange, onDelete }) {
|
||||
<Col flex="140px">
|
||||
<Input
|
||||
value={rule.name}
|
||||
onChange={(e) => onChange(index, { ...rule, name: e.target.value.replace(/[^a-zA-Z0-9_-]/g, '') })}
|
||||
onChange={(e) => onChange(index, { ...rule, name: e.target.value.replace(/[^a-zA-Z0-9_.-]/g, '') })}
|
||||
placeholder="acl_name"
|
||||
size="small"
|
||||
addonBefore={<FilterOutlined style={{ fontSize: 11 }} />}
|
||||
|
||||
@@ -1646,7 +1646,7 @@ const BackendServers = () => {
|
||||
label="Backend Name"
|
||||
rules={[
|
||||
{ required: true, message: 'Please enter backend name' },
|
||||
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
|
||||
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
|
||||
]}
|
||||
>
|
||||
<Input placeholder="e.g., web_servers" />
|
||||
@@ -1939,7 +1939,7 @@ const BackendServers = () => {
|
||||
label="Server Name"
|
||||
rules={[
|
||||
{ required: true, message: 'Please enter server name' },
|
||||
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
|
||||
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
|
||||
]}
|
||||
>
|
||||
<Input placeholder="e.g., web1" />
|
||||
|
||||
@@ -1381,7 +1381,7 @@ const FrontendManagement = () => {
|
||||
extra="Unique identifier for this frontend"
|
||||
rules={[
|
||||
{ required: true, message: 'Please enter frontend name' },
|
||||
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
|
||||
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
|
||||
]}
|
||||
>
|
||||
<Input placeholder="e.g., main_frontend" />
|
||||
|
||||
@@ -934,7 +934,7 @@ const SSLManagement = () => {
|
||||
label="Certificate Name"
|
||||
rules={[
|
||||
{ required: true, message: 'Please enter certificate name' },
|
||||
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
|
||||
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
|
||||
]}
|
||||
extra={selectedCertificate && selectedCertificate.id ? "Certificate name cannot be changed (used as file path on servers)" : "Used as file path: /etc/ssl/haproxy/{name}.pem"}
|
||||
tooltip={selectedCertificate && selectedCertificate.id ? "Certificate name is immutable after creation to maintain file system references" : null}
|
||||
|
||||
@@ -1442,7 +1442,7 @@ const WAFManagement = () => {
|
||||
label="Rule Name"
|
||||
rules={[
|
||||
{ required: true, message: 'Please enter rule name' },
|
||||
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
|
||||
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
|
||||
]}
|
||||
>
|
||||
<Input placeholder="e.g., api_rate_limit" />
|
||||
|
||||
Reference in New Issue
Block a user