gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/lib/certdbaccessor_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 "crypto/rand" 11 "crypto/x509/pkix" 12 "encoding/pem" 13 "math/big" 14 "os" 15 "testing" 16 "time" 17 18 "gitee.com/zhaochuninhefei/gmgo/sm2" 19 "gitee.com/zhaochuninhefei/gmgo/x509" 20 21 "gitee.com/zhaochuninhefei/cfssl-gm/certdb" 22 "gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/util" 23 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/mocks" 24 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/certificaterequest" 25 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/db" 26 dbutil "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/db/util" 27 cadbuser "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/server/user" 28 "gitee.com/zhaochuninhefei/fabric-gm/common/metrics/metricsfakes" 29 log "gitee.com/zhaochuninhefei/zcgolog/zclog" 30 "github.com/jmoiron/sqlx" 31 "github.com/pkg/errors" 32 "github.com/stretchr/testify/assert" 33 ) 34 35 func TestGetCertificatesDB(t *testing.T) { 36 os.RemoveAll("getCertDBTest") 37 defer os.RemoveAll("getCertDBTest") 38 log.Level = log.LOG_LEVEL_DEBUG 39 40 level := &dbutil.Levels{ 41 Affiliation: 1, 42 Identity: 1, 43 Certificate: 1, 44 } 45 mockOperationsServer := &mocks.OperationsServer{} 46 fakeCounter := &metricsfakes.Counter{} 47 fakeCounter.WithReturns(fakeCounter) 48 mockOperationsServer.NewCounterReturns(fakeCounter) 49 fakeHistogram := &metricsfakes.Histogram{} 50 fakeHistogram.WithReturns(fakeHistogram) 51 mockOperationsServer.NewHistogramReturns(fakeHistogram) 52 srv := &Server{ 53 Operations: mockOperationsServer, 54 levels: level, 55 } 56 ca, err := newCA("getCertDBTest/config.yaml", &CAConfig{}, srv, false) 57 util.FatalError(t, err, "Failed to get CA") 58 59 populateCertificatesTable(t, ca) 60 61 certReq := getCertReq("testCertificate1", "", "", false, false, nil, nil, nil, nil) 62 rows, err := ca.certDBAccessor.GetCertificates(certReq, "") 63 assert.NoError(t, err, "Failed to get certificates from database") 64 certs, err := readRows(rows) 65 assert.NoError(t, err) 66 assert.Equal(t, "testCertificate1", certs[0].Subject.CommonName) 67 68 certReq = getCertReq("", "1111", "", false, false, nil, nil, nil, nil) 69 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 70 assert.NoError(t, err, "Failed to get certificates from database") 71 certs, err = readRows(rows) 72 assert.NoError(t, err) 73 assert.Equal(t, big.NewInt(1111), certs[0].SerialNumber) 74 75 certReq = getCertReq("", "", "9876", false, false, nil, nil, nil, nil) 76 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 77 assert.NoError(t, err, "Failed to get certificates from database") 78 certs, err = readRows(rows) 79 assert.NoError(t, err) 80 assert.Equal(t, 2, len(certs)) 81 assert.Equal(t, []byte("9876"), certs[0].AuthorityKeyId) 82 83 certReq = getCertReq("", "", "", true, false, nil, nil, nil, nil) 84 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 85 assert.NoError(t, err, "Failed to get certificates from database") 86 certs, err = readRows(rows) 87 assert.NoError(t, err) 88 assert.Equal(t, 5, len(certs)) 89 90 certReq = getCertReq("", "", "", false, true, nil, nil, nil, nil) 91 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 92 assert.NoError(t, err, "Failed to get certificates from database") 93 certs, err = readRows(rows) 94 assert.NoError(t, err) 95 assert.Equal(t, 6, len(certs)) 96 97 certReq = getCertReq("", "1111", "", false, false, nil, nil, nil, nil) 98 rows, err = ca.certDBAccessor.GetCertificates(certReq, "dept1") 99 assert.NoError(t, err, "Failed to get certificates from database") 100 certs, err = readRows(rows) 101 assert.NoError(t, err) 102 assert.Equal(t, 1, len(certs)) 103 assert.Equal(t, "testCertificate1", certs[0].Subject.CommonName) 104 105 certReq = getCertReq("", "", "9876AB", false, false, nil, nil, nil, nil) 106 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 107 assert.NoError(t, err, "Failed to get certificates from database") 108 certs, err = readRows(rows) 109 assert.NoError(t, err) 110 assert.Equal(t, 1, len(certs)) 111 assert.Equal(t, "testCertificate3", certs[0].Subject.CommonName) 112 113 revokedStart := time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC) 114 certReq = getCertReq("", "", "", false, false, &revokedStart, nil, nil, nil) 115 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 116 assert.NoError(t, err, "Failed to get certificates from database") 117 certs, err = readRows(rows) 118 assert.NoError(t, err) 119 assert.Equal(t, 1, len(certs)) 120 assert.Equal(t, "revoked1", certs[0].Subject.CommonName) 121 122 revokedEnd := time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC) 123 certReq = getCertReq("", "", "", false, false, nil, &revokedEnd, nil, nil) 124 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 125 assert.NoError(t, err, "Failed to get certificates from database") 126 certs, err = readRows(rows) 127 assert.NoError(t, err) 128 assert.Equal(t, 2, len(certs)) 129 130 revokedStart = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC) 131 revokedEnd = time.Date(2017, time.August, 1, 0, 0, 0, 0, time.UTC) 132 certReq = getCertReq("", "", "", false, false, &revokedStart, &revokedEnd, nil, nil) 133 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 134 assert.NoError(t, err, "Failed to get certificates from database") 135 certs, err = readRows(rows) 136 assert.NoError(t, err) 137 assert.Equal(t, 1, len(certs)) 138 assert.Equal(t, "revoked2", certs[0].Subject.CommonName) 139 140 expiredStart := time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC) 141 certReq = getCertReq("", "", "", false, false, nil, nil, &expiredStart, nil) 142 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 143 assert.NoError(t, err, "Failed to get certificates from database") 144 certs, err = readRows(rows) 145 assert.NoError(t, err) 146 assert.Equal(t, 6, len(certs)) 147 148 dur, err := time.ParseDuration("+100h") 149 assert.NoError(t, err) 150 expiredEnd := time.Now().Add(dur).UTC() 151 certReq = getCertReq("", "", "", false, false, nil, nil, nil, &expiredEnd) 152 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 153 assert.NoError(t, err, "Failed to get certificates from database") 154 certs, err = readRows(rows) 155 assert.NoError(t, err) 156 assert.Equal(t, 7, len(certs)) 157 158 expiredStart = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC) 159 expiredEnd = time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC) 160 certReq = getCertReq("", "", "", false, false, nil, nil, &expiredStart, &expiredEnd) 161 rows, err = ca.certDBAccessor.GetCertificates(certReq, "") 162 assert.NoError(t, err, "Failed to get certificates from database") 163 certs, err = readRows(rows) 164 assert.NoError(t, err) 165 assert.Equal(t, 1, len(certs)) 166 assert.Equal(t, "expire1", certs[0].Subject.CommonName) 167 } 168 169 func readRows(rows *sqlx.Rows) ([]*x509.Certificate, error) { 170 var certs []*x509.Certificate 171 172 for rows.Next() { 173 var cert certPEM 174 err := rows.StructScan(&cert) 175 if err != nil { 176 return nil, errors.Errorf("Failed to get read row: %s", err) 177 } 178 179 block, rest := pem.Decode([]byte(cert.PEM)) 180 if block == nil || len(rest) > 0 { 181 return nil, errors.New("Certificate decoding error") 182 } 183 certificate, err := x509.ParseCertificate(block.Bytes) 184 if err != nil { 185 return nil, err 186 } 187 188 certs = append(certs, certificate) 189 } 190 191 return certs, nil 192 } 193 194 func populateCertificatesTable(t *testing.T, ca *CA) { 195 var err error 196 197 dur, err := time.ParseDuration("+100h") 198 util.FatalError(t, err, "Failed to parse duration '+100h'") 199 futureTime := time.Now().Add(dur).UTC() 200 201 ca.registry.InsertUser(&cadbuser.Info{ 202 Name: "testCertificate1", 203 Affiliation: "dept1", 204 }) 205 // Active Certs 206 err = testInsertCertificate(&certdb.CertificateRecord{ 207 Serial: "1111", 208 AKI: "9876", 209 Expiry: futureTime, 210 }, "testCertificate1", ca) 211 util.FatalError(t, err, "Failed to insert certificate with serial/AKI") 212 213 ca.registry.InsertUser(&cadbuser.Info{ 214 Name: "testCertificate2", 215 Affiliation: "dept1", 216 }) 217 err = testInsertCertificate(&certdb.CertificateRecord{ 218 Serial: "1112", 219 AKI: "9876", 220 Expiry: futureTime, 221 }, "testCertificate2", ca) 222 util.FatalError(t, err, "Failed to insert certificate with serial/AKI") 223 224 err = testInsertCertificate(&certdb.CertificateRecord{ 225 Serial: "1132", 226 AKI: "9876ab", 227 Expiry: futureTime, 228 }, "testCertificate3", ca) 229 util.FatalError(t, err, "Failed to insert certificate with revocation date") 230 231 // Expired 232 err = testInsertCertificate(&certdb.CertificateRecord{ 233 Serial: "1121", 234 AKI: "98765", 235 Expiry: time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC), 236 }, "expire1", ca) 237 util.FatalError(t, err, "Failed to insert certificate with expiration date") 238 239 // Not Expired 240 err = testInsertCertificate(&certdb.CertificateRecord{ 241 Serial: "1122", 242 AKI: "98765", 243 Expiry: futureTime, 244 }, "expire2", ca) 245 util.FatalError(t, err, "Failed to insert certificate with expiration date") 246 247 // Revoked 248 err = testInsertCertificate(&certdb.CertificateRecord{ 249 Serial: "1131", 250 AKI: "98765", 251 Expiry: futureTime, 252 RevokedAt: time.Date(2018, time.February, 15, 0, 0, 0, 0, time.UTC), 253 }, "revoked1", ca) 254 util.FatalError(t, err, "Failed to insert certificate with revocation date") 255 256 err = testInsertCertificate(&certdb.CertificateRecord{ 257 Serial: "1132", 258 AKI: "98765", 259 Expiry: futureTime, 260 RevokedAt: time.Date(2017, time.February, 15, 0, 0, 0, 0, time.UTC), 261 }, "revoked2", ca) 262 util.FatalError(t, err, "Failed to insert certificate with revocation date") 263 } 264 265 func testInsertCertificate(req *certdb.CertificateRecord, id string, ca *CA) error { 266 priv, err := sm2.GenerateKey(rand.Reader) 267 if err != nil { 268 return errors.Errorf("Failed to generate private key: %s", err) 269 } 270 271 serial := new(big.Int) 272 serial.SetString(req.Serial, 10) //base 10 273 274 template := x509.Certificate{ 275 Subject: pkix.Name{ 276 CommonName: id, 277 }, 278 SerialNumber: serial, 279 AuthorityKeyId: []byte(req.AKI), 280 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 281 } 282 283 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) 284 if err != nil { 285 log.Fatalf("Failed to create certificate: %s", err) 286 } 287 288 cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 289 290 var record = &db.CertRecord{ 291 ID: id, 292 CertificateRecord: certdb.CertificateRecord{ 293 Serial: req.Serial, 294 AKI: req.AKI, 295 CALabel: req.CALabel, 296 Status: req.Status, 297 Reason: req.Reason, 298 Expiry: req.Expiry.UTC(), 299 RevokedAt: req.RevokedAt.UTC(), 300 PEM: string(cert), 301 }, 302 } 303 304 db := ca.GetDB() 305 res, err := db.NamedExec("", insertSQL, record) 306 if err != nil { 307 return errors.Wrap(err, "Failed to insert record into database") 308 } 309 310 numRowsAffected, err := res.RowsAffected() 311 312 if numRowsAffected == 0 { 313 return errors.New("Failed to insert the certificate record; no rows affected") 314 } 315 316 if numRowsAffected != 1 { 317 return errors.Errorf("Expected to affect 1 entry in certificate database but affected %d", 318 numRowsAffected) 319 } 320 321 return err 322 } 323 324 func getCertReq(id, serial, aki string, notrevoked, notexpired bool, revokedTimeStart, revokedTimeEnd, expiredTimeStart, expiredTimeEnd *time.Time) *certificaterequest.Impl { 325 return &certificaterequest.Impl{ 326 ID: id, 327 SerialNumber: serial, 328 Aki: aki, 329 Notexpired: notexpired, 330 Notrevoked: notrevoked, 331 ExpiredTimeStart: expiredTimeStart, 332 ExpiredTimeEnd: expiredTimeEnd, 333 RevokedTimeStart: revokedTimeStart, 334 RevokedTimeEnd: revokedTimeEnd, 335 } 336 }