Archery + LDAP 一体化部署
Archery 是一个开源的 SQL 审核与运维管理平台,它主要面向 DBA 和开发人员,用于安全、可控地管理数据库变更、查询和慢 SQL 分析。
主要功能:
支持多种数据库:MySQL、PostgreSQL、SQLServer、ClickHouse 等
提供 SQL 审核、执行工单、慢 SQL 分析、查询权限控制
支持接入 LDAP、钉钉、企业微信、飞书 等认证方式
通过 Web 界面统一管理,提高数据库操作安全性与合规性
一、安装 Docker 与 Docker Compose
> 适用于 CentOS 7+
# 安装依赖 yum install -y yum-utils # 添加 Docker 官方阿里云镜像源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装 Docker 与 Compose 插件 yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 启动并设置开机自启 systemctl enable docker --now # 检查版本 docker -v docker-compose version || docker compose version # 若 docker-compose 插件不可用,可使用传统二进制安装: curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
二、部署 Archery
1. 下载 Archery 源码包
wget https://github.com/hhyo/Archery/archive/refs/tags/v1.13.0.tar.gz tar xf v1.13.0.tar.gz cd Archery-1.13.0/src/docker-compose
2. 启动容器服务
docker-compose -f docker-compose.yml up -d
# 默认会启动 `archery`、`mysql`、`redis`、`nginx` 等容器。
# 若端口冲突,请在 `.env` 中修改 `NGINX_PORT=9123`。
三、初始化数据库结构
1. 进入容器:
docker exec -it archery /bin/bash
2. 进入虚拟环境:
source /opt/venv4archery/bin/activate
cd /opt/archery
3. 执行表结构初始化:
python3 manage.py makemigrations sql
python3 manage.py migrate
4. 加载基础数据:
python3 manage.py dbshell < sql/fixtures/auth_group.sql
python3 manage.py dbshell < src/init_sql/mysql_slow_query_review.sql
5. 创建管理员用户:
python3 manage.py createsuperuser
6 退出容器:
exit
四、日志与访问
1. 查看运行日志:
docker logs archery -f --tail=100
2. 访问系统:
http://<服务器IP>:9123
五、部署LDAP(企业统一认证)
推荐 go-ldap-admin,它是一款基于 Go 语言开发的 轻量级 Web LDAP 管理平台。
它可视化地管理 LDAP 用户、组织、组、权限等信息,支持常见的 OpenLDAP 或 AD 环境。
主要特点:
简洁易用的 Web 管理界面
用户、组织、组、权限图形化管理
支持账号创建、修改、禁用、密码重置等操作
应用场景:
搭建统一身份认证系统(SSO)
为 Archery、Jenkins、GitLab、SonarQube 等系统提供 LDAP 认证支持
1. 安装:
# docker-compose.yml 文件
services: go-ldap-admin: image: docker.cnb.cool/opsre/go-ldap-admin container_name: go-ldap-admin hostname: go-ldap-admin restart: always environment: WAIT_HOSTS: openldap:389 configs: - source: go_ldap_admin_config target: /app/config.yml ports: - 8888:8888 volumes: - ./data/go-ldap-admin:/app/data depends_on: - openldap links: - openldap:go-ldap-admin-openldap networks: - go-ldap-admin openldap: image: docker.cnb.cool/znb/images/openldap:1.4.1 container_name: go-ldap-admin-openldap hostname: go-ldap-admin-openldap restart: always environment: TZ: Asia/Shanghai LDAP_ORGANISATION: "sh.com" LDAP_DOMAIN: "sh.com" LDAP_ADMIN_PASSWORD: "xxxxxx" command: [ '--copy-service' ] volumes: - ./data/openldap/database:/var/lib/ldap - ./data/openldap/config:/etc/ldap/slapd.d ports: - 389:389 networks: - go-ldap-admin phpldapadmin: image: docker.cnb.cool/znb/images/phpldapadmin:0.9.0 container_name: go-ldap-admin-phpldapadmin hostname: go-ldap-admin-phpldapadmin restart: always environment: TZ: Asia/Shanghai PHPLDAPADMIN_HTTPS: "false" PHPLDAPADMIN_LDAP_HOSTS: go-ldap-admin-openldap ports: - 8091:80 volumes: - ./data/phpadmin:/var/www/phpldapadmin depends_on: - openldap links: - openldap:go-ldap-admin-openldap networks: - go-ldap-admin configs: go_ldap_admin_config: content: | # delelopment system: # 设定模式(debug/release/test,正式版改为release) mode: release # url前缀 url-path-prefix: api # 程序监听端口 port: 8888 # 是否初始化数据(没有初始数据时使用, 已发布正式版改为false) init-data: true logs: # 日志等级(-1:Debug, 0:Info, 1:Warn, 2:Error, 3:DPanic, 4:Panic, 5:Fatal, -1<=level<=5, 参照zap.level源码) level: 0 # 日志路径 path: data/logs # 文件最大大小, M max-size: 50 # 备份数 max-backups: 100 # 存放时间, 天 max-age: 30 # 是否压缩 compress: false database: # 数据库类型 mysql sqlite3 driver: mysql # 数据库连接sqlite3数据文件的路径 source: data/go-ldap-admin.db mysql: # 用户名 username: root # 密码 password: xxxxxx # 数据库名 database: go_ldap_admin # 主机地址 host: 10.0.0.100 # 端口 port: 3306 # 连接字符串参数 query: parseTime=True&loc=Local&timeout=10000ms # 是否打印日志 log-mode: true # 数据库表前缀(无需再末尾添加下划线, 程序内部自动处理) table-prefix: tb # 编码方式 charset: utf8mb4 # 字符集(utf8mb4_general_ci速度比utf8mb4_unicode_ci快些) collation: utf8mb4_general_ci # jwt配置 jwt: # jwt标识 realm: test jwt # 服务端密钥 key: hjYtXJmMe4kyPqf1 # token过期时间, 小时 timeout: 12000 # 刷新token最大过期时间, 小时 max-refresh: 12000 # 令牌桶限流配置 rate-limit: # 填充一个令牌需要的时间间隔,毫秒 fill-interval: 50 # 桶容量 capacity: 200 # email configuration email: port: '465' user: 'xxxxxx@qq.con' from: 'ldap-admin后台' host: 'smtpdm.aliyun.com' is-ssl: true pass: 'xxxxxx' # # ldap 配置 ldap: # ldap服务器地址 url: ldap://10.0.0.100:389 # ladp最大连接数设置 max-conn: 10 # ldap服务器基础DN base-dn: "dc=sh,dc=com" # ldap管理员DN admin-dn: "cn=admin,dc=sh,dc=com" # ldap管理员密码 admin-pass: "xxxxxx" # ldap用户OU user-dn: "ou=people,dc=sh,dc=com" # ldap用户初始默认密码 user-init-password: "xxxxxx" # 是否允许更改分组DN group-name-modify: false # 是否允许更改用户DN user-name-modify: false # 用户密码加密方式 默认为 ssha 还可指定为 clear(表示不加密) user-password-encryption-type: "ssha" # 默认邮箱后缀 default-email-suffix: "sh.com" # 📢 即便用不到如下三段配置信息,也不要删除,否则会有一些奇怪的错误出现 dingtalk: # 配置获取详细文档参考: http://ldapdoc.shs.com/pages/94f43a/ flag: "dingtalk" # 作为钉钉在平台的标识 app-key: "xxxxxxxxxxxxxxx" # 应用的key app-secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" # 应用的secret agent-id: "12121212" # 目前agent-id未使用到,可忽略 enable-sync: false # 是否开启定时同步钉钉的任务 dept-sync-time: "0 30 2 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点 user-sync-time: "0 30 3 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点 dept-list: # 配置要同步的部门列表,配置留空则同步所有部门,在开头加^表示不同步此部门 #- "48456726" # 需要同步的部门ID #- "^61213417" # 不需要同步的部门ID is-update-syncd: false # 当钉钉用户的邮箱,手机号,部门等信息更新之后,是否同步更新,默认为false,如果你不了解这个字段的含义,则不建议开启 user-leave-range: 0 #按配置天数查离职时间范围内的用户,为0时不限制 wecom: # 配置获取详细文档参考:http://ldapdoc.shs.com/pages/cf1698/ flag: "wecom" # 作为微信在平台的标识 corp-id: "xxxx" # 企业微信企业ID agent-id: 1000003 # 企业微信中创建的应用ID corp-secret: "xxxxx" # 企业微信中创建的应用secret enable-sync: false # 是否开启定时同步企业微信的任务 dept-sync-time: "0 30 2 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点 user-sync-time: "0 30 3 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点 is-update-syncd: false # 当企微用户的邮箱,手机号,部门等信息更新之后,是否同步更新,默认为false,如果你不了解这个字段的含义,则不建议开启 feishu: # 配置获取详细文档参考:http://ldapdoc.shs.com/pages/83c90b/ flag: "feishu" # 作为飞书在平台的标识 app-id: "xxxxxxx" # 飞书的app-id app-secret: "xxxxxxxxxxx" # 飞书的app-secret enable-sync: false # 是否开启定时同步飞书的任务 dept-sync-time: "0 20 0 * * *" # 部门同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点 user-sync-time: "0 40 0 * * *" # 用户同步任务的时间点 * * * * * * 秒 分 时 日 月 周, 请把时间设置在凌晨 1 ~ 5 点,注意请把用户同步的任务滞后于部门同步时间,比如部门为2点,则用户为3点 dept-list: # 配置要同步的部门列表,配置留空则同步所有部门,在开头加^表示不同步此部门 #- "48456726" # 需要同步的部门ID #- "^61213417" # 不需要同步的部门ID is-update-syncd: false # 当飞书用户的邮箱,手机号,部门等信息更新之后,是否同步更新,默认为false,如果你不了解这个字段的含义,则不建议开启 networks: go-ldap-admin: driver: bridge
# 启动 docker-compose up -d
2. 访问系统:
http://<服务器IP>:8888
六、接入 LDAP
1. archery/settings.py 增加配置:
import ldap from django_auth_ldap.config import LDAPSearch ENABLE_LDAP = True LDAP_SERVER = "ldap://10.0.0.100:389" LDAP_BIND_DN = "cn=admin,dc=sh,dc=com" LDAP_BIND_PASSWORD = "xxxxxx" LDAP_SEARCH_BASE = "ou=people,dc=sh,dc=com" AUTH_LDAP_USER_SEARCH = LDAPSearch( "ou=people,dc=shs,dc=com", ldap.SCOPE_SUBTREE, "(uid=%(user)s)" ) LDAP_ATTR_MAP = { "username": "uid", "display": "cn", "email": "mail", } LDAP_AUTO_CREATE_USER = True
2. 重启archery
docker restart archery
七、接入Nginx
1. 部署nginx,并配置证书。修改nginx配置。
server{ listen 443 ssl; #监听的端口 server_name archery.xxx.com; ssl_protocols TLSv1.2 TLSv1.3; ssl_certificate /etc/nginx/cert/cert.crt; # 配置证书文件地址 ssl_certificate_key /etc/nginx/cert/cert.key; # 配置密钥文件地址 client_max_body_size 100m; #配置请求的body大小
location / { proxy_pass http://内网IP:9123; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
2. archery/settings.py 增加配置:
CSRF_TRUSTED_ORIGINS = ['https://archery.xxx.com']
3. 重启archery
docker restart archery
八、常见问题与排查
| `Access denied for user 'root'@'localhost'` | `.env` 中数据库密码不匹配 | 确认 `DATABASE_URL` 与 MySQL 容器一致 | | `AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance` | 未引入 `from django_auth_ldap.config import LDAPSearch` | 加入该 import | | `SERVER_DOWN: Can't contact LDAP server` | 容器网络无法访问 LDAP | 确保 Archery 和 LDAP 在同一网络 (`docker network ls`) | | 登录 LDAP 用户失败 | LDAP DN / Base 配置错误 | 使用 `ldapsearch` 测试,确认能查询用户 |

浙公网安备 33010602011771号