Cleanup unneeded harbor deployment files and switch to prod certificate.
This commit is contained in:
@@ -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 <password>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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:<hash>`
|
|
||||||
- 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.
|
|
||||||
@@ -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: <paste the line above>")
|
|
||||||
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)
|
|
||||||
@@ -22,7 +22,7 @@ expose:
|
|||||||
notary: notary-the-seas.local.mk-labs.cloud
|
notary: notary-the-seas.local.mk-labs.cloud
|
||||||
className: nginx
|
className: nginx
|
||||||
annotations:
|
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/ssl-redirect: "true"
|
||||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user