better password validator for open search
This commit is contained in:
parent
0bc7d57063
commit
e0e9e7507d
3 changed files with 36 additions and 22 deletions
|
|
@ -34,7 +34,8 @@ dependencies = [
|
|||
"structlog>=25.4.0",
|
||||
"docling-serve==1.5.0",
|
||||
"docling-core==2.48.1",
|
||||
"easyocr>=1.7.1; sys_platform != 'darwin'"
|
||||
"easyocr>=1.7.1; sys_platform != 'darwin'",
|
||||
"zxcvbn>=4.5.0"
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Configuration screen for OpenRAG TUI."""
|
||||
|
||||
import re
|
||||
from zxcvbn import zxcvbn
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Container, Vertical, Horizontal, ScrollableContainer
|
||||
from textual.screen import Screen
|
||||
|
|
@ -98,35 +99,36 @@ class DocumentsPathValidator(Validator):
|
|||
|
||||
|
||||
class PasswordValidator(Validator):
|
||||
"""Validator for OpenSearch admin password."""
|
||||
"""Validator for OpenSearch admin password using zxcvbn strength estimation."""
|
||||
|
||||
# Minimum acceptable score (0-4 scale: 0=weak, 4=very strong)
|
||||
MIN_SCORE = 3
|
||||
|
||||
def validate(self, value: str) -> ValidationResult:
|
||||
# Allow empty value (will be auto-generated)
|
||||
if not value:
|
||||
return self.success()
|
||||
|
||||
# Minimum length: 8 characters
|
||||
if len(value) < 8:
|
||||
return self.failure("Password must be at least 8 characters long")
|
||||
# Use zxcvbn to evaluate password strength
|
||||
result = zxcvbn(value)
|
||||
score = result["score"]
|
||||
|
||||
# Check for required character types
|
||||
has_uppercase = bool(re.search(r"[A-Z]", value))
|
||||
has_lowercase = bool(re.search(r"[a-z]", value))
|
||||
has_digit = bool(re.search(r"[0-9]", value))
|
||||
has_special = bool(re.search(r"[!@#$%^&*()_+\-=\[\]{};':\"\\|,.<>/?]", value))
|
||||
if score < self.MIN_SCORE:
|
||||
# Get feedback from zxcvbn
|
||||
feedback = result.get("feedback", {})
|
||||
warning = feedback.get("warning", "")
|
||||
suggestions = feedback.get("suggestions", [])
|
||||
|
||||
missing = []
|
||||
if not has_uppercase:
|
||||
missing.append("uppercase letter")
|
||||
if not has_lowercase:
|
||||
missing.append("lowercase letter")
|
||||
if not has_digit:
|
||||
missing.append("digit")
|
||||
if not has_special:
|
||||
missing.append("special character")
|
||||
# Build error message
|
||||
strength_labels = ["very weak", "weak", "fair", "strong", "very strong"]
|
||||
current_strength = strength_labels[score]
|
||||
|
||||
if missing:
|
||||
return self.failure(f"Password must contain: {', '.join(missing)}")
|
||||
if warning:
|
||||
return self.failure(f"Password is {current_strength}: {warning}")
|
||||
elif suggestions:
|
||||
return self.failure(f"Password is {current_strength}. {suggestions[0]}")
|
||||
else:
|
||||
return self.failure(f"Password is {current_strength}. Use a longer, more unique password.")
|
||||
|
||||
return self.success()
|
||||
|
||||
|
|
@ -200,7 +202,7 @@ class ConfigScreen(Screen):
|
|||
# OpenSearch Admin Password
|
||||
yield Label("OpenSearch Admin Password *")
|
||||
yield Static(
|
||||
"Min 8 chars with uppercase, lowercase, digit, and special character",
|
||||
"Validate your password here: https://lowe.github.io/tryzxcvbn/",
|
||||
classes="helper-text",
|
||||
)
|
||||
current_value = getattr(self.env_manager.config, "opensearch_password", "")
|
||||
|
|
|
|||
11
uv.lock
generated
11
uv.lock
generated
|
|
@ -2383,6 +2383,7 @@ dependencies = [
|
|||
{ name = "torch", version = "2.7.1+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "torch", version = "2.8.0", source = { registry = "https://pypi.org/simple" }, marker = "platform_machine != 'x86_64' or sys_platform != 'linux'" },
|
||||
{ name = "uvicorn" },
|
||||
{ name = "zxcvbn" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
|
|
@ -2422,6 +2423,7 @@ requires-dist = [
|
|||
{ name = "torch", marker = "platform_machine != 'x86_64' or sys_platform != 'linux'", specifier = ">=2.7.1" },
|
||||
{ name = "torch", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'", specifier = ">=2.7.1", index = "https://download.pytorch.org/whl/cu128" },
|
||||
{ name = "uvicorn", specifier = ">=0.35.0" },
|
||||
{ name = "zxcvbn", specifier = ">=4.5.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
|
|
@ -4173,3 +4175,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50e
|
|||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zxcvbn"
|
||||
version = "4.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ae/40/9366940b1484fd4e9423c8decbbf34a73bf52badb36281e082fe02b57aca/zxcvbn-4.5.0.tar.gz", hash = "sha256:70392c0fff39459d7f55d0211151401e79e76fcc6e2c22b61add62900359c7c1", size = 411249, upload-time = "2025-02-19T19:03:02.699Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/16/7410f8e714a109d43d17f4e27c8eabb351557653a9b570db1bd7dfdfd822/zxcvbn-4.5.0-py2.py3-none-any.whl", hash = "sha256:2b6eed621612ce6d65e6e4c7455b966acee87d0280e257956b1f06ccc66bd5ff", size = 409397, upload-time = "2025-02-19T19:03:00.521Z" },
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue