1
0
Fork 0

Add organizationalUnit to passtlscert middleware

This commit is contained in:
Eric 2021-07-28 16:42:09 +01:00 committed by GitHub
parent c76d58d532
commit 817ac8f256
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 339 additions and 157 deletions

View file

@ -315,16 +315,17 @@ func TestDo_dynamicConfiguration(t *testing.T) {
NotAfter: true,
NotBefore: true,
Sans: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
Province: true,
Locality: true,

View file

@ -288,6 +288,7 @@
"province": true,
"locality": true,
"organization": true,
"organizationalUnit": true,
"commonName": true,
"serialNumber": true,
"domainComponent": true

View file

@ -330,6 +330,7 @@
province = true
locality = true
organization = true
organizationalUnit = true
commonName = true
serialNumber = true
domainComponent = true

View file

@ -399,19 +399,19 @@ type StripPrefixRegex struct {
// TLSClientCertificateInfo holds the client TLS certificate info configuration.
type TLSClientCertificateInfo struct {
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty" export:"true"`
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty" export:"true"`
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty" export:"true"`
Subject *TLSCLientCertificateDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty" export:"true"`
Issuer *TLSCLientCertificateDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty" export:"true"`
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty" export:"true"`
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty" export:"true"`
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty" export:"true"`
Subject *TLSCLientCertificateSubjectDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty" export:"true"`
Issuer *TLSCLientCertificateIssuerDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty" export:"true"`
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
}
// +k8s:deepcopy-gen=true
// TLSCLientCertificateDNInfo holds the client TLS certificate distinguished name info configuration.
// TLSCLientCertificateIssuerDNInfo holds the client TLS certificate distinguished name info configuration.
// cf https://tools.ietf.org/html/rfc3739
type TLSCLientCertificateDNInfo struct {
type TLSCLientCertificateIssuerDNInfo struct {
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty" export:"true"`
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty" export:"true"`
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty" export:"true"`
@ -423,6 +423,21 @@ type TLSCLientCertificateDNInfo struct {
// +k8s:deepcopy-gen=true
// TLSCLientCertificateSubjectDNInfo holds the client TLS certificate distinguished name info configuration.
// cf https://tools.ietf.org/html/rfc3739
type TLSCLientCertificateSubjectDNInfo struct {
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty" export:"true"`
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty" export:"true"`
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty" export:"true"`
Organization bool `json:"organization,omitempty" toml:"organization,omitempty" yaml:"organization,omitempty" export:"true"`
OrganizationalUnit bool `json:"organizationalUnit,omitempty" toml:"organizationalUnit,omitempty" yaml:"organizationalUnit,omitempty" export:"true"`
CommonName bool `json:"commonName,omitempty" toml:"commonName,omitempty" yaml:"commonName,omitempty" export:"true"`
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
DomainComponent bool `json:"domainComponent,omitempty" toml:"domainComponent,omitempty" yaml:"domainComponent,omitempty" export:"true"`
}
// +k8s:deepcopy-gen=true
// Users holds a list of users.
type Users []string

View file

@ -1535,17 +1535,33 @@ func (in *TCPWeightedRoundRobin) DeepCopy() *TCPWeightedRoundRobin {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TLSCLientCertificateDNInfo) DeepCopyInto(out *TLSCLientCertificateDNInfo) {
func (in *TLSCLientCertificateIssuerDNInfo) DeepCopyInto(out *TLSCLientCertificateIssuerDNInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCLientCertificateDNInfo.
func (in *TLSCLientCertificateDNInfo) DeepCopy() *TLSCLientCertificateDNInfo {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCLientCertificateIssuerDNInfo.
func (in *TLSCLientCertificateIssuerDNInfo) DeepCopy() *TLSCLientCertificateIssuerDNInfo {
if in == nil {
return nil
}
out := new(TLSCLientCertificateDNInfo)
out := new(TLSCLientCertificateIssuerDNInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TLSCLientCertificateSubjectDNInfo) DeepCopyInto(out *TLSCLientCertificateSubjectDNInfo) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCLientCertificateSubjectDNInfo.
func (in *TLSCLientCertificateSubjectDNInfo) DeepCopy() *TLSCLientCertificateSubjectDNInfo {
if in == nil {
return nil
}
out := new(TLSCLientCertificateSubjectDNInfo)
in.DeepCopyInto(out)
return out
}
@ -1555,12 +1571,12 @@ func (in *TLSClientCertificateInfo) DeepCopyInto(out *TLSClientCertificateInfo)
*out = *in
if in.Subject != nil {
in, out := &in.Subject, &out.Subject
*out = new(TLSCLientCertificateDNInfo)
*out = new(TLSCLientCertificateSubjectDNInfo)
**out = **in
}
if in.Issuer != nil {
in, out := &in.Issuer, &out.Issuer
*out = new(TLSCLientCertificateDNInfo)
*out = new(TLSCLientCertificateIssuerDNInfo)
**out = **in
}
return

View file

@ -95,6 +95,7 @@ func TestDecodeConfiguration(t *testing.T) {
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.domaincomponent": "true",
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.locality": "true",
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.organization": "true",
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.organizationalunit": "true",
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.province": "true",
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.subject.serialnumber": "true",
"traefik.http.middlewares.Middleware11.passtlsclientcert.info.issuer.commonname": "true",
@ -366,16 +367,17 @@ func TestDecodeConfiguration(t *testing.T) {
NotAfter: true,
NotBefore: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
Province: true,
Locality: true,
@ -844,16 +846,17 @@ func TestEncodeConfiguration(t *testing.T) {
NotAfter: true,
NotBefore: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
Province: true,
Locality: true,
@ -1234,6 +1237,7 @@ func TestEncodeConfiguration(t *testing.T) {
"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.Organization": "true",
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.OrganizationalUnit": "true",
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.CommonName": "true",
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.SerialNumber": "true",
"traefik.HTTP.Middlewares.Middleware11.PassTLSClientCert.Info.Subject.DomainComponent": "true",

View file

@ -35,8 +35,10 @@ var attributeTypeNames = map[string]string{
"0.9.2342.19200300.100.1.25": "DC", // Domain component OID - RFC 2247
}
// DistinguishedNameOptions is a struct for specifying the configuration for the distinguished name info.
type DistinguishedNameOptions struct {
// IssuerDistinguishedNameOptions is a struct for specifying the configuration
// for the distinguished name info of the issuer. This information is defined in
// RFC3739, section 3.1.1.
type IssuerDistinguishedNameOptions struct {
CommonName bool
CountryName bool
DomainComponent bool
@ -46,12 +48,12 @@ type DistinguishedNameOptions struct {
StateOrProvinceName bool
}
func newDistinguishedNameOptions(info *dynamic.TLSCLientCertificateDNInfo) *DistinguishedNameOptions {
func newIssuerDistinguishedNameOptions(info *dynamic.TLSCLientCertificateIssuerDNInfo) *IssuerDistinguishedNameOptions {
if info == nil {
return nil
}
return &DistinguishedNameOptions{
return &IssuerDistinguishedNameOptions{
CommonName: info.CommonName,
CountryName: info.Country,
DomainComponent: info.DomainComponent,
@ -62,13 +64,44 @@ func newDistinguishedNameOptions(info *dynamic.TLSCLientCertificateDNInfo) *Dist
}
}
// SubjectDistinguishedNameOptions is a struct for specifying the configuration
// for the distinguished name info of the subject. This information is defined
// in RFC3739, section 3.1.2.
type SubjectDistinguishedNameOptions struct {
CommonName bool
CountryName bool
DomainComponent bool
LocalityName bool
OrganizationName bool
OrganizationalUnitName bool
SerialNumber bool
StateOrProvinceName bool
}
func newSubjectDistinguishedNameOptions(info *dynamic.TLSCLientCertificateSubjectDNInfo) *SubjectDistinguishedNameOptions {
if info == nil {
return nil
}
return &SubjectDistinguishedNameOptions{
CommonName: info.CommonName,
CountryName: info.Country,
DomainComponent: info.DomainComponent,
LocalityName: info.Locality,
OrganizationName: info.Organization,
OrganizationalUnitName: info.OrganizationalUnit,
SerialNumber: info.SerialNumber,
StateOrProvinceName: info.Province,
}
}
// tlsClientCertificateInfo is a struct for specifying the configuration for the passTLSClientCert middleware.
type tlsClientCertificateInfo struct {
notAfter bool
notBefore bool
sans bool
subject *DistinguishedNameOptions
issuer *DistinguishedNameOptions
subject *SubjectDistinguishedNameOptions
issuer *IssuerDistinguishedNameOptions
serialNumber bool
}
@ -78,10 +111,10 @@ func newTLSClientCertificateInfo(info *dynamic.TLSClientCertificateInfo) *tlsCli
}
return &tlsClientCertificateInfo{
issuer: newDistinguishedNameOptions(info.Issuer),
issuer: newIssuerDistinguishedNameOptions(info.Issuer),
notAfter: info.NotAfter,
notBefore: info.NotBefore,
subject: newDistinguishedNameOptions(info.Subject),
subject: newSubjectDistinguishedNameOptions(info.Subject),
serialNumber: info.SerialNumber,
sans: info.Sans,
}
@ -147,12 +180,12 @@ func (p *passTLSClientCert) getCertInfo(ctx context.Context, certs []*x509.Certi
var values []string
if p.info != nil {
subject := getDNInfo(ctx, p.info.subject, &peerCert.Subject)
subject := getSubjectDNInfo(ctx, p.info.subject, &peerCert.Subject)
if subject != "" {
values = append(values, fmt.Sprintf(`Subject="%s"`, strings.TrimSuffix(subject, subFieldSeparator)))
}
issuer := getDNInfo(ctx, p.info.issuer, &peerCert.Issuer)
issuer := getIssuerDNInfo(ctx, p.info.issuer, &peerCert.Issuer)
if issuer != "" {
values = append(values, fmt.Sprintf(`Issuer="%s"`, strings.TrimSuffix(issuer, subFieldSeparator)))
}
@ -187,7 +220,7 @@ func (p *passTLSClientCert) getCertInfo(ctx context.Context, certs []*x509.Certi
return strings.Join(headerValues, certSeparator)
}
func getDNInfo(ctx context.Context, options *DistinguishedNameOptions, cs *pkix.Name) string {
func getIssuerDNInfo(ctx context.Context, options *IssuerDistinguishedNameOptions, cs *pkix.Name) string {
if options == nil {
return ""
}
@ -229,6 +262,52 @@ func getDNInfo(ctx context.Context, options *DistinguishedNameOptions, cs *pkix.
return content.String()
}
func getSubjectDNInfo(ctx context.Context, options *SubjectDistinguishedNameOptions, cs *pkix.Name) string {
if options == nil {
return ""
}
content := &strings.Builder{}
// Manage non standard attributes
for _, name := range cs.Names {
// Domain Component - RFC 2247
if options.DomainComponent && attributeTypeNames[name.Type.String()] == "DC" {
content.WriteString(fmt.Sprintf("DC=%s%s", name.Value, subFieldSeparator))
}
}
if options.CountryName {
writeParts(ctx, content, cs.Country, "C")
}
if options.StateOrProvinceName {
writeParts(ctx, content, cs.Province, "ST")
}
if options.LocalityName {
writeParts(ctx, content, cs.Locality, "L")
}
if options.OrganizationName {
writeParts(ctx, content, cs.Organization, "O")
}
if options.OrganizationalUnitName {
writeParts(ctx, content, cs.OrganizationalUnit, "OU")
}
if options.SerialNumber {
writePart(ctx, content, cs.SerialNumber, "SN")
}
if options.CommonName {
writePart(ctx, content, cs.CommonName, "CN")
}
return content.String()
}
func writeParts(ctx context.Context, content io.StringWriter, entries []string, prefix string) {
for _, entry := range entries {
writePart(ctx, content, entry, prefix)

View file

@ -310,22 +310,22 @@ func TestPassTLSClientCert_PEM(t *testing.T) {
}
for _, test := range testCases {
tlsClientHeaders, err := New(context.Background(), next, test.config, "foo")
require.NoError(t, err)
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req)
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
tlsClientHeaders, err := New(context.Background(), next, test.config, "foo")
require.NoError(t, err)
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req)
assert.Equal(t, http.StatusOK, res.Code, "Http Status should be OK")
assert.Equal(t, "bar", res.Body.String(), "Should be the expected body")
@ -351,7 +351,7 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
}, fieldSeparator)
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,OU=Simple Signing Section,OU=Simple Signing Section 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"`,
`SerialNumber="1"`,
`NB="1544094616"`,
@ -376,13 +376,14 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
desc: "No TLS, with subject info",
config: dynamic.PassTLSClientCert{
Info: &dynamic.TLSClientCertificateInfo{
Subject: &dynamic.TLSCLientCertificateDNInfo{
CommonName: true,
Organization: true,
Locality: true,
Province: true,
Country: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
CommonName: true,
Organization: true,
OrganizationalUnit: true,
Locality: true,
Province: true,
Country: true,
SerialNumber: true,
},
},
},
@ -392,7 +393,7 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
config: dynamic.PassTLSClientCert{
PEM: false,
Info: &dynamic.TLSClientCertificateInfo{
Subject: &dynamic.TLSCLientCertificateDNInfo{},
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{},
},
},
},
@ -405,16 +406,17 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
NotBefore: true,
Sans: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
CommonName: true,
Country: true,
DomainComponent: true,
Locality: true,
Organization: true,
Province: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
CommonName: true,
Country: true,
DomainComponent: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
Province: true,
SerialNumber: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
CommonName: true,
Country: true,
DomainComponent: true,
@ -434,10 +436,30 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
Info: &dynamic.TLSClientCertificateInfo{
NotAfter: true,
Sans: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Organization: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
},
},
},
expectedHeader: `Subject="O=Cheese";Issuer="C=FR,C=US";NA="1632568236"`,
},
{
desc: "TLS with simple certificate, requesting non-existent info",
certContents: []string{minimalCheeseCrt},
config: dynamic.PassTLSClientCert{
Info: &dynamic.TLSClientCertificateInfo{
NotAfter: true,
Sans: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Organization: true,
// OrganizationalUnit is not set on this example certificate,
// so even though it's requested, it will be absent.
OrganizationalUnit: true,
},
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
},
},
@ -453,16 +475,17 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
NotBefore: true,
Sans: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
Province: true,
Locality: true,
@ -484,16 +507,17 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
NotBefore: true,
Sans: true,
SerialNumber: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
Province: true,
Locality: true,
@ -509,22 +533,22 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
}
for _, test := range testCases {
tlsClientHeaders, err := New(context.Background(), next, test.config, "foo")
require.NoError(t, err)
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req)
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
tlsClientHeaders, err := New(context.Background(), next, test.config, "foo")
require.NoError(t, err)
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req)
assert.Equal(t, http.StatusOK, res.Code, "Http Status should be OK")
assert.Equal(t, "bar", res.Body.String(), "Should be the expected body")
@ -621,12 +645,12 @@ func Test_getSANs(t *testing.T) {
}
for _, test := range testCases {
sans := getSANs(test.cert)
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
sans := getSANs(test.cert)
if len(test.expected) > 0 {
for i, expected := range test.expected {
assert.Equal(t, expected, sans[i])

View file

@ -156,6 +156,7 @@ func Test_buildConfiguration(t *testing.T) {
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/province": "true",
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/locality": "true",
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/organization": "true",
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/organizationalunit": "true",
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/commonName": "true",
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/serialNumber": "true",
"traefik/http/middlewares/Middleware12/passTLSClientCert/info/subject/domainComponent": "true",
@ -478,16 +479,17 @@ func Test_buildConfiguration(t *testing.T) {
NotAfter: true,
NotBefore: true,
Sans: true,
Subject: &dynamic.TLSCLientCertificateDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
Subject: &dynamic.TLSCLientCertificateSubjectDNInfo{
Country: true,
Province: true,
Locality: true,
Organization: true,
OrganizationalUnit: true,
CommonName: true,
SerialNumber: true,
DomainComponent: true,
},
Issuer: &dynamic.TLSCLientCertificateDNInfo{
Issuer: &dynamic.TLSCLientCertificateIssuerDNInfo{
Country: true,
Province: true,
Locality: true,