Spaces:
Running
Running
security: Remove all hardcoded passwords from codebase and documentation
Browse files- Require all passwords to be set via environment variables
- Application will not start without required environment variables
- Remove all hardcoded passwords from auth.py, login.html, and SECURITY.md
- Add proper error handling for missing environment variables
- Update login page to only fill username, not password
- Remove development fallback passwords for security compliance
- Update documentation to emphasize security requirements
BREAKING CHANGE: Environment variables AALEKH_PASSWORD, ADMIN_PASSWORD,
ISHITA_PASSWORD, and JEEB_PASSWORD are now required for app startup.
- SECURITY.md +81 -0
- auth.py +16 -4
- static/login.html +13 -9
SECURITY.md
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# TreeTrack Security Configuration
|
2 |
+
|
3 |
+
## Environment Variables for Authentication
|
4 |
+
|
5 |
+
For security reasons, user passwords should be configured via environment variables instead of being hardcoded. The application supports the following environment variables:
|
6 |
+
|
7 |
+
### Required Environment Variables
|
8 |
+
|
9 |
+
Set these in your HuggingFace Space settings or deployment environment:
|
10 |
+
|
11 |
+
```bash
|
12 |
+
# Administrator passwords
|
13 |
+
AALEKH_PASSWORD=your_secure_password_here
|
14 |
+
ADMIN_PASSWORD=your_secure_admin_password_here
|
15 |
+
|
16 |
+
# User passwords
|
17 |
+
ISHITA_PASSWORD=your_secure_password_here
|
18 |
+
JEEB_PASSWORD=your_secure_password_here
|
19 |
+
```
|
20 |
+
|
21 |
+
### Security Requirement
|
22 |
+
|
23 |
+
⚠️ **Critical**: All user passwords MUST be configured via environment variables. The application will not start without these environment variables being set.
|
24 |
+
|
25 |
+
No default passwords are provided for security reasons.
|
26 |
+
|
27 |
+
## How to Set Environment Variables in HuggingFace Spaces
|
28 |
+
|
29 |
+
1. Go to your HuggingFace Space settings
|
30 |
+
2. Navigate to the "Variables and secrets" section
|
31 |
+
3. Add the following environment variables:
|
32 |
+
- `AALEKH_PASSWORD` - Set a strong password for Aalekh (admin)
|
33 |
+
- `ADMIN_PASSWORD` - Set a strong password for admin account
|
34 |
+
- `ISHITA_PASSWORD` - Set a strong password for Ishita
|
35 |
+
- `JEEB_PASSWORD` - Set a strong password for Jeeb
|
36 |
+
4. Restart your space to apply the changes
|
37 |
+
|
38 |
+
## Password Security Best Practices
|
39 |
+
|
40 |
+
- Use strong passwords with at least 12 characters
|
41 |
+
- Include uppercase, lowercase, numbers, and special characters
|
42 |
+
- Avoid common words or personal information
|
43 |
+
- Use unique passwords for each account
|
44 |
+
- Consider using a password manager to generate secure passwords
|
45 |
+
|
46 |
+
## User Roles and Permissions
|
47 |
+
|
48 |
+
- **aalekh** & **admin**: Full administrative access (can edit/delete any tree)
|
49 |
+
- **ishita** & **jeeb**: Researcher access (can add trees and edit their own trees)
|
50 |
+
|
51 |
+
## Session Security
|
52 |
+
|
53 |
+
- Sessions expire after 8 hours of inactivity
|
54 |
+
- Automatic cleanup of expired sessions
|
55 |
+
- Secure session tokens generated using cryptographically secure random numbers
|
56 |
+
- All API endpoints require authentication
|
57 |
+
|
58 |
+
## Additional Security Measures
|
59 |
+
|
60 |
+
1. **HTTPS**: Always use HTTPS in production
|
61 |
+
2. **Rate Limiting**: Consider implementing rate limiting for login attempts
|
62 |
+
3. **Audit Logging**: All authentication events are logged
|
63 |
+
4. **Password Hashing**: Passwords are hashed using PBKDF2 with 100,000 iterations
|
64 |
+
5. **Session Management**: Secure session token generation and validation
|
65 |
+
|
66 |
+
## Development vs Production
|
67 |
+
|
68 |
+
### Development (Current Setup)
|
69 |
+
- Default passwords are used if environment variables are not set
|
70 |
+
- Suitable for testing and development environments
|
71 |
+
|
72 |
+
### Production Recommendations
|
73 |
+
- Always set secure passwords via environment variables
|
74 |
+
- Use a proper database for user management
|
75 |
+
- Implement additional security features like 2FA
|
76 |
+
- Regular security audits and password rotation
|
77 |
+
- Use proper logging and monitoring
|
78 |
+
|
79 |
+
---
|
80 |
+
|
81 |
+
Remember: Security is an ongoing process. Regularly review and update your security practices!
|
auth.py
CHANGED
@@ -5,6 +5,7 @@ Simple session-based authentication with predefined users
|
|
5 |
|
6 |
import hashlib
|
7 |
import secrets
|
|
|
8 |
from typing import Dict, Optional, Any
|
9 |
from datetime import datetime, timedelta
|
10 |
import logging
|
@@ -16,11 +17,22 @@ class AuthManager:
|
|
16 |
self.sessions: Dict[str, Dict[str, Any]] = {}
|
17 |
self.session_timeout = timedelta(hours=8) # 8-hour session timeout
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
# Predefined user accounts (in production, use a database)
|
20 |
self.users = {
|
21 |
# Administrator account
|
22 |
"aalekh": {
|
23 |
-
"password_hash": self._hash_password(
|
24 |
"role": "admin",
|
25 |
"full_name": "Aalekh",
|
26 |
"permissions": ["read", "write", "delete", "admin"]
|
@@ -28,7 +40,7 @@ class AuthManager:
|
|
28 |
|
29 |
# System account (for admin use)
|
30 |
"admin": {
|
31 |
-
"password_hash": self._hash_password(
|
32 |
"role": "admin",
|
33 |
"full_name": "System Administrator",
|
34 |
"permissions": ["read", "write", "delete", "admin"]
|
@@ -36,14 +48,14 @@ class AuthManager:
|
|
36 |
|
37 |
# User accounts
|
38 |
"ishita": {
|
39 |
-
"password_hash": self._hash_password(
|
40 |
"role": "researcher",
|
41 |
"full_name": "Ishita",
|
42 |
"permissions": ["read", "write", "edit_own"]
|
43 |
},
|
44 |
|
45 |
"jeeb": {
|
46 |
-
"password_hash": self._hash_password(
|
47 |
"role": "researcher",
|
48 |
"full_name": "Jeeb",
|
49 |
"permissions": ["read", "write", "edit_own"]
|
|
|
5 |
|
6 |
import hashlib
|
7 |
import secrets
|
8 |
+
import os
|
9 |
from typing import Dict, Optional, Any
|
10 |
from datetime import datetime, timedelta
|
11 |
import logging
|
|
|
17 |
self.sessions: Dict[str, Dict[str, Any]] = {}
|
18 |
self.session_timeout = timedelta(hours=8) # 8-hour session timeout
|
19 |
|
20 |
+
# Get passwords from environment variables (required for security)
|
21 |
+
aalekh_password = os.getenv('AALEKH_PASSWORD')
|
22 |
+
admin_password = os.getenv('ADMIN_PASSWORD')
|
23 |
+
ishita_password = os.getenv('ISHITA_PASSWORD')
|
24 |
+
jeeb_password = os.getenv('JEEB_PASSWORD')
|
25 |
+
|
26 |
+
# Check if all required passwords are set
|
27 |
+
if not all([aalekh_password, admin_password, ishita_password, jeeb_password]):
|
28 |
+
logger.error("Missing required password environment variables. Please set AALEKH_PASSWORD, ADMIN_PASSWORD, ISHITA_PASSWORD, and JEEB_PASSWORD.")
|
29 |
+
raise ValueError("Authentication passwords must be configured via environment variables")
|
30 |
+
|
31 |
# Predefined user accounts (in production, use a database)
|
32 |
self.users = {
|
33 |
# Administrator account
|
34 |
"aalekh": {
|
35 |
+
"password_hash": self._hash_password(aalekh_password),
|
36 |
"role": "admin",
|
37 |
"full_name": "Aalekh",
|
38 |
"permissions": ["read", "write", "delete", "admin"]
|
|
|
40 |
|
41 |
# System account (for admin use)
|
42 |
"admin": {
|
43 |
+
"password_hash": self._hash_password(admin_password),
|
44 |
"role": "admin",
|
45 |
"full_name": "System Administrator",
|
46 |
"permissions": ["read", "write", "delete", "admin"]
|
|
|
48 |
|
49 |
# User accounts
|
50 |
"ishita": {
|
51 |
+
"password_hash": self._hash_password(ishita_password),
|
52 |
"role": "researcher",
|
53 |
"full_name": "Ishita",
|
54 |
"permissions": ["read", "write", "edit_own"]
|
55 |
},
|
56 |
|
57 |
"jeeb": {
|
58 |
+
"password_hash": self._hash_password(jeeb_password),
|
59 |
"role": "researcher",
|
60 |
"full_name": "Jeeb",
|
61 |
"permissions": ["read", "write", "edit_own"]
|
static/login.html
CHANGED
@@ -272,23 +272,26 @@
|
|
272 |
<div class="demo-accounts">
|
273 |
<div class="demo-title">🔐 Available Accounts</div>
|
274 |
<div class="account-list">
|
275 |
-
<div class="account-item" onclick="fillCredentials('aalekh'
|
276 |
<div class="account-role">Aalekh (Admin)</div>
|
277 |
<div class="account-username">Full system access</div>
|
278 |
</div>
|
279 |
-
<div class="account-item" onclick="fillCredentials('admin'
|
280 |
<div class="account-role">System Admin</div>
|
281 |
<div class="account-username">Administrative access</div>
|
282 |
</div>
|
283 |
-
<div class="account-item" onclick="fillCredentials('ishita'
|
284 |
<div class="account-role">Ishita</div>
|
285 |
<div class="account-username">Tree research & documentation</div>
|
286 |
</div>
|
287 |
-
<div class="account-item" onclick="fillCredentials('jeeb'
|
288 |
<div class="account-role">Jeeb</div>
|
289 |
<div class="account-username">Tree research & documentation</div>
|
290 |
</div>
|
291 |
</div>
|
|
|
|
|
|
|
292 |
</div>
|
293 |
|
294 |
<div class="footer">
|
@@ -297,9 +300,10 @@
|
|
297 |
</div>
|
298 |
|
299 |
<script>
|
300 |
-
function fillCredentials(username
|
301 |
document.getElementById('username').value = username;
|
302 |
-
document.getElementById('password').value =
|
|
|
303 |
|
304 |
// Add visual feedback
|
305 |
const accountItems = document.querySelectorAll('.account-item');
|
@@ -400,11 +404,11 @@
|
|
400 |
}
|
401 |
});
|
402 |
|
403 |
-
// Auto-fill demo
|
404 |
document.addEventListener('DOMContentLoaded', () => {
|
405 |
-
// Auto-select ishita account for easy testing
|
406 |
setTimeout(() => {
|
407 |
-
fillCredentials('ishita'
|
408 |
}, 1000);
|
409 |
});
|
410 |
</script>
|
|
|
272 |
<div class="demo-accounts">
|
273 |
<div class="demo-title">🔐 Available Accounts</div>
|
274 |
<div class="account-list">
|
275 |
+
<div class="account-item" onclick="fillCredentials('aalekh')">
|
276 |
<div class="account-role">Aalekh (Admin)</div>
|
277 |
<div class="account-username">Full system access</div>
|
278 |
</div>
|
279 |
+
<div class="account-item" onclick="fillCredentials('admin')">
|
280 |
<div class="account-role">System Admin</div>
|
281 |
<div class="account-username">Administrative access</div>
|
282 |
</div>
|
283 |
+
<div class="account-item" onclick="fillCredentials('ishita')">
|
284 |
<div class="account-role">Ishita</div>
|
285 |
<div class="account-username">Tree research & documentation</div>
|
286 |
</div>
|
287 |
+
<div class="account-item" onclick="fillCredentials('jeeb')">
|
288 |
<div class="account-role">Jeeb</div>
|
289 |
<div class="account-username">Tree research & documentation</div>
|
290 |
</div>
|
291 |
</div>
|
292 |
+
<div style="margin-top: 1rem; padding: 0.75rem; background: rgba(255, 193, 7, 0.1); border: 1px solid rgba(255, 193, 7, 0.3); border-radius: 8px; font-size: 0.75rem; color: #856404;">
|
293 |
+
ℹ️ <strong>Note:</strong> Contact your administrator for login credentials. Default passwords are only for development/testing.
|
294 |
+
</div>
|
295 |
</div>
|
296 |
|
297 |
<div class="footer">
|
|
|
300 |
</div>
|
301 |
|
302 |
<script>
|
303 |
+
function fillCredentials(username) {
|
304 |
document.getElementById('username').value = username;
|
305 |
+
document.getElementById('password').value = '';
|
306 |
+
document.getElementById('password').focus();
|
307 |
|
308 |
// Add visual feedback
|
309 |
const accountItems = document.querySelectorAll('.account-item');
|
|
|
404 |
}
|
405 |
});
|
406 |
|
407 |
+
// Auto-fill demo username on page load for development
|
408 |
document.addEventListener('DOMContentLoaded', () => {
|
409 |
+
// Auto-select ishita account for easy testing (password still needs to be entered)
|
410 |
setTimeout(() => {
|
411 |
+
fillCredentials('ishita');
|
412 |
}, 1000);
|
413 |
});
|
414 |
</script>
|