Add serial number certificate to forward headers
This commit is contained in:
parent
3f1484480e
commit
5f50d2e230
8 changed files with 52 additions and 29 deletions
|
@ -70,6 +70,7 @@ http:
|
||||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true"
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true"
|
||||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true"
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true"
|
||||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true"
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true"
|
||||||
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.serialnumber=true"
|
||||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true"
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true"
|
||||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true"
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true"
|
||||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
|
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
|
||||||
|
|
|
@ -196,6 +196,7 @@
|
||||||
notAfter = true
|
notAfter = true
|
||||||
notBefore = true
|
notBefore = true
|
||||||
sans = true
|
sans = true
|
||||||
|
serialNumber = true
|
||||||
[http.middlewares.Middleware12.passTLSClientCert.info.subject]
|
[http.middlewares.Middleware12.passTLSClientCert.info.subject]
|
||||||
country = true
|
country = true
|
||||||
province = true
|
province = true
|
||||||
|
|
|
@ -239,6 +239,7 @@ http:
|
||||||
commonName: true
|
commonName: true
|
||||||
serialNumber: true
|
serialNumber: true
|
||||||
domainComponent: true
|
domainComponent: true
|
||||||
|
serialNumber: true
|
||||||
Middleware13:
|
Middleware13:
|
||||||
rateLimit:
|
rateLimit:
|
||||||
average: 42
|
average: 42
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/notAfter` | `true` |
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/notAfter` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/notBefore` | `true` |
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/notBefore` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/sans` | `true` |
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/sans` | `true` |
|
||||||
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/serialNumber` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/commonName` | `true` |
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/commonName` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/country` | `true` |
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/country` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/domainComponent` | `true` |
|
| `traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/domainComponent` | `true` |
|
||||||
|
|
|
@ -377,11 +377,12 @@ type StripPrefixRegex struct {
|
||||||
|
|
||||||
// TLSClientCertificateInfo holds the client TLS certificate info configuration.
|
// TLSClientCertificateInfo holds the client TLS certificate info configuration.
|
||||||
type TLSClientCertificateInfo struct {
|
type TLSClientCertificateInfo struct {
|
||||||
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty"`
|
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty"`
|
||||||
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty"`
|
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty"`
|
||||||
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty"`
|
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty"`
|
||||||
Subject *TLSCLientCertificateDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty"`
|
Subject *TLSCLientCertificateDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty"`
|
||||||
Issuer *TLSCLientCertificateDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty"`
|
Issuer *TLSCLientCertificateDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty"`
|
||||||
|
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -84,6 +84,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.notafter": "true",
|
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.notafter": "true",
|
||||||
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.notbefore": "true",
|
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.notbefore": "true",
|
||||||
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.sans": "true",
|
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.sans": "true",
|
||||||
|
"traefik.http.middlewares.Middleware11.passTLSClientCert.info.serialNumber": "true",
|
||||||
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.commonname": "true",
|
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.commonname": "true",
|
||||||
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.country": "true",
|
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.country": "true",
|
||||||
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.domaincomponent": "true",
|
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.domaincomponent": "true",
|
||||||
|
@ -294,8 +295,9 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
PassTLSClientCert: &dynamic.PassTLSClientCert{
|
PassTLSClientCert: &dynamic.PassTLSClientCert{
|
||||||
PEM: true,
|
PEM: true,
|
||||||
Info: &dynamic.TLSClientCertificateInfo{
|
Info: &dynamic.TLSClientCertificateInfo{
|
||||||
NotAfter: true,
|
NotAfter: true,
|
||||||
NotBefore: true,
|
NotBefore: true,
|
||||||
|
SerialNumber: true,
|
||||||
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
||||||
Country: true,
|
Country: true,
|
||||||
Province: true,
|
Province: true,
|
||||||
|
@ -699,8 +701,9 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
PassTLSClientCert: &dynamic.PassTLSClientCert{
|
PassTLSClientCert: &dynamic.PassTLSClientCert{
|
||||||
PEM: true,
|
PEM: true,
|
||||||
Info: &dynamic.TLSClientCertificateInfo{
|
Info: &dynamic.TLSClientCertificateInfo{
|
||||||
NotAfter: true,
|
NotAfter: true,
|
||||||
NotBefore: true,
|
NotBefore: true,
|
||||||
|
SerialNumber: true,
|
||||||
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
||||||
Country: true,
|
Country: true,
|
||||||
Province: true,
|
Province: true,
|
||||||
|
@ -1061,6 +1064,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.NotAfter": "true",
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.NotAfter": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.NotBefore": "true",
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.NotBefore": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Sans": "true",
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Sans": "true",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.SerialNumber": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.Country": "true",
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.Country": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.Province": "true",
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.Province": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.Locality": "true",
|
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.Locality": "true",
|
||||||
|
|
|
@ -64,11 +64,12 @@ func newDistinguishedNameOptions(info *dynamic.TLSCLientCertificateDNInfo) *Dist
|
||||||
|
|
||||||
// tlsClientCertificateInfo is a struct for specifying the configuration for the passTLSClientCert middleware.
|
// tlsClientCertificateInfo is a struct for specifying the configuration for the passTLSClientCert middleware.
|
||||||
type tlsClientCertificateInfo struct {
|
type tlsClientCertificateInfo struct {
|
||||||
notAfter bool
|
notAfter bool
|
||||||
notBefore bool
|
notBefore bool
|
||||||
sans bool
|
sans bool
|
||||||
subject *DistinguishedNameOptions
|
subject *DistinguishedNameOptions
|
||||||
issuer *DistinguishedNameOptions
|
issuer *DistinguishedNameOptions
|
||||||
|
serialNumber bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTLSClientCertificateInfo(info *dynamic.TLSClientCertificateInfo) *tlsClientCertificateInfo {
|
func newTLSClientCertificateInfo(info *dynamic.TLSClientCertificateInfo) *tlsClientCertificateInfo {
|
||||||
|
@ -77,11 +78,12 @@ func newTLSClientCertificateInfo(info *dynamic.TLSClientCertificateInfo) *tlsCli
|
||||||
}
|
}
|
||||||
|
|
||||||
return &tlsClientCertificateInfo{
|
return &tlsClientCertificateInfo{
|
||||||
issuer: newDistinguishedNameOptions(info.Issuer),
|
issuer: newDistinguishedNameOptions(info.Issuer),
|
||||||
notAfter: info.NotAfter,
|
notAfter: info.NotAfter,
|
||||||
notBefore: info.NotBefore,
|
notBefore: info.NotBefore,
|
||||||
subject: newDistinguishedNameOptions(info.Subject),
|
subject: newDistinguishedNameOptions(info.Subject),
|
||||||
sans: info.Sans,
|
serialNumber: info.SerialNumber,
|
||||||
|
sans: info.Sans,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +157,13 @@ func (p *passTLSClientCert) getCertInfo(ctx context.Context, certs []*x509.Certi
|
||||||
values = append(values, fmt.Sprintf(`Issuer="%s"`, strings.TrimSuffix(issuer, subFieldSeparator)))
|
values = append(values, fmt.Sprintf(`Issuer="%s"`, strings.TrimSuffix(issuer, subFieldSeparator)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.info.serialNumber && peerCert.SerialNumber != nil {
|
||||||
|
sn := peerCert.SerialNumber.String()
|
||||||
|
if sn != "" {
|
||||||
|
values = append(values, fmt.Sprintf(`SerialNumber="%s"`, strings.TrimSuffix(sn, subFieldSeparator)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if p.info.notBefore {
|
if p.info.notBefore {
|
||||||
values = append(values, fmt.Sprintf(`NB="%d"`, uint64(peerCert.NotBefore.Unix())))
|
values = append(values, fmt.Sprintf(`NB="%d"`, uint64(peerCert.NotBefore.Unix())))
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,6 +345,7 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
|
||||||
minimalCheeseCertAllInfo := strings.Join([]string{
|
minimalCheeseCertAllInfo := strings.Join([]string{
|
||||||
`Subject="C=FR,ST=Some-State,O=Cheese"`,
|
`Subject="C=FR,ST=Some-State,O=Cheese"`,
|
||||||
`Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2"`,
|
`Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2"`,
|
||||||
|
`SerialNumber="481535886039632329873080491016862977516759989652"`,
|
||||||
`NB="1544094636"`,
|
`NB="1544094636"`,
|
||||||
`NA="1632568236"`,
|
`NA="1632568236"`,
|
||||||
}, fieldSeparator)
|
}, fieldSeparator)
|
||||||
|
@ -352,6 +353,7 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
|
||||||
completeCertAllInfo := strings.Join([]string{
|
completeCertAllInfo := strings.Join([]string{
|
||||||
`Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=*.cheese.com"`,
|
`Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=*.cheese.com"`,
|
||||||
`Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2"`,
|
`Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2"`,
|
||||||
|
`SerialNumber="1"`,
|
||||||
`NB="1544094616"`,
|
`NB="1544094616"`,
|
||||||
`NA="1607166616"`,
|
`NA="1607166616"`,
|
||||||
`SAN="*.cheese.org,*.cheese.net,*.cheese.com,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2"`,
|
`SAN="*.cheese.org,*.cheese.net,*.cheese.com,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2"`,
|
||||||
|
@ -399,9 +401,10 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
|
||||||
certContents: []string{minimalCheeseCrt},
|
certContents: []string{minimalCheeseCrt},
|
||||||
config: dynamic.PassTLSClientCert{
|
config: dynamic.PassTLSClientCert{
|
||||||
Info: &dynamic.TLSClientCertificateInfo{
|
Info: &dynamic.TLSClientCertificateInfo{
|
||||||
NotAfter: true,
|
NotAfter: true,
|
||||||
NotBefore: true,
|
NotBefore: true,
|
||||||
Sans: true,
|
Sans: true,
|
||||||
|
SerialNumber: true,
|
||||||
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
||||||
CommonName: true,
|
CommonName: true,
|
||||||
Country: true,
|
Country: true,
|
||||||
|
@ -446,9 +449,10 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
|
||||||
certContents: []string{completeCheeseCrt},
|
certContents: []string{completeCheeseCrt},
|
||||||
config: dynamic.PassTLSClientCert{
|
config: dynamic.PassTLSClientCert{
|
||||||
Info: &dynamic.TLSClientCertificateInfo{
|
Info: &dynamic.TLSClientCertificateInfo{
|
||||||
NotAfter: true,
|
NotAfter: true,
|
||||||
NotBefore: true,
|
NotBefore: true,
|
||||||
Sans: true,
|
Sans: true,
|
||||||
|
SerialNumber: true,
|
||||||
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
||||||
Country: true,
|
Country: true,
|
||||||
Province: true,
|
Province: true,
|
||||||
|
@ -476,9 +480,10 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
|
||||||
certContents: []string{minimalCheeseCrt, completeCheeseCrt},
|
certContents: []string{minimalCheeseCrt, completeCheeseCrt},
|
||||||
config: dynamic.PassTLSClientCert{
|
config: dynamic.PassTLSClientCert{
|
||||||
Info: &dynamic.TLSClientCertificateInfo{
|
Info: &dynamic.TLSClientCertificateInfo{
|
||||||
NotAfter: true,
|
NotAfter: true,
|
||||||
NotBefore: true,
|
NotBefore: true,
|
||||||
Sans: true,
|
Sans: true,
|
||||||
|
SerialNumber: true,
|
||||||
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
Subject: &dynamic.TLSCLientCertificateDNInfo{
|
||||||
Country: true,
|
Country: true,
|
||||||
Province: true,
|
Province: true,
|
||||||
|
|
Loading…
Reference in a new issue