- 01-infra/nginx-configs: add MinIO /minio/ and /minio-console/ location blocks (port 9000 S3 API, port 9001 Console UI, path stripping via rewrite) - 03-apiservice: integrate MinIO minio-python SDK for file upload - requirements.txt: add minio==7.2.11 - app/core/config.py: add MINIO_ENDPOINT, ACCESS_KEY, SECRET_KEY, BUCKET_FINANCE, USE_SSL - app/services/minio_client.py: new — upload_file(), get_presigned_url(), delete_file() - app/routes/pages.py: replace local /data/uploads/ write with MinIO upload to finance bucket - docker-compose.yml: pass MinIO env vars to container - .env.example: document MinIO vars - 07-minio/.env.example: add MINIO_SVC_ACCESS_KEY/SECRET_KEY section - 07-minio/README.md: add Python minio SDK and Airflow DAG usage guide - CLAUDE.md: project context (servers, SSH, paths, service distribution) - document-obsidiant/: initial Obsidian docs for all services
218 lines
6.1 KiB
Markdown
218 lines
6.1 KiB
Markdown
---
|
|
tags:
|
|
- project/sriphat
|
|
- security
|
|
- sso
|
|
- keycloak
|
|
- rbac
|
|
created: 2026-05-07
|
|
status: active
|
|
---
|
|
|
|
# Security Strategy
|
|
|
|
## หลักการออกแบบ
|
|
|
|
ระบบออกแบบตามหลัก **Defense in Depth** สำหรับสภาพแวดล้อมโรงพยาบาล:
|
|
|
|
1. **Network Isolation** — ทุก service อยู่ใน `shared_data_network`
|
|
2. **Centralized Authentication** — SSO ผ่าน Keycloak เท่านั้น
|
|
3. **Schema Separation** — แยก raw / analytics / production data
|
|
4. **Row-Level Security** — PostgreSQL RLS จำกัดข้อมูลต่อ user
|
|
5. **API Key Management** — Permission-based API access
|
|
|
|
---
|
|
|
|
## Network Security
|
|
|
|
```
|
|
Internet
|
|
│
|
|
▼
|
|
Nginx Reverse Proxy (port 80/443)
|
|
│
|
|
│ ← ทุก request ต้องผ่าน Nginx
|
|
│
|
|
shared_data_network (Docker internal)
|
|
├── keycloak
|
|
├── postgres
|
|
├── sdp-supabase-* (12 containers)
|
|
├── apiservice
|
|
├── superset
|
|
├── airflow-*
|
|
├── minio
|
|
└── redis
|
|
```
|
|
|
|
**Rules:**
|
|
- ไม่มี service ใดที่ bind ตรงกับ `0.0.0.0` ยกเว้นผ่าน Nginx
|
|
- Redis ไม่ expose port ออกภายนอก
|
|
- Supabase services ไม่ expose port ออกภายนอก (ผ่าน Kong เท่านั้น)
|
|
|
|
---
|
|
|
|
## Authentication (SSO with Keycloak)
|
|
|
|
### Flow
|
|
|
|
```
|
|
User
|
|
│
|
|
├─ Web UI → Keycloak (OIDC Login) → redirect back with token
|
|
│
|
|
└─ API Client → API Key (จาก Admin UI) → Bearer token
|
|
```
|
|
|
|
### Keycloak Realms
|
|
|
|
| Realm | Services |
|
|
|-------|---------|
|
|
| `master` | Admin (ปิด public access) |
|
|
| `sriphat` | Superset, MinIO, Airflow, API Service |
|
|
|
|
### Client Configurations
|
|
|
|
| Service | Client ID | Flow |
|
|
|---------|-----------|------|
|
|
| API Service | `apiservice` | Authorization Code |
|
|
| Superset | `superset-client` | Authorization Code |
|
|
| MinIO | `minio-client` | Authorization Code + PKCE |
|
|
| Airflow | `airflow-client` | Authorization Code |
|
|
|
|
---
|
|
|
|
## API Key Security (API Service)
|
|
|
|
### Permission System
|
|
|
|
```
|
|
API Client (ระบบที่ขอใช้ API)
|
|
│
|
|
└── API Keys (ถูก encrypt ด้วย AES)
|
|
│
|
|
└── Permissions:
|
|
- feed.checkpoint:write
|
|
- (เพิ่มได้ตามต้องการ)
|
|
```
|
|
|
|
### API Key Lifecycle
|
|
|
|
```bash
|
|
# 1. Admin สร้าง API Client
|
|
POST /apiservice/admin/api-clients
|
|
|
|
# 2. Generate API Key สำหรับ Client
|
|
POST /apiservice/admin/api-keys/generate
|
|
?client_id=1
|
|
&permissions=feed.checkpoint:write
|
|
&name=his-production-key
|
|
|
|
# 3. ใช้งาน API Key
|
|
curl -H "Authorization: Bearer <key>" \
|
|
https://ai.sriphat.com/apiservice/api/v1/feed/checkpoint
|
|
```
|
|
|
|
---
|
|
|
|
## Database Security (Schema Separation)
|
|
|
|
### PostgreSQL Schemas
|
|
|
|
| Schema | ใช้งาน | สิทธิ์ |
|
|
|--------|--------|--------|
|
|
| `public` | Default | แล้วแต่ config |
|
|
| `raw_data` | ข้อมูลดิบจาก Airbyte | Airflow write, BI read-only |
|
|
| `analytics` | ข้อมูลที่ transform แล้ว | BI read-only |
|
|
| `operationbi` | Operation KPIs | API Service write, Superset read |
|
|
| `fastapi` | API Service metadata | API Service only |
|
|
| `_analytics` | Supabase Logflare | Internal only |
|
|
| `_realtime` | Supabase Realtime | Internal only |
|
|
|
|
### Row-Level Security (RLS)
|
|
|
|
```sql
|
|
-- ตัวอย่าง: จำกัดข้อมูลตาม department
|
|
ALTER TABLE patient_data ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY department_isolation ON patient_data
|
|
USING (department = current_setting('app.current_department'));
|
|
|
|
-- Set context ใน connection
|
|
SET app.current_department = 'OPD';
|
|
```
|
|
|
|
---
|
|
|
|
## Secrets Management
|
|
|
|
### ไฟล์ Secrets
|
|
|
|
| ไฟล์ | ความสำคัญ | ต้องทำ |
|
|
|------|---------|--------|
|
|
| `.env.global` | HIGH | ไม่ commit ลง git |
|
|
| `02-supabase/.env` | HIGH | ไม่ commit ลง git |
|
|
| `03-apiservice/.env` | HIGH | ไม่ commit ลง git |
|
|
| `07-minio/.env` | HIGH | ไม่ commit ลง git |
|
|
|
|
### Key Secrets ที่ต้อง Rotate
|
|
|
|
| Secret | Location | แนะนำ Rotation |
|
|
|--------|----------|--------------|
|
|
| `DB_PASSWORD` | `.env.global` | 90 วัน |
|
|
| `JWT_SECRET` (Supabase) | `02-supabase/.env` | เมื่อมีเหตุ |
|
|
| `KEYCLOAK_ADMIN_PASSWORD` | `.env.global` | 90 วัน |
|
|
| `ADMIN_SECRET_KEY` (API) | `03-apiservice/.env` | 90 วัน |
|
|
| `MINIO_ROOT_PASSWORD` | `07-minio/.env` | 90 วัน |
|
|
| `AIRFLOW__CORE__FERNET_KEY` | `05-airflow/.env` | ไม่ rotate (data loss) |
|
|
| `SUPERSET_SECRET_KEY` | `.env.global` | ไม่ rotate (session loss) |
|
|
|
|
---
|
|
|
|
## Security Checklist
|
|
|
|
### Pre-Production
|
|
|
|
- [ ] เปลี่ยน passwords ทั้งหมดจาก default
|
|
- [ ] เปิด HTTPS ใน Nginx (Let's Encrypt หรือ internal CA)
|
|
- [ ] ตั้งค่า Keycloak realm `sriphat` (ไม่ใช่ `master`)
|
|
- [ ] เชื่อมต่อ LDAP/AD ของโรงพยาบาล
|
|
- [ ] Enable RLS ใน PostgreSQL
|
|
- [ ] ตั้งค่า firewall rules (จำกัด inbound ports)
|
|
- [ ] Setup audit logging
|
|
- [ ] กำหนด session timeout ใน Keycloak
|
|
|
|
### Ongoing
|
|
|
|
- [ ] Review API Keys ที่ active ทุก 30 วัน
|
|
- [ ] Monitor Dozzle สำหรับ unusual access patterns
|
|
- [ ] Backup secrets ไว้ใน secure vault (HashiCorp Vault หรือ similar)
|
|
- [ ] Rotate passwords ตามกำหนด
|
|
|
|
---
|
|
|
|
## SSL/TLS Configuration
|
|
|
|
Nginx จัดการ SSL termination:
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name ai.sriphat.com;
|
|
|
|
ssl_certificate /etc/nginx/ssl/cert.pem;
|
|
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
|
|
|
# Force HTTPS
|
|
# Redirect http → https ผ่าน Nginx
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Related
|
|
|
|
- [[00-Project-Overview]]
|
|
- [[01-Infrastructure]] (Keycloak setup)
|
|
- [[03-API-Service]] (API Key management)
|
|
- [[08-Operations-Runbook]]
|