From 2c550c284d19b02e2ff4c9c9e066cf548349a033 Mon Sep 17 00:00:00 2001 From: Romain Date: Thu, 13 Oct 2022 15:08:08 +0200 Subject: [PATCH] Remove raw cert escape in PassTLSClientCert middleware --- .../middlewares/http/passtlsclientcert.md | 20 +++++++++---------- .../kubernetes-crd-definition-v1.yml | 2 +- .../traefik.containo.us_middlewares.yaml | 2 +- integration/fixtures/k8s/01-traefik-crd.yml | 2 +- integration/tls_client_headers_test.go | 2 +- pkg/config/dynamic/middlewares.go | 2 +- .../passtlsclientcert/pass_tls_client_cert.go | 4 +--- .../pass_tls_client_cert_test.go | 2 +- 8 files changed, 17 insertions(+), 19 deletions(-) diff --git a/docs/content/middlewares/http/passtlsclientcert.md b/docs/content/middlewares/http/passtlsclientcert.md index 39a1a9ef5..28c5f7fff 100644 --- a/docs/content/middlewares/http/passtlsclientcert.md +++ b/docs/content/middlewares/http/passtlsclientcert.md @@ -16,10 +16,10 @@ PassTLSClientCert adds the selected data from the passed client TLS certificate ## Configuration Examples -Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. +Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. ```yaml tab="Docker" -# Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. +# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. labels: - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" ``` @@ -35,7 +35,7 @@ spec: ``` ```yaml tab="Consul Catalog" -# Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header +# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" ``` @@ -46,13 +46,13 @@ spec: ``` ```yaml tab="Rancher" -# Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. +# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. labels: - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" ``` ```yaml tab="File (YAML)" -# Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. +# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. http: middlewares: test-passtlsclientcert: @@ -61,13 +61,13 @@ http: ``` ```toml tab="File (TOML)" -# Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. +# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. [http.middlewares] [http.middlewares.test-passtlsclientcert.passTLSClientCert] pem = true ``` -??? example "Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header" +??? example "Pass the pem in the `X-Forwarded-Tls-Client-Cert` header" ```yaml tab="Docker" # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header @@ -254,12 +254,12 @@ http: PassTLSClientCert can add two headers to the request: -- `X-Forwarded-Tls-Client-Cert` that contains the escaped pem. +- `X-Forwarded-Tls-Client-Cert` that contains the pem. - `X-Forwarded-Tls-Client-Cert-Info` that contains all the selected certificate information in an escaped string. !!! info - * Each header value is a string that has been escaped in order to be a valid URL query. + * `X-Forwarded-Tls-Client-Cert-Info` 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. @@ -371,7 +371,7 @@ The following example shows a complete certificate and explains each of the midd ### `pem` -The `pem` option sets the `X-Forwarded-Tls-Client-Cert` header with the escaped certificate. +The `pem` option sets the `X-Forwarded-Tls-Client-Cert` header with the certificate. In the example, it is the part between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` delimiters: diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 17dc336f6..9bd6b37a7 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -1300,7 +1300,7 @@ spec: type: object pem: description: PEM sets the X-Forwarded-Tls-Client-Cert header with - the escaped certificate. + the certificate. type: boolean type: object plugin: diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml index 26cb51d2e..d7bd0b82c 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml @@ -723,7 +723,7 @@ spec: type: object pem: description: PEM sets the X-Forwarded-Tls-Client-Cert header with - the escaped certificate. + the certificate. type: boolean type: object plugin: diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 17dc336f6..9bd6b37a7 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -1300,7 +1300,7 @@ spec: type: object pem: description: PEM sets the X-Forwarded-Tls-Client-Cert header with - the escaped certificate. + the certificate. type: boolean type: object plugin: diff --git a/integration/tls_client_headers_test.go b/integration/tls_client_headers_test.go index d9c158efb..3bc587acd 100644 --- a/integration/tls_client_headers_test.go +++ b/integration/tls_client_headers_test.go @@ -65,6 +65,6 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) { }, } - err = try.RequestWithTransport(request, 2*time.Second, tr, try.BodyContains("Forwarded-Tls-Client-Cert: MIIDNTCCAh0CFD0QQcHXUJuKwMBYDA%2BbBExVSP26MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazENMAsGA1UEAwwEcm9vdDAeFw0yMTAxMDgxNzQ0MjRaFw0zMTAxMDYxNzQ0MjRaMFgxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazEPMA0GA1UEAwwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYK2z8gLPOfFLgXNWP2460aeJ9vrH47x%2FlhKLlv4amSDHDx8Cmz%2F6blOUM8XOfMRW1xx%2B%2BAgChWN9dx%2Fkf7G2xlA5grZxRvUQ6xj7AvFG9TQUA3muNh2hvm9c3IjaZBNKH27bRKuDIBvZBvXdX4NL%2FaaFy7w7v7IKxk8j4WkfB23sgyH43g4b7NqKHJugZiedFu5GALmtLbShVOFbjWcre7Wvatdw8dIBmiFJqZQT3UjIuGAgqczIShtLxo4V%2BXyVkIPmzfPrRV%2B4zoMFIFOIaj3syyxb4krPBtxhe7nz2cWvvq0wePB2y4YbAAoVY8NYpd5JsMFwZtG6Uk59ygv4QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDaPg69wNeFNFisfBJTrscqVCTW%2BB80gMhpLdxXD%2BKO0%2FWgc5xpB%2FwLSirNtRQyxAa3%2BEEcIwJv%2Fwdh8EyjlDLSpFm%2F8ghntrKhkOfIOPDFE41M5HNfx%2FFuh5btKEenOL%2FXdapqtNUt2ZE4RrsfbL79sPYepa9kDUVi2mCbeH5ollZ0MDU68HpB2YwHbCEuQNk5W3pjYK2NaDkVnxTkfEDM1k%2B3QydO1lqB5JJmcrs59BEveTqaJ3eeh%2F0I4OOab6OkTTZ0JNjJp1573oxO%2Bfce%2FbfGud8xHY5gSN9huU7U6RsgvO7Dhmal%2FsDNl8XC8oU90hVDVXZdA7ewh4jjaoIv")) + err = try.RequestWithTransport(request, 2*time.Second, tr, try.BodyContains("Forwarded-Tls-Client-Cert: MIIDNTCCAh0CFD0QQcHXUJuKwMBYDA+bBExVSP26MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazENMAsGA1UEAwwEcm9vdDAeFw0yMTAxMDgxNzQ0MjRaFw0zMTAxMDYxNzQ0MjRaMFgxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazEPMA0GA1UEAwwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYK2z8gLPOfFLgXNWP2460aeJ9vrH47x/lhKLlv4amSDHDx8Cmz/6blOUM8XOfMRW1xx++AgChWN9dx/kf7G2xlA5grZxRvUQ6xj7AvFG9TQUA3muNh2hvm9c3IjaZBNKH27bRKuDIBvZBvXdX4NL/aaFy7w7v7IKxk8j4WkfB23sgyH43g4b7NqKHJugZiedFu5GALmtLbShVOFbjWcre7Wvatdw8dIBmiFJqZQT3UjIuGAgqczIShtLxo4V+XyVkIPmzfPrRV+4zoMFIFOIaj3syyxb4krPBtxhe7nz2cWvvq0wePB2y4YbAAoVY8NYpd5JsMFwZtG6Uk59ygv4QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDaPg69wNeFNFisfBJTrscqVCTW+B80gMhpLdxXD+KO0/Wgc5xpB/wLSirNtRQyxAa3+EEcIwJv/wdh8EyjlDLSpFm/8ghntrKhkOfIOPDFE41M5HNfx/Fuh5btKEenOL/XdapqtNUt2ZE4RrsfbL79sPYepa9kDUVi2mCbeH5ollZ0MDU68HpB2YwHbCEuQNk5W3pjYK2NaDkVnxTkfEDM1k+3QydO1lqB5JJmcrs59BEveTqaJ3eeh/0I4OOab6OkTTZ0JNjJp1573oxO+fce/bfGud8xHY5gSN9huU7U6RsgvO7Dhmal/sDNl8XC8oU90hVDVXZdA7ewh4jjaoIv")) c.Assert(err, checker.IsNil) } diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index cddc7409e..0d849c273 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -416,7 +416,7 @@ type InFlightReq struct { // This middleware adds the selected data from the passed client TLS certificate to a header. // More info: https://doc.traefik.io/traefik/v2.9/middlewares/http/passtlsclientcert/ type PassTLSClientCert struct { - // PEM sets the X-Forwarded-Tls-Client-Cert header with the escaped certificate. + // PEM sets the X-Forwarded-Tls-Client-Cert header with the certificate. PEM bool `json:"pem,omitempty" toml:"pem,omitempty" yaml:"pem,omitempty" export:"true"` // Info selects the specific client certificate details you want to add to the X-Forwarded-Tls-Client-Cert-Info header. Info *TLSClientCertificateInfo `json:"info,omitempty" toml:"info,omitempty" yaml:"info,omitempty" export:"true"` diff --git a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go index 099446745..cddf0ad32 100644 --- a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go +++ b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go @@ -325,13 +325,11 @@ func writePart(ctx context.Context, content io.StringWriter, entry, prefix strin // sanitize As we pass the raw certificates, remove the useless data and make it http request compliant. func sanitize(cert []byte) string { - cleaned := strings.NewReplacer( + return strings.NewReplacer( "-----BEGIN CERTIFICATE-----", "", "-----END CERTIFICATE-----", "", "\n", "", ).Replace(string(cert)) - - return url.QueryEscape(cleaned) } // getCertificates Build a string with the client certificates. diff --git a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go index 6aca1c189..96c1bdffa 100644 --- a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go +++ b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go @@ -610,7 +610,7 @@ WqeUSNGYV//RunTeuRDAf5OxehERb1srzBXhRZ3cZdzXbgR/`, content := sanitize(test.toSanitize) - expected := url.QueryEscape(strings.ReplaceAll(test.expected, "\n", "")) + expected := strings.ReplaceAll(test.expected, "\n", "") assert.Equal(t, expected, content, "The sanitized certificates should be equal") }) }