proxy-pool/internal/controlplane/tlsreload/identity.go

50 lines
1.6 KiB
Go

package tlsreload
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net/url"
"proxy-pool/internal/domain/workerruntime"
)
var ErrInvalidSPIFFEIdentity = errors.New("invalid SPIFFE workload identity")
// ResolveSPIFFEIdentity returns the logical Worker or Checker ID encoded in a
// role-specific SPIFFE URI SAN. It only accepts the exact identity shape that
// the Controller authorizer accepts for a control-plane request.
func ResolveSPIFFEIdentity(certificateFile, keyFile, trustDomain, environment, role string) (string, error) {
if certificateFile == "" || keyFile == "" || trustDomain == "" || environment == "" || (role != "worker" && role != "checker") {
return "", ErrInvalidSPIFFEIdentity
}
certificate, err := tls.LoadX509KeyPair(certificateFile, keyFile)
if err != nil || len(certificate.Certificate) == 0 {
return "", fmt.Errorf("%w: load client certificate", ErrInvalidSPIFFEIdentity)
}
leaf, err := x509.ParseCertificate(certificate.Certificate[0])
if err != nil {
return "", fmt.Errorf("%w: parse client certificate", ErrInvalidSPIFFEIdentity)
}
var identity string
for _, uri := range leaf.URIs {
candidate, ok := spiffeIdentity(uri, trustDomain, environment, role)
if !ok {
continue
}
if identity != "" {
return "", ErrInvalidSPIFFEIdentity
}
identity = candidate
}
if !workerruntime.ValidIdentifier(identity) {
return "", ErrInvalidSPIFFEIdentity
}
return identity, nil
}
func spiffeIdentity(uri *url.URL, trustDomain, environment, role string) (string, bool) {
return workerruntime.SPIFFEIdentity(uri, trustDomain, environment, role)
}