1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 05:40:11 +01:00

Improve tls client cert handling

* Improve nginx setup to transfer auth information to the fcgiwrap
 backend.
 * Add instructions for creating client certs for testing.
 * Add debug output to see if and which client cert has been used when
   calling the csaf_provider.go .
This commit is contained in:
Bernhard Reiter 2022-02-15 18:20:24 +01:00
parent a71f490999
commit 2905a30cc0
No known key found for this signature in database
GPG key ID: 2B7BA3BF9BC3A554
4 changed files with 98 additions and 16 deletions

View file

@ -14,6 +14,7 @@ import (
"html/template" "html/template"
"log" "log"
"net/http" "net/http"
"os"
"strings" "strings"
) )
@ -69,16 +70,22 @@ func (c *controller) bind(pim *pathInfoMux) {
func (c *controller) auth( func (c *controller) auth(
fn func(http.ResponseWriter, *http.Request), fn func(http.ResponseWriter, *http.Request),
) 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) { return func(rw http.ResponseWriter, r *http.Request) {
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") hash := r.Header.Get("X-CSAF-PROVIDER-AUTH")
if !c.cfg.checkPassword(hash) { if !c.cfg.checkPassword(hash) {
http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden) http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return return
} }
}
fn(rw, r) fn(rw, r)
} }
} }

View file

@ -12,25 +12,36 @@ server {
# Other Config # Other Config
# ... # ...
ssl_client_certificate /etc/ssl/ca.crt; ssl_client_certificate /etc/ssl/rootca-cert.pem;
ssl_verify_client optional; ssl_verify_client optional;
ssl_verify_depth 2; ssl_verify_depth 2;
location ~* /.well-known/csaf/(red|green|amber)/{ # This example allows access to all three TLP locations for all certs.
autoindex on;a location ~ /.well-known/csaf/(red|green|amber)/{
autoindex on;
# in this location access is only allowed with client certs
if ($ssl_client_verify != SUCCESS){ 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` Reload or restart nginx to apply the changes (e.g. `systemctl reload nginx`
on Debian or Ubuntu.) on Debian or Ubuntu.)
To test this: To test this see [development-client-certs.md](development-client-certs.md) and
* From the browser after importing the ```userA.pfx``` and the navigation to the protected directories. * From the browser after importing the `testclient1.p12`:
* With curl: ```curl https://{serverURL}/.well-known/csaf/red/ --cert /etc/ssl/userA.crt --key /etc/ssl/userA.key```. nagivate to the protected directories.
* With curl: `curl https://{serverURL}/.well-known/csaf/red/ --cert-type p12 --cert testclient1.crt`

View file

@ -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
```

View file

@ -46,6 +46,10 @@ location /cgi-bin/ {
fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param CSAF_CONFIG /usr/lib/csaf/config.toml; 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 { server {
root /usr/share/nginx/html;
location / { location / {
# Other config # Other config
# ... # ...
@ -74,7 +80,7 @@ server {
Place the binary under `/usr/lib/cgi-bin/csaf_provider.go`. Place the binary under `/usr/lib/cgi-bin/csaf_provider.go`.
Make sure `/usr/lib/cgi-bin/` exists. 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 # upload_signature = true