@@ -0,0 +1,91 @@
1+package util
2+
3+import (
4+ "crypto/x509/pkix"
5+ "encoding/asn1"
6+ "io/ioutil"
7+ "os"
8+ "testing"
9+
10+ "github.com/stretchr/testify/assert"
11+)
12+
13+// Test certificate created with an OpenSSL command in the following form:
14+// openssl req -x509 -newkey rsa:4096 -keyout key-unused.pem -out cert.pem -nodes -subj "/CN=oauth-proxy test ca"
15+
16+var (
17+ testCA1Subj = "CN=oauth-proxy test ca"
18+ testCA1 = `-----BEGIN CERTIFICATE-----
19+MIICuTCCAaGgAwIBAgIFAKuKEWowDQYJKoZIhvcNAQELBQAwHjEcMBoGA1UEAxMT
20+b2F1dGgtcHJveHkgdGVzdCBjYTAeFw0xNzEwMjQyMDExMzJaFw0xOTEwMjQyMDEx
21+MzJaMB4xHDAaBgNVBAMTE29hdXRoLXByb3h5IHRlc3QgY2EwggEiMA0GCSqGSIb3
22+DQEBAQUAA4IBDwAwggEKAoIBAQC5/kmgKNiECuxlj27yTWBWOMVvIB0AaRhQrMA7
23+3iSCk/SHhaTabUuXUGRwmCAewT/y9oX3rTdfnSPCn7praU/27lRFBgOGFrTzAZH6
24+voisF54I3ZxWZgHDJ/ig/KFwd0Y8OATj9/k9uAJSCe6aT7BouJPZVWNGF2dF5BOJ
25+EwFsJiN2s8HpF14DhxFOMMtlckdMHGxi3wj3E/hBCfGvGGU4Wezz48vEWWC1ajWM
26+qVq2vVWi1bcNft8FjWa5wTGpdlDQJM7yvKYJPwRkEjgIXtF1ra3JM3WTTFZO9Yhd
27+QXwO7IWRTdTaypKTNbTDKuWQZsm7xQM9sNcFkukGb3o+uBpLAgMBAAEwDQYJKoZI
28+hvcNAQELBQADggEBAHJNrUfHhN7VOUF60pG8sOEkx0ztjbtbYMj2N9Kb0oSya+re
29+Kmb2Z4JgyV7XHCZ03Jch6L7UBI3Y6/Lp1zdwU03LFayVUchLkvFonoXpRRP5UFYN
30++36xP3ZL1qBYFphARsCk6/tl36czH4oF5gTlhWCRy3upNzn+INk467hnCKt5xuse
31+zhm+xQv/VN1poI0S/oCg9HLA9iKpoqGJByN32yoFr3QViLPqkmJ1v8EiH0Ns+1m3
32+pP5YlVqdRCVrxgT80PIMsvQhfcuIrbbeiRDEUdEX7FqebuGCEa2757MTdW7UYQiB
33+7kgECMnwAOlJME8aDKnmTBajaMy6xCSC87V7wps=
34+-----END CERTIFICATE-----
35+`
36+ testCA2Subj = "CN=oauth-proxy second test ca"
37+ testCA2 = `-----BEGIN CERTIFICATE-----
38+MIICxzCCAa+gAwIBAgIFAKuMKewwDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAxMa
39+b2F1dGgtcHJveHkgc2Vjb25kIHRlc3QgY2EwHhcNMTcxMDI1MTYxMTQxWhcNMTkx
40+MDI1MTYxMTQxWjAlMSMwIQYDVQQDExpvYXV0aC1wcm94eSBzZWNvbmQgdGVzdCBj
41+YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdTkEOJ+QpOHy0PqGDR
42+fu8NFyo7BJwAnI+P1G32UXMeecCwBgGJEyv6eHEFV6jH/U2K2H0hynaCFxRuIdTA
43+EeS4s4BAbKqFhQ62I9lF3HVuqRPOe5FYdUl80eQynME22fWQ6/sZdQds0sFqaJBz
44+R4KQQxVULT19Br/6zwQZZhC1NtzSwCqi4CoO2OM7ctUKRvtC87LNGWapz5I4eh0A
45+/q4XJaSObsBCAJD7OVMa1LM3sSINUnvvGoSBKTuJ8MRk/BQRAO/PwXxsa+2h+k+w
46+D6sLExrBgWzAAPQKRKF+nLYVhz9AKn4JBpZt9j4PvTKz1SDcJ5wVEzOfVmii7Ui3
47+EFcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAiy58XvhOka3drXv2bwl95FwNtodj
48+L2MmIdF0pp01O0ryREcC1kogamdOS/UHQs4okuCjwinR/UgU+cFGCDYHfeENtUTw
49+Ox2OikYD7bXUpNzbQ4QyF0+cKwAgxD4ai5xSV/NUvMkL1aE8tLyxGm6VkhhyvxU1
50+U9kvLha6KBWOCNd2fBJxgg8RAxFV3vR+xLdEtXnBAeTURrHM19gwMtd16y6gUZTZ
51+Xbl3Ix0t2+sqi0hpEF/iVFdCp5TXiicSnZCtePzCfHePAEfbh5hS0bq8Lbb9DZ6d
52++2jX3AVuYhQPuutxla+vNp2XRcMTbzwXyi/Ig4nHKmPLFXsEbv+4tSwxyQ==
53+-----END CERTIFICATE-----
54+`
55+)
56+
57+func makeTestCertFile(t *testing.T, pem, dir string) *os.File {
58+ file, err := ioutil.TempFile(dir, "test-certfile")
59+ assert.NoError(t, err)
60+ _, err = file.Write([]byte(pem))
61+ assert.NoError(t, err)
62+ return file
63+}
64+
65+func TestGetCertPool_NoRoots(t *testing.T) {
66+ _, err := GetCertPool([]string(nil))
67+ assert.Error(t, err, "invalid empty list of Root CAs file paths")
68+}
69+
70+func TestGetCertPool(t *testing.T) {
71+ tempDir, err := ioutil.TempDir("", "certtest")
72+ assert.NoError(t, err)
73+ defer os.RemoveAll(tempDir)
74+ certFile1 := makeTestCertFile(t, testCA1, tempDir)
75+ certFile2 := makeTestCertFile(t, testCA2, tempDir)
76+
77+ certPool, err := GetCertPool([]string{certFile1.Name(), certFile2.Name()})
78+ assert.NoError(t, err)
79+
80+ subj := certPool.Subjects()
81+ got := make([]string, 0)
82+ for i := range subj {
83+ var subject pkix.RDNSequence
84+ _, err := asn1.Unmarshal(subj[i], &subject)
85+ assert.NoError(t, err)
86+ got = append(got, subject.String())
87+ }
88+
89+ expectedSubjects := []string{testCA1Subj, testCA2Subj}
90+ assert.Equal(t, expectedSubjects, got)
91+}