zenny455/self-hosted-cloud-security-lab
GitHub: zenny455/self-hosted-cloud-security-lab
一个基于 Docker Compose 的自托管私有云安全实验室,分阶段演示从基础设施部署到 IAM、数据加密、安全监控和合规审计的完整云安全最佳实践。
Stars: 0 | Forks: 0
# 🔐 自托管云安全实验室
## 📌 目录
- [项目概述](#-project-overview)
- [架构](#architecture)
- [技术栈](#technology-stack)
- [前置条件](#-prerequisites)
- [项目结构](#-project-structure)
- [阶段 1:基础设施设置](#phase-1--infrastructure-setup)
- [阶段 2:身份与访问管理](#phase-2--identity--access-management)
- [阶段 3:数据安全与加密](#phase-3--data-security--encryption)
- [IAM 策略参考](#-iam-policy-reference)
## 📖 项目概述
本项目实现了一个完全自托管的私有云环境,重点涵盖了六个阶段的安全最佳实践:
1. **基础设施设置** — 通过 Docker Compose 部署所有服务
2. **身份与访问管理** — 通过 Keycloak 实现 SSO、RBAC 和 MFA
3. **数据安全与加密** — TLS 终止、AES-256 静态加密,以及使用 HashiCorp Vault 进行密钥管理
4. **安全监控** — Fail2ban、GoAccess、日志分析
5. **漏洞扫描** — Trivy 容器镜像扫描
6. **合规审计** — CIS Benchmark 差距分析
该技术栈使用 Docker 直接部署在 Linux 主机上(无需虚拟机),可以在任何安装了 Docker 的 Linux 机器上复现。
## 架构
```
Browser (HTTPS)
│
▼
┌─────────────┐
│ Nginx │ ← Reverse proxy + TLS termination (self-signed cert)
│ Port 80/443│
└──────┬──────┘
│
┌────┼──────────────────────────────────┐
│ │ │
▼ ▼ ▼ ▼
Nextcloud Keycloak MinIO HashiCorp Vault
nextcloud.local keycloak.local minio.local vault.local
:80 :8080 :9001 :8200
(OIDC SP) (Identity Provider) (Object Store) (Secrets Engine)
│
▼
PostgreSQL
(DB backend)
```
所有四个服务都可以通过 `.local` 主机名访问,这些主机名在 `/etc/hosts` 中被映射到 `127.0.0.1`。
## 技术栈
| 工具 | 角色 |
|------|------|
| **Linux** | 宿主机操作系统或虚拟机 |
| **Docker & Docker Compose** | 所有服务的容器运行时 |
| **Nextcloud** | 核心自托管云存储平台 |
| **PostgreSQL** | Nextcloud 的数据库后端 |
| **MinIO** | 兼容 S3 的本地对象存储 |
| **Keycloak** | 身份提供者 (IdP) — 通过 OIDC 实现 SSO、RBAC、MFA |
| **HashiCorp Vault** | 集中式密钥和加密密钥管理 |
| **Nginx** | 具有 TLS 终止功能的反向代理 |
| **Fail2ban** | 暴力破解和入侵防御 |
| **GoAccess** | 实时 Nginx 日志分析 |
| **Trivy** | 容器镜像漏洞扫描器 |
| **Timeshift** | 宿主机级别快照(替代虚拟机快照) |
## ✅ 前置条件
- Linux (Ubuntu 20.04+ 或 Debian)
- Docker CE 20.10+ 和 Docker Compose v2 插件
- `openssl`(用于生成 TLS 证书)
- 浏览器(推荐使用 Chrome/Firefox)
- 整个技术栈需约 4 GB 可用内存
### 安装 Docker (Ubuntu/Mint)
```
# 添加 Docker 官方 GPT key 和 repo
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 将自己添加到 docker 组(避免需要 sudo)
sudo usermod -aG docker $USER
newgrp docker
# 验证
docker --version
docker compose version
```
## 📁 项目结构
```
~/cloud-security-lab/
├── docker-compose.yml # Full stack definition
├── nginx/
│ ├── certs/
│ │ ├── lab.crt # Self-signed TLS certificate
│ │ └── lab.key # Private key
│ └── conf/
│ └── default.conf # Nginx reverse proxy config
├── nextcloud-data/ # Nextcloud persistent data volume
└── minio-data/ # MinIO object storage volume
```
在部署前创建文件夹结构:
```
mkdir -p ~/cloud-security-lab/nginx/{certs,conf}
mkdir -p ~/cloud-security-lab/{nextcloud-data,minio-data}
cd ~/cloud-security-lab
```
## 阶段 1 — 基础设施设置
### 1. 本地 DNS 配置
将所有四个服务的主机名添加到 `/etc/hosts` 中,以便您的浏览器将它们解析为 localhost:
```
sudo nano /etc/hosts
```
添加以下行:
```
127.0.0.1 nextcloud.local
127.0.0.1 keycloak.local
127.0.0.1 minio.local
127.0.0.1 vault.local
```
### 2. docker-compose.yml
创建 `~/cloud-security-lab/docker-compose.yml`:
### 3. Nginx 配置 (HTTP — 初始)
创建 `~/cloud-security-lab/nginx/conf/default.conf`:
```
server {
listen 80;
server_name nextcloud.local;
location / { proxy_pass http://nextcloud:80; proxy_set_header Host $host; }
}
server {
listen 80;
server_name keycloak.local;
location / { proxy_pass http://keycloak:8080; proxy_set_header Host $host; }
}
server {
listen 80;
server_name minio.local;
location / { proxy_pass http://minio:9001; proxy_set_header Host $host; }
}
server {
listen 80;
server_name vault.local;
location / { proxy_pass http://vault:8200; proxy_set_header Host $host; }
}
```
### 4. 部署技术栈
```
cd ~/cloud-security-lab
docker compose up -d
# 验证所有容器是否正在运行
docker compose ps
```
预期输出:所有六个服务均显示为 `Up` 状态。
### 5. 修复 Nextcloud 信任域名
```
docker compose exec nextcloud php occ config:system:set trusted_domains 1 --value=nextcloud.local
```
### 6. 验证访问
在浏览器中打开每个 URL:
| 服务 | URL |
|---------|-----|
| Nextcloud | http://nextcloud.local |
| Keycloak | http://keycloak.local |
| MinIO Console | http://minio.local |
| Vault UI | http://vault.local |
## 阶段 2 — 身份与访问管理
### 1. 创建 Keycloak Realm
1. 导航至 `http://keycloak.local` → 以 admin 身份登录
2. 点击 **Create Realm** → 命名为 `cloud-lab` → 保存
### 2. 创建角色
在 `cloud-lab` realm 中 → **Realm roles** → 创建角色:
| 角色 | 用途 |
|------|---------|
| `admin` | 完全管理访问权限 |
| `editor` | 文件管理 + 有限的管理委派 |
| `viewer` | 只读访问权限 |
### 3. 创建测试用户
为每个角色执行 **Realm → Users → Add user**。创建后:
1. 进入 **Credentials** → 设置密码 → 关闭 “Temporary”(临时)
2. 进入 **Role mapping** → 分配相应的角色
### 4. 将 Nextcloud 注册为 Keycloak Client
1. 在 `cloud-lab` realm 中 → **Clients** → 创建 client
2. **Client ID:** `nextcloud`
3. **Client authentication:** 开启(机密 client)
4. **Valid Redirect URIs:** `http://nextcloud.local/apps/sociallogin/custom_oidc/keycloak`
5. 保存,然后从 Credentials 标签页复制 **Client Secret**
### 5. 在 Nextcloud 中配置社交登录
1. 以 admin 身份登录 Nextcloud → **Apps** → 搜索 “Social Login” → 启用
2. 进入 **Settings → Administration → Social login**
3. 添加一个 **Custom OpenID Connect** 提供商:
| 字段 | 值 |
|-------|-------|
| Internal name | `keycloak` |
| Title | `Keycloak` |
| Authorize URL | `http://keycloak.local/realms/cloud-lab/protocol/openid-connect/auth` |
| Token URL | `http://keycloak.local/realms/cloud-lab/protocol/openid-connect/token` |
| UserInfo URL | `http://keycloak.local/realms/cloud-lab/protocol/openid-connect/userinfo` |
| Logout URL | `http://keycloak.local/realms/cloud-lab/protocol/openid-connect/logout` |
| Client ID | `nextcloud` |
| Client Secret | *(来自 Keycloak Credentials 标签页)* |
| Scope | `openid profile email` |
| Groups claim | `groups` |
### 6. 修复组/角色同步(关键)
默认情况下,Keycloak 不会将角色暴露给 UserInfo endpoint。请添加一个自定义 mapper:
1. `cloud-lab` realm → **Client scopes** → `roles` → **Mappers** → 添加 mapper → By configuration → **User Realm Role**
2. 设置 **Token Claim Name:** `groups`
3. 启用 **Add to userinfo**
4. 保存
验证方式:**Clients → nextcloud → Client scopes → Evaluate** → 选择一个用户 → **Generated user info** — 确认出现了 `groups` 数组。
### 7. 启用 MFA (TOTP)
1. `cloud-lab` realm → **Authentication** → **Required actions**
2. 启用 **Configure OTP** 并将其设置为 **Default action**
所有用户在首次登录时都会被提示注册身份验证器应用(Google Authenticator、FreeOTP 等)。
### 8. 委派管理员权限
在 Nextcloud 中 → **Settings → Administration → Administration privileges**:
- `editor` 组 → 仅授予:**Background jobs**、**Theming**
- `viewer` 组 → 不作委派
## 阶段 3 — 数据安全与加密
### 1. 生成自签名 TLS 证书
```
cd ~/cloud-security-lab/nginx/certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout lab.key \
-out lab.crt \
-subj "/CN=*.local/O=CloudSecLab/C=PK"
```
### 2. 更新 Nginx 以支持 HTTPS
将 `nginx/conf/default.conf` 替换为 HTTPS 配置:
```
# 所有服务的 HTTP → HTTPS 重定向
server {
listen 80;
server_name nextcloud.local keycloak.local minio.local vault.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name nextcloud.local;
ssl_certificate /etc/nginx/certs/lab.crt;
ssl_certificate_key /etc/nginx/certs/lab.key;
location / {
proxy_pass http://nextcloud:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
server {
listen 443 ssl;
server_name keycloak.local;
ssl_certificate /etc/nginx/certs/lab.crt;
ssl_certificate_key /etc/nginx/certs/lab.key;
location / {
proxy_pass http://keycloak:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
server {
listen 443 ssl;
server_name minio.local;
ssl_certificate /etc/nginx/certs/lab.crt;
ssl_certificate_key /etc/nginx/certs/lab.key;
location / {
proxy_pass http://minio:9001;
proxy_set_header Host $host;
}
}
server {
listen 443 ssl;
server_name vault.local;
ssl_certificate /etc/nginx/certs/lab.crt;
ssl_certificate_key /etc/nginx/certs/lab.key;
location / {
proxy_pass http://vault:8200;
proxy_set_header Host $host;
}
}
```
重载 Nginx:
```
docker compose restart nginx
```
### 3. 告知 Nextcloud 其处于 HTTPS 代理之后
```
docker compose exec nextcloud php occ config:system:set overwriteprotocol --value=https
```
### 4. 在 Nextcloud 中启用服务端加密
1. **Settings → Administration → Security** → 启用 **Server-side encryption**
2. 如果上传失败,请显式设置加密模块:
```
docker compose exec nextcloud php occ encryption:set-default-module OC_DEFAULT_MODULE
```
文件在静态存储时使用 **AES-256-CTR** 加密。您可以通过检查容器内的原始字节来进行验证:
```
docker compose exec nextcloud cat /var/www/html/data//files/
# 输出将显示:HBEGIN:oc_encryption_module:OC_DEFAULT_MODULE:cipher:AES-256-CTR...
```
### 5. HashiCorp Vault — 密钥管理
Vault 在 **dev 模式**下运行(已预初始化,无需解封)。使用 token `myroot` 在 `https://vault.local` 登录。
**创建密钥:**
1. 在 `secret/` 处启用 **KV v2** secrets engine
2. 创建密钥:`secret/database` → 添加 key `password` → 保存
**密钥轮换**是内置功能:每次更新都会创建一个新版本。所有以前的版本都可以通过 **Version History** 进行检索。
**通过 CLI:**
```
# 进入 vault 容器
docker compose exec vault sh
# 设置 vault address 和 token
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='myroot'
# 写入 secret
vault kv put secret/database password="InitialPass123"
# 读取 secret
vault kv get secret/database
# 更新(创建版本 2)
vault kv put secret/database password="RotatedPass456"
# 查看版本历史
vault kv metadata get secret/database
```
## 📋 IAM 策略参考
**Realm:** `cloud-lab` | **认证方式:** OpenID Connect(Authorization Code 流程)
### 角色与权限
| 角色 | 权限 |
|------|-------------|
| `admin` | 完全的 Nextcloud 管理访问权限 — 用户管理、安全、加密、应用、共享及所有其他设置 |
| `editor` | 标准文件操作(上传、编辑、共享、删除自有文件)+ 仅委派 **Background jobs** 和 **Theming** 的访问权限 |
| `viewer` | 无管理访问权限;通过标准文件权限对共享内容进行只读访问 |
### 认证策略
- 所有用户均通过 **Keycloak SSO**(“Sign in with Keycloak” 按钮)进行认证
- 本地 Nextcloud `admin` 账户绕过 SSO — 仅保留作为 **break-glass**(紧急备用)凭证使用
- **TOTP MFA** 在 **整个 realm 范围内**强制执行 — 适用于所有角色,而不仅是管理员
- 从 Keycloak 的 UserInfo 响应中的 `groups` claim 中读取组成员身份(由自定义的 “User Realm Role” mapper 填充)
## 🔄 实用命令
```
# 启动所有服务
docker compose up -d
# 停止所有服务
docker compose down
# 查看特定服务的日志
docker compose logs -f nextcloud
# 仅重启 Nginx(在配置更改后)
docker compose restart nginx
# 通过 Shell 进入容器
docker compose exec nextcloud bash
docker compose exec vault sh
# 检查加密状态
docker compose exec nextcloud php occ encryption:status
# 对 image 运行 Trivy 漏洞扫描
trivy image nextcloud:27
```
## 📄 许可证
本项目是出于学术目的而创建的,作为拉合尔管理与技术大学 (University of Management & Technology, Lahore) CY464 — 云安全课程的一部分。
标签:DevSecOps, Docker, 上游代理, 安全合规, 安全防御评估, 测试用例, 版权保护, 私有云存储, 网络代理, 请求拦截, 身份与访问管理