Skip to content

Commit e4772a6

Browse files
committed
fix: remove hardcoded password hashes and improve code quality
Security fixes: - Remove hardcoded password hash from SQL schema (security vulnerability) - Replace with secure user creation via setup script - Update all documentation to emphasize secure user creation practices Code quality improvements: - Fix SQL schema: use ENUM types and constants instead of duplicated literals - Fix Dockerfile: sort package names alphabetically and merge RUN instructions - Fix CI/CD: correct Node.js paths (ui/web -> src/ui/web) and update CodeQL actions Documentation updates: - Add security warnings about not hardcoding credentials - Update README.md, DEPLOYMENT.md, QUICK_START.md, docs/secrets.md - Emphasize use of setup script for secure user creation - Add production security best practices
1 parent f5b75e4 commit e4772a6

File tree

7 files changed

+116
-33
lines changed

7 files changed

+116
-33
lines changed

DEPLOYMENT.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,27 @@ PGPASSWORD=${POSTGRES_PASSWORD:-changeme} psql -h localhost -p 5435 -U warehouse
6565

6666
### 5. Create Default Users
6767

68+
**⚠️ Security Note:** The SQL schema does not contain hardcoded password hashes. Users must be created using the setup script, which generates secure password hashes from environment variables.
69+
6870
```bash
6971
# Activate virtual environment
7072
source env/bin/activate
7173

74+
# Set password via environment variable (optional, defaults to 'changeme' for development)
75+
export DEFAULT_ADMIN_PASSWORD=your-secure-password-here
76+
7277
# Create default admin and user accounts
7378
python scripts/setup/create_default_users.py
7479
```
7580

7681
**Default Login Credentials:**
7782
- **Username:** `admin`
78-
- **Password:** `changeme` (or value of `DEFAULT_ADMIN_PASSWORD` env var)
83+
- **Password:** Value of `DEFAULT_ADMIN_PASSWORD` environment variable (default: `changeme` for development only)
84+
85+
**⚠️ Production Security:**
86+
- Always set strong, unique passwords via environment variables
87+
- Never use default passwords in production
88+
- The setup script generates unique bcrypt hashes with random salts - no credentials are exposed in source code
7989

8090
### 6. (Optional) Install RAPIDS for GPU-Accelerated Forecasting
8191

Dockerfile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ WORKDIR /app
3939

