From fbe5bd2d94aa9dcea2ce8862aa935092be79c511 Mon Sep 17 00:00:00 2001 From: continuist Date: Sun, 24 Aug 2025 18:00:07 -0400 Subject: [PATCH] Improve security #16 --- Docker_Registry_Install_Guide.md | 44 +++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/Docker_Registry_Install_Guide.md b/Docker_Registry_Install_Guide.md index 6b5d060..b266379 100644 --- a/Docker_Registry_Install_Guide.md +++ b/Docker_Registry_Install_Guide.md @@ -198,8 +198,13 @@ RestrictSUIDSGID=yes RemoveIPC=yes ProtectProc=invisible ProcSubset=pid + +# Allow loopback for upstream to registry and allow the server's public IP(s) for binds: IPAddressDeny=any IPAddressAllow=127.0.0.1 +IPAddressAllow= +# If using IPv6, uncomment and set: +# IPAddressAllow= LimitNOFILE=65536 ExecStartPre=/usr/sbin/nginx -t -c /etc/registry/nginx.conf ExecStart=/usr/sbin/nginx -g 'daemon off;' -c /etc/registry/nginx.conf @@ -261,7 +266,9 @@ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'; # 443: unauthenticated pulls only server { - listen 443 ssl http2; + listen :443 ssl http2; + # If IPv6, also: + # listen []:443 ssl http2; ssl_certificate /etc/registry/certs/registry.crt; ssl_certificate_key /etc/registry/certs/private/registry.key; ssl_protocols TLSv1.2 TLSv1.3; @@ -285,7 +292,9 @@ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'; # 4443: authenticated pushes only (mTLS) server { - listen 4443 ssl http2; + listen :4443 ssl http2; + # If IPv6, also: + # listen []:4443 ssl http2; ssl_certificate /etc/registry/certs/registry.crt; ssl_certificate_key /etc/registry/certs/private/registry.key; ssl_protocols TLSv1.2 TLSv1.3; @@ -315,7 +324,7 @@ EOF sudo chown root:root /etc/registry/nginx.conf sudo chmod 644 /etc/registry/nginx.conf -**Note (Private CA):** OCSP stapling is disabled because our CA is private (no public OCSP responder). Clients trust the registry via the installed CA certificate. If you later migrate to a public CA, re-enable stapling and add a DNS resolver and `ssl_trusted_certificate`. +**Note (Private CA):** OCSP stapling is disabled because our CA is private (no public OCSP responder). Clients trust the registry via the installed CA certificate. If migrating to a public CA later, enable stapling and add `resolver` + `ssl_trusted_certificate`. ``` ### 2.6 Install Container Policy @@ -351,6 +360,13 @@ sudo openssl genrsa -out private/registry.key 4096 sudo cp /opt/APP_NAME/registry/openssl.conf /etc/registry/certs/requests/ sudo chown root:root /etc/registry/certs/requests/openssl.conf +# Ensure OpenSSL config includes subjectAltName for REGISTRY_HOST and SERVER_IP +# The config should contain: +# [ req_ext ] +# subjectAltName = DNS:REGISTRY_HOST,IP: +# If IPv6: +# subjectAltName = DNS:REGISTRY_HOST,IP:,IP: + # Generate server certificate signing request in requests subdirectory sudo openssl req -new -key private/registry.key \ -out requests/registry.csr \ @@ -407,6 +423,8 @@ sudo chmod 755 /etc/registry/certs # Verify certificate creation sudo openssl x509 -in /etc/registry/certs/registry.crt -text -noout | grep -E "(Subject:|DNS:|IP Address:)" +# Reminder: clients must use exactly REGISTRY_HOST (or those IPs) in pulls/pushes + # 3. Install server CA certificate in system trust store (for curl, wget, etc.) sudo cp /etc/registry/certs/ca/ca.crt /usr/local/share/ca-certificates/registry-ca.crt @@ -517,12 +535,32 @@ This setup implements a multi-layered security approach: ### 4.2 Enable and Start Services ```bash +# Reload systemd and start services +sudo systemctl daemon-reload + # Start as the service user sudo -u CI_SERVICE_USER sh -lc 'systemctl --user daemon-reload && systemctl --user enable --now registry.service' sudo systemctl enable --now registry-proxy.service # One-time: ensure host dir ownership matches rootless ID map sudo -u CI_SERVICE_USER podman unshare chown -R 100000:100000 /var/lib/registry + +### 4.1 Self-test + +```bash +# 1) Listening sockets (should show nginx on the chosen IPs/ports): +sudo ss -ltnp '( sport = :443 or sport = :4443 )' + +# 2) From another host on an allowed network: +curl -vk https://REGISTRY_HOST/v2/ | grep -i Docker-Distribution-Api-Version # expect 200 + header +curl -vk https://REGISTRY_HOST/v2/_catalog # expect 403 (blocked) +curl -vk --cert client.crt --key client.key https://REGISTRY_HOST:4443/v2/ | \ + grep -i Docker-Distribution-Api-Version # expect 200 + header + +# 3) Signature enforcement (on a client with CA + org-cosign.pub + policy.json): +# - Pull unsigned image from your registry -> should FAIL +# - Sign image with your org key, push via 4443, pull via 443 -> should SUCCEED +``` ``` ## Step 5: Verify Installation