Skip to content

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-SHA256encrptAlg 默认 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

步骤结果
生成新 salthaRDKOkinRmcSaLWFXNBpfQIf5pqq9Ui
生成新 hash8b17c5597c029515e63fde1f5a3bbc38
数据库更新UPDATE 1
重启 Coredocker-compose restart core
旧密码验证HTTP 401(已失效) ✅
新密码验证HTTP 200(登录成功) ✅

五、注意事项

  1. 为什么不能通过 API 改密码:Harbor 的密码修改接口 (xxx) 要求提供 old_password,如果旧密码未知则无法使用。

  2. updateInitPassword 逻辑:Harbor Core 启动时会检查 admin 用户是否有 salt。如果有 salt(即已初始化),不会重置密码,因此直接数据库更新不会被启动流程覆盖。

  3. password_version 字段:务必设置为 sha256,否则验证时使用错误的哈希算法会导致登录失败。

  4. 清理临时文件:操作完成后记得删除服务器上的临时脚本文件。