Back to skills
extension
Category: OtherAPI key required

harbor skills

Harbor 镜像仓库综合管理技能。用于 Harbor 日常运维、项目与镜像管理、安全扫描、清理策略、CI/CD 集成、GitOps、复制规则、存储管理、备份恢复、webhook 联动等所有 Harbor 相关操作。当用户提到 Harbor、镜像仓库管理、Docker 镜像、镜像安全扫描、CI/CD 镜像推送/拉取、GitOps 镜像策略、Harbor Webhook 时触发此技能。

personAuthor: user_91733031hubcommunity

Harbor Manager

Harbor 是企业级容器镜像仓库(CNCF 毕业项目)。

环境准备

首次使用需要配置连接信息,优先使用环境变量(可在 TOOLS.md 中预填):

| 变量 | 说明 | 示例 | |------|------|------| | HARBOR_URL | Harbor 地址(不含 /) | https://harbor.mycompany.com | | HARBOR_USERNAME | 管理员账号 | admin | | HARBOR_PASSWORD | 密码或 API Token | Harbor12345 |

或通过对话传入。Token 优先(比密码更安全)。

快速诊断

# 检查 Harbor 健康状态
curl -s -u "$HARBOR_USER:$HARBOR_PASS" "$HARBOR_URL/api/v2.0/health" | jq .

# 列出所有项目(Python)
python3 -c "
import requests, os
r = requests.get(f'{os.environ[\"HARBOR_URL\"]}/api/v2.0/projects',
    headers={'Authorization': f'Basic {os.environ[\"HARBOR_AUTH\"]}'})
print(r.json())
"

项目管理

创建项目

curl -X POST "$HARBOR_URL/api/v2.0/projects" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{
    "project_name": "my-app",
    "public": false,
    "metadata": {"description": "业务镜像仓库", "storage_quota": "500G"}
  }'

修改存储配额(Python)

# refs: references/harbor-api.md
import requests, base64, os

auth = base64.b64encode(f"{u}:{p}".encode()).decode()
headers = {"Authorization": f"Basic {auth}", "Content-Type": "application/json"}

# 查找项目ID
proj = requests.get(f"{url}/api/v2.0/projects", params={"name": "my-app"}, headers=headers).json()[0]
pid = proj["project_id"]

# 更新配额(单位:bytes,500G = 500*1024^3)
requests.put(f"{url}/api/v2.0/projects/{pid}",
    headers=headers, json={"metadata": {"storage_quota": str(500*1024**3)}})
print(f"项目 {pid} 配额已更新为 500G")

镜像管理

列出镜像

# 按项目列出所有镜像
curl "$HARBOR_URL/api/v2.0/projects/my-app/repositories" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '.[].name'

# 查看某镜像的所有标签
curl "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/tags" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '.[].name'

# 镜像详情(含大小、扫描状态)
curl "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/artifacts?with_tag=true&with_scan_overview=true" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '.[].{tags: .tag, size: .size, scan: .scan_summary}'

删除镜像(按标签)

# 删除指定标签(保留其他标签)
curl -X DELETE \
  "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/tags/v1.2.3" \
  -u "$HARBOR_USER:$HARBOR_PASS"

# 批量删除(用 jq 生成)
TAGS=$(curl -s "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/tags" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq -r '.[].name | select(startswith("v0"))')
for tag in $TAGS; do
  echo "删除: $tag"
  curl -X DELETE "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/tags/$tag" \
    -u "$HARBOR_USER:$HARBOR_PASS"
done

删除不留用的镜像(Python)

# refs: references/cleanup-policy.md
import requests, base64, os, datetime

def delete_artifact(project, repo, reference, dry_run=True):
    url = f"{os.environ['HARBOR_URL']}/api/v2.0/projects/{project}/repositories/{repo}/artifacts/{reference}"
    if dry_run:
        print(f"[演练] 应删除: {url}")
    else:
        r = requests.delete(url, headers=auth_header)
        print(f"[已删除] {reference}" if r.status_code == 200 else f"[失败] {r.status_code}")

注意:Harbor GC 需要手动触发,删除后运行垃圾回收。

清理策略

配置保留策略

策略规则在 references/cleanup-policy.md 中有详细说明。

典型场景:

| 场景 | 规则 | |------|------| | 保留最近 N 个版本 | kept_tags >= N(按 push 时间排序) | | 删除 N 天前镜像 | pushed_time < now - N days | | 保留带有特定前缀的标签 | tag =~ ^release- | | 清理快照版本 | tag =~ ^snap- |

演练模式(评估影响)

python3 /root/.openclaw/workspace/skills/harbor-manager/scripts/cleanup_dryrun.py \
  --project my-app --repo my-app--api --policy "保留最近5个" --url "$HARBOR_URL"

清理策略推荐 YAML 格式

# 清理策略示例(用于自动化脚本生成)
project: my-app
repo: my-app--api
rules:
  - action: delete
    condition: tag not in recent(5)
    exclude:
      tags: ["latest", "stable", "release-*"]
  - action: delete
    condition: pushed_time < days_ago(30)
    exclude:
      tags: ["latest"]

垃圾回收(GC)

