Add organizationalUnit to passtlscert middleware
This commit is contained in:
parent
c76d58d532
commit
817ac8f256
18 changed files with 339 additions and 157 deletions
|
@ -76,6 +76,7 @@ http:
|
|||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
|
||||
|
@ -104,6 +105,7 @@ http:
|
|||
province: true
|
||||
locality: true
|
||||
organization: true
|
||||
organizationalUnit: true
|
||||
commonName: true
|
||||
serialNumber: true
|
||||
domainComponent: true
|
||||
|
@ -127,6 +129,7 @@ http:
|
|||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
|
||||
|
@ -148,6 +151,7 @@ http:
|
|||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent": "true",
|
||||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality": "true",
|
||||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization": "true",
|
||||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit": "true",
|
||||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province": "true",
|
||||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber": "true",
|
||||
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname": "true",
|
||||
|
@ -171,6 +175,7 @@ http:
|
|||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
|
||||
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
|
||||
|
@ -197,6 +202,7 @@ http:
|
|||
province: true
|
||||
locality: true
|
||||
organization: true
|
||||
organizationalUnit: true
|
||||
commonName: true
|
||||
serialNumber: true
|
||||
domainComponent: true
|
||||
|
@ -223,6 +229,7 @@ http:
|
|||
province = true
|
||||
locality = true
|
||||
organization = true
|
||||
organizationalUnit = true
|
||||
commonName = true
|
||||
serialNumber = true
|
||||
domainComponent = true
|
||||
|
@ -247,7 +254,7 @@ PassTLSClientCert can add two headers to the request:
|
|||
|
||||
!!! info
|
||||
|
||||
* The headers are filled with escaped string so it can be safely placed inside a URL query.
|
||||
* Each header value is a string that has been escaped in order to be a valid URL query.
|
||||
* These options only work accordingly to the [MutualTLS configuration](../../https/tls.md#client-authentication-mtls).
|
||||
That is to say, only the certificates that match the `clientAuth.clientAuthType` policy are passed.
|
||||
|
||||
|
@ -412,15 +419,18 @@ In the example, it is the part between `-----BEGIN CERTIFICATE-----` and `-----E
|
|||
!!! warning "`X-Forwarded-Tls-Client-Cert` value could exceed the web server header size limit"
|
||||
|
||||
The header size limit of web servers is commonly between 4kb and 8kb.
|
||||
You could change the server configuration to allow bigger header or use the `info` option with the needed field(s).
|
||||
If that turns out to be a problem, and if reconfiguring the server to allow larger headers is not an option,
|
||||
one can alleviate the problem by selecting only the interesting parts of the cert,
|
||||
through the use of the `info` options described below. (And by setting `pem` to false).
|
||||
|
||||
### `info`
|
||||
|
||||
The `info` option selects the specific client certificate details you want to add to the `X-Forwarded-Tls-Client-Cert-Info` header.
|
||||
|
||||
The value of the header is an escaped concatenation of all the selected certificate details.
|
||||
But in the following, unless specified otherwise, all the header values examples are shown unescaped, for readability.
|
||||
|
||||
The following example shows an unescaped result that uses all the available fields:
|
||||
The following example shows such a concatenation, when all the available fields are selected:
|
||||
|
||||
```text
|
||||
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=*.example.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";NB="1544094616";NA="1607166616";SAN="*.example.org,*.example.net,*.example.com,test@example.org,test@example.net,10.0.1.0,10.0.1.2"
|
||||
|
@ -441,7 +451,7 @@ The data is taken from the following certificate part:
|
|||
Not After : Dec 5 11:10:16 2020 GMT
|
||||
```
|
||||
|
||||
The escaped `notAfter` info part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
NA="1607166616"
|
||||
|
@ -458,7 +468,7 @@ Validity
|
|||
Not Before: Dec 6 11:10:16 2018 GMT
|
||||
```
|
||||
|
||||
The escaped `notBefore` info part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
NB="1544094616"
|
||||
|
@ -475,7 +485,7 @@ The data is taken from the following certificate part:
|
|||
DNS:*.example.org, DNS:*.example.net, DNS:*.example.com, IP Address:10.0.1.0, IP Address:10.0.1.2, email:test@example.org, email:test@example.net
|
||||
```
|
||||
|
||||
The escape SANs info part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
SAN="*.example.org,*.example.net,*.example.com,test@example.org,test@example.net,10.0.1.0,10.0.1.2"
|
||||
|
@ -501,7 +511,7 @@ Set the `info.subject.country` option to `true` to add the `country` information
|
|||
|
||||
The data is taken from the subject part with the `C` key.
|
||||
|
||||
The escape country info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
C=FR,C=US
|
||||
|
@ -513,7 +523,7 @@ Set the `info.subject.province` option to `true` to add the `province` informati
|
|||
|
||||
The data is taken from the subject part with the `ST` key.
|
||||
|
||||
The escape province info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
ST=Cheese org state,ST=Cheese com state
|
||||
|
@ -525,7 +535,7 @@ Set the `info.subject.locality` option to `true` to add the `locality` informati
|
|||
|
||||
The data is taken from the subject part with the `L` key.
|
||||
|
||||
The escape locality info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
L=TOULOUSE,L=LYON
|
||||
|
@ -537,19 +547,31 @@ Set the `info.subject.organization` option to `true` to add the `organization` i
|
|||
|
||||
The data is taken from the subject part with the `O` key.
|
||||
|
||||
The escape organization info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
O=Cheese,O=Cheese 2
|
||||
```
|
||||
|
||||
##### `info.subject.organizationalUnit`
|
||||
|
||||
Set the `info.subject.organizationalUnit` option to `true` to add the `organizationalUnit` information into the subject.
|
||||
|
||||
The data is taken from the subject part with the `OU` key.
|
||||
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
OU=Cheese Section,OU=Cheese Section 2
|
||||
```
|
||||
|
||||
##### `info.subject.commonName`
|
||||
|
||||
Set the `info.subject.commonName` option to `true` to add the `commonName` information into the subject.
|
||||
|
||||
The data is taken from the subject part with the `CN` key.
|
||||
|
||||
The escape common name info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
CN=*.example.com
|
||||
|
@ -561,7 +583,7 @@ Set the `info.subject.serialNumber` option to `true` to add the `serialNumber` i
|
|||
|
||||
The data is taken from the subject part with the `SN` key.
|
||||
|
||||
The escape serial number info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
SN=1234567890
|
||||
|
@ -573,7 +595,7 @@ Set the `info.subject.domainComponent` option to `true` to add the `domainCompon
|
|||
|
||||
The data is taken from the subject part with the `DC` key.
|
||||
|
||||
The escape domain component info in the subject part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
DC=org,DC=cheese
|
||||
|
@ -595,7 +617,7 @@ Set the `info.issuer.country` option to `true` to add the `country` information
|
|||
|
||||
The data is taken from the issuer part with the `C` key.
|
||||
|
||||
The escape country info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
C=FR,C=US
|
||||
|
@ -607,7 +629,7 @@ Set the `info.issuer.province` option to `true` to add the `province` informatio
|
|||
|
||||
The data is taken from the issuer part with the `ST` key.
|
||||
|
||||
The escape province info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
ST=Signing State,ST=Signing State 2
|
||||
|
@ -619,7 +641,7 @@ Set the `info.issuer.locality` option to `true` to add the `locality` informatio
|
|||
|
||||
The data is taken from the issuer part with the `L` key.
|
||||
|
||||
The escape locality info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
L=TOULOUSE,L=LYON
|
||||
|
@ -631,7 +653,7 @@ Set the `info.issuer.organization` option to `true` to add the `organization` in
|
|||
|
||||
The data is taken from the issuer part with the `O` key.
|
||||
|
||||
The escape organization info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
O=Cheese,O=Cheese 2
|
||||
|
@ -643,7 +665,7 @@ Set the `info.issuer.commonName` option to `true` to add the `commonName` inform
|
|||
|
||||
The data is taken from the issuer part with the `CN` key.
|
||||
|
||||
The escape common name info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
CN=Simple Signing CA 2
|
||||
|
@ -655,7 +677,7 @@ Set the `info.issuer.serialNumber` option to `true` to add the `serialNumber` in
|
|||
|
||||
The data is taken from the issuer part with the `SN` key.
|
||||
|
||||
The escape serial number info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
SN=1234567890
|
||||
|
@ -667,7 +689,7 @@ Set the `info.issuer.domainComponent` option to `true` to add the `domainCompone
|
|||
|
||||
The data is taken from the issuer part with the `DC` key.
|
||||
|
||||
The escape domain component info in the issuer part is formatted as below:
|
||||
And it is formatted as follows in the header:
|
||||
|
||||
```text
|
||||
DC=org,DC=cheese
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
- "traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.domaincomponent=true"
|
||||
- "traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.locality=true"
|
||||
- "traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organization=true"
|
||||
- "traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organizationalunit=true"
|
||||
- "traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.province=true"
|
||||
- "traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.serialnumber=true"
|
||||
- "traefik.http.middlewares.middleware13.passtlsclientcert.pem=true"
|
||||
|
|
|
@ -217,6 +217,7 @@
|
|||
province = true
|
||||
locality = true
|
||||
organization = true
|
||||
organizationalUnit = true
|
||||
commonName = true
|
||||
serialNumber = true
|
||||
domainComponent = true
|
||||
|
|
|
@ -250,6 +250,7 @@ http:
|
|||
province: true
|
||||
locality: true
|
||||
organization: true
|
||||
organizationalUnit: true
|
||||
commonName: true
|
||||
serialNumber: true
|
||||
domainComponent: true
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/info/subject/domainComponent` | `true` |
|
||||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/info/subject/locality` | `true` |
|
||||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/info/subject/organization` | `true` |
|
||||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/info/subject/organizationalUnit` | `true` |
|
||||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/info/subject/province` | `true` |
|
||||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/info/subject/serialNumber` | `true` |
|
||||
| `traefik/http/middlewares/Middleware13/passTLSClientCert/pem` | `true` |
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.domaincomponent": "true",
|
||||
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.locality": "true",
|
||||
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organization": "true",
|
||||
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organizationalunit": "true",
|
||||
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.province": "true",
|
||||
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.serialnumber": "true",
|
||||
"traefik.http.middlewares.middleware13.passtlsclientcert.pem": "true",
|
||||
|
|
|
@ -398,8 +398,9 @@ spec:
|
|||
info configuration.
|
||||
properties:
|
||||
issuer:
|
||||
description: TLSCLientCertificateDNInfo holds the client TLS
|
||||
certificate distinguished name info configuration. cf https://tools.ietf.org/html/rfc3739
|
||||
description: TLSCLientCertificateIssuerDNInfo holds the client
|
||||
TLS certificate distinguished name info configuration. cf
|
||||
https://tools.ietf.org/html/rfc3739
|
||||
properties:
|
||||
commonName:
|
||||
type: boolean
|
||||
|
@ -425,8 +426,9 @@ spec:
|
|||
serialNumber:
|
||||
type: boolean
|
||||
subject:
|
||||
description: TLSCLientCertificateDNInfo holds the client TLS
|
||||
certificate distinguished name info configuration. cf https://tools.ietf.org/html/rfc3739
|
||||
description: TLSCLientCertificateSubjectDNInfo holds the client
|
||||
TLS certificate distinguished name info configuration. cf
|
||||
https://tools.ietf.org/html/rfc3739
|
||||
properties:
|
||||
commonName:
|
||||
type: boolean
|
||||
|
@ -438,6 +440,8 @@ spec:
|
|||
type: boolean
|
||||
organization:
|
||||
type: boolean
|
||||
organizationalUnit:
|
||||
type: boolean
|
||||
province:
|
||||
type: boolean
|
||||
serialNumber:
|
||||
|
|
|
@ -840,8 +840,9 @@ spec:
|
|||
info configuration.
|
||||
properties:
|
||||
issuer:
|
||||
description: TLSCLientCertificateDNInfo holds the client TLS
|
||||
certificate distinguished name info configuration. cf https://tools.ietf.org/html/rfc3739
|
||||
description: TLSCLientCertificateIssuerDNInfo holds the client
|
||||
TLS certificate distinguished name info configuration. cf
|
||||
https://tools.ietf.org/html/rfc3739
|
||||
properties:
|
||||
commonName:
|
||||
type: boolean
|
||||
|
@ -867,8 +868,9 @@ spec:
|
|||
serialNumber:
|
||||
type: boolean
|
||||
subject:
|
||||
description: TLSCLientCertificateDNInfo holds the client TLS
|
||||
certificate distinguished name info configuration. cf https://tools.ietf.org/html/rfc3739
|
||||
description: TLSCLientCertificateSubjectDNInfo holds the client
|
||||
TLS certificate distinguished name info configuration. cf
|
||||
https://tools.ietf.org/html/rfc3739
|
||||
properties:
|
||||
commonName:
|
||||
type: boolean
|
||||
|
@ -880,6 +882,8 @@ spec:
|
|||
type: boolean
|
||||
organization:
|
||||
type: boolean
|
||||
organizationalUnit:
|
||||
type: boolean
|
||||
province:
|
||||
type: boolean
|
||||
serialNumber:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -288,6 +288,7 @@
|
|||
"province": true,
|
||||
"locality": true,
|
||||
"organization": true,
|
||||
"organizationalUnit": true,
|
||||
"commonName": true,
|
||||
"serialNumber": true,
|
||||
"domainComponent": true
|
||||
|
|
|
@ -330,6 +330,7 @@
|
|||
province = true
|
||||
locality = true
|
||||
organization = true
|
||||
organizationalUnit = true
|
||||
commonName = true
|
||||
serialNumber = true
|
||||
domainComponent = true
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -866,17 +866,21 @@
|
|||
<q-card-section v-if="middleware.passTLSClientCert && middleware.passTLSClientCert.info && middleware.passTLSClientCert.info.subject">
|
||||
<div class="row items-start no-wrap">
|
||||
<div class="col">
|
||||
<div class="text-subtitle2">Common Name</div>
|
||||
<boolean-state :value="!!exData(middleware).info.subject.commonName"/>
|
||||
<div class="text-subtitle2">Organizational Unit</div>
|
||||
<boolean-state :value="!!exData(middleware).info.subject.organizationalUnit"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-subtitle2">Serial Number</div>
|
||||
<boolean-state :value="!!exData(middleware).info.subject.serialNumber"/>
|
||||
<div class="text-subtitle2">Common Name</div>
|
||||
<boolean-state :value="!!exData(middleware).info.subject.commonName"/>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section v-if="middleware.passTLSClientCert && middleware.passTLSClientCert.info && middleware.passTLSClientCert.info.subject">
|
||||
<div class="row items-start no-wrap">
|
||||
<div class="col">
|
||||
<div class="text-subtitle2">Serial Number</div>
|
||||
<boolean-state :value="!!exData(middleware).info.subject.serialNumber"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-subtitle2">Domain Component</div>
|
||||
<boolean-state :value="!!exData(middleware).info.subject.domainComponent"/>
|
||||
|
|
Loading…
Reference in a new issue