Files
jigoong a587be08bd feat: MinIO integration — bucket finance, API service upload, Nginx routing
- 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
2026-05-20 17:42:39 +07:00

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]]