# HTTPS Setup Guide for ROA2WEB on IIS

Complete guide for enabling HTTPS on ROA2WEB deployed on Windows Server with IIS.

---

## 🎯 Quick Start

### Option 1: Automated Setup (Recommended)

Run the automated PowerShell script:

```powershell
# On Windows Server (PowerShell as Administrator)
cd C:\path\to\roa2web\deployment\windows\scripts

# Enable HTTPS with self-signed certificate
.\Enable-HTTPS.ps1

# Or specify custom settings
.\Enable-HTTPS.ps1 -IISSiteName "Default Web Site" -CertificateDnsName "10.0.20.36"
```

### Option 2: Manual Setup

Follow the step-by-step instructions in the [Manual Configuration](#manual-configuration) section below.

---

## 🔐 Certificate Options

### Self-Signed Certificate (Development/Testing)

**Pros:**
- Quick setup (5 minutes)
- No cost
- Works immediately

**Cons:**
- Browser security warnings
- Not trusted by default
- Not recommended for production

**Use when:**
- Internal development
- Testing HTTPS functionality
- Private internal network

### CA-Issued Certificate (Production)

**Pros:**
- Trusted by all browsers
- No security warnings
- Professional appearance

**Cons:**
- Requires domain name
- May have cost (unless using Let's Encrypt)
- More setup steps

**Use when:**
- Production deployment
- Public-facing application
- Customer/client access

---

## 🚀 Automated Setup Details

### Prerequisites

- Windows Server 2016+ (or Windows 10/11 Pro)
- IIS installed and configured
- Administrator privileges
- ROA2WEB already deployed

### Running the Script

**Basic usage (auto-detect settings):**

```powershell
.\Enable-HTTPS.ps1
```

The script will:
1. Auto-detect your server's hostname and IP
2. Create a self-signed certificate
3. Configure HTTPS binding on IIS
4. Enable HTTP to HTTPS redirect
5. Test the configuration

**Custom DNS name:**

```powershell
.\Enable-HTTPS.ps1 -CertificateDnsName "roa2web.company.com"
```

**Use existing certificate:**

```powershell
# List available certificates
Get-ChildItem cert:\LocalMachine\My | Select-Object Thumbprint, Subject, FriendlyName

# Use specific certificate
.\Enable-HTTPS.ps1 -UseExistingCert -CertThumbprint "ABC123..."
```

**For IIS application (not site root):**

```powershell
.\Enable-HTTPS.ps1 -IISSiteName "Default Web Site"
```

**Custom HTTPS port:**

```powershell
.\Enable-HTTPS.ps1 -Port 8443
```

### Script Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `IISSiteName` | String | "Default Web Site" | IIS site name |
| `CertificateDnsName` | String | Auto-detect | DNS name for certificate |
| `UseExistingCert` | Switch | False | Use existing certificate |
| `CertThumbprint` | String | "" | Thumbprint of existing cert |
| `Port` | Int | 443 | HTTPS port |
| `IPAddress` | String | "*" | Bind to specific IP or all (*) |

---

## 🔧 Manual Configuration

### Step 1: Create SSL Certificate

#### Option A: Self-Signed Certificate

```powershell
# Create certificate for IP address (10.0.20.36)
$cert = New-SelfSignedCertificate `
    -DnsName "10.0.20.36" `
    -CertStoreLocation "cert:\LocalMachine\My" `
    -NotAfter (Get-Date).AddYears(5) `
    -FriendlyName "ROA2WEB SSL Certificate" `
    -KeyUsage DigitalSignature, KeyEncipherment `
    -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")

# Display certificate info
$cert | Select-Object Subject, Thumbprint, NotAfter
```

#### Option B: CA-Issued Certificate

**Using IIS Manager:**

1. Open IIS Manager (`inetmgr`)
2. Select your server in the left panel
3. Double-click "Server Certificates"
4. Click "Create Certificate Request..." in right panel
5. Fill in certificate details:
   - Common Name: `10.0.20.36` (or your domain)
   - Organization: Your company name
   - City, State, Country
6. Save the CSR file
7. Submit CSR to Certificate Authority (CA)
8. Once received, import certificate:
   - Click "Complete Certificate Request..."
   - Browse to certificate file
   - Give it a friendly name: "ROA2WEB SSL Certificate"

**Popular Certificate Authorities:**
- **Let's Encrypt** (Free, automated): https://letsencrypt.org/
- **DigiCert** (Commercial): https://www.digicert.com/
- **Sectigo** (Commercial): https://sectigo.com/
- **GlobalSign** (Commercial): https://www.globalsign.com/

### Step 2: Configure HTTPS Binding

```powershell
Import-Module WebAdministration

# Add HTTPS binding to site
New-WebBinding -Name "Default Web Site" -Protocol "https" -Port 443 -IPAddress "*"

# Attach certificate to binding
$cert = Get-ChildItem -Path "cert:\LocalMachine\My" |
    Where-Object {$_.FriendlyName -eq "ROA2WEB SSL Certificate"}

Push-Location
Set-Location IIS:\SslBindings
$cert | New-Item "0.0.0.0!443"
Pop-Location
```

### Step 3: Enable HTTP to HTTPS Redirect

**Option A: Automatic (via script)**

The `Enable-HTTPS.ps1` script will offer to add the redirect rule automatically.

**Option B: Manual Edit**

Edit `C:\inetpub\wwwroot\roa2web\frontend\web.config`:

```xml
<rewrite>
    <rules>
        <!-- Add this rule FIRST (before other rules) -->
        <rule name="Force HTTPS" stopProcessing="true">
            <match url="(.*)" />
            <conditions>
                <add input="{HTTPS}" pattern="off" />
            </conditions>
            <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
        </rule>

        <!-- Existing rules below... -->
        <rule name="API Reverse Proxy" stopProcessing="true">
            <!-- ... -->
        </rule>
    </rules>
</rewrite>
```

**Option C: IIS Manager GUI**

1. Open IIS Manager
2. Navigate to your site
3. Double-click "URL Rewrite"
4. Click "Add Rule(s)..." → "Blank rule"
5. Configure:
   - Name: `Force HTTPS`
   - Match URL: `(.*)`
   - Conditions: Add condition
     - Input: `{HTTPS}`
     - Pattern: `off`
   - Action:
     - Type: `Redirect`
     - URL: `https://{HTTP_HOST}/{R:1}`
     - Redirect type: `Permanent (301)`

### Step 4: Test Configuration

```powershell
# Restart IIS site
Restart-Website "Default Web Site"

# Test HTTPS locally (self-signed cert)
Invoke-WebRequest https://localhost -SkipCertificateCheck

# Test from browser
Start-Process "https://10.0.20.36/roa2web"
```

---

## 🧪 Testing HTTPS Configuration

### Browser Testing

1. **Access via HTTPS:**
   ```
   https://10.0.20.36/roa2web
   ```

2. **Check for security warnings:**
   - **Self-signed cert**: You'll see a warning - this is normal
   - **CA-issued cert**: No warning - connection is secure

3. **Verify redirect:**
   - Try accessing: `http://10.0.20.36/roa2web`
   - Should automatically redirect to: `https://10.0.20.36/roa2web`

4. **Check console for mixed content:**
   - Open browser DevTools (F12)
   - Look for mixed content warnings
   - All resources should load over HTTPS

### PowerShell Testing

```powershell
# Test HTTPS binding
Get-WebBinding -Name "Default Web Site" -Protocol "https"

# Test certificate
$cert = Get-ChildItem cert:\LocalMachine\My |
    Where-Object {$_.FriendlyName -eq "ROA2WEB SSL Certificate"}
$cert | Select-Object Subject, Thumbprint, NotAfter, DnsNameList

# Test HTTPS response
Invoke-WebRequest https://localhost/roa2web -SkipCertificateCheck

# Test from external IP
Invoke-WebRequest https://10.0.20.36/roa2web -SkipCertificateCheck

# View IIS SSL bindings
netsh http show sslcert
```

### Network Testing

```bash
# Test from Linux/Mac client
curl -k https://10.0.20.36/roa2web

# Check certificate details
openssl s_client -connect 10.0.20.36:443 -servername 10.0.20.36

# Test redirect
curl -I http://10.0.20.36/roa2web
# Should return: HTTP/1.1 301 Moved Permanently
# Location: https://10.0.20.36/roa2web
```

---

## 🐛 Troubleshooting

### HTTPS Not Working

**Symptom:** Can't access site via HTTPS

**Check:**
```powershell
# Verify HTTPS binding exists
Get-WebBinding -Name "Default Web Site"

# Check if port 443 is listening
netstat -ano | findstr :443

# View SSL certificate bindings
netsh http show sslcert
```

**Fix:**
```powershell
# Remove and recreate binding
Remove-WebBinding -Name "Default Web Site" -Protocol "https" -Port 443
New-WebBinding -Name "Default Web Site" -Protocol "https" -Port 443

# Reattach certificate
$cert = Get-ChildItem cert:\LocalMachine\My |
    Where-Object {$_.FriendlyName -eq "ROA2WEB SSL Certificate"}
Push-Location IIS:\SslBindings
$cert | New-Item "0.0.0.0!443" -Force
Pop-Location
```

### Certificate Warning in Browser

**Symptom:** Browser shows "Your connection is not private" or similar warning

**Cause:**
- Self-signed certificate (not trusted by default)
- Expired certificate
- Hostname mismatch

**Solutions:**

1. **For Development (self-signed):**
   - Click "Advanced" → "Proceed anyway"
   - This is expected behavior for self-signed certificates

2. **For Production:**
   - Replace with CA-issued certificate
   - Ensure certificate CN matches the URL you're accessing

3. **For Internal Network:**
   - Add certificate to Trusted Root CA:
   ```powershell
   $cert = Get-ChildItem cert:\LocalMachine\My\<THUMBPRINT>
   $store = Get-Item cert:\LocalMachine\Root
   $store.Open("ReadWrite")
   $store.Add($cert)
   $store.Close()
   ```

### HTTP Not Redirecting to HTTPS

**Symptom:** HTTP URLs still work, no automatic redirect

**Check:**
```powershell
# Verify web.config has redirect rule
Get-Content C:\inetpub\wwwroot\roa2web\frontend\web.config |
    Select-String "Force HTTPS"
```

**Fix:**
- Ensure redirect rule is present in web.config
- Verify rule is BEFORE other rewrite rules
- Check rule is not disabled
- Restart IIS site:
  ```powershell
  Restart-Website "Default Web Site"
  ```

### Mixed Content Warnings

**Symptom:** Console shows "Mixed Content" warnings

**Cause:** Some resources loading over HTTP instead of HTTPS

**Fix:**
1. Check frontend code for hardcoded `http://` URLs
2. Update to use relative URLs or `https://`
3. Update API base URL in frontend config:
   ```javascript
   // src/config.js or similar
   const API_BASE_URL = window.location.protocol === 'https:'
       ? 'https://10.0.20.36/api'
       : 'http://10.0.20.36/api';
   ```

### API Calls Failing After HTTPS

**Symptom:** Frontend loads but API calls fail with CORS or SSL errors

**Check:**
```powershell
# Verify backend is accessible
Invoke-WebRequest http://localhost:8000/health

# Check IIS URL Rewrite is forwarding correctly
Get-WebConfiguration -Filter "system.webServer/rewrite/rules"
```

**Fix:**
- Update CORS settings in FastAPI backend to allow HTTPS origin
- Verify web.config proxy rules are correct
- Check backend logs for errors

---

## 🔒 Security Best Practices

### 1. Use Strong Certificates

```powershell
# For production, use CA-issued certificates
# Minimum key size: 2048 bits (4096 recommended)
# Use SHA-256 or higher
```

### 2. Enable HSTS (Strict Transport Security)

Already configured in `web.config` (lines 115-124):

```xml
<rule name="Add HSTS Header" preCondition="IsHTTPS">
    <match serverVariable="RESPONSE_Strict-Transport-Security" pattern=".*" />
    <action type="Rewrite" value="max-age=31536000; includeSubDomains" />
</rule>
```

This tells browsers to always use HTTPS for your site.

### 3. Disable Weak SSL/TLS Protocols

```powershell
# Disable SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1
# Enable only TLS 1.2 and TLS 1.3

# Run as Administrator
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Name 'Enabled' -Value 1 -PropertyType 'DWord'
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Name 'DisabledByDefault' -Value 0 -PropertyType 'DWord'

# Restart required
Restart-Computer
```

### 4. Secure Cookie Settings

Update FastAPI backend cookie settings:

```python
# backend/app/main.py
response.set_cookie(
    key="access_token",
    value=token,
    httponly=True,
    secure=True,  # Only send over HTTPS
    samesite="lax"
)
```

### 5. Regular Certificate Renewal

- CA certificates typically expire in 1-2 years
- Let's Encrypt certificates expire in 90 days
- Set up reminders or automated renewal

```powershell
# Check certificate expiry
$cert = Get-ChildItem cert:\LocalMachine\My |
    Where-Object {$_.FriendlyName -eq "ROA2WEB SSL Certificate"}
$cert.NotAfter

# Days until expiry
($cert.NotAfter - (Get-Date)).Days
```

---

## 📚 Additional Resources

### Documentation
- [IIS SSL Configuration](https://docs.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis)
- [Let's Encrypt](https://letsencrypt.org/)
- [SSL/TLS Best Practices](https://wiki.mozilla.org/Security/Server_Side_TLS)

### Testing Tools
- [SSL Labs Server Test](https://www.ssllabs.com/ssltest/) - Comprehensive SSL/TLS analysis
- [SSL Checker](https://www.sslshopper.com/ssl-checker.html) - Quick certificate validation
- [Why No Padlock?](https://www.whynopadlock.com/) - Find mixed content issues

### Certificate Providers
- **Free:**
  - [Let's Encrypt](https://letsencrypt.org/) (Automated, 90-day validity)
  - [ZeroSSL](https://zerossl.com/) (Free tier available)

- **Commercial:**
  - [DigiCert](https://www.digicert.com/)
  - [Sectigo](https://sectigo.com/)
  - [GlobalSign](https://www.globalsign.com/)

---

## ✅ Quick Reference

### Essential Commands

```powershell
# View all certificates
Get-ChildItem cert:\LocalMachine\My

# View IIS bindings
Get-WebBinding -Name "Default Web Site"

# View SSL bindings
netsh http show sslcert

# Test HTTPS
Invoke-WebRequest https://localhost -SkipCertificateCheck

# Restart IIS site
Restart-Website "Default Web Site"

# Enable HTTPS (automated script)
.\Enable-HTTPS.ps1
```

### Configuration Files

- **IIS bindings**: IIS Manager → Site → Bindings
- **web.config**: `C:\inetpub\wwwroot\roa2web\frontend\web.config`
- **Certificates**: Certificate Manager (`certmgr.msc`)
- **Backend config**: `C:\inetpub\wwwroot\roa2web\backend\.env`

### Access Points

- **HTTP**: `http://10.0.20.36/roa2web` (redirects to HTTPS)
- **HTTPS**: `https://10.0.20.36/roa2web`
- **API**: `https://10.0.20.36/api/*` (proxied to backend)
- **Health**: `https://10.0.20.36/health`

---

*Last Updated: 2025-01-18*
*ROA2WEB HTTPS Setup Guide v1.0*
