2018-08-29 09:36:03 +00:00
package middlewares
import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"net"
"net/http"
"net/http/httptest"
"net/url"
"regexp"
"strings"
"testing"
2018-11-14 09:18:03 +00:00
"github.com/containous/traefik/old/types"
2018-08-29 09:36:03 +00:00
"github.com/containous/traefik/testhelpers"
2019-01-08 08:46:04 +00:00
"github.com/stretchr/testify/assert"
2018-08-29 09:36:03 +00:00
"github.com/stretchr/testify/require"
)
const (
2019-01-08 08:46:04 +00:00
signingCA = ` Certificate :
Data :
Version : 3 ( 0x2 )
Serial Number : 2 ( 0x2 )
Signature Algorithm : sha1WithRSAEncryption
Issuer : DC = org , DC = cheese , O = Cheese , O = Cheese 2 , OU = Cheese Section , OU = Cheese Section 2 , CN = Simple Root CA , CN = Simple Root CA 2 , C = FR , C = US , L = TOULOUSE , L = LYON , ST = Root State , ST = Root State 2 / emailAddress = root @ signing . com / emailAddress = root2 @ signing . com
Validity
Not Before : Dec 6 11 : 10 : 0 9 2018 GMT
Not After : Dec 5 11 : 10 : 0 9 2028 GMT
Subject : DC = org , DC = cheese , O = Cheese , O = Cheese 2 , OU = Simple Signing Section , OU = Simple Signing Section 2 , CN = Simple Signing CA , CN = Simple Signing CA 2 , C = FR , C = US , L = TOULOUSE , L = LYON , ST = Signing State , ST = Signing State 2 / emailAddress = simple @ signing . com / emailAddress = simple2 @ signing . com
Subject Public Key Info :
Public Key Algorithm : rsaEncryption
RSA Public - Key : ( 2048 bit )
Modulus :
00 : c3 : 9 d : 9 f : 61 : 15 : 57 : 3 f : 78 : cc : e7 : 5 d : 20 : e2 : 3 e :
2 e : 79 : 4 a : c3 : 3 a : 0 c : 26 : 40 : 18 : db : 87 : 0 8 : 85 : c2 : f7 :
af : 87 : 13 : 1 a : ff : 67 : 8 a : b7 : 2 b : 58 : a7 : cc : 89 : dd : 77 :
ff : 5 e : 27 : 65 : 11 : 80 : 82 : 8 f : af : a0 : af : 25 : 86 : ec : a2 :
4 f : 20 : 0 e : 14 : 15 : 16 : 12 : d7 : 74 : 5 a : c3 : 99 : bd : 3 b : 81 :
c8 : 63 : 6 f : fc : 90 : 14 : 86 : d2 : 39 : ee : 87 : b2 : ff : 6 d : a5 :
69 : da : ab : 5 a : 3 a : 97 : cd : 23 : 37 : 6 a : 4 b : ba : 63 : cd : a1 :
a9 : e6 : 79 : aa : 37 : b8 : d1 : 90 : c9 : 24 : b5 : e8 : 70 : fc : 15 :
ad : 39 : 97 : 28 : 73 : 47 : 66 : f6 : 22 : 79 : 5 a : b0 : 03 : 83 : 8 a :
f1 : ca : ae : 8 b : 50 : 1 e : c8 : fa : 0 d : 9 f : 76 : 2 e : 00 : c2 : 0 e :
75 : bc : 47 : 5 a : b6 : d8 : 05 : ed : 5 a : bc : 6 d : 50 : 50 : 36 : 6 b :
ab : ab : 69 : f6 : 9 b : 1 b : 6 c : 7 e : a8 : 9 f : b2 : 33 : 3 a : 3 c : 8 c :
6 d : 5 e : 83 : ce : 17 : 82 : 9 e : 10 : 51 : a6 : 39 : ec : 98 : 4 e : 50 :
b7 : b1 : aa : 8 b : ac : bb : a1 : 60 : 1 b : ea : 31 : 3 b : b8 : 0 a : ea :
63 : 41 : 79 : b5 : ec : ee : 19 : e9 : 85 : 8 e : f3 : 6 d : 93 : 80 : da :
98 : 58 : a2 : 40 : 93 : a5 : 53 : eb : 1 d : 24 : b6 : 66 : 07 : ec : 58 :
10 : 63 : e7 : fa : 6 e : 18 : 60 : 74 : 76 : 15 : 39 : 3 c : f4 : 95 : 95 :
7 e : df
Exponent : 65537 ( 0x10001 )
X509v3 extensions :
X509v3 Key Usage : critical
Certificate Sign , CRL Sign
X509v3 Basic Constraints : critical
CA : TRUE , pathlen : 0
X509v3 Subject Key Identifier :
1 E : 52 : A2 : E8 : 54 : D5 : 37 : EB : D5 : A8 : 1 D : E4 : C2 : 04 : 1 D : 37 : E2 : F7 : 70 : 03
X509v3 Authority Key Identifier :
keyid : 36 : 70 : 35 : AA : F0 : F6 : 93 : B2 : 86 : 5 D : 32 : 73 : F9 : 41 : 5 A : 3 F : 3 B : C8 : BC : 8 B
Signature Algorithm : sha1WithRSAEncryption
76 : f3 : 16 : 21 : 27 : 6 d : a2 : 2 e : e8 : 18 : 49 : aa : 54 : 1 e : f8 : 3 b : 07 : fa :
65 : 50 : d8 : 1 f : a2 : cf : 64 : 6 c : 15 : e0 : 0 f : c8 : 46 : b2 : d7 : b8 : 0 e : cd :
05 : 3 b : 06 : fb : dd : c6 : 2 f : 01 : ae : bd : 69 : d3 : bb : 55 : 47 : a9 : f6 : e5 :
ba : be : 4 b : 45 : fb : 2 e : 3 c : 33 : e0 : 57 : d4 : 3 e : 8 e : 3 e : 11 : f2 : 0 a : f1 :
7 d : 06 : ab : 04 : 2 e : a5 : 76 : 20 : c2 : db : a4 : 68 : 5 a : 39 : 00 : 62 : 2 a : 1 d :
c2 : 12 : b1 : 90 : 66 : 8 c : 36 : a8 : fd : 83 : d1 : 1 b : da : 23 : a7 : 1 d : 5 b : e6 :
9 b : 40 : c4 : 78 : 25 : c7 : b7 : 6 b : 75 : 35 : cf : bb : 37 : 4 a : 4 f : fc : 7 e : 32 :
1 f : 8 c : cf : 12 : d2 : c9 : c8 : 99 : d9 : 4 a : 55 : 0 a : 1 e : ac : de : b4 : cb : 7 c :
bf : c4 : fb : 60 : 2 c : a8 : f7 : e7 : 63 : 5 c : b0 : 1 c : 62 : af : 01 : 3 c : fe : 4 d :
3 c : 0 b : 18 : 37 : 4 c : 25 : fc : d0 : b2 : f6 : b2 : f1 : c3 : f4 : 0 f : 53 : d6 : 1 e :
b5 : fa : bc : d8 : ad : dd : 1 c : f5 : 45 : 9 f : af : fe : 0 a : 01 : 79 : 92 : 9 a : d8 :
71 : db : 37 : f3 : 1 e : bd : fb : c7 : 1 e : 0 a : 0 f : 97 : 2 a : 61 : f3 : 7 b : 19 : 93 :
9 c : a6 : 8 a : 69 : cd : b0 : f5 : 91 : 02 : a5 : 1 b : 10 : f4 : 80 : 5 d : 42 : af : 4 e :
82 : 12 : 30 : 3 e : d3 : a7 : 11 : 14 : ce : 50 : 91 : 04 : 80 : d7 : 2 a : 03 : ef : 71 :
10 : b8 : db : a5
-- -- - BEGIN CERTIFICATE -- -- -
MIIFzTCCBLWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCCAWQxEzARBgoJkiaJk / Is
ZAEZFgNvcmcxFjAUBgoJkiaJk / IsZAEZFgZjaGVlc2UxDzANBgNVBAoMBkNoZWVz
ZTERMA8GA1UECgwIQ2hlZXNlIDIxFzAVBgNVBAsMDkNoZWVzZSBTZWN0aW9uMRkw
FwYDVQQLDBBDaGVlc2UgU2VjdGlvbiAyMRcwFQYDVQQDDA5TaW1wbGUgUm9vdCBD
QTEZMBcGA1UEAwwQU2ltcGxlIFJvb3QgQ0EgMjELMAkGA1UEBhMCRlIxCzAJBgNV
BAYTAlVTMREwDwYDVQQHDAhUT1VMT1VTRTENMAsGA1UEBwwETFlPTjETMBEGA1UE
CAwKUm9vdCBTdGF0ZTEVMBMGA1UECAwMUm9vdCBTdGF0ZSAyMR8wHQYJKoZIhvcN
AQkBFhByb290QHNpZ25pbmcuY29tMSAwHgYJKoZIhvcNAQkBFhFyb290MkBzaWdu
aW5nLmNvbTAeFw0xODEyMDYxMTEwMDlaFw0yODEyMDUxMTEwMDlaMIIBhDETMBEG
CgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBmNoZWVzZTEPMA0GA1UE
CgwGQ2hlZXNlMREwDwYDVQQKDAhDaGVlc2UgMjEfMB0GA1UECwwWU2ltcGxlIFNp
Z25pbmcgU2VjdGlvbjEhMB8GA1UECwwYU2ltcGxlIFNpZ25pbmcgU2VjdGlvbiAy
MRowGAYDVQQDDBFTaW1wbGUgU2lnbmluZyBDQTEcMBoGA1UEAwwTU2ltcGxlIFNp
Z25pbmcgQ0EgMjELMAkGA1UEBhMCRlIxCzAJBgNVBAYTAlVTMREwDwYDVQQHDAhU
T1VMT1VTRTENMAsGA1UEBwwETFlPTjEWMBQGA1UECAwNU2lnbmluZyBTdGF0ZTEY
MBYGA1UECAwPU2lnbmluZyBTdGF0ZSAyMSEwHwYJKoZIhvcNAQkBFhJzaW1wbGVA
c2lnbmluZy5jb20xIjAgBgkqhkiG9w0BCQEWE3NpbXBsZTJAc2lnbmluZy5jb20w
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDnZ9hFVc / eMznXSDiPi55
SsM6DCZAGNuHCIXC96 + HExr / Z4q3K1inzIndd / 9 eJ2URgIKPr6CvJYbsok8gDhQV
FhLXdFrDmb07gchjb / yQFIbSOe6Hsv9tpWnaq1o6l80jN2pLumPNoanmeao3uNGQ
ySS16HD8Fa05lyhzR2b2InlasAODivHKrotQHsj6DZ92LgDCDnW8R1q22AXtWrxt
UFA2a6urafabG2x + qJ + yMzo8jG1eg84Xgp4QUaY57JhOULexqousu6FgG + oxO7gK
6 mNBebXs7hnphY7zbZOA2phYokCTpVPrHSS2ZgfsWBBj5 / puGGB0dhU5PPSVlX7f
AgMBAAGjZjBkMA4GA1UdDwEB / wQEAwIBBjASBgNVHRMBAf8ECDAGAQH / AgEAMB0G
A1UdDgQWBBQeUqLoVNU369WoHeTCBB034vdwAzAfBgNVHSMEGDAWgBQ2cDWq8PaT
soZdMnP5QVo / O8i8izANBgkqhkiG9w0BAQUFAAOCAQEAdvMWISdtoi7oGEmqVB74
Owf6ZVDYH6LPZGwV4A / IRrLXuA7NBTsG + 93 GLwGuvWnTu1VHqfblur5LRfsuPDPg
V9Q + jj4R8grxfQarBC6ldiDC26RoWjkAYiodwhKxkGaMNqj9g9Eb2iOnHVvmm0DE
eCXHt2t1Nc + 7 N0pP / H4yH4zPEtLJyJnZSlUKHqzetMt8v8T7YCyo9 + djXLAcYq8B
PP5NPAsYN0wl / NCy9rLxw / QPU9Yetfq82K3dHPVFn6 / + CgF5kprYcds38x69 + 8 ce
Cg + XKmHzexmTnKaKac2w9ZECpRsQ9IBdQq9OghIwPtOnERTOUJEEgNcqA + 9 xELjb
pQ ==
-- -- - END CERTIFICATE -- -- -
`
minimalCheeseCrt = ` -- -- - BEGIN CERTIFICATE -- -- -
MIIEQDCCAygCFFRY0OBk / L5Se0IZRj3CMljawL2UMA0GCSqGSIb3DQEBCwUAMIIB
hDETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBmNoZWVzZTEP
MA0GA1UECgwGQ2hlZXNlMREwDwYDVQQKDAhDaGVlc2UgMjEfMB0GA1UECwwWU2lt
cGxlIFNpZ25pbmcgU2VjdGlvbjEhMB8GA1UECwwYU2ltcGxlIFNpZ25pbmcgU2Vj
dGlvbiAyMRowGAYDVQQDDBFTaW1wbGUgU2lnbmluZyBDQTEcMBoGA1UEAwwTU2lt
cGxlIFNpZ25pbmcgQ0EgMjELMAkGA1UEBhMCRlIxCzAJBgNVBAYTAlVTMREwDwYD
VQQHDAhUT1VMT1VTRTENMAsGA1UEBwwETFlPTjEWMBQGA1UECAwNU2lnbmluZyBT
dGF0ZTEYMBYGA1UECAwPU2lnbmluZyBTdGF0ZSAyMSEwHwYJKoZIhvcNAQkBFhJz
aW1wbGVAc2lnbmluZy5jb20xIjAgBgkqhkiG9w0BCQEWE3NpbXBsZTJAc2lnbmlu
Zy5jb20wHhcNMTgxMjA2MTExMDM2WhcNMjEwOTI1MTExMDM2WjAzMQswCQYDVQQG
EwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEPMA0GA1UECgwGQ2hlZXNlMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAskX / bUtwFo1gF2BTPNaNcTUMaRFu
FMZozK8IgLjccZ4kZ0R9oFO6Yp8Zl / IvPaf7tE26PI7XP7eHriUdhnQzX7iioDd0
RZa68waIhAGc + xPzRFrP3b3yj3S2a9Rve3c0K + SCV + EtKAwsxMqQDhoo9PcBfo5B
RHfht07uD5MncUcGirwN + / pxHV5xzAGPcc7On0 / 5 L7bq / G + 63 nhu78zw9XyuLaHC
PM5VbOUvpyIESJHbMMzTdFGL8ob9VKO + Kr1kVGdEA9i8FLGl3xz / GBKuW / JD0xyW
DrU29mri5vYWHmkuv7ZWHGXnpXjTtPHwveE9 / 0 / ArnmpMyR9JtqFr1oEvQIDAQAB
MA0GCSqGSIb3DQEBCwUAA4IBAQBHta + NWXI08UHeOkGzOTGRiWXsOH2dqdX6gTe9
xF1AIjyoQ0gvpoGVvlnChSzmlUj + vnx / nOYGIt1poE3hZA3ZHZD / awsvGyp3GwWD
IfXrEViSCIyF + 8 tNNKYyUcEO3xdAsAUGgfUwwF / mZ6MBV5 + A / ZEEILlTq8zFt9dV
vdKzIt7fZYxYBBHFSarl1x8pDgWXlf3hAufevGJXip9xGYmznF0T5cq1RbWJ4be3
/ 9 K7yuWhuBYC3sbTbCneHBa91M82za + PIISc1ygCYtWSBoZKSAqLk0rkZpHaekDP
WqeUSNGYV //RunTeuRDAf5OxehERb1srzBXhRZ3cZdzXbgR/
-- -- - END CERTIFICATE -- -- -
`
completeCheeseCrt = ` Certificate :
Data :
Version : 3 ( 0x2 )
Serial Number : 1 ( 0x1 )
Signature Algorithm : sha1WithRSAEncryption
Issuer : DC = org , DC = cheese , O = Cheese , O = Cheese 2 , OU = Simple Signing Section , OU = Simple Signing Section 2 , CN = Simple Signing CA , CN = Simple Signing CA 2 , C = FR , C = US , L = TOULOUSE , L = LYON , ST = Signing State , ST = Signing State 2 / emailAddress = simple @ signing . com / emailAddress = simple2 @ signing . com
Validity
Not Before : Dec 6 11 : 10 : 16 2018 GMT
Not After : Dec 5 11 : 10 : 16 2020 GMT
Subject : DC = org , DC = cheese , O = Cheese , O = Cheese 2 , OU = Simple Signing Section , OU = Simple Signing Section 2 , CN = * . cheese . org , CN = * . cheese . com , C = FR , C = US , L = TOULOUSE , L = LYON , ST = Cheese org state , ST = Cheese com state / emailAddress = cert @ cheese . org / emailAddress = cert @ scheese . com
Subject Public Key Info :
Public Key Algorithm : rsaEncryption
RSA Public - Key : ( 2048 bit )
Modulus :
00 : de : 77 : fa : 8 d : 03 : 70 : 30 : 39 : dd : 51 : 1 b : cc : 60 : db :
a9 : 5 a : 13 : b1 : af : fe : 2 c : c6 : 38 : 9 b : 88 : 0 a : 0 f : 8 e : d9 :
1 b : a1 : 1 d : af : 0 d : 66 : e4 : 13 : 5 b : bc : 5 d : 36 : 92 : d7 : 5 e :
d0 : fa : 88 : 29 : d3 : 78 : e1 : 81 : de : 98 : b2 : a9 : 22 : 3 f : bf :
8 a : af : 12 : 92 : 63 : d4 : a9 : c3 : f2 : e4 : 7 e : d2 : dc : a2 : c5 :
39 : 1 c : 7 a : eb : d7 : 12 : 70 : 63 : 2 e : 41 : 47 : e0 : f0 : 0 8 : e8 :
dc : be : 0 9 : 01 : ec : 28 : 0 9 : af : 35 : d7 : 79 : 9 c : 50 : 35 : d1 :
6 b : e5 : 87 : 7 b : 34 : f6 : d2 : 31 : 65 : 1 d : 18 : 42 : 69 : 6 c : 04 :
11 : 83 : fe : 44 : ae : 90 : 92 : 2 d : 0 b : 75 : 39 : 57 : 62 : e6 : 17 :
2 f : 47 : 2 b : c7 : 53 : dd : 10 : 2 d : c9 : e3 : 06 : 13 : d2 : b9 : ba :
63 : 2 e : 3 c : 7 d : 83 : 6 b : d6 : 89 : c9 : cc : 9 d : 4 d : bf : 9 f : e8 :
a3 : 7 b : da : c8 : 99 : 2 b : ba : 66 : d6 : 8 e : f8 : 41 : 41 : a0 : c9 :
d0 : 5 e : c8 : 11 : a4 : 55 : 4 a : 93 : 83 : 87 : 63 : 04 : 63 : 41 : 9 c :
fb : 68 : 04 : 67 : c2 : 71 : 2 f : f2 : 65 : 1 d : 02 : 5 d : 15 : db : 2 c :
d9 : 04 : 69 : 85 : c2 : 7 d : 0 d : ea : 3 b : ac : 85 : f8 : d4 : 8 f : 0 f :
c5 : 70 : b2 : 45 : e1 : ec : b2 : 54 : 0 b : e9 : f7 : 82 : b4 : 9 b : 1 b :
2 d : b9 : 25 : d4 : ab : ca : 8 f : 5 b : 44 : 3 e : 15 : dd : b8 : 7 f : b7 :
ee : f9
Exponent : 65537 ( 0x10001 )
X509v3 extensions :
X509v3 Key Usage : critical
Digital Signature , Key Encipherment
X509v3 Basic Constraints :
CA : FALSE
X509v3 Extended Key Usage :
TLS Web Server Authentication , TLS Web Client Authentication
X509v3 Subject Key Identifier :
94 : BA : 73 : 78 : A2 : 87 : FB : 58 : 28 : 28 : CF : 98 : 3 B : C2 : 45 : 70 : 16 : 6 E : 29 : 2 F
X509v3 Authority Key Identifier :
keyid : 1 E : 52 : A2 : E8 : 54 : D5 : 37 : EB : D5 : A8 : 1 D : E4 : C2 : 04 : 1 D : 37 : E2 : F7 : 70 : 03
X509v3 Subject Alternative Name :
DNS : * . cheese . org , DNS : * . cheese . net , DNS : * . cheese . com , IP Address : 10.0 .1 .0 , IP Address : 10.0 .1 .2 , email : test @ cheese . org , email : test @ cheese . net
Signature Algorithm : sha1WithRSAEncryption
76 : 6 b : 05 : b0 : 0 e : 34 : 11 : b1 : 83 : 99 : 91 : dc : ae : 1 b : e2 : 0 8 : 15 : 8 b :
16 : b2 : 9 b : 27 : 1 c : 02 : ac : b5 : df : 1 b : d0 : d0 : 75 : a4 : 2 b : 2 c : 5 c : 65 :
ed : 99 : ab : f7 : cd : fe : 38 : 3 f : c3 : 9 a : 22 : 31 : 1 b : ac : 8 c : 1 c : c2 : f9 :
5 d : d4 : 75 : 7 a : 2 e : 72 : c7 : 85 : a9 : 04 : af : 9 f : 2 a : cc : d3 : 96 : 75 : f0 :
8 e : c7 : c6 : 76 : 48 : ac : 45 : a4 : b9 : 02 : 1 e : 2 f : c0 : 15 : c4 : 07 : 0 8 : 92 :
cb : 27 : 50 : 67 : a1 : c8 : 05 : c5 : 3 a : b3 : a6 : 48 : be : eb : d5 : 59 : ab : a2 :
1 b : 95 : 30 : 71 : 13 : 5 b : 0 a : 9 a : 73 : 3 b : 60 : cc : 10 : d0 : 6 a : c7 : e5 : d7 :
8 b : 2 f : f9 : 2 e : 98 : f2 : ff : 81 : 14 : 24 : 0 9 : e3 : 4 b : 55 : 57 : 0 9 : 1 a : 22 :
74 : f1 : f6 : 40 : 13 : 31 : 43 : 89 : 71 : 0 a : 96 : 1 a : 05 : 82 : 1 f : 83 : 3 a : 87 :
9 b : 17 : 25 : ef : 5 a : 55 : f2 : 2 d : cd : 0 d : 4 d : e4 : 81 : 58 : b6 : e3 : 8 d : 0 9 :
62 : 9 a : 0 c : bd : e4 : e5 : 5 c : f0 : 95 : da : cb : c7 : 34 : 2 c : 34 : 5 f : 6 d : fc :
60 : 7 b : 12 : 5 b : 86 : fd : df : 21 : 89 : 3 b : 48 : 0 8 : 30 : bf : 67 : ff : 8 c : e6 :
9 b : 53 : cc : 87 : 36 : 47 : 70 : 40 : 3 b : d9 : 90 : 2 a : d2 : d2 : 82 : c6 : 9 c : f5 :
d1 : d8 : e0 : e6 : fd : aa : 2 f : 95 : 7 e : 39 : ac : fc : 4 e : d4 : ce : 65 : b3 : ec :
c6 : 98 : 8 a : 31
-- -- - BEGIN CERTIFICATE -- -- -
MIIGWjCCBUKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCCAYQxEzARBgoJkiaJk / Is
ZAEZFgNvcmcxFjAUBgoJkiaJk / IsZAEZFgZjaGVlc2UxDzANBgNVBAoMBkNoZWVz
ZTERMA8GA1UECgwIQ2hlZXNlIDIxHzAdBgNVBAsMFlNpbXBsZSBTaWduaW5nIFNl
Y3Rpb24xITAfBgNVBAsMGFNpbXBsZSBTaWduaW5nIFNlY3Rpb24gMjEaMBgGA1UE
AwwRU2ltcGxlIFNpZ25pbmcgQ0ExHDAaBgNVBAMME1NpbXBsZSBTaWduaW5nIENB
IDIxCzAJBgNVBAYTAkZSMQswCQYDVQQGEwJVUzERMA8GA1UEBwwIVE9VTE9VU0Ux
DTALBgNVBAcMBExZT04xFjAUBgNVBAgMDVNpZ25pbmcgU3RhdGUxGDAWBgNVBAgM
D1NpZ25pbmcgU3RhdGUgMjEhMB8GCSqGSIb3DQEJARYSc2ltcGxlQHNpZ25pbmcu
Y29tMSIwIAYJKoZIhvcNAQkBFhNzaW1wbGUyQHNpZ25pbmcuY29tMB4XDTE4MTIw
NjExMTAxNloXDTIwMTIwNTExMTAxNlowggF2MRMwEQYKCZImiZPyLGQBGRYDb3Jn
MRYwFAYKCZImiZPyLGQBGRYGY2hlZXNlMQ8wDQYDVQQKDAZDaGVlc2UxETAPBgNV
BAoMCENoZWVzZSAyMR8wHQYDVQQLDBZTaW1wbGUgU2lnbmluZyBTZWN0aW9uMSEw
HwYDVQQLDBhTaW1wbGUgU2lnbmluZyBTZWN0aW9uIDIxFTATBgNVBAMMDCouY2hl
ZXNlLm9yZzEVMBMGA1UEAwwMKi5jaGVlc2UuY29tMQswCQYDVQQGEwJGUjELMAkG
A1UEBhMCVVMxETAPBgNVBAcMCFRPVUxPVVNFMQ0wCwYDVQQHDARMWU9OMRkwFwYD
VQQIDBBDaGVlc2Ugb3JnIHN0YXRlMRkwFwYDVQQIDBBDaGVlc2UgY29tIHN0YXRl
MR4wHAYJKoZIhvcNAQkBFg9jZXJ0QGNoZWVzZS5vcmcxHzAdBgkqhkiG9w0BCQEW
EGNlcnRAc2NoZWVzZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQDed / qNA3AwOd1RG8xg26laE7Gv / izGOJuICg + O2RuhHa8NZuQTW7xdNpLXXtD6
iCnTeOGB3piyqSI / v4qvEpJj1KnD8uR + 0 tyixTkceuvXEnBjLkFH4PAI6Ny + CQHs
KAmvNdd5nFA10Wvlh3s09tIxZR0YQmlsBBGD / kSukJItC3U5V2LmFy9HK8dT3RAt
yeMGE9K5umMuPH2Da9aJycydTb + f6KN72siZK7pm1o74QUGgydBeyBGkVUqTg4dj
BGNBnPtoBGfCcS / yZR0CXRXbLNkEaYXCfQ3qO6yF + NSPD8VwskXh7LJUC + n3grSb
Gy25JdSryo9bRD4V3bh / t + 75 AgMBAAGjgeAwgd0wDgYDVR0PAQH / BAQDAgWgMAkG
A1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQW
BBSUunN4oof7WCgoz5g7wkVwFm4pLzAfBgNVHSMEGDAWgBQeUqLoVNU369WoHeTC
BB034vdwAzBhBgNVHREEWjBYggwqLmNoZWVzZS5vcmeCDCouY2hlZXNlLm5ldIIM
Ki5jaGVlc2UuY29thwQKAAEAhwQKAAECgQ90ZXN0QGNoZWVzZS5vcmeBD3Rlc3RA
Y2hlZXNlLm5ldDANBgkqhkiG9w0BAQUFAAOCAQEAdmsFsA40EbGDmZHcrhviCBWL
FrKbJxwCrLXfG9DQdaQrLFxl7Zmr983 + OD / DmiIxG6yMHML5XdR1ei5yx4WpBK + f
KszTlnXwjsfGdkisRaS5Ah4vwBXEBwiSyydQZ6HIBcU6s6ZIvuvVWauiG5UwcRNb
CppzO2DMENBqx + XXiy / 5 Lpjy / 4 EUJAnjS1VXCRoidPH2QBMxQ4lxCpYaBYIfgzqH
mxcl71pV8i3NDU3kgVi2440JYpoMveTlXPCV2svHNCw0X238YHsSW4b93yGJO0gI
ML9n / 4 zmm1PMhzZHcEA72ZAq0tKCxpz10djg5v2qL5V + Oaz8TtTOZbPsxpiKMQ ==
-- -- - END CERTIFICATE -- -- -
`
2018-08-29 09:36:03 +00:00
minimalCert = ` -- -- - BEGIN CERTIFICATE -- -- -
MIIDGTCCAgECCQCqLd75YLi2kDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJG
UjETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UEBwwIVG91bG91c2UxITAfBgNV
BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xODA3MTgwODI4MTZaFw0x
ODA4MTcwODI4MTZaMEUxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRl
MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC / + frDMMTLQyXG34F68BPhQq0kzK4LIq9Y0 / gl
FjySZNn1C0QDWA1ubVCAcA6yY204I9cxcQDPNrhC7JlS5QA8Y5rhIBrqQlzZizAi
Rj3NTrRjtGUtOScnHuJaWjLy03DWD + aMwb7q718xt5SEABmmUvLwQK + EjW2MeDwj
y8 / UEIpvrRDmdhGaqv7IFpIDkcIF7FowJ / hwDvx3PMc + z / JWK0ovzpvgbx69AVbw
ZxCimeha65rOqVi + lEetD26le + WnOdYsdJ2IkmpPNTXGdfb15xuAc + gFXfMCh7Iw
3 Ynl6dZtZM / Ok2kiA7 / OsmVnRKkWrtBfGYkI9HcNGb3zrk6nAgMBAAEwDQYJKoZI
hvcNAQELBQADggEBAC / R + Yvhh1VUhcbK49olWsk / JKqfS3VIDQYZg1Eo + JCPbwgS
I1BSYVfMcGzuJTX6ua3m / AHzGF3Tap4GhF4tX12jeIx4R4utnjj7 / YKkTvuEM2f4
xT56YqI7zalGScIB0iMeyNz1QcimRl + M / 49 au8ow9hNX8C2tcA2cwd / 9 OIj / 6 T8q
SBRHc6ojvbqZSJCO0jziGDT1L3D + EDgTjED4nd77v / NRdP + egb0q3P0s4dnQ / 5 AV
aQlQADUn61j3ScbGJ4NSeZFFvsl38jeRi / MEzp0bGgNBcPj6JHi7qbbauZcZfQ05
jECvgAY7Nfd9mZ1KtyNaW31is + kag7NsvjxU / kM =
-- -- - END CERTIFICATE -- -- - `
)
func getCleanCertContents ( certContents [ ] string ) string {
var re = regexp . MustCompile ( "-----BEGIN CERTIFICATE-----(?s)(.*)" )
var cleanedCertContent [ ] string
for _ , certContent := range certContents {
cert := re . FindString ( string ( certContent ) )
cleanedCertContent = append ( cleanedCertContent , sanitize ( [ ] byte ( cert ) ) )
}
return strings . Join ( cleanedCertContent , "," )
}
func getCertificate ( certContent string ) * x509 . Certificate {
roots := x509 . NewCertPool ( )
2019-01-08 08:46:04 +00:00
ok := roots . AppendCertsFromPEM ( [ ] byte ( signingCA ) )
2018-08-29 09:36:03 +00:00
if ! ok {
panic ( "failed to parse root certificate" )
}
block , _ := pem . Decode ( [ ] byte ( certContent ) )
if block == nil {
panic ( "failed to parse certificate PEM" )
}
cert , err := x509 . ParseCertificate ( block . Bytes )
if err != nil {
panic ( "failed to parse certificate: " + err . Error ( ) )
}
return cert
}
func buildTLSWith ( certContents [ ] string ) * tls . ConnectionState {
var peerCertificates [ ] * x509 . Certificate
for _ , certContent := range certContents {
peerCertificates = append ( peerCertificates , getCertificate ( certContent ) )
}
return & tls . ConnectionState { PeerCertificates : peerCertificates }
}
var myPassTLSClientCustomHandler = http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
w . Write ( [ ] byte ( "bar" ) )
} )
func getExpectedSanitized ( s string ) string {
return url . QueryEscape ( strings . Replace ( s , "\n" , "" , - 1 ) )
}
func TestSanitize ( t * testing . T ) {
testCases := [ ] struct {
desc string
toSanitize [ ] byte
expected string
} {
{
desc : "Empty" ,
} ,
{
desc : "With a minimal cert" ,
2019-01-08 08:46:04 +00:00
toSanitize : [ ] byte ( minimalCheeseCrt ) ,
expected : getExpectedSanitized ( ` MIIEQDCCAygCFFRY0OBk / L5Se0IZRj3CMljawL2UMA0GCSqGSIb3DQEBCwUAMIIB
hDETMBEGCgmSJomT8ixkARkWA29yZzEWMBQGCgmSJomT8ixkARkWBmNoZWVzZTEP
MA0GA1UECgwGQ2hlZXNlMREwDwYDVQQKDAhDaGVlc2UgMjEfMB0GA1UECwwWU2lt
cGxlIFNpZ25pbmcgU2VjdGlvbjEhMB8GA1UECwwYU2ltcGxlIFNpZ25pbmcgU2Vj
dGlvbiAyMRowGAYDVQQDDBFTaW1wbGUgU2lnbmluZyBDQTEcMBoGA1UEAwwTU2lt
cGxlIFNpZ25pbmcgQ0EgMjELMAkGA1UEBhMCRlIxCzAJBgNVBAYTAlVTMREwDwYD
VQQHDAhUT1VMT1VTRTENMAsGA1UEBwwETFlPTjEWMBQGA1UECAwNU2lnbmluZyBT
dGF0ZTEYMBYGA1UECAwPU2lnbmluZyBTdGF0ZSAyMSEwHwYJKoZIhvcNAQkBFhJz
aW1wbGVAc2lnbmluZy5jb20xIjAgBgkqhkiG9w0BCQEWE3NpbXBsZTJAc2lnbmlu
Zy5jb20wHhcNMTgxMjA2MTExMDM2WhcNMjEwOTI1MTExMDM2WjAzMQswCQYDVQQG
EwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEPMA0GA1UECgwGQ2hlZXNlMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAskX / bUtwFo1gF2BTPNaNcTUMaRFu
FMZozK8IgLjccZ4kZ0R9oFO6Yp8Zl / IvPaf7tE26PI7XP7eHriUdhnQzX7iioDd0
RZa68waIhAGc + xPzRFrP3b3yj3S2a9Rve3c0K + SCV + EtKAwsxMqQDhoo9PcBfo5B
RHfht07uD5MncUcGirwN + / pxHV5xzAGPcc7On0 / 5 L7bq / G + 63 nhu78zw9XyuLaHC
PM5VbOUvpyIESJHbMMzTdFGL8ob9VKO + Kr1kVGdEA9i8FLGl3xz / GBKuW / JD0xyW
DrU29mri5vYWHmkuv7ZWHGXnpXjTtPHwveE9 / 0 / ArnmpMyR9JtqFr1oEvQIDAQAB
MA0GCSqGSIb3DQEBCwUAA4IBAQBHta + NWXI08UHeOkGzOTGRiWXsOH2dqdX6gTe9
xF1AIjyoQ0gvpoGVvlnChSzmlUj + vnx / nOYGIt1poE3hZA3ZHZD / awsvGyp3GwWD
IfXrEViSCIyF + 8 tNNKYyUcEO3xdAsAUGgfUwwF / mZ6MBV5 + A / ZEEILlTq8zFt9dV
vdKzIt7fZYxYBBHFSarl1x8pDgWXlf3hAufevGJXip9xGYmznF0T5cq1RbWJ4be3
/ 9 K7yuWhuBYC3sbTbCneHBa91M82za + PIISc1ygCYtWSBoZKSAqLk0rkZpHaekDP
WqeUSNGYV //RunTeuRDAf5OxehERb1srzBXhRZ3cZdzXbgR/`),
2018-08-29 09:36:03 +00:00
} ,
}
for _ , test := range testCases {
test := test
t . Run ( test . desc , func ( t * testing . T ) {
t . Parallel ( )
2019-01-08 08:46:04 +00:00
assert . Equal ( t , test . expected , sanitize ( test . toSanitize ) , "The sanitized certificates should be equal" )
2018-08-29 09:36:03 +00:00
} )
}
}
func TestTlsClientheadersWithPEM ( t * testing . T ) {
testCases := [ ] struct {
desc string
certContents [ ] string // set the request TLS attribute if defined
tlsClientCertHeaders * types . TLSClientHeaders
expectedHeader string
} {
{
desc : "No TLS, no option" ,
} ,
{
desc : "TLS, no option" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { minimalCheeseCrt } ,
2018-08-29 09:36:03 +00:00
} ,
{
desc : "No TLS, with pem option true" ,
tlsClientCertHeaders : & types . TLSClientHeaders { PEM : true } ,
} ,
{
desc : "TLS with simple certificate, with pem option true" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { minimalCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders { PEM : true } ,
2019-01-08 08:46:04 +00:00
expectedHeader : getCleanCertContents ( [ ] string { minimalCheeseCrt } ) ,
2018-08-29 09:36:03 +00:00
} ,
{
desc : "TLS with complete certificate, with pem option true" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { completeCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders { PEM : true } ,
2019-01-08 08:46:04 +00:00
expectedHeader : getCleanCertContents ( [ ] string { completeCheeseCrt } ) ,
2018-08-29 09:36:03 +00:00
} ,
{
desc : "TLS with two certificate, with pem option true" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { minimalCheeseCrt , completeCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders { PEM : true } ,
2019-01-08 08:46:04 +00:00
expectedHeader : getCleanCertContents ( [ ] string { minimalCheeseCrt , completeCheeseCrt } ) ,
2018-08-29 09:36:03 +00:00
} ,
}
for _ , test := range testCases {
tlsClientHeaders := NewTLSClientHeaders ( & types . Frontend { PassTLSClientCert : test . tlsClientCertHeaders } )
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 , myPassTLSClientCustomHandler )
test := test
t . Run ( test . desc , func ( t * testing . T ) {
t . Parallel ( )
require . Equal ( t , http . StatusOK , res . Code , "Http Status should be OK" )
require . Equal ( t , "bar" , res . Body . String ( ) , "Should be the expected body" )
if test . expectedHeader != "" {
2019-01-08 08:46:04 +00:00
assert . Equal ( t , test . expectedHeader , req . Header . Get ( xForwardedTLSClientCert ) , "The request header should contain the cleaned certificate" )
2018-08-29 09:36:03 +00:00
} else {
2019-01-08 08:46:04 +00:00
assert . Empty ( t , req . Header . Get ( xForwardedTLSClientCert ) )
2018-08-29 09:36:03 +00:00
}
2019-01-08 08:46:04 +00:00
assert . Empty ( t , res . Header ( ) . Get ( xForwardedTLSClientCert ) , "The response header should be always empty" )
2018-08-29 09:36:03 +00:00
} )
}
}
func TestGetSans ( t * testing . T ) {
urlFoo , err := url . Parse ( "my.foo.com" )
require . NoError ( t , err )
urlBar , err := url . Parse ( "my.bar.com" )
require . NoError ( t , err )
testCases := [ ] struct {
desc string
cert * x509 . Certificate // set the request TLS attribute if defined
expected [ ] string
} {
{
desc : "With nil" ,
} ,
{
desc : "Certificate without Sans" ,
cert : & x509 . Certificate { } ,
} ,
{
desc : "Certificate with all Sans" ,
cert : & x509 . Certificate {
DNSNames : [ ] string { "foo" , "bar" } ,
EmailAddresses : [ ] string { "test@test.com" , "test2@test.com" } ,
IPAddresses : [ ] net . IP { net . IPv4 ( 10 , 0 , 0 , 1 ) , net . IPv4 ( 10 , 0 , 0 , 2 ) } ,
URIs : [ ] * url . URL { urlFoo , urlBar } ,
} ,
expected : [ ] string { "foo" , "bar" , "test@test.com" , "test2@test.com" , "10.0.0.1" , "10.0.0.2" , urlFoo . String ( ) , urlBar . String ( ) } ,
} ,
}
for _ , test := range testCases {
sans := getSANs ( test . cert )
test := test
t . Run ( test . desc , func ( t * testing . T ) {
t . Parallel ( )
if len ( test . expected ) > 0 {
for i , expected := range test . expected {
2019-01-08 08:46:04 +00:00
assert . Equal ( t , expected , sans [ i ] )
2018-08-29 09:36:03 +00:00
}
} else {
2019-01-08 08:46:04 +00:00
assert . Empty ( t , sans )
2018-08-29 09:36:03 +00:00
}
} )
}
}
func TestTlsClientheadersWithCertInfos ( t * testing . T ) {
2019-01-08 08:46:04 +00:00
minimalCheeseCertAllInfos := ` 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",NB=1544094636,NA=1632568236,SAN= `
completeCertAllInfos := ` 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",NB=1544094616,NA=1607166616,SAN=*.cheese.org,*.cheese.net,*.cheese.com,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2 `
2018-08-29 09:36:03 +00:00
testCases := [ ] struct {
desc string
certContents [ ] string // set the request TLS attribute if defined
tlsClientCertHeaders * types . TLSClientHeaders
expectedHeader string
} {
{
desc : "No TLS, no option" ,
} ,
{
desc : "TLS, no option" ,
certContents : [ ] string { minimalCert } ,
} ,
{
desc : "No TLS, with pem option true" ,
tlsClientCertHeaders : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
CommonName : true ,
Organization : true ,
Locality : true ,
Province : true ,
Country : true ,
SerialNumber : true ,
} ,
} ,
} ,
} ,
{
desc : "No TLS, with pem option true with no flag" ,
tlsClientCertHeaders : & types . TLSClientHeaders {
PEM : false ,
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos { } ,
2018-08-29 09:36:03 +00:00
} ,
} ,
} ,
{
desc : "TLS with simple certificate, with all infos" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { minimalCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
NotBefore : true ,
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
} ,
Issuer : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
2018-08-29 09:36:03 +00:00
} ,
Sans : true ,
} ,
} ,
2019-01-08 08:46:04 +00:00
expectedHeader : url . QueryEscape ( minimalCheeseCertAllInfos ) ,
2018-08-29 09:36:03 +00:00
} ,
{
desc : "TLS with simple certificate, with some infos" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { minimalCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
Organization : true ,
} ,
2019-01-08 08:46:04 +00:00
Issuer : & types . TLSCLientCertificateDNInfos {
Country : true ,
} ,
2018-08-29 09:36:03 +00:00
Sans : true ,
} ,
} ,
2019-01-08 08:46:04 +00:00
expectedHeader : url . QueryEscape ( ` Subject="O=Cheese",Issuer="C=FR,C=US",NA=1632568236,SAN= ` ) ,
2018-08-29 09:36:03 +00:00
} ,
{
desc : "TLS with complete certificate, with all infos" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { completeCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
NotBefore : true ,
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
} ,
Issuer : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
2018-08-29 09:36:03 +00:00
} ,
Sans : true ,
} ,
} ,
expectedHeader : url . QueryEscape ( completeCertAllInfos ) ,
} ,
{
desc : "TLS with 2 certificates, with all infos" ,
2019-01-08 08:46:04 +00:00
certContents : [ ] string { minimalCheeseCrt , completeCheeseCrt } ,
2018-08-29 09:36:03 +00:00
tlsClientCertHeaders : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
NotBefore : true ,
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
} ,
Issuer : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
2018-08-29 09:36:03 +00:00
} ,
Sans : true ,
} ,
} ,
2019-01-08 08:46:04 +00:00
expectedHeader : url . QueryEscape ( strings . Join ( [ ] string { minimalCheeseCertAllInfos , completeCertAllInfos } , ";" ) ) ,
2018-08-29 09:36:03 +00:00
} ,
}
for _ , test := range testCases {
tlsClientHeaders := NewTLSClientHeaders ( & types . Frontend { PassTLSClientCert : test . tlsClientCertHeaders } )
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 , myPassTLSClientCustomHandler )
test := test
t . Run ( test . desc , func ( t * testing . T ) {
t . Parallel ( )
require . Equal ( t , http . StatusOK , res . Code , "Http Status should be OK" )
require . Equal ( t , "bar" , res . Body . String ( ) , "Should be the expected body" )
if test . expectedHeader != "" {
2019-01-08 08:46:04 +00:00
expected , err := url . QueryUnescape ( test . expectedHeader )
require . NoError ( t , err )
actual , err2 := url . QueryUnescape ( req . Header . Get ( xForwardedTLSClientCertInfos ) )
require . NoError ( t , err2 )
require . Equal ( t , expected , actual , "The request header should contain the cleaned certificate" )
2018-08-29 09:36:03 +00:00
} else {
require . Empty ( t , req . Header . Get ( xForwardedTLSClientCertInfos ) )
}
require . Empty ( t , res . Header ( ) . Get ( xForwardedTLSClientCertInfos ) , "The response header should be always empty" )
} )
}
}
func TestNewTLSClientHeadersFromStruct ( t * testing . T ) {
testCases := [ ] struct {
desc string
frontend * types . Frontend
expected * TLSClientHeaders
} {
{
desc : "Without frontend" ,
} ,
{
desc : "frontend without the option" ,
frontend : & types . Frontend { } ,
expected : & TLSClientHeaders { } ,
} ,
{
desc : "frontend with the pem set false" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
PEM : false ,
} ,
} ,
expected : & TLSClientHeaders { PEM : false } ,
} ,
{
desc : "frontend with the pem set true" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
PEM : true ,
} ,
} ,
expected : & TLSClientHeaders { PEM : true } ,
} ,
{
desc : "frontend with the Infos with no flag" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : false ,
NotBefore : false ,
Sans : false ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos { } ,
} ,
} ,
{
desc : "frontend with the Infos basic" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
NotBefore : true ,
Sans : true ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
NotBefore : true ,
NotAfter : true ,
Sans : true ,
} ,
} ,
} ,
{
desc : "frontend with the Infos NotAfter" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
NotAfter : true ,
} ,
} ,
} ,
{
desc : "frontend with the Infos NotBefore" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotBefore : true ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
NotBefore : true ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Sans" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
Sans : true ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
Sans : true ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Subject Organization" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
Organization : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
OrganizationName : true ,
2018-08-29 09:36:03 +00:00
} ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Subject Country" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
Country : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
CountryName : true ,
2018-08-29 09:36:03 +00:00
} ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Subject SerialNumber" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
SerialNumber : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
2018-08-29 09:36:03 +00:00
SerialNumber : true ,
} ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Subject Province" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
Province : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
StateOrProvinceName : true ,
2018-08-29 09:36:03 +00:00
} ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Subject Locality" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
Locality : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
LocalityName : true ,
2018-08-29 09:36:03 +00:00
} ,
} ,
} ,
} ,
{
desc : "frontend with the Infos Subject CommonName" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
CommonName : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
2018-08-29 09:36:03 +00:00
CommonName : true ,
} ,
} ,
} ,
} ,
{
2019-01-08 08:46:04 +00:00
desc : "frontend with the Infos Issuer" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
Issuer : & types . TLSCLientCertificateDNInfos {
CommonName : true ,
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
SerialNumber : true ,
Province : true ,
} ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
Issuer : & DistinguishedNameOptions {
CommonName : true ,
CountryName : true ,
DomainComponent : true ,
LocalityName : true ,
OrganizationName : true ,
SerialNumber : true ,
StateOrProvinceName : true ,
} ,
} ,
} ,
} ,
{
desc : "frontend with the Sans Infos" ,
2018-08-29 09:36:03 +00:00
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
Sans : true ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
Sans : true ,
} ,
} ,
} ,
{
desc : "frontend with the Infos all" ,
frontend : & types . Frontend {
PassTLSClientCert : & types . TLSClientHeaders {
Infos : & types . TLSClientCertificateInfos {
NotAfter : true ,
NotBefore : true ,
2019-01-08 08:46:04 +00:00
Subject : & types . TLSCLientCertificateDNInfos {
2018-08-29 09:36:03 +00:00
CommonName : true ,
Country : true ,
Locality : true ,
Organization : true ,
Province : true ,
SerialNumber : true ,
} ,
2019-01-08 08:46:04 +00:00
Issuer : & types . TLSCLientCertificateDNInfos {
Country : true ,
DomainComponent : true ,
Locality : true ,
Organization : true ,
SerialNumber : true ,
Province : true ,
} ,
2018-08-29 09:36:03 +00:00
Sans : true ,
} ,
} ,
} ,
expected : & TLSClientHeaders {
PEM : false ,
Infos : & TLSClientCertificateInfos {
NotBefore : true ,
NotAfter : true ,
Sans : true ,
2019-01-08 08:46:04 +00:00
Subject : & DistinguishedNameOptions {
CountryName : true ,
StateOrProvinceName : true ,
LocalityName : true ,
OrganizationName : true ,
CommonName : true ,
SerialNumber : true ,
} ,
Issuer : & DistinguishedNameOptions {
CountryName : true ,
DomainComponent : true ,
LocalityName : true ,
OrganizationName : true ,
SerialNumber : true ,
StateOrProvinceName : true ,
2018-08-29 09:36:03 +00:00
} ,
} } ,
} ,
}
for _ , test := range testCases {
test := test
t . Run ( test . desc , func ( t * testing . T ) {
t . Parallel ( )
require . Equal ( t , test . expected , NewTLSClientHeaders ( test . frontend ) )
} )
}
}