gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/lib/servercertificates_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lib 8 9 import ( 10 "bytes" 11 "fmt" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "strings" 16 "testing" 17 18 "gitee.com/zhaochuninhefei/gmgo/gmhttp/httptest" 19 20 http "gitee.com/zhaochuninhefei/gmgo/gmhttp" 21 22 "gitee.com/zhaochuninhefei/cfssl-gm/certdb" 23 "gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/api" 24 "gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/util" 25 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/caerrors" 26 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/mocks" 27 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/certificaterequest" 28 dbutil "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/db/util" 29 dbuser "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/user" 30 "gitee.com/zhaochuninhefei/fabric-gm/common/metrics/metricsfakes" 31 "github.com/pkg/errors" 32 "github.com/stretchr/testify/assert" 33 ) 34 35 func TestCertificatesHandler(t *testing.T) { 36 ctx := new(serverRequestContextImpl) 37 req, err := http.NewRequest("GET", "", bytes.NewReader([]byte{})) 38 assert.NoError(t, err) 39 ctx.req = req 40 _, err = certificatesHandler(ctx) 41 util.ErrorContains(t, err, "No authorization header", "Failed to catch error") 42 } 43 44 func TestAuthChecks(t *testing.T) { 45 ctxMock := new(mocks.ServerRequestContext) 46 ctxMock.On("GetCaller").Return(nil, errors.New("Failed to get caller")) 47 err := authChecks(ctxMock) 48 util.ErrorContains(t, err, "Failed to get caller", "Expected to catch error from GetCaller() func") 49 50 ctx := new(serverRequestContextImpl) 51 user := &dbuser.Record{ 52 Name: "NotRegistrar", 53 } 54 ctx.caller = dbuser.New(user, nil) 55 err = authChecks(ctx) 56 assert.Error(t, err, "Caller does not possess the appropriate attributes to request manage certificates") 57 58 attributes := []api.Attribute{ 59 api.Attribute{ 60 Name: "hf.Registrar.Roles", 61 Value: "peer,client", 62 }, 63 } 64 65 attr, err := util.Marshal(attributes, "attributes") 66 util.FatalError(t, err, "Failed to marshal attributes") 67 user = &dbuser.Record{ 68 Name: "Registrar", 69 Attributes: string(attr), 70 } 71 ctx.caller = dbuser.New(user, nil) 72 err = authChecks(ctx) 73 assert.NoError(t, err, "Should not fail, caller has 'hf.Registrar.Roles' attribute") 74 75 attributes = []api.Attribute{ 76 api.Attribute{ 77 Name: "hf.Revoker", 78 Value: "true", 79 }, 80 } 81 attr, err = util.Marshal(attributes, "attributes") 82 util.FatalError(t, err, "Failed to marshal attributes") 83 user = &dbuser.Record{ 84 Name: "Revoker", 85 Attributes: string(attr), 86 } 87 ctx.caller = dbuser.New(user, nil) 88 err = authChecks(ctx) 89 assert.NoError(t, err, "Should not fail, caller has 'hf.Revoker' with a value of 'true' attribute") 90 91 ctx = new(serverRequestContextImpl) 92 attributes = []api.Attribute{ 93 api.Attribute{ 94 Name: "hf.Revoker", 95 Value: "false", 96 }, 97 } 98 attr, err = util.Marshal(attributes, "attributes") 99 util.FatalError(t, err, "Failed to marshal attributes") 100 user = &dbuser.Record{ 101 Name: "NotRevoker", 102 Attributes: string(attr), 103 } 104 ctx.caller = dbuser.New(user, nil) 105 err = authChecks(ctx) 106 assert.Error(t, err, "Should fail, caller has 'hf.Revoker' but with a value of 'false' attribute") 107 } 108 109 func TestProcessCertificateRequest(t *testing.T) { 110 ctx := new(mocks.ServerRequestContext) 111 ctx.On("TokenAuthentication").Return("", errors.New("Token Auth Failed")) 112 err := processCertificateRequest(ctx) 113 util.ErrorContains(t, err, "Token Auth Failed", "Should have failed token auth") 114 115 ctx = new(mocks.ServerRequestContext) 116 ctx.On("TokenAuthentication").Return("", nil) 117 ctx.On("HasRole", "hf.Revoker").Return(errors.New("Does not have attribute")) 118 attr, err := util.Marshal([]api.Attribute{}, "attributes") 119 util.FatalError(t, err, "Failed to marshal attributes") 120 user := &dbuser.Record{ 121 Name: "NotRevoker", 122 Attributes: string(attr), 123 } 124 ctx.On("GetCaller").Return(dbuser.New(user, nil), nil) 125 126 err = processCertificateRequest(ctx) 127 t.Log("Error: ", err) 128 util.ErrorContains(t, err, fmt.Sprintf("%d", caerrors.ErrAuthorizationFailure), "Should have failed to due improper permissions") 129 130 ctx = new(mocks.ServerRequestContext) 131 ctx.On("TokenAuthentication").Return("", nil) 132 ctx.On("HasRole", "hf.Revoker").Return(nil) 133 ctx.On("GetCaller").Return(dbuser.New(user, nil), nil) 134 req, err := http.NewRequest("POST", "", bytes.NewReader([]byte{})) 135 util.FatalError(t, err, "Failed to get HTTP request") 136 ctx.On("GetReq").Return(req) 137 err = processCertificateRequest(ctx) 138 t.Log("Error: ", err) 139 util.ErrorContains(t, err, "Invalid request", "Should have failed to incorrect method type on HTTP request") 140 141 } 142 143 func TestProcessGetCertificateRequest(t *testing.T) { 144 ctx := new(serverRequestContextImpl) 145 req, err := http.NewRequest("GET", "", bytes.NewReader([]byte{})) 146 util.FatalError(t, err, "Failed to get GET HTTP request") 147 148 url := req.URL.Query() 149 url.Add("revoked_end", "2012-12-123") 150 req.URL.RawQuery = url.Encode() 151 ctx.req = req 152 err = processGetCertificateRequest(ctx) 153 assert.Error(t, err, "Invalid time format, should have failed") 154 155 req, err = http.NewRequest("GET", "", bytes.NewReader([]byte{})) 156 util.FatalError(t, err, "Failed to get GET HTTP request") 157 url = req.URL.Query() 158 url.Add("notrevoked", "not_bool") 159 req.URL.RawQuery = url.Encode() 160 ctx.req = req 161 162 err = processGetCertificateRequest(ctx) 163 assert.Error(t, err, "Invalid boolean value, should have failed") 164 165 req, err = http.NewRequest("GET", "", bytes.NewReader([]byte{})) 166 util.FatalError(t, err, "Failed to get GET HTTP request") 167 url = req.URL.Query() 168 url.Add("revoked_end", "2012-12-12") 169 url.Add("notrevoked", "true") 170 req.URL.RawQuery = url.Encode() 171 ctx.req = req 172 173 err = processGetCertificateRequest(ctx) 174 assert.Error(t, err, "Invalid combination of filters, should have failed") 175 } 176 177 type mockHTTPWriter struct { 178 http.ResponseWriter 179 t *testing.T 180 } 181 182 // Header returns the header map that will be sent by WriteHeader. 183 func (m *mockHTTPWriter) Header() http.Header { 184 return m.ResponseWriter.Header() 185 } 186 187 // WriteHeader sends an HTTP response header with status code. 188 func (m *mockHTTPWriter) WriteHeader(scode int) { 189 m.WriteHeader(1) 190 } 191 192 // Write writes the data to the connection as part of an HTTP reply. 193 func (m *mockHTTPWriter) Write(buf []byte) (int, error) { 194 w := m.ResponseWriter 195 if !strings.Contains(string(buf), "certs") && !strings.Contains(string(buf), "BEGIN CERTIFICATE") && !strings.Contains(string(buf), "caname") { 196 m.t.Error("Invalid response being sent back from certificates endpoint") 197 } 198 return w.Write(buf) 199 } 200 201 // Write writes the data to the connection as part of an HTTP reply. 202 func (m *mockHTTPWriter) Flush() {} 203 204 func TestServerGetCertificates(t *testing.T) { 205 os.RemoveAll("getCertTest") 206 defer os.RemoveAll("getCertTest") 207 var err error 208 209 level := &dbutil.Levels{ 210 Affiliation: 1, 211 Identity: 1, 212 Certificate: 1, 213 } 214 mockOperationsServer := &mocks.OperationsServer{} 215 fakeCounter := &metricsfakes.Counter{} 216 fakeCounter.WithReturns(fakeCounter) 217 mockOperationsServer.NewCounterReturns(fakeCounter) 218 fakeHistogram := &metricsfakes.Histogram{} 219 fakeHistogram.WithReturns(fakeHistogram) 220 mockOperationsServer.NewHistogramReturns(fakeHistogram) 221 srv := &Server{ 222 Operations: mockOperationsServer, 223 levels: level, 224 } 225 ca, err := newCA("getCertTest/config.yaml", &CAConfig{}, srv, false) 226 util.FatalError(t, err, "Failed to get CA") 227 228 ctx := new(serverRequestContextImpl) 229 req, err := http.NewRequest("GET", "", bytes.NewReader([]byte{})) 230 util.FatalError(t, err, "Failed to get GET HTTP request") 231 232 user := &dbuser.Record{ 233 Name: "NotRevoker", 234 } 235 ctx.caller = dbuser.New(user, nil) 236 237 ctx.req = req 238 ctx.ca = ca 239 w := httptest.NewRecorder() 240 ctx.resp = &mockHTTPWriter{w, t} 241 242 err = testInsertCertificate(&certdb.CertificateRecord{ 243 Serial: "1111", 244 AKI: "9876", 245 }, "testCertificate", ca) 246 util.FatalError(t, err, "Failed to insert certificate with serial/AKI") 247 248 err = getCertificates(ctx, &certificaterequest.Impl{}) 249 assert.NoError(t, err, "Should not have returned error, failed to process GET certificate request") 250 251 mockCtx := new(mocks.ServerRequestContext) 252 mockCtx.On("GetResp").Return(nil) 253 mockCtx.On("GetCaller").Return(nil, errors.New("failed to get caller")) 254 err = getCertificates(mockCtx, nil) 255 util.ErrorContains(t, err, "failed to get caller", "did not get correct error response") 256 257 testUser := dbuser.New(&dbuser.Record{Name: "testuser"}, nil) 258 mockCtx = new(mocks.ServerRequestContext) 259 mockCtx.On("GetResp").Return(nil) 260 mockCtx.On("GetCaller").Return(testUser, nil) 261 mockCtx.On("GetCertificates", (*certificaterequest.Impl)(nil), "").Return(nil, errors.New("failed to get certificates")) 262 err = getCertificates(mockCtx, nil) 263 util.ErrorContains(t, err, "failed to get certificates", "did not get correct error response") 264 } 265 266 func TestStoreCert(t *testing.T) { 267 dir, err := ioutil.TempDir("", "testStoreCert") 268 assert.NoError(t, err, "failed to create temp directory") 269 defer os.RemoveAll(dir) 270 271 cd := NewCertificateDecoder(dir) 272 err = cd.storeCert("testID", dir, []byte("testing store cert function")) 273 assert.NoError(t, err, "failed to store cert") 274 275 filePath := filepath.Join(dir, "testID.pem") 276 assert.Equal(t, true, util.FileExists(filePath)) 277 278 cert, err := ioutil.ReadFile(filePath) 279 assert.NoError(t, err, "failed to read certificate file") 280 assert.Equal(t, "testing store cert function", string(cert)) 281 282 err = cd.storeCert("testID", dir, []byte("testing store cert function - second cert")) 283 assert.NoError(t, err, "failed to store cert") 284 285 filePath = filepath.Join(dir, "testID-1.pem") 286 assert.Equal(t, true, util.FileExists(filePath)) 287 cert, err = ioutil.ReadFile(filePath) 288 assert.NoError(t, err, "failed to read certificate file") 289 assert.Equal(t, "testing store cert function", string(cert)) 290 291 filePath = filepath.Join(dir, "testID-2.pem") 292 assert.Equal(t, true, util.FileExists(filePath)) 293 cert, err = ioutil.ReadFile(filePath) 294 assert.NoError(t, err, "failed to read certificate file") 295 assert.Equal(t, "testing store cert function - second cert", string(cert)) 296 297 err = cd.storeCert("testID", dir, []byte("testing store cert function - third cert")) 298 assert.NoError(t, err, "failed to store cert") 299 filePath = filepath.Join(dir, "testID-3.pem") 300 assert.Equal(t, true, util.FileExists(filePath)) 301 302 // Error case - renaming a certificate file that does not exist should fail 303 cd = NewCertificateDecoder(dir) 304 cd.certIDCount["testID2"] = 1 305 err = cd.storeCert("testID2", dir, []byte("testing store cert function")) 306 util.ErrorContains(t, err, "Failed to rename certificate", "Should have failed") 307 }