This release is a pre-release and may not be stable for production use.
Harbor Container Registry Plugin for Waldur Site Agent
This plugin provides production-ready integration between Waldur Mastermind and Harbor container registry, enabling automated management of Harbor projects, storage quotas, and OIDC-based access control.
Features
- ✅ Automated Project Management: Creates Harbor projects for each Waldur resource
- ✅ Storage Quota Management: Configurable storage limits with usage tracking
- ✅ OIDC Integration: Automatic OIDC group creation and assignment for access control
- ✅ Usage Reporting: Reports container storage usage back to Waldur for billing
- ✅ Robot Account Authentication: Uses Harbor robot accounts for API operations
- ✅ Production Ready: All operations tested and working with Harbor API v2.0
Architecture & Mapping
Waldur ↔ Harbor Resource Mapping
graph TB
subgraph "Waldur Mastermind"
WC[Waldur Customer<br/>customer-slug]
WP[Waldur Project<br/>project-slug]
WR1[Waldur Resource 1<br/>resource-slug-1]
WR2[Waldur Resource 2<br/>resource-slug-2]
WU1[Waldur User 1]
WU2[Waldur User 2]
WU3[Waldur User 3]
end
subgraph "Harbor Registry"
HG[OIDC Group<br/>waldur-project-slug]
HP1[Harbor Project 1<br/>waldur-resource-slug-1]
HP2[Harbor Project 2<br/>waldur-resource-slug-2]
HQ1[Storage Quota 1<br/>e.g., 10GB]
HQ2[Storage Quota 2<br/>e.g., 20GB]
HR1[Container Repos 1]
HR2[Container Repos 2]
end
subgraph "OIDC Provider"
OG[OIDC Group<br/>waldur-project-slug]
OU1[OIDC User 1]
OU2[OIDC User 2]
OU3[OIDC User 3]
end
%% Relationships
WC --> WP
WP --> WR1
WP --> WR2
WP --> WU1
WP --> WU2
WP --> WU3
%% Waldur to Harbor mapping
WR1 -.->|"1:1 mapping"| HP1
WR2 -.->|"1:1 mapping"| HP2
WP -.->|"1:1 mapping"| HG
%% Harbor internal relationships
HG -->|"Developer role"| HP1
HG -->|"Developer role"| HP2
HP1 --> HQ1
HP2 --> HQ2
HP1 --> HR1
HP2 --> HR2
%% OIDC relationships
WU1 -.->|"SSO identity"| OU1
WU2 -.->|"SSO identity"| OU2
WU3 -.->|"SSO identity"| OU3
OU1 --> OG
OU2 --> OG
OU3 --> OG
HG -.->|"Same group"| OG
%% Styling
classDef waldur fill:#e1f5fe
classDef harbor fill:#fff3e0
classDef oidc fill:#f3e5f5
class WC,WP,WR1,WR2,WU1,WU2,WU3 waldur
class HG,HP1,HP2,HQ1,HQ2,HR1,HR2 harbor
class OG,OU1,OU2,OU3 oidc
Key Mapping Rules
-
Waldur Resource → Harbor Project (1:1)
- Each Waldur resource creates a separate Harbor project
- Provides complete isolation between different registry resources
- Project names:
{allocation_prefix}{resource_slug}
-
Waldur Project → OIDC Group (1:1)
- One OIDC group per Waldur project for access control
- All project team members get access to ALL Harbor projects within the Waldur project
- Group names:
{oidc_group_prefix}{project_slug}
-
Storage Management
- Each Harbor project gets individual storage quota
- Quotas set based on Waldur resource limits
- Usage reported back to Waldur for billing
Installation
- Install the plugin alongside waldur-site-agent:
# From the workspace root
uv sync --all-packages
- Configure the plugin in your waldur-site-agent configuration file
Configuration
Add the Harbor backend configuration to your waldur-site-agent-config.yaml:
offerings:
harbor-registry:
backend_type: harbor
backend_settings:
# Harbor instance URL
harbor_url: "https://harbor.example.com"
# Robot account credentials (ensure robot has sufficient permissions)
robot_username: "robot$waldur-agent"
robot_password: "your-robot-password-here"
# Default storage quota in GB for new projects
default_storage_quota_gb: 10
# Naming prefixes
oidc_group_prefix: "waldur-" # OIDC groups: waldur-{project_slug}
allocation_prefix: "waldur-" # Harbor projects: waldur-{resource_slug}
# Harbor project role for OIDC groups
# 1=Admin, 2=Developer (recommended), 3=Guest, 4=Maintainer
project_role_id: 2
backend_components:
storage:
measured_unit: "GB"
accounting_type: "limit"
label: "Container Storage"
unit_factor: 1
# Waldur API settings
api_url: "https://waldur.example.com/api/"
api_token: "your-waldur-api-token"
# Offering UUID in Waldur
offering_uuid: "harbor-offering-uuid"
Robot Account Permissions
Critical: The Harbor robot account must have the following permissions:
- ✅ Project creation (
POST /api/v2.0/projects) - ✅ Project deletion (
DELETE /api/v2.0/projects/{id}) - REQUIRED for proper resource lifecycle - ✅ Quota management (
GET/PUT /api/v2.0/quotas) - ✅ User group management (
GET/POST /api/v2.0/usergroups) - ✅ Project member management (
GET/POST/DELETE /api/v2.0/projects/{id}/members)
✅ Verified: All operations including project deletion are working with proper system-level robot account permissions.
Harbor Setup
1. Create Robot Account
- Login to Harbor as admin
- Navigate to Administration → Robot Accounts
- Create a new robot account with system-level permissions:
- Level: System (not project-specific)
- Permissions:
- Project: Create, Read, Update, Delete
- Resource: Create, Read, Update
- Member: Create, Read, Update, Delete
- Quota: Read, Update
- Save the credentials for configuration
Note: The robot account needs system-level permissions to delete projects. Project-level robot accounts cannot delete their own projects.
2. Configure OIDC Authentication
- Navigate to Administration → Configuration → Authentication
- Set Auth Mode to "OIDC"
- Configure OIDC provider settings:
- OIDC Endpoint: Your identity provider URL
- OIDC Client ID: Harbor client ID in your IdP
- OIDC Client Secret: Harbor client secret
- OIDC Scope:
openid,email,profile,groups - Group Claim Name:
groups(or your IdP's group claim)
3. Configure Storage Quotas
- Navigate to Administration → Configuration → System Settings
- Set appropriate global storage quota limits
- Individual project quotas will be managed by the agent
Usage
Running the Agent
# Process orders (create/delete Harbor projects)
uv run waldur_site_agent -m order_process -c config.yaml
# Report usage back to Waldur
uv run waldur_site_agent -m report -c config.yaml
# Synchronize memberships (OIDC group management)
uv run waldur_site_agent -m membership_sync -c config.yaml
Systemd Service
Create a systemd service for automated operation:
[Unit]
Description=Waldur Harbor Agent - Order Processing
After=network.target
[Service]
Type=simple
User=waldur
ExecStart=/usr/local/bin/waldur_site_agent -m order_process -c /etc/waldur/harbor-config.yaml
Restart=on-failure
RestartSec=60
[Install]
WantedBy=multi-user.target
API Operations
The plugin implements the following Harbor API operations:
✅ Project Management (Fully Working)
- ✅ Create project with minimal payload
- ✅ Get project details and metadata
- ✅ List all projects
- ✅ Delete project (complete resource lifecycle)
✅ Storage Quota Management (Fully Working)
- ✅ Set project storage quotas
- ✅ Update project storage quotas
- ✅ Query current quota usage
- ✅ Report storage consumption for billing
✅ OIDC Group Management (Fully Working)
- ✅ Create OIDC groups
- ✅ Assign groups to projects with specified roles (Admin/Developer/Guest/Maintainer)
- ✅ List existing user groups
- ✅ Search for specific groups
✅ Usage Reporting (Fully Working)
- ✅ Query project storage usage via quota API
- ✅ Report repository counts
- ✅ Track storage consumption for Waldur billing
- ✅ Get project metadata and statistics
🔄 Supported Waldur Operations
- ✅ order_process: Create/update Harbor projects and quotas
- ✅ report: Report storage usage back to Waldur
- ✅ membership_sync: Manage OIDC group memberships
- ✅ diagnostics: Health checks and connectivity testing
- ❌ pause: Not supported (Harbor has no pause concept, returns False)
Testing
Run the test suite:
# Run all Harbor plugin tests
uv run pytest plugins/harbor/tests/ -v
# Run with coverage
uv run pytest plugins/harbor/tests/ --cov=waldur_site_agent_harbor
Troubleshooting
✅ Known Issues & Solutions
1. CSRF Token Errors (SOLVED)
Symptom: 403 Forbidden - CSRF token not found in request
Root Cause: Harbor's session-based authentication requires CSRF tokens for persistent sessions.
✅ Solution: The plugin now uses direct HTTP requests with authentication tuples instead of persistent sessions, which bypasses CSRF requirements entirely.
Technical Details:
# OLD (caused CSRF issues)
session = requests.Session()
session.headers.update({"Authorization": "Basic ..."})
response = session.post(url, json=data)
# NEW (works perfectly)
auth = (username, password)
response = requests.post(url, auth=auth, json=data)
2. Robot Account Permissions
Symptoms:
- Can list projects but cannot create them
- Can create projects but cannot set quotas
- Cannot create OIDC groups
✅ Solution: Ensure robot account has system-level permissions:
- Login to Harbor as admin
- Go to Administration → Robot Accounts
- Edit your robot account
- Grant these system-level permissions:
- Project: Create, Read, Update, Delete
- Resource: Create, Read, Update
- Member: Create, Read, Update, Delete
- Quota: Read, Update
Critical: Without project deletion permissions, Harbor projects will accumulate when Waldur resources are terminated, leading to storage waste and potential quota issues.
Common Issues
-
Authentication Failures
- ✅ Verify robot account credentials in configuration
- ✅ Test connectivity:
curl -u "robot\$user:pass" https://harbor.example.com/api/v2.0/health - ✅ Ensure Harbor API v2.0 is enabled
-
OIDC Group Issues
- ✅ Verify OIDC configuration in Harbor (Administration → Configuration → Authentication)
- ✅ Check group claim configuration (
groupsis common) - ✅ Ensure OIDC provider is properly configured
-
Storage Quota Problems
- ✅ Check global quota settings in Harbor (Administration → Configuration → System Settings)
- ✅ Verify project-specific quotas:
curl -u "robot\$user:pass" https://harbor.example.com/api/v2.0/quotas - ✅ Monitor Harbor system storage availability
Debugging
Enable Debug Logging
# In waldur-site-agent config
logging:
level: DEBUG
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
Test Harbor Client Directly
from waldur_site_agent_harbor.client import HarborClient
client = HarborClient("https://harbor.example.com", "robot$user", "password")
# Test connectivity
print("Ping:", client.ping())
# List projects
projects = client.list_resources()
print("Projects:", [p.name for p in projects])
# Test permissions
try:
# This should work if permissions are correct
group_id = client.create_user_group("test-group")
print("Group created:", group_id)
except Exception as e:
print("Permission issue:", e)
Check Logs
# For systemd deployments
journalctl -u waldur-harbor-agent -f --since "1 hour ago"
# For direct execution
tail -f /var/log/waldur-site-agent.log
Verification Commands
Test robot account permissions manually:
# Test authentication
curl -u "robot\$username:password" https://harbor.example.com/api/v2.0/health
# Test project listing
curl -u "robot\$username:password" https://harbor.example.com/api/v2.0/projects
# Test quota access
curl -u "robot\$username:password" https://harbor.example.com/api/v2.0/quotas
# Test group management
curl -u "robot\$username:password" https://harbor.example.com/api/v2.0/usergroups
# Test project deletion permissions (CRITICAL)
# First create a test project
curl -X POST -H "Content-Type: application/json" \
-u "robot\$username:password" \
-d '{"project_name":"deletion-test","metadata":{"public":"false"}}' \
https://harbor.example.com/api/v2.0/projects
# Then try to delete it (should return 200/204, not 403)
# Get project ID first, then delete
curl -X DELETE -u "robot\$username:password" \
https://harbor.example.com/api/v2.0/projects/{project_id}
Expected Results
- ✅ 200/201 for creation operations
- ✅ 200 for read operations
- ✅ 200/204 for update operations
- ✅ 200/204 for deletion operations
- ❌ 403 Forbidden indicates insufficient permissions
Development
Project Structure
plugins/harbor/
├── waldur_site_agent_harbor/
│ ├── __init__.py
│ ├── backend.py # HarborBackend implementation
│ ├── client.py # Harbor API client
│ └── exceptions.py # Custom exceptions
├── tests/
│ ├── test_harbor_backend.py
│ └── test_harbor_client.py
├── pyproject.toml
└── README.md
Adding New Features
- Extend the
HarborClientclass for new API operations - Update
HarborBackendto utilize new client methods - Add corresponding tests
- Update documentation
License
This plugin is part of the Waldur Site Agent project and follows the same licensing terms.
Support
For issues and questions:
- Create an issue in the Waldur Site Agent repository
- Contact the OpenNode team
Metadata
Release files for waldur-site-agent-harbor 1.0.8rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| waldur_site_agent_harbor-1.0.8rc1.tar.gz | 18.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| waldur_site_agent_harbor-1.0.8rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 33.8 kB
Release files / waldur_site_agent_harbor-1.0.8rc1.tar.gz
| Download URL | waldur_site_agent_harbor-1.0.8rc1.tar.gz |
|---|---|
| Size | 18.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
41f6443a9cbf9106246f4d6bfecf2e9d9d732abaefa603c63c94c28bd78fedec
|
|
BLAKE2b-256 checksum How to use checksums |
236a49f4153d6fae2b59f3286af7f4211368a79cbae6c24f2d46649efe4e1c9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / waldur_site_agent_harbor-1.0.8rc1-py3-none-any.whl
| Download URL | waldur_site_agent_harbor-1.0.8rc1-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5c8773ef04a4ccbb285fcb8ada17e4447c1757d7693f75b30ee72795a3e4e77b
|
|
BLAKE2b-256 checksum How to use checksums |
588ee65b474a188b88140998afc98cfd2abf76e37ed4735910e52d019745446b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|