github.com/49746628/fabric-ca-gm@v2.0.0-alpha.0.20200822143404-8a07eefa7452+incompatible/lib/dbaccessor_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lib_test 8 9 import ( 10 "fmt" 11 "os" 12 "strings" 13 "testing" 14 15 "github.com/hyperledger/fabric-ca/internal/pkg/api" 16 . "github.com/hyperledger/fabric-ca/lib" 17 "github.com/hyperledger/fabric-ca/lib/server/db" 18 "github.com/hyperledger/fabric-ca/lib/server/db/sqlite" 19 cadbuser "github.com/hyperledger/fabric-ca/lib/server/user" 20 "github.com/jmoiron/sqlx" 21 _ "github.com/mattn/go-sqlite3" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 const ( 26 dbPath = "/tmp/dbtesting" 27 28 sqliteTruncateTables = ` 29 DELETE FROM Users; 30 DELETE FROM affiliations; 31 ` 32 33 rootDB = "rootDir/fabric_ca.db" 34 ) 35 36 type TestAccessor struct { 37 Accessor *Accessor 38 DB *db.DB 39 } 40 41 func (ta *TestAccessor) Truncate() { 42 Truncate(ta.DB) 43 } 44 45 func TestSQLite(t *testing.T) { 46 cleanTestSlateSQ(t) 47 defer cleanTestSlateSQ(t) 48 49 if _, err := os.Stat(dbPath); err != nil { 50 if os.IsNotExist(err) { 51 os.MkdirAll(dbPath, 0755) 52 } 53 } else { 54 err = os.RemoveAll(dbPath) 55 if err != nil { 56 t.Errorf("RemoveAll failed: %s", err) 57 } 58 os.MkdirAll(dbPath, 0755) 59 } 60 dataSource := dbPath + "/fabric-ca.db" 61 sqlitedb, err := getSqliteDb(dataSource) 62 if err != nil { 63 t.Error("Failed to open connection to DB") 64 } 65 accessor := NewDBAccessor(sqlitedb) 66 67 ta := TestAccessor{ 68 Accessor: accessor, 69 DB: sqlitedb, 70 } 71 testEverything(ta, t) 72 } 73 74 // Truncate truncates the DB 75 func Truncate(db *db.DB) { 76 var sql []string 77 sql = []string{sqliteTruncateTables} 78 79 for _, expr := range sql { 80 if len(strings.TrimSpace(expr)) == 0 { 81 continue 82 } 83 if _, err := db.Exec("", expr); err != nil { 84 panic(err) 85 } 86 } 87 } 88 89 func TestEmptyAccessor(t *testing.T) { 90 a := &Accessor{} 91 ui := cadbuser.Info{} 92 err := a.InsertUser(nil) 93 if err == nil { 94 t.Error("Passing in nil should have resulted in an error") 95 } 96 97 err = a.InsertUser(&ui) 98 if err == nil { 99 t.Error("Empty Accessor InsertUser should have failed") 100 } 101 } 102 103 func TestDBCreation(t *testing.T) { 104 cleanTestSlateSQ(t) 105 defer cleanTestSlateSQ(t) 106 107 os.Mkdir(rootDir, 0755) 108 109 testWithExistingDbAndTablesAndUser(t) 110 testWithExistingDbAndTable(t) 111 testWithExistingDb(t) 112 } 113 114 func createSQLiteDB(path string, t *testing.T) (*db.DB, *TestAccessor) { 115 sqlxdb, err := sqlx.Open("sqlite3", path) 116 assert.NoError(t, err, "Failed to open SQLite database") 117 118 sqlitedb := db.New(sqlxdb, "", nil) 119 accessor := NewDBAccessor(sqlitedb) 120 121 ta := &TestAccessor{ 122 Accessor: accessor, 123 DB: sqlitedb, 124 } 125 126 return sqlitedb, ta 127 } 128 129 // Test that an already bootstrapped database properly get inspected and bootstrapped with any new identities on the 130 // next server start 131 func testWithExistingDbAndTablesAndUser(t *testing.T) { 132 var err error 133 134 err = os.RemoveAll(rootDB) 135 if err != nil { 136 t.Errorf("RemoveAll failed: %s", err) 137 } 138 db, acc := createSQLiteDB(rootDB, t) 139 140 _, err = db.Exec("", "CREATE TABLE IF NOT EXISTS users (id VARCHAR(64), token bytea, type VARCHAR(64), affiliation VARCHAR(64), attributes VARCHAR(256), state INTEGER, max_enrollments INTEGER, level INTEGER DEFAULT 0)") 141 assert.NoError(t, err, "Error creating users table") 142 143 srv := TestGetServer2(false, rootPort, rootDir, "", -1, t) 144 srv.CA.Config.DB.Datasource = "fabric_ca.db" 145 146 err = srv.Start() 147 assert.NoError(t, err, "Failed to start server") 148 149 err = srv.Stop() 150 assert.NoError(t, err, "Failed to stop server") 151 152 // Add additional user to registry and start server and confirm that it correctly get added 153 srv.RegisterBootstrapUser("admin2", "admin2pw", "") 154 155 err = srv.Start() 156 assert.NoError(t, err, "Failed to start server") 157 158 _, err = acc.Accessor.GetUser("admin2", nil) 159 assert.NoError(t, err, "Failed to correctly insert 'admin2' during second server bootstrap") 160 161 err = srv.Stop() 162 assert.NoError(t, err, "Failed to stop server") 163 164 err = db.Close() 165 assert.NoError(t, err, "Failed to close DB") 166 } 167 168 // Test starting a server with an already existing database and tables, but not bootstrapped 169 func testWithExistingDbAndTable(t *testing.T) { 170 var err error 171 172 err = os.RemoveAll(rootDB) 173 if err != nil { 174 t.Errorf("RemoveAll failed: %s", err) 175 } 176 db, acc := createSQLiteDB(rootDB, t) 177 178 srv := TestGetServer2(false, rootPort, rootDir, "", -1, t) 179 srv.CA.Config.DB.Datasource = "fabric_ca.db" 180 181 _, err = db.Exec("", "CREATE TABLE IF NOT EXISTS users (id VARCHAR(64), token bytea, type VARCHAR(64), affiliation VARCHAR(64), attributes VARCHAR(256), state INTEGER, max_enrollments INTEGER, level INTEGER DEFAULT 0)") 182 assert.NoError(t, err, "Error creating users table") 183 184 err = srv.Start() 185 assert.NoError(t, err, "Failed to start server") 186 187 _, err = acc.Accessor.GetUser("admin", nil) 188 assert.NoError(t, err, "Failed to correctly insert 'admin' during second server bootstrap") 189 190 err = srv.Stop() 191 assert.NoError(t, err, "Failed to stop server") 192 193 err = db.Close() 194 assert.NoError(t, err, "Failed to close DB") 195 } 196 197 // Test starting a server with an already existing database, but no tables or users 198 func testWithExistingDb(t *testing.T) { 199 var err error 200 201 err = os.RemoveAll(rootDB) 202 if err != nil { 203 t.Errorf("RemoveAll failed: %s", err) 204 } 205 db, acc := createSQLiteDB(rootDB, t) 206 207 srv := TestGetServer2(false, rootPort, rootDir, "", -1, t) 208 srv.CA.Config.DB.Datasource = "fabric_ca.db" 209 210 err = srv.Start() 211 assert.NoError(t, err, "Failed to start server") 212 213 _, err = acc.Accessor.GetUser("admin", nil) 214 assert.NoError(t, err, "Failed to correctly insert 'admin' during second server bootstrap") 215 216 err = srv.Stop() 217 assert.NoError(t, err, "Failed to stop server") 218 219 err = db.Close() 220 assert.NoError(t, err, "Failed to close DB") 221 } 222 223 func cleanTestSlateSQ(t *testing.T) { 224 err := os.RemoveAll(rootDir) 225 if err != nil { 226 t.Errorf("RemoveAll failed: %s", err) 227 } 228 err = os.RemoveAll(dbPath) 229 if err != nil { 230 t.Errorf("RemoveAll failed: %s", err) 231 } 232 } 233 234 func testEverything(ta TestAccessor, t *testing.T) { 235 testInsertAndGetUser(ta, t) 236 testModifyAttribute(ta, t) 237 testDeleteUser(ta, t) 238 testUpdateUser(ta, t) 239 testInsertAndGetAffiliation(ta, t) 240 testDeleteAffiliation(ta, t) 241 testInsertAndGetFilteredUsers(ta, t) 242 } 243 244 func testInsertAndGetUser(ta TestAccessor, t *testing.T) { 245 t.Log("TestInsertAndGetUser") 246 ta.Truncate() 247 248 insert := cadbuser.Info{ 249 Name: "testId", 250 Pass: "123456", 251 Type: "client", 252 Attributes: []api.Attribute{ 253 api.Attribute{ 254 Name: "hf.Registrar.Roles", 255 Value: "peer,client,orderer,user", 256 }, 257 api.Attribute{ 258 Name: "hf.Revoker", 259 Value: "false", 260 }, 261 api.Attribute{ 262 Name: "hf.Registrar.Attributes", 263 Value: "*", 264 }, 265 api.Attribute{ 266 Name: "xyz", 267 Value: "xyz", 268 }, 269 }, 270 } 271 272 err := ta.Accessor.InsertUser(&insert) 273 if err != nil { 274 t.Errorf("Error occured during insert query of ID: %s, error: %s", insert.Name, err) 275 } 276 277 user, err := ta.Accessor.GetUser(insert.Name, nil) 278 if err != nil { 279 t.Errorf("Error occured during querying of id: %s, error: %s", insert.Name, err) 280 } 281 282 if user.GetName() != insert.Name { 283 t.Error("Incorrect ID retrieved") 284 } 285 } 286 287 func testInsertAndGetFilteredUsers(ta TestAccessor, t *testing.T) { 288 t.Log("TestInsertAndGetFilteredUsers") 289 ta.Truncate() 290 // create user 291 insert := cadbuser.Info{ 292 Name: "testTypesClient", 293 Pass: "123456", 294 Type: "client", 295 Attributes: []api.Attribute{ 296 api.Attribute{ 297 Name: "hf.Registrar.Roles", 298 Value: "peer,client,orderer,user", 299 }, 300 api.Attribute{ 301 Name: "hf.Revoker", 302 Value: "false", 303 }, 304 api.Attribute{ 305 Name: "hf.Registrar.Attributes", 306 Value: "*", 307 }, 308 api.Attribute{ 309 Name: "xyz", 310 Value: "xyz", 311 }, 312 }, 313 } 314 // insert user 315 err := ta.Accessor.InsertUser(&insert) 316 if err != nil { 317 t.Errorf("Error occured during insert query of ID: %s, error: %s", insert.Name, err) 318 } 319 // test get the user 320 rows, err := ta.Accessor.GetFilteredUsers("", "client,orderer") 321 if err != nil { 322 t.Errorf("Failed to get users by affiliation: %s, and type: %s, error: %s", "", "client,orderer", err) 323 } 324 325 typesClientSuccessFlag := false 326 for rows.Next() { 327 var id cadbuser.Record 328 err := rows.StructScan(&id) 329 if err != nil { 330 t.Errorf("Failed to get read row! error: %s", err) 331 } 332 // get the target user 333 if id.Name == "testTypesClient" && id.Type == "client" { 334 typesClientSuccessFlag = true 335 } 336 } 337 // not success 338 if !typesClientSuccessFlag { 339 t.Errorf("Test InsertAndGetFilteredUsers Failed!") 340 } 341 342 // test type=* and affiliation is not nil 343 // insert affiliation 344 err = ta.Accessor.InsertAffiliation("Bank1", "Banks", 0) 345 if err != nil { 346 t.Errorf("Error occured during insert query of group: %s, error: %s", "Bank1", err) 347 } 348 // change user info 349 insert.Name = "testTypesStar" 350 insert.Type = "*" 351 insert.Affiliation = "Bank1" 352 // insert user 353 err = ta.Accessor.InsertUser(&insert) 354 if err != nil { 355 t.Errorf("Error occured during insert query of ID: %s, error: %s", insert.Name, err) 356 } 357 // test get the user 358 rows, err = ta.Accessor.GetFilteredUsers("Bank1", "*") 359 if err != nil { 360 t.Errorf("Failed to get users by affiliation: %s, and type: %s, error: %s", "Bank1", "*", err) 361 } 362 // use the success flag to tag success 363 affiliationsTypeStarSuccessFlag := false 364 for rows.Next() { 365 var id cadbuser.Record 366 err := rows.StructScan(&id) 367 if err != nil { 368 t.Errorf("Failed to get read row! error: %s", err) 369 } 370 // get the target user 371 if id.Affiliation == "Bank1" && id.Name == "testTypesStar" { 372 affiliationsTypeStarSuccessFlag = true 373 } 374 } 375 // not success 376 if !affiliationsTypeStarSuccessFlag { 377 t.Errorf("Test InsertAndGetFilteredUsers Failed!") 378 } 379 380 // test get all user 381 affiliationsTypeStarSuccessFlag = false 382 typesClientSuccessFlag = false 383 // test get all users 384 rows, err = ta.Accessor.GetFilteredUsers("", "*") 385 if err != nil { 386 t.Errorf("Failed to get users by affiliation: %s, and type: %s, error: %s", "", "*", err) 387 } 388 for rows.Next() { 389 var id cadbuser.Record 390 err := rows.StructScan(&id) 391 if err != nil { 392 t.Errorf("Failed to get read row! error: %s", err) 393 } 394 // get the target user 395 if id.Affiliation == "Bank1" && id.Name == "testTypesStar" { 396 affiliationsTypeStarSuccessFlag = true 397 } 398 if id.Name == "testTypesClient" && id.Type == "client" { 399 typesClientSuccessFlag = true 400 } 401 } 402 // not success 403 if !(affiliationsTypeStarSuccessFlag && typesClientSuccessFlag) { 404 t.Errorf("Test InsertAndGetFilteredUsers Failed!") 405 } 406 } 407 408 func testModifyAttribute(ta TestAccessor, t *testing.T) { 409 410 user, err := ta.Accessor.GetUser("testId", nil) 411 assert.NoError(t, err, "Failed to get user") 412 413 err = user.ModifyAttributes([]api.Attribute{ 414 api.Attribute{ 415 Name: "hf.Registrar.Roles", 416 Value: "peer", 417 }, 418 api.Attribute{ 419 Name: "hf.Revoker", 420 Value: "", 421 }, 422 api.Attribute{ 423 Name: "xyz", 424 Value: "", 425 }, 426 api.Attribute{ 427 Name: "hf.IntermediateCA", 428 Value: "true", 429 }, 430 }) 431 assert.NoError(t, err, "Failed to modify user's attributes") 432 433 user, err = ta.Accessor.GetUser("testId", nil) 434 assert.NoError(t, err, "Failed to get user") 435 436 _, err = user.GetAttribute("hf.Revoker") 437 assert.Error(t, err, "Should have returned an error, attribute should have been deleted") 438 439 // Removes last attribute in the slice, should have correctly removed it 440 _, err = user.GetAttribute("xyz") 441 assert.Error(t, err, "Should have returned an error, attribute should have been deleted") 442 443 attr, err := user.GetAttribute("hf.IntermediateCA") 444 assert.NoError(t, err, "Failed to add attribute") 445 assert.Equal(t, "true", attr.Value, "Incorrect value for attribute 'hf.IntermediateCA") 446 447 attr, err = user.GetAttribute("hf.Registrar.Roles") 448 assert.NoError(t, err, "Failed to get attribute") 449 assert.Equal(t, "peer", attr.Value, "Incorrect value for attribute 'hf.Registrar.Roles") 450 451 // Test to make sure that any existing attributes that were not modified continue to exist in there original state 452 attr, err = user.GetAttribute("hf.Registrar.Attributes") 453 assert.NoError(t, err, "Failed to get attribute") 454 assert.Equal(t, "*", attr.Value) 455 } 456 457 func testDeleteUser(ta TestAccessor, t *testing.T) { 458 t.Log("TestDeleteUser") 459 ta.Truncate() 460 461 insert := cadbuser.Info{ 462 Name: "testId", 463 Pass: "123456", 464 Type: "client", 465 Attributes: []api.Attribute{}, 466 } 467 468 err := ta.Accessor.InsertUser(&insert) 469 if err != nil { 470 t.Errorf("Error occured during insert query of id: %s, error: %s", insert.Name, err) 471 } 472 473 _, err = ta.Accessor.DeleteUser(insert.Name) 474 if err != nil { 475 t.Errorf("Error occured during deletion of ID: %s, error: %s", insert.Name, err) 476 } 477 478 _, err = ta.Accessor.GetUser(insert.Name, nil) 479 if err == nil { 480 t.Error("Should have errored, and not returned any results") 481 } 482 } 483 484 func testUpdateUser(ta TestAccessor, t *testing.T) { 485 t.Log("TestUpdateUser") 486 ta.Truncate() 487 488 insert := cadbuser.Info{ 489 Name: "testId", 490 Pass: "123456", 491 Type: "client", 492 Attributes: []api.Attribute{}, 493 MaxEnrollments: 1, 494 } 495 496 err := ta.Accessor.InsertUser(&insert) 497 if err != nil { 498 t.Errorf("Error occured during insert query of ID: %s, error: %s", insert.Name, err) 499 } 500 501 insert.Pass = "654321" 502 503 err = ta.Accessor.UpdateUser(nil, true) 504 if err == nil { 505 t.Error("Passing in nil should have resulted in an error") 506 } 507 508 err = ta.Accessor.UpdateUser(&insert, true) 509 if err != nil { 510 t.Errorf("Error occured during update query of ID: %s, error: %s", insert.Name, err) 511 } 512 513 user, err := ta.Accessor.GetUser(insert.Name, nil) 514 if err != nil { 515 t.Errorf("Error occured during querying of ID: %s, error: %s", insert.Name, err) 516 } 517 518 err = user.Login(insert.Pass, -1) 519 if err != nil { 520 t.Error("Failed to login in user: ", err) 521 } 522 523 } 524 525 func testInsertAndGetAffiliation(ta TestAccessor, t *testing.T) { 526 ta.Truncate() 527 528 err := ta.Accessor.InsertAffiliation("Bank1", "Banks", 0) 529 if err != nil { 530 t.Errorf("Error occured during insert query of group: %s, error: %s", "Bank1", err) 531 } 532 533 group, err := ta.Accessor.GetAffiliation("Bank1") 534 if err != nil { 535 t.Errorf("Error occured during querying of name: %s, error: %s", "Bank1", err) 536 } 537 538 if group.GetName() != "Bank1" { 539 t.Error("Failed to query") 540 } 541 542 } 543 544 func testDeleteAffiliation(ta TestAccessor, t *testing.T) { 545 ta.Truncate() 546 547 err := ta.Accessor.InsertAffiliation("Banks.Bank2", "Banks", 0) 548 if err != nil { 549 t.Errorf("Error occured during insert query of group: %s, error: %s", "Bank2", err) 550 } 551 552 _, err = ta.Accessor.DeleteAffiliation("Banks.Bank2", true, true, true) 553 if err != nil { 554 t.Errorf("Error occured during deletion of group: %s, error: %s", "Bank2", err) 555 } 556 557 _, err = ta.Accessor.GetAffiliation("Banks.Bank2") 558 if err == nil { 559 t.Error("Should have errored, and not returned any results") 560 } 561 } 562 563 func TestDBErrorMessages(t *testing.T) { 564 var err error 565 566 cleanTestSlateSQ(t) 567 defer cleanTestSlateSQ(t) 568 569 if _, err = os.Stat(dbPath); err != nil { 570 if os.IsNotExist(err) { 571 os.MkdirAll(dbPath, 0755) 572 } 573 } else { 574 err = os.RemoveAll(dbPath) 575 if err != nil { 576 t.Errorf("RemoveAll failed: %s", err) 577 } 578 os.MkdirAll(dbPath, 0755) 579 } 580 581 dataSource := dbPath + "/fabric-ca.db" 582 sqlitedb, err := getSqliteDb(dataSource) 583 if err != nil { 584 t.Error("Failed to open connection to DB") 585 } 586 accessor := NewDBAccessor(sqlitedb) 587 588 ta := TestAccessor{ 589 Accessor: accessor, 590 DB: sqlitedb, 591 } 592 593 expectedErr := "Failed to get %s" 594 _, err = ta.Accessor.GetAffiliation("hyperledger") 595 if assert.Error(t, err, "Should have errored, and not returned any results") { 596 assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "affiliation")) 597 } 598 599 _, err = ta.Accessor.GetUser("testuser", []string{}) 600 if assert.Error(t, err, "Should have errored, and not returned any results") { 601 assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "User")) 602 } 603 604 newCertDBAcc := NewCertDBAccessor(sqlitedb, 0) 605 _, err = newCertDBAcc.GetCertificateWithID("serial", "aki") 606 if assert.Error(t, err, "Should have errored, and not returned any results") { 607 assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "Certificate")) 608 } 609 } 610 611 func getSqliteDb(datasource string) (*db.DB, error) { 612 sqliteDB := sqlite.NewDB(datasource, "", nil) 613 err := sqliteDB.Connect() 614 if err != nil { 615 return nil, err 616 } 617 testdb, err := sqliteDB.Create() 618 if err != nil { 619 return nil, err 620 } 621 return testdb, nil 622 }