Auth configuration in docker
This commit is contained in:
@@ -24,3 +24,8 @@ _ReSharper*/
|
||||
DataBackup/
|
||||
*.db
|
||||
/.claude/*
|
||||
|
||||
# Production secrets and configuration
|
||||
auth-secrets.json
|
||||
docker-compose.yml
|
||||
docker-compose.override.yml
|
||||
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
# Docker Deployment Guide
|
||||
|
||||
## Authentication Configuration for Production
|
||||
|
||||
The application supports two methods for configuring authentication credentials in Docker:
|
||||
|
||||
### Option 1: Volume-Mounted JSON File (Recommended)
|
||||
|
||||
This approach allows you to edit credentials without rebuilding the container.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Generate Password Hashes** (on your development machine):
|
||||
```bash
|
||||
# Run the app locally and navigate to:
|
||||
https://localhost:<port>/dev/hash-password?password=YourPassword
|
||||
```
|
||||
|
||||
2. **Create `auth-secrets.json`** on your Docker host:
|
||||
```bash
|
||||
cp auth-secrets.example.json auth-secrets.json
|
||||
```
|
||||
|
||||
3. **Edit `auth-secrets.json`** and replace the placeholder hashes:
|
||||
```json
|
||||
{
|
||||
"Authentication": {
|
||||
"Users": [
|
||||
{
|
||||
"Email": "admin@example.com",
|
||||
"PasswordHash": "$2a$11$actual.hash.here",
|
||||
"Role": "Administrator",
|
||||
"DisplayName": "Administrator"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. **Mount the file in Docker Compose**:
|
||||
```yaml
|
||||
volumes:
|
||||
- ./auth-secrets.json:/app/secrets/auth-secrets.json:ro
|
||||
```
|
||||
|
||||
5. **Update credentials**: Simply edit `auth-secrets.json` on the host and restart the container:
|
||||
```bash
|
||||
docker-compose restart webapp
|
||||
```
|
||||
|
||||
**Security Note**: Set proper file permissions on the host:
|
||||
```bash
|
||||
chmod 600 auth-secrets.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Option 2: Environment Variables
|
||||
|
||||
This approach is useful for container orchestration platforms (Kubernetes, Docker Swarm, etc.).
|
||||
|
||||
**Docker Compose Example**:
|
||||
```yaml
|
||||
environment:
|
||||
- TSA_Authentication__Users__0__Email=admin@example.com
|
||||
- TSA_Authentication__Users__0__PasswordHash=$2a$11$hash...
|
||||
- TSA_Authentication__Users__0__Role=Administrator
|
||||
- TSA_Authentication__Users__0__DisplayName=Administrator
|
||||
- TSA_Authentication__Users__1__Email=advisor@example.com
|
||||
- TSA_Authentication__Users__1__PasswordHash=$2a$11$hash...
|
||||
- TSA_Authentication__Users__1__Role=Advisor
|
||||
- TSA_Authentication__Users__1__DisplayName=Chapter Advisor
|
||||
```
|
||||
|
||||
**Docker Run Example**:
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-e ASPNETCORE_ENVIRONMENT=Production \
|
||||
-e TSA_Authentication__Users__0__Email=admin@example.com \
|
||||
-e TSA_Authentication__Users__0__PasswordHash='$2a$11$hash...' \
|
||||
-e TSA_Authentication__Users__0__Role=Administrator \
|
||||
-e TSA_Authentication__Users__0__DisplayName=Administrator \
|
||||
tsa-chapter-organizer:latest
|
||||
```
|
||||
|
||||
**Kubernetes Secret Example**:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: tsa-auth-secrets
|
||||
type: Opaque
|
||||
stringData:
|
||||
TSA_Authentication__Users__0__Email: "admin@example.com"
|
||||
TSA_Authentication__Users__0__PasswordHash: "$2a$11$hash..."
|
||||
TSA_Authentication__Users__0__Role: "Administrator"
|
||||
TSA_Authentication__Users__0__DisplayName: "Administrator"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Building and Running
|
||||
|
||||
### Build the Docker Image
|
||||
|
||||
```bash
|
||||
cd WebApp
|
||||
docker build -t tsa-chapter-organizer:latest .
|
||||
```
|
||||
|
||||
### Run with Docker Compose
|
||||
|
||||
```bash
|
||||
# Copy and customize the example
|
||||
cp docker-compose.example.yml docker-compose.yml
|
||||
|
||||
# Edit auth-secrets.json with your credentials
|
||||
cp auth-secrets.example.json auth-secrets.json
|
||||
# (Edit the file and replace hashes)
|
||||
|
||||
# Start the container
|
||||
docker-compose up -d
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f webapp
|
||||
```
|
||||
|
||||
### Access the Application
|
||||
|
||||
- HTTP: `http://localhost:8080`
|
||||
- HTTPS: `https://localhost:8081` (if configured)
|
||||
|
||||
---
|
||||
|
||||
## Managing Users
|
||||
|
||||
### Adding a New User
|
||||
|
||||
**With Volume-Mounted File:**
|
||||
1. Edit `auth-secrets.json` on the host
|
||||
2. Add new user entry to the `Users` array
|
||||
3. Restart the container: `docker-compose restart webapp`
|
||||
|
||||
**With Environment Variables:**
|
||||
1. Add new environment variables (increment the index number)
|
||||
2. Recreate the container: `docker-compose up -d`
|
||||
|
||||
### Changing a Password
|
||||
|
||||
1. Generate new hash using the dev endpoint (on local dev machine)
|
||||
2. Update the `PasswordHash` value in your configuration
|
||||
3. Restart/recreate the container
|
||||
|
||||
### Removing a User
|
||||
|
||||
1. Remove the user entry from your configuration
|
||||
2. Restart/recreate the container
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **File Permissions**:
|
||||
```bash
|
||||
chmod 600 auth-secrets.json
|
||||
chown root:root auth-secrets.json
|
||||
```
|
||||
|
||||
2. **Never Commit Secrets**: Add to `.gitignore`:
|
||||
```
|
||||
auth-secrets.json
|
||||
docker-compose.yml
|
||||
```
|
||||
|
||||
3. **Use HTTPS in Production**: Configure SSL/TLS certificates
|
||||
|
||||
4. **Backup Credentials**: Store encrypted backups of `auth-secrets.json`
|
||||
|
||||
5. **Password Rotation**: Periodically regenerate password hashes
|
||||
|
||||
6. **Monitor Access**: Review application logs for failed login attempts:
|
||||
```bash
|
||||
docker-compose logs webapp | grep "Failed login"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
Check logs:
|
||||
```bash
|
||||
docker-compose logs webapp
|
||||
```
|
||||
|
||||
### Can't Login
|
||||
|
||||
1. Verify `auth-secrets.json` is properly mounted:
|
||||
```bash
|
||||
docker exec tsa-app ls -la /app/secrets/
|
||||
```
|
||||
|
||||
2. Check if the file is being loaded:
|
||||
```bash
|
||||
docker-compose logs webapp | grep "secrets"
|
||||
```
|
||||
|
||||
3. Verify JSON syntax:
|
||||
```bash
|
||||
cat auth-secrets.json | jq .
|
||||
```
|
||||
|
||||
### Forgot Admin Password
|
||||
|
||||
1. Generate a new password hash locally
|
||||
2. Update `auth-secrets.json` on the host
|
||||
3. Restart the container
|
||||
|
||||
---
|
||||
|
||||
## Example: Complete Setup
|
||||
|
||||
```bash
|
||||
# 1. Generate password hashes locally
|
||||
# Navigate to: https://localhost:5001/dev/hash-password?password=MySecurePass123
|
||||
|
||||
# 2. Create secrets file
|
||||
cat > auth-secrets.json <<EOF
|
||||
{
|
||||
"Authentication": {
|
||||
"Users": [
|
||||
{
|
||||
"Email": "admin@myschool.edu",
|
||||
"PasswordHash": "$2a$11$paste_hash_here",
|
||||
"Role": "Administrator",
|
||||
"DisplayName": "TSA Admin"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# 3. Set permissions
|
||||
chmod 600 auth-secrets.json
|
||||
|
||||
# 4. Create docker-compose.yml
|
||||
cp docker-compose.example.yml docker-compose.yml
|
||||
|
||||
# 5. Start the application
|
||||
docker-compose up -d
|
||||
|
||||
# 6. Check it's running
|
||||
docker-compose ps
|
||||
curl http://localhost:8080
|
||||
|
||||
# 7. Login
|
||||
# Navigate to http://localhost:8080/login
|
||||
# Use: admin@myschool.edu / MySecurePass123
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Production Deployment Checklist
|
||||
|
||||
- [ ] Generated secure password hashes
|
||||
- [ ] Created `auth-secrets.json` with production credentials
|
||||
- [ ] Set file permissions to 600
|
||||
- [ ] Configured HTTPS/SSL certificates
|
||||
- [ ] Updated `ASPNETCORE_URLS` for production domain
|
||||
- [ ] Configured volume for database persistence
|
||||
- [ ] Removed development endpoints (already done in code)
|
||||
- [ ] Set up log monitoring
|
||||
- [ ] Configured automatic backups
|
||||
- [ ] Tested login with all user roles
|
||||
- [ ] Tested rate limiting (5 failed attempts)
|
||||
- [ ] Documented admin password securely
|
||||
- [ ] Added `auth-secrets.json` to `.gitignore`
|
||||
@@ -7,6 +7,20 @@ using WebApp.Components;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Configure authentication secrets for production (Docker, etc.)
|
||||
if (builder.Environment.IsProduction())
|
||||
{
|
||||
// Option 1: Load from volume-mounted secrets file
|
||||
var secretsPath = "/app/secrets/auth-secrets.json";
|
||||
if (File.Exists(secretsPath))
|
||||
{
|
||||
builder.Configuration.AddJsonFile(secretsPath, optional: false, reloadOnChange: true);
|
||||
}
|
||||
|
||||
// Option 2: Environment variables with prefix
|
||||
builder.Configuration.AddEnvironmentVariables(prefix: "TSA_");
|
||||
}
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllersWithViews();
|
||||
builder.Services.AddRazorComponents()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"Authentication": {
|
||||
"Users": [
|
||||
{
|
||||
"Email": "admin@example.com",
|
||||
"PasswordHash": "$2a$11$REPLACE_WITH_ACTUAL_HASH",
|
||||
"Role": "Administrator",
|
||||
"DisplayName": "Administrator"
|
||||
},
|
||||
{
|
||||
"Email": "advisor@example.com",
|
||||
"PasswordHash": "$2a$11$REPLACE_WITH_ACTUAL_HASH",
|
||||
"Role": "Advisor",
|
||||
"DisplayName": "Chapter Advisor"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
webapp:
|
||||
image: tsa-chapter-organizer:latest
|
||||
container_name: tsa-app
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "8081:8081"
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Production
|
||||
- ASPNETCORE_URLS=https://+:8081;http://+:8080
|
||||
- ASPNETCORE_HTTPS_PORT=8081
|
||||
|
||||
# Option 2: Environment Variables approach (uncomment to use)
|
||||
# - TSA_Authentication__Users__0__Email=admin@example.com
|
||||
# - TSA_Authentication__Users__0__PasswordHash=$2a$11$...
|
||||
# - TSA_Authentication__Users__0__Role=Administrator
|
||||
# - TSA_Authentication__Users__0__DisplayName=Administrator
|
||||
# - TSA_Authentication__Users__1__Email=advisor@example.com
|
||||
# - TSA_Authentication__Users__1__PasswordHash=$2a$11$...
|
||||
# - TSA_Authentication__Users__1__Role=Advisor
|
||||
# - TSA_Authentication__Users__1__DisplayName=Chapter Advisor
|
||||
|
||||
volumes:
|
||||
# Option 1: Volume-mounted secrets file (recommended for easy editing)
|
||||
- ./auth-secrets.json:/app/secrets/auth-secrets.json:ro
|
||||
|
||||
# Database persistence
|
||||
- ./data:/app/data
|
||||
|
||||
# HTTPS certificate (if needed)
|
||||
# - ./certs:/https:ro
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
# Uncomment if using HTTPS with certificate
|
||||
# environment:
|
||||
# - ASPNETCORE_Kestrel__Certificates__Default__Password=your-cert-password
|
||||
# - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
|
||||
Reference in New Issue
Block a user