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

6.1 KiB

tags, created, status
tags created status
project/sriphat
security
sso
keycloak
rbac
2026-05-07 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

# 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)

-- ตัวอย่าง: จำกัดข้อมูลตาม 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:

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
}