主题
Harbor Admin 密码丢失 — 直接数据库重置实战
当 Harbor admin 密码丢失且无法通过 UI/API 修改(因为修改密码接口要求提供旧密码)时,可以通过直接操作 PostgreSQL 数据库来重置密码。本文记录在 Harbor v2.11.2 上完成 admin 密码重置的完整过程,包括密码哈希算法逆向分析、新哈希生成、数据库更新和验证。
适用对象:Harbor v2.x(本地数据库认证模式),拥有服务器 SSH 和 Docker 权限。
一、环境信息
| 项目 | 值 |
|---|---|
| 服务器 | 192.168.122.156 |
| Harbor 版本 | v2.11.2 |
| 部署方式 | docker-compose(/root/harbor/) |
| 对外端口 | 30000(HTTP) |
| 数据库容器 | harbor-db(PostgreSQL) |
| 数据库名 | registry |
二、密码哈希算法分析
2.1 源码确认
Harbor v2.11.2 密码哈希的核心逻辑在 src/common/utils/encrypt.go:
go
// Encrypt encrypts the content with salt
func Encrypt(content string, salt string, encrptAlg string) string {
return fmt.Sprintf("%x", pbkdf2.Key([]byte(content), []byte(salt), 4096, 16, HashAlg[encrptAlg]))
}参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
| 算法 | PBKDF2-HMAC-SHA256 | encrptAlg 默认 sha256 |
| 迭代次数 | 4096 | 固定值 |
| 输出长度 | 16 字节(32 位十六进制) | dklen=16 |
2.2 密码生成与验证流程
在 src/pkg/user/manager.go 中:
go
// 生成新密码
func injectPasswd(u *commonmodels.User, password string) {
salt := utils.GenerateRandomString() // 生成 32 字符随机 salt
u.Password = xxx salt, utils.SHA256) // PBKDF2 哈希
u.Salt = salt
u.PasswordVersion = utils.SHA256
}
// 验证密码
func (m *manager) MatchLocalPassword(ctx context.Context, usernameOrEmail, password string) (*commonmodels.User, error) {
// ...
if utils.Encrypt(password, entry.Salt, entry.PasswordVersion) == entry.Password {
// 匹配成功
}
}结论:password = xxx salt, 4096, 16) → 输出 32 位十六进制字符串。
三、操作步骤
3.1 查看当前 admin 用户信息
bash
docker exec harbor-db psql -U postgres -d registry \
-c "SELECT user_id, username, salt, password, password_version FROM harbor_user WHERE user_id = 1;"3.2 生成新密码哈希
在服务器上用 Python 生成新密码的哈希值和 salt:
python
import hashlib
import binascii
import os
import string
new_pw = "你的新密码"
# 生成 32 字符随机 salt(与 Harbor 格式一致)
chars = string.ascii_letters + string.digits
new_salt = "".join([chars[b % len(chars)] for b in os.urandom(32)])
# 计算 PBKDF2 哈希
new_hash = hashlib.pbkdf2_hmac("sha256", new_pw.encode(), new_salt.encode(), 4096, dklen=16)
new_hash_hex = binascii.hexlify(new_hash).decode()
print(f"salt: {new_salt}")
print(f"hash: {new_hash_hex}")3.3 更新数据库
bash
docker exec harbor-db psql -U postgres -d registry -c \
"UPDATE harbor_user SET \
password = 'xxx', \
salt = '<new_salt>', \
password_version = 'sha256', \
update_time = NOW() \
WHERE user_id = 1;"预期输出:UPDATE 1
3.4 重启 Harbor Core
Harbor Core 会在内存中缓存用户信息,需要重启使其重新加载:
bash
cd /root/harbor && docker-compose restart core注意:直接
docker restart harbor-core可能被服务器安全策略禁止,使用docker-compose restart更可靠。
3.5 验证新密码
bash
# 测试新密码(预期 HTTP 200)
curl -sk -u admin:xxx http://<harbor_addr>:<port>/api/v2.0/users/current -w "\nHTTP_CODE: %{http_code}\n"
# 确认旧密码已失效(预期 HTTP 401)
curl -sk -u admin:xxx http://<harbor_addr>:<port>/api/v2.0/users/current -w "\nHTTP_CODE: %{http_code}\n"四、实际操作记录
本次操作将 admin 密码重置为 xxx:
| 步骤 | 结果 |
|---|---|
| 生成新 salt | haRDKOkinRmcSaLWFXNBpfQIf5pqq9Ui |
| 生成新 hash | 8b17c5597c029515e63fde1f5a3bbc38 |
| 数据库更新 | UPDATE 1 ✅ |
| 重启 Core | docker-compose restart core ✅ |
| 旧密码验证 | HTTP 401(已失效) ✅ |
| 新密码验证 | HTTP 200(登录成功) ✅ |
五、注意事项
为什么不能通过 API 改密码:Harbor 的密码修改接口 (
xxx) 要求提供old_password,如果旧密码未知则无法使用。updateInitPassword逻辑:Harbor Core 启动时会检查 admin 用户是否有 salt。如果有 salt(即已初始化),不会重置密码,因此直接数据库更新不会被启动流程覆盖。password_version字段:务必设置为sha256,否则验证时使用错误的哈希算法会导致登录失败。清理临时文件:操作完成后记得删除服务器上的临时脚本文件。