Initial commit: ROA2WEB - FastAPI + Vue.js + Telegram Bot
Modern ERP Reports Application with microservices architecture Tech Stack: - Backend: FastAPI + python-oracledb (Oracle DB integration) - Frontend: Vue.js 3 + PrimeVue + Vite - Telegram Bot: python-telegram-bot + SQLite - Infrastructure: Shared database pool, JWT authentication, SSH tunnel Features: - FastAPI backend with async Oracle connection pool - Vue.js 3 responsive frontend with PrimeVue components - Telegram bot alternative interface - Microservices architecture with shared components - Complete deployment support (Linux Docker + Windows IIS) - Comprehensive testing (Playwright E2E + pytest) Repository Structure: - reports-app/ - Main application (backend, frontend, telegram-bot) - shared/ - Shared components (database pool, auth, utils) - deployment/ - Deployment scripts (Linux & Windows) - docs/ - Project documentation - security/ - Security scanning and git hooks
This commit is contained in:
283
security/validate_security.py
Normal file
283
security/validate_security.py
Normal file
@@ -0,0 +1,283 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
🔍 ROA2WEB Security Validation Tool
|
||||
Validates that all security measures are properly implemented and functioning.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
class SecurityValidator:
|
||||
"""Validates security implementation"""
|
||||
|
||||
def __init__(self, repo_path: str = "."):
|
||||
self.repo_path = Path(repo_path)
|
||||
self.errors = []
|
||||
self.warnings = []
|
||||
self.checks_passed = 0
|
||||
self.total_checks = 0
|
||||
|
||||
def check(self, condition: bool, success_msg: str, error_msg: str, is_warning: bool = False):
|
||||
"""Check a condition and track results"""
|
||||
self.total_checks += 1
|
||||
if condition:
|
||||
print(f"✅ {success_msg}")
|
||||
self.checks_passed += 1
|
||||
else:
|
||||
if is_warning:
|
||||
print(f"⚠️ {error_msg}")
|
||||
self.warnings.append(error_msg)
|
||||
else:
|
||||
print(f"❌ {error_msg}")
|
||||
self.errors.append(error_msg)
|
||||
|
||||
def validate_files_exist(self):
|
||||
"""Validate that all security files exist"""
|
||||
print("\n🔍 Checking Security Files...")
|
||||
|
||||
required_files = [
|
||||
"security/secrets_scanner.py",
|
||||
"security/git_cleanup.py",
|
||||
"security/install_hooks.sh",
|
||||
"security/setup_security.sh",
|
||||
"security/git_hooks/pre-commit",
|
||||
"security/git_hooks/commit-msg",
|
||||
"security/README.md",
|
||||
"security/SECURITY_PROCEDURES.md"
|
||||
]
|
||||
|
||||
for file_path in required_files:
|
||||
full_path = self.repo_path / file_path
|
||||
self.check(
|
||||
full_path.exists(),
|
||||
f"Security file exists: {file_path}",
|
||||
f"Missing security file: {file_path}"
|
||||
)
|
||||
|
||||
def validate_gitignore(self):
|
||||
"""Validate .gitignore security patterns"""
|
||||
print("\n🛡️ Checking .gitignore Security...")
|
||||
|
||||
gitignore_path = self.repo_path / ".gitignore"
|
||||
|
||||
if not gitignore_path.exists():
|
||||
self.check(False, "", ".gitignore file missing")
|
||||
return
|
||||
|
||||
with open(gitignore_path, 'r') as f:
|
||||
gitignore_content = f.read()
|
||||
|
||||
critical_patterns = [
|
||||
"*.env.*",
|
||||
"!.env.example",
|
||||
"*.pem",
|
||||
"*.key",
|
||||
"*secret*",
|
||||
"*credential*",
|
||||
"*password*",
|
||||
".serena/cache/",
|
||||
".serena/memories/"
|
||||
]
|
||||
|
||||
for pattern in critical_patterns:
|
||||
self.check(
|
||||
pattern in gitignore_content,
|
||||
f"Security pattern in .gitignore: {pattern}",
|
||||
f"Missing .gitignore pattern: {pattern}",
|
||||
is_warning=True
|
||||
)
|
||||
|
||||
def validate_git_hooks(self):
|
||||
"""Validate git hooks installation"""
|
||||
print("\n🪝 Checking Git Hooks...")
|
||||
|
||||
hooks_dir = self.repo_path / ".git" / "hooks"
|
||||
|
||||
self.check(
|
||||
hooks_dir.exists(),
|
||||
"Git hooks directory exists",
|
||||
"Git hooks directory missing"
|
||||
)
|
||||
|
||||
required_hooks = ["pre-commit", "commit-msg"]
|
||||
|
||||
for hook in required_hooks:
|
||||
hook_path = hooks_dir / hook
|
||||
self.check(
|
||||
hook_path.exists(),
|
||||
f"Git hook installed: {hook}",
|
||||
f"Git hook missing: {hook}"
|
||||
)
|
||||
|
||||
if hook_path.exists():
|
||||
self.check(
|
||||
os.access(hook_path, os.X_OK),
|
||||
f"Git hook executable: {hook}",
|
||||
f"Git hook not executable: {hook}"
|
||||
)
|
||||
|
||||
def validate_scripts_executable(self):
|
||||
"""Validate that scripts are executable"""
|
||||
print("\n🔧 Checking Script Permissions...")
|
||||
|
||||
executable_scripts = [
|
||||
"security/secrets_scanner.py",
|
||||
"security/git_cleanup.py",
|
||||
"security/install_hooks.sh",
|
||||
"security/setup_security.sh"
|
||||
]
|
||||
|
||||
for script in executable_scripts:
|
||||
script_path = self.repo_path / script
|
||||
if script_path.exists():
|
||||
self.check(
|
||||
os.access(script_path, os.X_OK),
|
||||
f"Script executable: {script}",
|
||||
f"Script not executable: {script}"
|
||||
)
|
||||
|
||||
def validate_scanner_functionality(self):
|
||||
"""Validate scanner can run"""
|
||||
print("\n🔍 Testing Security Scanner...")
|
||||
|
||||
try:
|
||||
# Import and test scanner
|
||||
sys.path.append(str(self.repo_path))
|
||||
import security.secrets_scanner as scanner
|
||||
|
||||
s = scanner.SecretsScanner(self.repo_path)
|
||||
self.check(
|
||||
len(s.CRITICAL_PATTERNS) > 0,
|
||||
f"Scanner patterns loaded: {len(s.CRITICAL_PATTERNS)} patterns",
|
||||
"Scanner patterns not loaded"
|
||||
)
|
||||
|
||||
self.check(
|
||||
len(s.SUSPICIOUS_FILES) > 0,
|
||||
f"Scanner file patterns loaded: {len(s.SUSPICIOUS_FILES)} patterns",
|
||||
"Scanner file patterns not loaded"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.check(
|
||||
False,
|
||||
"Scanner functionality test passed",
|
||||
f"Scanner functionality test failed: {e}"
|
||||
)
|
||||
|
||||
def validate_git_repository(self):
|
||||
"""Validate git repository status"""
|
||||
print("\n📦 Checking Git Repository...")
|
||||
|
||||
try:
|
||||
# Check if in git repo
|
||||
result = subprocess.run(
|
||||
['git', 'status'],
|
||||
cwd=self.repo_path,
|
||||
capture_output=True,
|
||||
check=True
|
||||
)
|
||||
|
||||
self.check(
|
||||
True,
|
||||
"Git repository status OK",
|
||||
"Git repository issues detected"
|
||||
)
|
||||
|
||||
except subprocess.CalledProcessError:
|
||||
self.check(
|
||||
False,
|
||||
"Git repository status OK",
|
||||
"Not in a valid git repository"
|
||||
)
|
||||
|
||||
def check_environment_files(self):
|
||||
"""Check for environment files that should be protected"""
|
||||
print("\n🔐 Checking Environment Files...")
|
||||
|
||||
# Find .env files
|
||||
env_files = []
|
||||
for root, dirs, files in os.walk(self.repo_path):
|
||||
for file in files:
|
||||
if file.endswith('.env') and not file.endswith('.env.example'):
|
||||
rel_path = os.path.relpath(os.path.join(root, file), self.repo_path)
|
||||
env_files.append(rel_path)
|
||||
|
||||
for env_file in env_files:
|
||||
# Check if file is in git tracking
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['git', 'ls-files', env_file],
|
||||
cwd=self.repo_path,
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
|
||||
if result.stdout.strip():
|
||||
self.check(
|
||||
False,
|
||||
"",
|
||||
f"Environment file tracked in git: {env_file}",
|
||||
is_warning=True
|
||||
)
|
||||
else:
|
||||
self.check(
|
||||
True,
|
||||
f"Environment file properly ignored: {env_file}",
|
||||
""
|
||||
)
|
||||
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
|
||||
def run_validation(self):
|
||||
"""Run complete security validation"""
|
||||
print("🔒 ROA2WEB Security Validation")
|
||||
print("=" * 50)
|
||||
|
||||
self.validate_files_exist()
|
||||
self.validate_gitignore()
|
||||
self.validate_git_hooks()
|
||||
self.validate_scripts_executable()
|
||||
self.validate_scanner_functionality()
|
||||
self.validate_git_repository()
|
||||
self.check_environment_files()
|
||||
|
||||
# Print summary
|
||||
print("\n" + "=" * 50)
|
||||
print("📊 VALIDATION SUMMARY")
|
||||
print("=" * 50)
|
||||
|
||||
print(f"✅ Checks passed: {self.checks_passed}/{self.total_checks}")
|
||||
|
||||
if self.errors:
|
||||
print(f"❌ Errors: {len(self.errors)}")
|
||||
for error in self.errors:
|
||||
print(f" • {error}")
|
||||
|
||||
if self.warnings:
|
||||
print(f"⚠️ Warnings: {len(self.warnings)}")
|
||||
for warning in self.warnings:
|
||||
print(f" • {warning}")
|
||||
|
||||
# Overall status
|
||||
if not self.errors:
|
||||
if not self.warnings:
|
||||
print("\n🎉 VALIDATION PASSED - Security implementation complete!")
|
||||
return True
|
||||
else:
|
||||
print("\n✅ VALIDATION PASSED - Minor warnings noted")
|
||||
return True
|
||||
else:
|
||||
print("\n❌ VALIDATION FAILED - Critical issues found")
|
||||
return False
|
||||
|
||||
def main():
|
||||
validator = SecurityValidator()
|
||||
success = validator.run_validation()
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user