4040
# Install system dependencies
4141
RUN apt-get update && apt-get install -y \
42-
gcc \
4342
g++ \
43+
gcc \
4444
git \
4545
&& rm -rf /var/lib/apt/lists/*
4646

@@ -58,8 +58,8 @@ WORKDIR /app
5858

5959
# Install runtime dependencies
6060
RUN apt-get update && apt-get install -y \
61-
git \
6261
curl \
62+
git \
6363
&& rm -rf /var/lib/apt/lists/*
6464

6565
# Copy Python dependencies from backend-deps stage
@@ -86,8 +86,9 @@ ENV PYTHONUNBUFFERED=1
8686
COPY --from=frontend-builder /app/src/ui/web/build ./src/ui/web/build
8787

8888
# Create non-root user for security
89-
RUN groupadd -r appuser && useradd -r -g appuser appuser
90-
RUN chown -R appuser:appuser /app
89+
RUN groupadd -r appuser && \
90+
useradd -r -g appuser appuser && \
91+
chown -R appuser:appuser /app
9192
USER appuser
9293

9394
# Health check

QUICK_START.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ PGPASSWORD=${POSTGRES_PASSWORD:-changeme} psql -h localhost -p 5435 -U warehouse
2525
PGPASSWORD=${POSTGRES_PASSWORD:-changeme} psql -h localhost -p 5435 -U warehouse -d warehouse -f data/postgres/004_inventory_movements_schema.sql
2626
PGPASSWORD=${POSTGRES_PASSWORD:-changeme} psql -h localhost -p 5435 -U warehouse -d warehouse -f scripts/setup/create_model_tracking_tables.sql
2727

28-
# Create default users
28+
# Create default users (generates secure password hashes from environment variables)
2929
python scripts/setup/create_default_users.py
3030
```
3131

32+
**⚠️ Security Note:** The SQL schema does not contain hardcoded password hashes. Users are created securely via the setup script using environment variables.
33+
3234
**Note:** For detailed setup instructions, see [DEPLOYMENT.md](DEPLOYMENT.md)
3335

3436
### 2. Start Server
@@ -80,9 +82,10 @@ python scripts/setup/create_default_users.py
8082
```
8183

8284
**Password not working?**
83-
- Default password is `changeme`
84-
- Check your `.env` file for `DEFAULT_ADMIN_PASSWORD`
85+
- Default password is `changeme` (development only)
86+
- Check your `.env` file for `DEFAULT_ADMIN_PASSWORD` environment variable
8587
- Recreate users: `python scripts/setup/create_default_users.py`
88+
- **Note:** The SQL schema does not create users - they must be created via the setup script
8689

8790
**Port already in use?**
8891
```bash

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,24 @@ PGPASSWORD=${POSTGRES_PASSWORD:-changeme} psql -h localhost -p 5435 -U warehouse
258258

259259
### Step 6: Create Default Users
260260

261+
**⚠️ Security Note:** The SQL schema (`data/postgres/000_schema.sql`) does not contain hardcoded password hashes. Users must be created using the setup script, which generates secure password hashes from environment variables.
262+
261263
```bash
264+
# Set password via environment variable (optional, defaults to 'changeme' for development)
265+
export DEFAULT_ADMIN_PASSWORD=your-secure-password-here
266+
262267
# Create default admin and operator users
263268
python scripts/setup/create_default_users.py
264269
```
265270

266271
**Default Credentials:**
267-
- **Admin user**: `admin` / `changeme` (role: admin)
268-
- **Operator user**: `user` / `changeme` (role: operator)
272+
- **Admin user**: `admin` / Value of `DEFAULT_ADMIN_PASSWORD` env var (default: `changeme` for development only)
273+
- **Operator user**: `user` / Value of `DEFAULT_USER_PASSWORD` env var (default: `changeme` for development only)
274+
275+
**⚠️ Production Security:**
276+
- Always set strong, unique passwords via environment variables
277+
- Never use default passwords in production
278+
- The setup script generates unique bcrypt hashes with random salts - no credentials are exposed in source code
269279

270280
### Step 7: Install RAPIDS for GPU-Accelerated Forecasting
271281

data/postgres/000_schema.sql

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,25 @@ CREATE TABLE IF NOT EXISTS equipment_telemetry (
3333
value DOUBLE PRECISION NOT NULL
3434
);
3535

36+
-- User role and status ENUM types
37+
DO $$
38+
BEGIN
39+
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_role') THEN
40+
CREATE TYPE user_role AS ENUM ('admin', 'manager', 'supervisor', 'operator', 'viewer');
41+
END IF;
42+
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_status') THEN
43+
CREATE TYPE user_status AS ENUM ('active', 'inactive', 'suspended', 'pending');
44+
END IF;
45+
END $$;
46+
3647
-- User authentication and authorization tables
3748
CREATE TABLE IF NOT EXISTS users (
3849
id SERIAL PRIMARY KEY,
3950
username TEXT UNIQUE NOT NULL,
4051
email TEXT UNIQUE NOT NULL,
4152
full_name TEXT NOT NULL,
42-
role TEXT NOT NULL CHECK (role IN ('admin', 'manager', 'supervisor', 'operator', 'viewer')),
43-
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended', 'pending')),
53+
role user_role NOT NULL,
54+
status user_status NOT NULL DEFAULT 'active',
4455
hashed_password TEXT NOT NULL,
4556
created_at TIMESTAMPTZ DEFAULT now(),
4657
updated_at TIMESTAMPTZ DEFAULT now(),
@@ -109,16 +120,15 @@ ON CONFLICT (sku) DO UPDATE SET
109120
reorder_point = EXCLUDED.reorder_point,
110121
updated_at = now();
111122

112-
-- Sample users (passwords set via DEFAULT_ADMIN_PASSWORD env var, hashed with bcrypt)
113-
INSERT INTO users (username, email, full_name, role, status, hashed_password) VALUES
114-
('admin', 'admin@warehouse.com', 'System Administrator', 'admin', 'active', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/8KzqK2a'),
115-
('manager1', 'manager1@warehouse.com', 'John Manager', 'manager', 'active', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/8KzqK2a'),
116-
('supervisor1', 'supervisor1@warehouse.com', 'Jane Supervisor', 'supervisor', 'active', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/8KzqK2a'),
117-
('operator1', 'operator1@warehouse.com', 'Bob Operator', 'operator', 'active', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/8KzqK2a'),
118-
('viewer1', 'viewer1@warehouse.com', 'Alice Viewer', 'viewer', 'active', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/8KzqK2a')
119-
ON CONFLICT (username) DO UPDATE SET
120-
email = EXCLUDED.email,
121-
full_name = EXCLUDED.full_name,
122-
role = EXCLUDED.role,
123-
status = EXCLUDED.status,
124-
updated_at = now();
123+
-- Sample users should be created using the setup script: scripts/setup/create_default_users.py
124+
-- This script properly generates password hashes from environment variables and does not expose
125+
-- sensitive credentials in source code. Never hardcode password hashes in SQL files.
126+
--
127+
-- To create default users, run:
128+
-- python scripts/setup/create_default_users.py
129+
--
130+
-- The script uses the following environment variables:
131+
-- - DEFAULT_ADMIN_PASSWORD: Password for the admin user (default: 'changeme')
132+
-- - DEFAULT_USER_PASSWORD: Password for regular users (default: 'changeme')
133+
--
134+
-- For production deployments, always set strong passwords via environment variables.

docs/secrets.md

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,48 @@ ERP_API_KEY=your-erp-api-key
6767
## Security Best Practices
6868

6969
1. **Never commit secrets to version control**
70-
2. **Use secrets management systems in production**
71-
3. **Rotate credentials regularly**
72-
4. **Use least privilege principle**
73-
5. **Enable audit logging**
74-
6. **Use secure communication protocols**
75-
7. **Implement proper access controls**
76-
8. **Regular security audits**
70+
2. **Never hardcode password hashes in SQL files or source code**
71+
- Password hashes should be generated dynamically from environment variables
72+
- Use the setup script (`scripts/setup/create_default_users.py`) to create users securely
73+
- The SQL schema (`data/postgres/000_schema.sql`) does not contain hardcoded credentials
74+
3. **Use secrets management systems in production**
75+
4. **Rotate credentials regularly**
76+
5. **Use least privilege principle**
77+
6. **Enable audit logging**
78+
7. **Use secure communication protocols**
79+
8. **Implement proper access controls**
80+
9. **Regular security audits**
81+
82+
## User Creation Security
83+
84+
### ⚠️ Important: Never Hardcode Password Hashes
85+
86+
**The SQL schema file (`data/postgres/000_schema.sql`) does NOT contain hardcoded password hashes or sample user data.** This is a security best practice to prevent credential exposure in source code.
87+
88+
### Creating Users Securely
89+
90+
Users must be created using the setup script, which:
91+
- Generates unique bcrypt hashes with random salts
92+
- Reads passwords from environment variables (never hardcoded)
93+
- Does not expose credentials in source code
94+
95+
**To create default users:**
96+
```bash
97+
# Set password via environment variable
98+
export DEFAULT_ADMIN_PASSWORD=your-secure-password-here
99+
100+
# Run the setup script
101+
python scripts/setup/create_default_users.py
102+
```
103+
104+
**Environment Variables:**
105+
- `DEFAULT_ADMIN_PASSWORD` - Password for the admin user (default: `changeme` for development only)
106+
- `DEFAULT_USER_PASSWORD` - Password for regular users (default: `changeme` for development only)
107+
108+
**For Production:**
109+
- Always set strong, unique passwords via environment variables
110+
- Never use default passwords in production
111+
- Consider using a secrets management system (AWS Secrets Manager, HashiCorp Vault, etc.)
77112

78113
## JWT Secret Configuration
79114

scripts/README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,27 @@ Starts all development infrastructure services (PostgreSQL, Redis, Kafka, Milvus
226226

227227
**Script:** `scripts/setup/create_default_users.py`
228228

229-
Creates default users with proper password hashing.
229+
Creates default users with proper password hashing. This script:
230+
- Generates unique bcrypt password hashes with random salts
231+
- Reads passwords from environment variables (never hardcoded)
232+
- Does not expose credentials in source code
233+
- **Security:** The SQL schema does not contain hardcoded password hashes - users must be created via this script
230234

231235
**Usage:**
232236
```bash
237+
# Set password via environment variable (optional, defaults to 'changeme' for development)
238+
export DEFAULT_ADMIN_PASSWORD=your-secure-password-here
239+
240+
# Create default users
233241
python scripts/setup/create_default_users.py
234242
```
235243

244+
**Environment Variables:**
245+
- `DEFAULT_ADMIN_PASSWORD` - Password for admin user (default: `changeme` for development only)
246+
- `DEFAULT_USER_PASSWORD` - Password for regular users (default: `changeme` for development only)
247+
248+
**⚠️ Production:** Always set strong, unique passwords via environment variables. Never use default passwords in production.
249+
236250
**SQL Script:** `scripts/setup/create_model_tracking_tables.sql`
237251

238252
Creates tables for tracking model training history and predictions.

0 commit comments

Comments
 (0)