# 1. 触发 GC(拉取管理员 credentials)
curl -X POST "$HARBOR_URL/api/v2.0/system/gc/schedule" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{"schedule":{"type":"manual"}}'

# 2. 查看 GC 状态
curl "$HARBOR_URL/api/v2.0/system/gc" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '.[] | {id: .id, status: .job_status, start: .start_time}'

# 3. GC 完成后清理孤儿 Blob(自动执行,也可手动触发)
curl -X POST "$HARBOR_URL/api/v2.0/system/gc/schedule" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{"schedule":{"type":"none"}, "dry_run": false}'

⚠️ GC 期间 Harbor 会进入维护模式,建议在低峰期执行。

存储使用情况

# 查看项目存储使用
curl "$HARBOR_URL/api/v2.0/projects/my-app" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '{name: .name, storage: .metadata.storage_quota, used: .metadata.storage_quota_used}'

# 查看系统总体存储
curl "$HARBOR_URL/api/v2.0/statistics" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '{total: .total_storage, used: .used_storage, free: .free_storage}'

复制管理

创建复制规则

curl -X POST "$HARBOR_URL/api/v2.0/replication/policies" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "backup-to-dr-site",
    "src_registry": {"id": 1, "name": "local"},
    "dest_registry": {"id": 2, "name": "dr-harbor"},
    "filters": [
      {"type": "name", "value": "my-app/.*"},
      {"type": "tag", "value": ".*"}
    ],
    "trigger": {"type": "scheduled", "trigger_settings": {"cron": "0 2 * * * *"}},
    "deletion": true,
    "override": true
  }'

触发立即执行

curl -X POST "$HARBOR_URL/api/v2.0/replication/executions" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{"policy_id": 3}'

# 查看执行状态
curl "$HARBOR_URL/api/v2.0/replication/executions?policy_id=3" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '.[] | {id: .id, status: .status, summary: .status_ext}'

代理缓存(Proxy Cache)

创建代理缓存项目

curl -X POST "$HARBOR_URL/api/v2.0/projects" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{
    "project_name": "proxy-cache-dockerhub",
    "public": false,
    "metadata": {
      "proxy_cache_name": "dockerhub",
      "description": "Docker Hub 代理缓存"
    }
  }'

使用代理缓存拉取镜像

# Pod 层面配置代理(通过 /etc/docker/daemon.json)
{
  "registry-mirrors": ["https://proxy-cache-dockerhub.harbor.mycompany.com"]
}

# 或手动拉取
docker pull proxy-cache-dockerhub.library/nginx:latest

漏洞扫描

触发全量扫描

# 扫描单个镜像
curl -X POST \
  "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/artifacts/sha256:abc123.../scan" \
  -u "$HARBOR_USER:$HARBOR_PASS"

# 扫描整个项目所有镜像
curl -X POST \
  "$HARBOR_URL/api/v2.0/projects/my-app/scanAll" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{"selector":"all"}'

获取扫描报告

# 获取镜像扫描摘要
curl "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/artifacts/v1.2.3?with_scan_summary=true" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '{scan: .scan_summary}'

# 导出详细扫描报告(CSV格式)
curl "$HARBOR_URL/api/v2.0/projects/my-app/repositories/my-app--api/artifacts/v1.2.3/scan_report?accept=text/csv" \
  -u "$HARBOR_USER:$HARBOR_PASS"

自动扫描策略

# 设置自动化扫描:镜像推送后自动触发扫描
curl -X PUT "$HARBOR_URL/api/v2.0/projects/my-app" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{"auto_scan": true}'

镜像签名(Notary)

# 1. 启用 Notary(需在 Harbor 部署时配置)
# 2. 对镜像签名(需安装 docker content trust 相关工具)
DOCKER_CONTENT_TRUST=1
DOCKER_CONTENT_TRUST_SERVER="$HARBOR_URL"
docker pull my-app/my-app--api:v1.2.3
docker tag my-app/my-app--api:v1.2.3 harbor.mycompany.com/my-app/my-app--api:v1.2.3
docker push harbor.mycompany.com/my-app/my-app--api:v1.2.3

# 3. 验证签名
DOCKER_CONTENT_TRUST=1
docker pull harbor.mycompany.com/my-app/my-app--api:v1.2.3

机器人账号(Robot Account)

创建项目机器人账号

curl -X POST "$HARBOR_URL/api/v2.0/projects/my-app/robots" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ci-pipeline",
    "description": "CI/CD流水线使用",
    "access": [
      {"resource": "/project/my-app/repository", "action": "push"},
      {"resource": "/project/my-app/repository", "action": "pull"}
    ],
    "expires_at": 0  # 永不过期
  }'

CI 使用机器人账号

# 获取机器人 token(创建时返回的 credentials.secret)
docker login "$HARBOR_URL" -u "robot$my-app$ci-pipeline" -p "$ROBOT_TOKEN"

# Jenkinsfile / GitLab CI 示例
environment:
  DOCKER_AUTH:
    script: |
      TOKEN=$(curl -s -u "robot\$my-app\$ci-pipeline:$ROBOT_SECRET" \
        "$HARBOR_URL/api/v2.0/robots/1/token" | jq -r '.token')
      echo $TOKEN | docker login -u "robot\$my-app\$ci-pipeline" --password-stdin "$HARBOR_URL"

