From df91305e13f24f81bb918482a5fb1072c6b575d9 Mon Sep 17 00:00:00 2001 From: Ryan Blundon Date: Thu, 4 Jun 2026 22:51:53 -0500 Subject: [PATCH] Cleanup unneeded harbor deployment files and switch to prod certificate. --- .../harbor/REGISTRY_HTPASSWD_SETUP.md | 117 ------------------ .../harbor/generate-registry-htpasswd.py | 83 ------------- cluster/platform/harbor/values.yaml | 2 +- 3 files changed, 1 insertion(+), 201 deletions(-) delete mode 100644 cluster/platform/harbor/REGISTRY_HTPASSWD_SETUP.md delete mode 100755 cluster/platform/harbor/generate-registry-htpasswd.py diff --git a/cluster/platform/harbor/REGISTRY_HTPASSWD_SETUP.md b/cluster/platform/harbor/REGISTRY_HTPASSWD_SETUP.md deleted file mode 100644 index d3fbdd4..0000000 --- a/cluster/platform/harbor/REGISTRY_HTPASSWD_SETUP.md +++ /dev/null @@ -1,117 +0,0 @@ -# Harbor Registry HTPASSWD Setup Instructions - -## Problem Fixed -The Harbor Helm chart requires TWO credential keys for registry authentication: -- `REGISTRY_PASSWD` - plain text password -- `REGISTRY_HTPASSWD` - bcrypt-hashed htpasswd format - -Previously, only REGISTRY_PASSWD was configured, causing Harbor registry pod failures. - -## Solution Implemented -**Option B: Pre-stored hash in 1Password** - -This approach was chosen because: -1. Aligns with mk-labs pattern of storing credentials directly in 1Password -2. More maintainable and predictable than template-based hashing -3. Simpler to troubleshoot and validate -4. No dependency on ExternalSecrets template engine capabilities - -## 1Password Setup Required - -### Step 1: Generate the htpasswd hash - -You need to generate a bcrypt hash of the registry password. The username must be `harbor_registry_user`. - -**Using Python (recommended):** -```bash -python3 -c "import bcrypt; password=input('Enter registry password: '); print(f'harbor_registry_user:{bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=10)).decode()}')" -``` - -**Using htpasswd tool (if available):** -```bash -htpasswd -nbB harbor_registry_user -``` - -### Step 2: Add field to 1Password - -1. Open 1Password and navigate to: **mk-labs vault** → **the-seas** item -2. Add a new field: - - **Label:** `registry-htpasswd` - - **Type:** password/text field - - **Value:** The full htpasswd line from Step 1 - - Example format: `harbor_registry_user:$2b$10$abcd1234...` - -### Step 3: Verify the configuration - -The ExternalSecret has been updated to pull both fields: -```yaml -- secretKey: REGISTRY_PASSWD - remoteRef: - key: the-seas - property: registry-password - -- secretKey: REGISTRY_HTPASSWD - remoteRef: - key: the-seas - property: registry-htpasswd -``` - -### Step 4: Apply and verify - -After adding the field to 1Password: - -```bash -# The ExternalSecret will automatically sync within 1h, or force sync: -kubectl delete externalsecret harbor-credentials -n harbor -kubectl apply -f /home/hermes/git/homelab/cluster/platform/harbor/externalsecret.yaml - -# Verify the secret contains both keys: -kubectl get secret harbor-credentials -n harbor -o jsonpath='{.data}' | jq 'keys' -``` - -Expected output should include both: -- `REGISTRY_PASSWD` -- `REGISTRY_HTPASSWD` - -## Verification Commands - -```bash -# Check if secret exists and has correct keys -kubectl get secret harbor-credentials -n harbor -o json | jq '.data | keys' - -# Verify REGISTRY_HTPASSWD format (should show username:$2b$...) -kubectl get secret harbor-credentials -n harbor -o jsonpath='{.data.REGISTRY_HTPASSWD}' | base64 -d - -# Check Harbor registry pod logs for authentication success -kubectl logs -n harbor -l component=registry --tail=50 -``` - -## Troubleshooting - -**ExternalSecret not syncing:** -- Check ExternalSecret status: `kubectl describe externalsecret harbor-credentials -n harbor` -- Verify 1Password Connect is running: `kubectl get pods -n external-secrets` -- Check that field name matches exactly: `registry-htpasswd` (lowercase, hyphen) - -**Hash format issues:** -- Ensure bcrypt hash starts with `$2b$` or `$2a$` -- Verify full line includes username: `harbor_registry_user:` -- No extra whitespace or newlines in the 1Password field - -**Registry pod still failing:** -- Verify Harbor values.yaml references the correct existingSecret name -- Check registry pod environment variables contain both keys -- Review registry pod logs for specific authentication errors - -## Files Modified - -- `/home/hermes/git/homelab/cluster/platform/harbor/externalsecret.yaml` - - Added REGISTRY_HTPASSWD secretKey mapping - - Updated documentation comment with new field name - -## Reference - -Harbor Helm Chart documentation: -https://github.com/goharbor/harbor-helm/blob/main/values.yaml - -Search for "REGISTRY_HTPASSWD" to see the requirement in the values.yaml file. diff --git a/cluster/platform/harbor/generate-registry-htpasswd.py b/cluster/platform/harbor/generate-registry-htpasswd.py deleted file mode 100755 index 88af59d..0000000 --- a/cluster/platform/harbor/generate-registry-htpasswd.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python3 -""" -Generate bcrypt htpasswd entry for Harbor registry credentials. - -Usage: - ./generate-registry-htpasswd.py - -This will prompt for the registry password and output the properly formatted -htpasswd line to add to 1Password as the 'registry-htpasswd' field. -""" - -import sys -import getpass - -try: - import bcrypt -except ImportError: - print("ERROR: bcrypt module not installed.") - print("Install with: pip3 install bcrypt") - sys.exit(1) - -def generate_htpasswd(username, password): - """Generate bcrypt htpasswd entry.""" - # Using cost factor 10 (2^10 = 1024 rounds) - standard bcrypt setting - hashed = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=10)) - return f"{username}:{hashed.decode('utf-8')}" - -def main(): - username = "harbor_registry_user" - - print("=" * 70) - print("Harbor Registry HTPASSWD Generator") - print("=" * 70) - print() - print(f"Username: {username} (fixed)") - print() - - # Get password securely - password = getpass.getpass("Enter registry password: ") - - if not password: - print("ERROR: Password cannot be empty") - sys.exit(1) - - # Confirm password - password_confirm = getpass.getpass("Confirm password: ") - - if password != password_confirm: - print("ERROR: Passwords do not match") - sys.exit(1) - - print() - print("Generating bcrypt hash...") - htpasswd_entry = generate_htpasswd(username, password) - - print() - print("=" * 70) - print("SUCCESS! Copy the line below to 1Password:") - print("=" * 70) - print() - print(htpasswd_entry) - print() - print("=" * 70) - print() - print("Next steps:") - print("1. Copy the line above (entire line including username and hash)") - print("2. Open 1Password → mk-labs vault → the-seas item") - print("3. Add new field:") - print(" - Label: registry-htpasswd") - print(" - Value: ") - print("4. Save the 1Password item") - print("5. ExternalSecret will sync within 1 hour (or force delete/recreate)") - print() - -if __name__ == "__main__": - try: - main() - except KeyboardInterrupt: - print("\nOperation cancelled.") - sys.exit(1) - except Exception as e: - print(f"ERROR: {e}", file=sys.stderr) - sys.exit(1) diff --git a/cluster/platform/harbor/values.yaml b/cluster/platform/harbor/values.yaml index 346312b..0aa2fcf 100644 --- a/cluster/platform/harbor/values.yaml +++ b/cluster/platform/harbor/values.yaml @@ -22,7 +22,7 @@ expose: notary: notary-the-seas.local.mk-labs.cloud className: nginx annotations: - cert-manager.io/cluster-issuer: letsencrypt-staging + cert-manager.io/cluster-issuer: letsencrypt-prod nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/proxy-body-size: "0"