1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 11:55:40 +01:00
* Adds option to require Client Certificate and a Password to aquire write access in provider

* Removed unnecessary flavourtext from provider markdown file

* Fixed and simplified the auth middleware

Co-authored-by: Jan Höfelmeyer <Jan Höfelmeyer jhoefelmeyer@intevation.de>
Co-authored-by: Sascha L. Teichmann <sascha.teichmann@intevation.de>
This commit is contained in:
JanHoefelmeyer 2022-07-13 14:09:27 +02:00 committed by GitHub
parent 50024915f4
commit 2ac7940206
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 24 deletions

View file

@ -48,6 +48,7 @@ type config struct {
TLPs []tlp `toml:"tlps"` TLPs []tlp `toml:"tlps"`
UploadSignature bool `toml:"upload_signature"` UploadSignature bool `toml:"upload_signature"`
CanonicalURLPrefix string `toml:"canonical_url_prefix"` CanonicalURLPrefix string `toml:"canonical_url_prefix"`
CertificateAndPassword bool `toml:"certificate_and_password"`
NoPassphrase bool `toml:"no_passphrase"` NoPassphrase bool `toml:"no_passphrase"`
NoValidation bool `toml:"no_validation"` NoValidation bool `toml:"no_validation"`
NoWebUI bool `toml:"no_web_ui"` NoWebUI bool `toml:"no_web_ui"`

View file

@ -72,36 +72,57 @@ func (c *controller) bind(pim *pathInfoMux) {
pim.handleFunc("/api/create", c.auth(api(c.create))) pim.handleFunc("/api/create", c.auth(api(c.create)))
} }
// auth wraps the given http.HandlerFunc and returns an new one after authenticating the // authenticate checks if the incoming request confirms with the
// password contained in the header "X-CSAF-PROVIDER-AUTH" with the "password" config value // configured authentication mechanism.
// if set, otherwise returns the given http.HandlerFunc. func (c *controller) authenticate(r *http.Request) bool {
verify := os.Getenv("SSL_CLIENT_VERIFY")
log.Printf("SSL_CLIENT_VERIFY: %s\n", verify)
if verify == "SUCCESS" || strings.HasPrefix(verify, "FAILED") {
// potentially we want to see the Issuer when there is a problem
// but it is not clear if we get this far in case of "FAILED".
// docs (accessed 2022-03-31 when 1.20.2 was current stable):
// https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify
log.Printf("SSL_CLIENT_I_DN: %s\n", os.Getenv("SSL_CLIENT_I_DN"))
}
checkCert := func() bool {
return verify == "SUCCESS" && (c.cfg.Issuer == nil || *c.cfg.Issuer == os.Getenv("SSL_CLIENT_I_DN"))
}
checkPassword := func() bool {
return c.cfg.checkPassword(r.Header.Get("X-CSAF-PROVIDER-AUTH"))
}
if c.cfg.CertificateAndPassword {
if c.cfg.Password == nil {
log.Println("No password set, declining access.")
return false
}
log.Printf("user: %s\n", os.Getenv("SSL_CLIENT_S_DN"))
return checkPassword() && checkCert()
}
switch {
case checkCert():
log.Printf("user: %s\n", os.Getenv("SSL_CLIENT_S_DN"))
case c.cfg.Password == nil:
log.Println("No password set, declining access.")
return false
default:
return checkPassword()
}
return true
}
// auth is a middleware to decorate endpoints with authentication.
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) {
return func(rw http.ResponseWriter, r *http.Request) { return func(rw http.ResponseWriter, r *http.Request) {
if !c.authenticate(r) {
verify := os.Getenv("SSL_CLIENT_VERIFY")
log.Printf("SSL_CLIENT_VERIFY: %s\n", verify)
if verify == "SUCCESS" || strings.HasPrefix(verify, "FAILED") {
// potentially we want to see the Issuer when there is a problem
// but it is not clear if we get this far in case of "FAILED".
// docs (accessed 2022-03-31 when 1.20.2 was current stable):
// https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify
log.Printf("SSL_CLIENT_I_DN: %s\n", os.Getenv("SSL_CLIENT_I_DN"))
}
switch {
case verify == "SUCCESS" && (c.cfg.Issuer == nil || *c.cfg.Issuer == os.Getenv("SSL_CLIENT_I_DN")):
log.Printf("user: %s\n", os.Getenv("SSL_CLIENT_S_DN"))
case c.cfg.Password == nil:
log.Println("No password set, declining access.")
http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden) http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return return
default:
if pa := r.Header.Get("X-CSAF-PROVIDER-AUTH"); !c.cfg.checkPassword(pa) {
http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
} }
fn(rw, r) fn(rw, r)
} }

View file

@ -15,6 +15,7 @@ Following options are supported in the config file:
- web: Specify the web folder. Default: `/var/www/html`. - web: Specify the web folder. Default: `/var/www/html`.
- upload_signature: Send signature with the request, an additional input-field in the web interface will be shown to let user enter an ascii armored signature. Default: `false`. - upload_signature: Send signature with the request, an additional input-field in the web interface will be shown to let user enter an ascii armored signature. Default: `false`.
- canonical_url_prefix: start of the URL where contents shall be accessible from the internet. Default: `https://$SERVER_NAME`. - canonical_url_prefix: start of the URL where contents shall be accessible from the internet. Default: `https://$SERVER_NAME`.
- certificate_and_password: Require password and a valid Client Certificate for write access. Default: false
- no_passphrase: Let the user send the request without having to send a password. If set to true, the input-field in the web interface will be omitted. Default: `false`. - no_passphrase: Let the user send the request without having to send a password. If set to true, the input-field in the web interface will be omitted. Default: `false`.
- no_validation: Skip validation of the uploaded CSAF document against the JSON schema. Default: `false`. - no_validation: Skip validation of the uploaded CSAF document against the JSON schema. Default: `false`.
- no_web_ui: Disable the web interface. Default: `false`. - no_web_ui: Disable the web interface. Default: `false`.