diff --git a/cmd/csaf_provider/controller.go b/cmd/csaf_provider/controller.go index 5ea05f4..8d54e52 100644 --- a/cmd/csaf_provider/controller.go +++ b/cmd/csaf_provider/controller.go @@ -14,6 +14,7 @@ import ( "html/template" "log" "net/http" + "os" "strings" ) @@ -69,15 +70,21 @@ func (c *controller) bind(pim *pathInfoMux) { func (c *controller) auth( fn func(http.ResponseWriter, *http.Request), ) func(http.ResponseWriter, *http.Request) { - - if c.cfg.Password == nil { - return fn - } return func(rw http.ResponseWriter, r *http.Request) { - hash := r.Header.Get("X-CSAF-PROVIDER-AUTH") - if !c.cfg.checkPassword(hash) { + log.Printf("SSL_CLIENT_VERIFY: %s\n", os.Getenv("SSL_CLIENT_VERIFY")) + if os.Getenv("SSL_CLIENT_VERIFY") == "SUCCESS" { + log.Printf("user: %s\n", os.Getenv("SSL_CLIENT_S_DN")) + log.Printf("ca: %s\n", os.Getenv("SSL_CLIENT_I_DN")) + } else if c.cfg.Password == nil { + log.Printf("No password set, declining access.") http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden) return + } else { + hash := r.Header.Get("X-CSAF-PROVIDER-AUTH") + if !c.cfg.checkPassword(hash) { + http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden) + return + } } fn(rw, r) } diff --git a/docs/client-certificate-setup.md b/docs/client-certificate-setup.md index e996e5b..1c42ba8 100644 --- a/docs/client-certificate-setup.md +++ b/docs/client-certificate-setup.md @@ -12,25 +12,36 @@ server { # Other Config # ... - ssl_client_certificate /etc/ssl/ca.crt; + ssl_client_certificate /etc/ssl/rootca-cert.pem; ssl_verify_client optional; ssl_verify_depth 2; - location ~* /.well-known/csaf/(red|green|amber)/{ - autoindex on;a + # This example allows access to all three TLP locations for all certs. + location ~ /.well-known/csaf/(red|green|amber)/{ + autoindex on; + # in this location access is only allowed with client certs if ($ssl_client_verify != SUCCESS){ - return 403; + # we use status code 404 == "Not Found", because we do not + # want to reveal if this location exists or not. + return 404; } } - } ``` -This will restrict the access to the defined paths in the ```location``` directive to only authenticated client certificates. +This will restrict the access to the defined paths in the ```location``` +directive to only authenticated client certificates issued by the CAs +which are configured with `ssl_client_certificate`. + +If you want to restrict each path of `green`, `amber` and `red` +differently, you could use several location blocks +each which a single `if` that matches the `$ssl_client_i_dn` variable +to CAs that you would want to allow for that location. Reload or restart nginx to apply the changes (e.g. `systemctl reload nginx` on Debian or Ubuntu.) -To test this: -* From the browser after importing the ```userA.pfx``` and the navigation to the protected directories. -* With curl: ```curl https://{serverURL}/.well-known/csaf/red/ --cert /etc/ssl/userA.crt --key /etc/ssl/userA.key```. +To test this see [development-client-certs.md](development-client-certs.md) and +* From the browser after importing the `testclient1.p12`: +nagivate to the protected directories. +* With curl: `curl https://{serverURL}/.well-known/csaf/red/ --cert-type p12 --cert testclient1.crt` diff --git a/docs/development-client-certs.md b/docs/development-client-certs.md new file mode 100644 index 0000000..8763721 --- /dev/null +++ b/docs/development-client-certs.md @@ -0,0 +1,58 @@ +# Create TLS client certificates (for testing) + +For testing and development purposes we reuse +the bare bones certificate authority from the +[development-ca.md](development-ca.md). + +(In production setups, it is very likely that two different CAs +would used for server and for client certificates.) + +The following lines directly create the client certificate. +(As opposed to first creating a certificate signing request and +then signing it.) + +```bash +# being in devca1/ +certtool --generate-privkey --outfile testclient1-key.pem + +echo ' +organization = "CSAF Tools Development (internal)" +country = DE +cn = "TLS Test Client 1" + +tls_www_client +signing_key +encryption_key + +serial = 020 +expiration_days = 50 +' > gnutls-certtool.testclient1.template + +certtool --generate-certificate --load-privkey testclient1-key.pem --outfile testclient1.crt --load-ca-certificate rootca-cert.pem --load-ca-privkey rootca-key.pem --template gnutls-certtool.testclient1.template + +certtool --load-ca-certificate rootca-cert.pem --load-certificate testclient1.crt --load-privkey testclient1-key.pem --to-p12 --p12-name "Test Client 1" --null-password --outder --outfile testclient1.p12 +``` + +and we do a second one with shorter expiration day: + +```bash +certtool --generate-privkey --outfile testclient2-key.pem + +echo ' +organization = "CSAF Tools Development (internal)" +country = DE +cn = "TLS Test Client 2" + +tls_www_client +signing_key +encryption_key + +serial = 021 +expiration_days = 1 +' > gnutls-certtool.testclient2.template + +certtool --generate-certificate --load-privkey testclient2-key.pem --outfile testclient2.crt --load-ca-certificate rootca-cert.pem --load-ca-privkey rootca-key.pem --template gnutls-certtool.testclient2.template + +certtool --load-ca-certificate rootca-cert.pem --load-certificate testclient2.crt --load-privkey testclient2-key.pem --to-p12 --p12-name "Test Client 2" --null-password --outder --outfile testclient2.p12 +``` + diff --git a/docs/provider-setup.md b/docs/provider-setup.md index d737f03..86d6506 100644 --- a/docs/provider-setup.md +++ b/docs/provider-setup.md @@ -46,6 +46,10 @@ location /cgi-bin/ { fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param CSAF_CONFIG /usr/lib/csaf/config.toml; + + fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify; + fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn; + fastcgi_param SSL_CLIENT_I_DN $ssl_client_i_dn; } ``` @@ -54,6 +58,8 @@ Add to `/etc/nginx/sites-enabled/default`: ``` server { + root /usr/share/nginx/html; + location / { # Other config # ... @@ -74,7 +80,7 @@ server { Place the binary under `/usr/lib/cgi-bin/csaf_provider.go`. Make sure `/usr/lib/cgi-bin/` exists. -Create configuarion file under `/usr/lib/csaf/config.toml`: +Create configuration file under `/usr/lib/csaf/config.toml`: ``` # upload_signature = true