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:
parent
a71f490999
commit
2905a30cc0
4 changed files with 98 additions and 16 deletions
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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`
|
||||||
|
|
||||||
|
|
|
||||||
58
docs/development-client-certs.md
Normal file
58
docs/development-client-certs.md
Normal 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
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue