Improve security #15
Some checks are pending
CI/CD Pipeline (Fully Isolated DinD) / Run Tests (DinD) (push) Waiting to run
CI/CD Pipeline (Fully Isolated DinD) / Build and Push Docker Images (DinD) (push) Blocked by required conditions
CI/CD Pipeline (Fully Isolated DinD) / Deploy to Production (push) Blocked by required conditions
Some checks are pending
CI/CD Pipeline (Fully Isolated DinD) / Run Tests (DinD) (push) Waiting to run
CI/CD Pipeline (Fully Isolated DinD) / Build and Push Docker Images (DinD) (push) Blocked by required conditions
CI/CD Pipeline (Fully Isolated DinD) / Deploy to Production (push) Blocked by required conditions
This commit is contained in:
parent
7b1e38fb95
commit
a2dcc545c5
1 changed files with 37 additions and 3 deletions
|
@ -194,6 +194,12 @@ ProtectHostname=yes
|
||||||
LockPersonality=yes
|
LockPersonality=yes
|
||||||
MemoryDenyWriteExecute=yes
|
MemoryDenyWriteExecute=yes
|
||||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||||
|
RestrictSUIDSGID=yes
|
||||||
|
RemoveIPC=yes
|
||||||
|
ProtectProc=invisible
|
||||||
|
ProcSubset=pid
|
||||||
|
IPAddressDeny=any
|
||||||
|
IPAddressAllow=127.0.0.1
|
||||||
LimitNOFILE=65536
|
LimitNOFILE=65536
|
||||||
ExecStartPre=/usr/sbin/nginx -t -c /etc/registry/nginx.conf
|
ExecStartPre=/usr/sbin/nginx -t -c /etc/registry/nginx.conf
|
||||||
ExecStart=/usr/sbin/nginx -g 'daemon off;' -c /etc/registry/nginx.conf
|
ExecStart=/usr/sbin/nginx -g 'daemon off;' -c /etc/registry/nginx.conf
|
||||||
|
@ -218,11 +224,15 @@ error_log /var/log/registry-proxy/error.log;
|
||||||
|
|
||||||
http {
|
http {
|
||||||
server_tokens off;
|
server_tokens off;
|
||||||
|
|
||||||
|
# Rate/connection limits (tune for CI bursts as needed)
|
||||||
limit_req_zone $binary_remote_addr zone=reg_read:10m rate=10r/s;
|
limit_req_zone $binary_remote_addr zone=reg_read:10m rate=10r/s;
|
||||||
limit_req_zone $binary_remote_addr zone=reg_write:10m rate=5r/s;
|
limit_req_zone $binary_remote_addr zone=reg_write:10m rate=5r/s;
|
||||||
limit_conn_zone $binary_remote_addr zone=perip:10m;
|
limit_conn_zone $binary_remote_addr zone=perip:10m;
|
||||||
# Note: Tune these limits based on your expected load. Adjust if CI bursts cause 429s.
|
|
||||||
client_max_body_size 2g;
|
client_max_body_size 2g;
|
||||||
|
|
||||||
|
# TLS hardening
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
|
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
|
||||||
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
|
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
|
||||||
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
||||||
|
@ -232,8 +242,11 @@ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
||||||
ssl_session_cache shared:SSL:10m;
|
ssl_session_cache shared:SSL:10m;
|
||||||
ssl_session_timeout 10m;
|
ssl_session_timeout 10m;
|
||||||
ssl_session_tickets off;
|
ssl_session_tickets off;
|
||||||
ssl_stapling on;
|
|
||||||
ssl_stapling_verify on;
|
# OCSP stapling is intentionally DISABLED for private CA deployments.
|
||||||
|
# (Clients trust via installed CA cert; no public OCSP endpoint exists.)
|
||||||
|
|
||||||
|
# Proxy settings
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Connection "";
|
proxy_set_header Connection "";
|
||||||
proxy_request_buffering off;
|
proxy_request_buffering off;
|
||||||
|
@ -243,6 +256,7 @@ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
||||||
fastcgi_temp_path /run/registry-proxy/fastcgi_temp;
|
fastcgi_temp_path /run/registry-proxy/fastcgi_temp;
|
||||||
uwsgi_temp_path /run/registry-proxy/uwsgi_temp;
|
uwsgi_temp_path /run/registry-proxy/uwsgi_temp;
|
||||||
scgi_temp_path /run/registry-proxy/scgi_temp;
|
scgi_temp_path /run/registry-proxy/scgi_temp;
|
||||||
|
|
||||||
upstream reg { server 127.0.0.1:5000; }
|
upstream reg { server 127.0.0.1:5000; }
|
||||||
|
|
||||||
# 443: unauthenticated pulls only
|
# 443: unauthenticated pulls only
|
||||||
|
@ -252,8 +266,11 @@ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
||||||
ssl_certificate_key /etc/registry/certs/private/registry.key;
|
ssl_certificate_key /etc/registry/certs/private/registry.key;
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
# Hide catalog & tag listings
|
||||||
location = /v2/_catalog { return 403; }
|
location = /v2/_catalog { return 403; }
|
||||||
location ~ ^/v2/.+/tags/list { return 403; }
|
location ~ ^/v2/.+/tags/list { return 403; }
|
||||||
|
|
||||||
location /v2/ {
|
location /v2/ {
|
||||||
limit_req zone=reg_read burst=20 nodelay;
|
limit_req zone=reg_read burst=20 nodelay;
|
||||||
limit_conn perip 20;
|
limit_conn perip 20;
|
||||||
|
@ -273,8 +290,14 @@ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
||||||
ssl_certificate_key /etc/registry/certs/private/registry.key;
|
ssl_certificate_key /etc/registry/certs/private/registry.key;
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
# mTLS client auth via private Client CA
|
||||||
ssl_client_certificate /etc/registry/certs/clients/ca.crt;
|
ssl_client_certificate /etc/registry/certs/clients/ca.crt;
|
||||||
ssl_verify_client on;
|
ssl_verify_client on;
|
||||||
|
|
||||||
|
# Optional: enable client-cert revocation (publish a CRL and uncomment)
|
||||||
|
# ssl_crl /etc/registry/certs/clients/ca.crl;
|
||||||
|
|
||||||
location /v2/ {
|
location /v2/ {
|
||||||
limit_req zone=reg_write burst=10;
|
limit_req zone=reg_write burst=10;
|
||||||
limit_conn perip 20;
|
limit_conn perip 20;
|
||||||
|
@ -291,6 +314,8 @@ EOF
|
||||||
# Set proper permissions for nginx config (root-owned)
|
# Set proper permissions for nginx config (root-owned)
|
||||||
sudo chown root:root /etc/registry/nginx.conf
|
sudo chown root:root /etc/registry/nginx.conf
|
||||||
sudo chmod 644 /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`.
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.6 Install Container Policy
|
### 2.6 Install Container Policy
|
||||||
|
@ -536,6 +561,15 @@ curl -k -X PUT https://YOUR_ACTUAL_IP_ADDRESS/v2/ -I | grep 403 || echo "WARNING
|
||||||
# 4443 requires client cert
|
# 4443 requires client cert
|
||||||
curl -kI https://YOUR_ACTUAL_IP_ADDRESS:4443/v2/ | egrep '400|401|403' || echo "WARNING: 4443 may not require auth"
|
curl -kI https://YOUR_ACTUAL_IP_ADDRESS:4443/v2/ | egrep '400|401|403' || echo "WARNING: 4443 may not require auth"
|
||||||
|
|
||||||
|
# 443 should return 200 with registry API header; catalog is forbidden
|
||||||
|
curl -vk https://REGISTRY_HOST/v2/ | grep -i Docker-Distribution-Api-Version
|
||||||
|
curl -vk https://REGISTRY_HOST/v2/_catalog # expect 403
|
||||||
|
|
||||||
|
# 4443 requires mTLS, should return 200 with client certs
|
||||||
|
curl -vk --cert client.crt --key client.key https://REGISTRY_HOST:4443/v2/ | grep -i Docker-Distribution-Api-Version
|
||||||
|
|
||||||
|
# OCSP stapling is intentionally disabled; you should not expect stapling-related headers in responses.
|
||||||
|
|
||||||
# Verify Podman is using non-home paths
|
# Verify Podman is using non-home paths
|
||||||
sudo su - CI_SERVICE_USER -c "env PODMAN_ROOT=/var/tmp/podman-\$(id -u)/root PODMAN_RUNROOT=/run/user/\$(id -u)/podman-run PODMAN_TMPDIR=/var/tmp/podman-\$(id -u)/tmp XDG_DATA_HOME=/var/tmp/podman-\$(id -u)/xdg-data XDG_CONFIG_HOME=/var/tmp/podman-\$(id -u)/xdg-config podman info --format '{{.Store.GraphRoot}} {{.Store.RunRoot}}'"
|
sudo su - CI_SERVICE_USER -c "env PODMAN_ROOT=/var/tmp/podman-\$(id -u)/root PODMAN_RUNROOT=/run/user/\$(id -u)/podman-run PODMAN_TMPDIR=/var/tmp/podman-\$(id -u)/tmp XDG_DATA_HOME=/var/tmp/podman-\$(id -u)/xdg-data XDG_CONFIG_HOME=/var/tmp/podman-\$(id -u)/xdg-config podman info --format '{{.Store.GraphRoot}} {{.Store.RunRoot}}'"
|
||||||
```
|
```
|
||||||
|
|
Loading…
Add table
Reference in a new issue