mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 21:17:58 +08:00
feat: add configurable mTLS identity extraction with fallback chain (#3640)
Add support for configurable identity attributes in mTLS authentication, allowing identity extraction from CommonName, Subject DN, Email SAN, URI SAN, or DNSName SAN with fallback chain support. Includes regex pattern matching for URI SANs (e.g., SPIFFE workload IDs). - Add MTLSConfig with identity attributes, URISANPattern, and index fields - Implement extractMTLSIdentity with fallback chain logic - Move the mtls tests in the api package to pkg/api/mtls_test.go Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
@@ -67,6 +68,10 @@ type CertificateOptions struct {
|
||||
// If nil, no email addresses will be included.
|
||||
EmailAddresses []string
|
||||
|
||||
// URIs contains the URIs for the Subject Alternative Name extension.
|
||||
// If nil, no URIs will be included.
|
||||
URIs []string
|
||||
|
||||
// Hostname is the hostname or IP address for server certificates.
|
||||
// For server certificates, this is required and will be added to DNSNames or IPAddresses
|
||||
// based on whether it's a valid IP address or a DNS name.
|
||||
@@ -404,6 +409,27 @@ func applyOptions(template *x509.Certificate, opts *CertificateOptions, certType
|
||||
template.EmailAddresses = opts.EmailAddresses
|
||||
}
|
||||
|
||||
// Apply URIs
|
||||
if opts.URIs != nil {
|
||||
templateURIs := make([]*url.URL, 0, len(opts.URIs))
|
||||
for _, uriStr := range opts.URIs {
|
||||
uri, err := url.Parse(uriStr)
|
||||
if err != nil {
|
||||
// Skip invalid URIs - could log error in production
|
||||
continue
|
||||
}
|
||||
|
||||
// Validate that the URI has a valid scheme (url.Parse accepts URIs without schemes)
|
||||
if uri.Scheme == "" {
|
||||
// Skip URIs without a scheme - could log error in production
|
||||
continue
|
||||
}
|
||||
|
||||
templateURIs = append(templateURIs, uri)
|
||||
}
|
||||
template.URIs = templateURIs
|
||||
}
|
||||
|
||||
// Apply CommonName - if provided, override the default; otherwise keep default from initializeTemplate
|
||||
if opts.CommonName != "" {
|
||||
template.Subject.CommonName = opts.CommonName
|
||||
|
||||
@@ -240,6 +240,30 @@ func TestApplyOptionsCoverage(t *testing.T) {
|
||||
So(cert.EmailAddresses, ShouldContain, "admin@example.com")
|
||||
})
|
||||
|
||||
Convey("Test with URIs including invalid URI", func() {
|
||||
// Mix of valid and invalid URIs - invalid ones should be skipped
|
||||
customURIs := []string{
|
||||
"spiffe://example.org/workload/test",
|
||||
"not a valid uri", // Invalid URI - should be skipped
|
||||
"https://example.com",
|
||||
"://invalid", // Invalid URI - should be skipped
|
||||
}
|
||||
opts := &tls.CertificateOptions{
|
||||
Hostname: "localhost",
|
||||
URIs: customURIs,
|
||||
}
|
||||
certPEM, _, err := tls.GenerateServerCert(caCertPEM, caKeyPEM, opts)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
certBlock, _ := pem.Decode(certPEM)
|
||||
cert, err := x509.ParseCertificate(certBlock.Bytes)
|
||||
So(err, ShouldBeNil)
|
||||
// Should only contain valid URIs (2 out of 4)
|
||||
So(len(cert.URIs), ShouldEqual, 2)
|
||||
So(cert.URIs[0].String(), ShouldEqual, "spiffe://example.org/workload/test")
|
||||
So(cert.URIs[1].String(), ShouldEqual, "https://example.com")
|
||||
})
|
||||
|
||||
Convey("Test with all options combined", func() {
|
||||
customNotBefore := time.Now().Add(-12 * time.Hour)
|
||||
customNotAfter := time.Now().Add(365 * 24 * time.Hour)
|
||||
|
||||
Reference in New Issue
Block a user