github.com/secure-build/gitlab-runner@v12.5.0+incompatible/helpers/tls/ca_chain/resolver_url_test.go (about) 1 package ca_chain 2 3 import ( 4 "bytes" 5 "crypto/x509" 6 "errors" 7 "testing" 8 9 "github.com/sirupsen/logrus" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 type fetcherMockFactory func(t *testing.T) fetcher 14 15 func newFetcherMock(url string, data []byte, err error) fetcherMockFactory { 16 return func(t *testing.T) fetcher { 17 return func(url string) ([]byte, error) { 18 assert.Equal(t, url, url) 19 20 return data, err 21 } 22 } 23 } 24 25 type decoderMockFactory func(t *testing.T) decoder 26 27 func newDecoderMock(inputData []byte, cert *x509.Certificate, err error) decoderMockFactory { 28 return func(t *testing.T) decoder { 29 return func(data []byte) (*x509.Certificate, error) { 30 assert.Equal(t, inputData, data) 31 32 return cert, err 33 } 34 } 35 } 36 37 func TestUrlResolver_Resolve(t *testing.T) { 38 testError := errors.New("test-error") 39 url1 := "url1" 40 41 testCACertificate := loadCertificate(t, testCACert) 42 testCertificate := loadCertificate(t, testCert) 43 testCertificateWithURL := loadCertificate(t, testCert) 44 testCertificateWithURL.IssuingCertificateURL = []string{url1, "url2"} 45 46 tests := map[string]struct { 47 certs []*x509.Certificate 48 mockLoopLimit int 49 mockFetcher fetcherMockFactory 50 mockDecoder decoderMockFactory 51 expectedError string 52 expectedCerts []*x509.Certificate 53 expectedOutput []string 54 }{ 55 "empty input chain": { 56 certs: nil, 57 mockLoopLimit: defaultURLResolverLoopLimit, 58 expectedError: "", 59 expectedCerts: nil, 60 expectedOutput: nil, 61 }, 62 "last certificate without URL": { 63 certs: []*x509.Certificate{testCertificate}, 64 mockLoopLimit: defaultURLResolverLoopLimit, 65 expectedError: "", 66 expectedCerts: []*x509.Certificate{testCertificate}, 67 expectedOutput: []string{ 68 "Certificate doesn't provide parent URL: exiting the loop", 69 }, 70 }, 71 "last certificate with URL and fetcher error": { 72 certs: []*x509.Certificate{testCertificateWithURL}, 73 mockLoopLimit: defaultURLResolverLoopLimit, 74 mockFetcher: newFetcherMock(url1, nil, testError), 75 expectedError: "error while fetching issuer certificate: remote fetch failure: test-error", 76 expectedCerts: nil, 77 expectedOutput: []string{ 78 "Remote certificate fetching error", 79 }, 80 }, 81 "last certificate with URL and decoder error": { 82 certs: []*x509.Certificate{testCertificateWithURL}, 83 mockLoopLimit: defaultURLResolverLoopLimit, 84 mockFetcher: newFetcherMock(url1, []byte("test"), nil), 85 mockDecoder: newDecoderMock([]byte("test"), nil, testError), 86 expectedError: "error while fetching issuer certificate: decoding failure: test-error", 87 expectedCerts: nil, 88 expectedOutput: []string{ 89 "Certificate decoding error", 90 }, 91 }, 92 "last certificate with URL with not self signed": { 93 certs: []*x509.Certificate{testCertificateWithURL}, 94 mockLoopLimit: defaultURLResolverLoopLimit, 95 mockFetcher: newFetcherMock(url1, []byte("test"), nil), 96 mockDecoder: newDecoderMock([]byte("test"), testCertificate, nil), 97 expectedError: "", 98 expectedCerts: []*x509.Certificate{testCertificateWithURL, testCertificate}, 99 expectedOutput: []string{ 100 "Appending the certificate to the chain", 101 }, 102 }, 103 "last certificate with URL with self signed": { 104 certs: []*x509.Certificate{testCertificateWithURL}, 105 mockLoopLimit: defaultURLResolverLoopLimit, 106 mockFetcher: newFetcherMock(url1, []byte("test"), nil), 107 mockDecoder: newDecoderMock([]byte("test"), testCACertificate, nil), 108 expectedError: "", 109 expectedCerts: []*x509.Certificate{testCertificateWithURL, testCACertificate}, 110 expectedOutput: []string{ 111 "Fetched issuer certificate is a ROOT certificate so exiting the loop", 112 }, 113 }, 114 "infinite loop": { 115 certs: []*x509.Certificate{testCertificateWithURL}, 116 mockLoopLimit: 3, 117 mockFetcher: newFetcherMock(url1, []byte("test"), nil), 118 mockDecoder: newDecoderMock([]byte("test"), testCertificateWithURL, nil), 119 expectedError: "", 120 expectedCerts: []*x509.Certificate{testCertificateWithURL, testCertificateWithURL, testCertificateWithURL}, 121 expectedOutput: []string{ 122 "urlResolver loop limit exceeded; exiting the loop", 123 }, 124 }, 125 } 126 127 for tn, tc := range tests { 128 t.Run(tn, func(t *testing.T) { 129 out := new(bytes.Buffer) 130 131 logger := logrus.New() 132 logger.SetLevel(logrus.DebugLevel) 133 logger.SetOutput(out) 134 135 r := newURLResolver(logger).(*urlResolver) 136 r.loopLimit = tc.mockLoopLimit 137 138 if tc.mockFetcher != nil { 139 r.fetcher = tc.mockFetcher(t) 140 } 141 142 if tc.mockDecoder != nil { 143 r.decoder = tc.mockDecoder(t) 144 } 145 146 newCerts, err := r.Resolve(tc.certs) 147 148 if tc.expectedError != "" { 149 assert.EqualError(t, err, tc.expectedError) 150 } else { 151 assert.NoError(t, err) 152 } 153 154 assert.Equal(t, tc.expectedCerts, newCerts) 155 156 output := out.String() 157 if len(tc.expectedOutput) > 0 { 158 for _, expectedLine := range tc.expectedOutput { 159 assert.Contains(t, output, expectedLine) 160 } 161 } else { 162 assert.Empty(t, output) 163 } 164 }) 165 } 166 }