mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 18:36:30 +02:00
83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
package evaluator
|
|
|
|
import (
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"io/ioutil"
|
|
|
|
lru "github.com/hashicorp/golang-lru"
|
|
"github.com/rakyll/statik/fs"
|
|
|
|
_ "github.com/pomerium/pomerium/authorize/evaluator/opa/policy" // load static assets
|
|
"github.com/pomerium/pomerium/internal/log"
|
|
)
|
|
|
|
var isValidClientCertificateCache, _ = lru.New2Q(100)
|
|
|
|
func isValidClientCertificate(ca, cert string) (bool, error) {
|
|
// when ca is the empty string, client certificates are always accepted
|
|
if ca == "" {
|
|
return true, nil
|
|
}
|
|
|
|
// when cert is the empty string, no client certificate was supplied
|
|
if cert == "" {
|
|
return false, nil
|
|
}
|
|
|
|
cacheKey := [2]string{ca, cert}
|
|
|
|
value, ok := isValidClientCertificateCache.Get(cacheKey)
|
|
if ok {
|
|
return value.(bool), nil
|
|
}
|
|
|
|
roots := x509.NewCertPool()
|
|
roots.AppendCertsFromPEM([]byte(ca))
|
|
|
|
xcert, err := parseCertificate(cert)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
_, verifyErr := xcert.Verify(x509.VerifyOptions{
|
|
Roots: roots,
|
|
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
})
|
|
valid := verifyErr == nil
|
|
|
|
if verifyErr != nil {
|
|
log.Debug().Err(verifyErr).Msg("client certificate failed verification: %w")
|
|
}
|
|
|
|
isValidClientCertificateCache.Add(cacheKey, valid)
|
|
|
|
return valid, nil
|
|
}
|
|
|
|
func parseCertificate(pemStr string) (*x509.Certificate, error) {
|
|
block, _ := pem.Decode([]byte(pemStr))
|
|
if block == nil {
|
|
return nil, fmt.Errorf("invalid certificate")
|
|
}
|
|
if block.Type != "CERTIFICATE" {
|
|
return nil, fmt.Errorf("unknown PEM type: %s", block.Type)
|
|
}
|
|
return x509.ParseCertificate(block.Bytes)
|
|
}
|
|
|
|
const statikNamespace = "rego"
|
|
|
|
func readPolicy(fn string) ([]byte, error) {
|
|
statikFS, err := fs.NewWithNamespace(statikNamespace)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r, err := statikFS.Open(fn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Close()
|
|
return ioutil.ReadAll(r)
|
|
}
|