RBAC 权限管理

# 添加项目成员
curl -X POST "$HARBOR_URL/api/v2.0/projects/my-app/members" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{"member_user": {"username": "dev-user"}, "role_id": 2}'  # 2=开发者

# 角色ID说明:1=项目管理员, 2=开发者, 3=访客, 4=维护者

Webhook

创建 Webhook

curl -X POST "$HARBOR_URL/api/v2.0/projects/my-app/webhook" \
  -u "$HARBOR_USER:$HARBOR_PASS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ci-trigger",
    "targets": [{
      "type": "http",
      "address": "https://ci.mycompany.com/webhook/harbor",
      "skip_cert_verify": true,
      "auth_header": "Bearer xxxxx"
    }],
    "event_types": ["SCANNING_COMPLETED", "PUSH_ARTIFACT", "DELETE_ARTIFACT"]
  }'

Webhook payload 示例:

{
  "type": "PUSH_ARTIFACT",
  "occur_at": 1700000000,
  "artifact": {
    "media_type": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:abc123",
    "tags": ["v1.2.3"]
  },
  "project": {"id": 1, "name": "my-app"},
  "repository": {"name": "my-app--api"}
}

审计日志

# 查看项目审计日志
curl "$HARBOR_URL/api/v2.0/projects/my-app/logs?page=1&page_size=20" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq '.'

# 导出为 CSV
curl "$HARBOR_URL/api/v2.0/projects/my-app/logs?page=1&page_size=100&sort=op_time_desc" \
  -u "$HARBOR_USER:$HARBOR_PASS" | jq -r '.[] | [.op_time, .username, .resource, .operation] | @csv'

备份与恢复

备份(Harbor 数据)

# 备份清单(推荐 cron 定期执行)
# refs: references/backup-recovery.md
BACKUP_DIR="/data/harbor-backup"
DATE=$(date +%Y%m%d_%H%M%S)

# 1. 备份数据库
docker exec -t harbor-db pg_dump -U postgres registry > "$BACKUP_DIR/harbor-db-$DATE.sql"

# 2. 备份核心配置(shared volume)
tar czf "$BACKUP_DIR/harbor-config-$DATE.tar.gz" \
  /data/harbor/redis /data/harbor/registry /data/harbor/trivy-adapter

# 3. 上传至对象存储
# rclone sync "$BACKUP_DIR/" "s3:my-bucket/harbor-backups/"

echo "备份完成: $DATE"

恢复

# 1. 停止 Harbor
cd /opt/harbor && docker-compose down

# 2. 恢复数据库
docker exec -i harbor-db psql -U postgres registry < "$BACKUP_DIR/harbor-db-$DATE.sql"

# 3. 恢复配置文件
tar xzf "$BACKUP_DIR/harbor-config-$DATE.tar.gz" -C /

# 4. 重启 Harbor
docker-compose up -d

合规性检查

# 等保 2.0 / GDPR 检查项(详见 references/compliance.md)
# 自动化检查脚本:
python3 /root/.openclaw/workspace/skills/harbor-manager/scripts/compliance_check.py \
  --harbor-url "$HARBOR_URL" --auth "$HARBOR_USER:$HARBOR_PASS" \
  --standard " 等保2级" --output /tmp/harbor-compliance-report.html

检查项包括:

  • ✅ 匿名访问是否关闭
  • ✅ Robot Account 是否有过期设置
  • ✅ 镜像扫描覆盖率
  • ✅ CVE 漏洞是否在可接受阈值内
  • ✅ 审计日志保留时长
  • ✅ HTTPS 强制开启
  • ✅ 密码策略配置

CI/CD 集成速查

| 工具 | 集成方式 | |------|---------| | Jenkins | withCredentials([string(credentialsId: 'harbor', variable: 'HARBOR_TOKEN')]) + docker login | | GitLab CI | image: docker:latest + before_script 登录 | | GitHub Actions | uses: docker/login-action@v3 | | Argo CD | Application YAML 中引用 Image Updater 或使用 Argo CD Image Updater | | Tekton | Task 中用 dockerauth secret 登录后 docker push |

GitOps 配置管理

参考 references/gitops.md 了解更多 GitOps 工具与 Harbor 的集成方式。

参考文档

| 文件 | 内容 | |------|------| | references/harbor-api.md | 完整 Harbor API v2.0 参考(认证、请求格式、错误码) | | references/cleanup-policy.md | 镜像清理策略详细规则与演练脚本 | | references/webhook.md | Webhook 事件类型与 payload 格式说明 | | references/backup-recovery.md | 备份恢复详细步骤与灾难恢复预案 | | references/gitops.md | GitOps 集成(Argo CD / Flux / Helm) | | references/compliance.md | 等保2.0 / GDPR 合规检查项说明 | | scripts/cleanup_dryrun.py | 清理演练脚本 | | scripts/compliance_check.py | 合规性检查脚本 | | scripts/robot_account.py | 机器人账号创建与轮换脚本 |