github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/lib/dasqlite_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package lib_test 18 19 import ( 20 "fmt" 21 "os" 22 "strings" 23 "testing" 24 25 "github.com/hyperledger/fabric-ca/api" 26 . "github.com/hyperledger/fabric-ca/lib" 27 "github.com/hyperledger/fabric-ca/lib/dbutil" 28 "github.com/hyperledger/fabric-ca/lib/spi" 29 "github.com/jmoiron/sqlx" 30 _ "github.com/mattn/go-sqlite3" 31 "github.com/stretchr/testify/assert" 32 ) 33 34 const ( 35 dbPath = "/tmp/dbtesting" 36 37 sqliteTruncateTables = ` 38 DELETE FROM Users; 39 DELETE FROM affiliations; 40 ` 41 42 rootDB = "rootDir/fabric_ca.db" 43 ) 44 45 type TestAccessor struct { 46 Accessor *Accessor 47 DB *sqlx.DB 48 } 49 50 func (ta *TestAccessor) Truncate() { 51 Truncate(ta.DB) 52 } 53 54 func TestSQLite(t *testing.T) { 55 cleanTestSlateSQ(t) 56 defer cleanTestSlateSQ(t) 57 58 if _, err := os.Stat(dbPath); err != nil { 59 if os.IsNotExist(err) { 60 os.MkdirAll(dbPath, 0755) 61 } 62 } else { 63 err = os.RemoveAll(dbPath) 64 if err != nil { 65 t.Errorf("RemoveAll failed: %s", err) 66 } 67 os.MkdirAll(dbPath, 0755) 68 } 69 dataSource := dbPath + "/fabric-ca.db" 70 db, err := dbutil.NewUserRegistrySQLLite3(dataSource) 71 if err != nil { 72 t.Error("Failed to open connection to DB") 73 } 74 accessor := NewDBAccessor(db) 75 76 ta := TestAccessor{ 77 Accessor: accessor, 78 DB: db, 79 } 80 testEverything(ta, t) 81 } 82 83 // Truncate truncates the DB 84 func Truncate(db *sqlx.DB) { 85 var sql []string 86 sql = []string{sqliteTruncateTables} 87 88 for _, expr := range sql { 89 if len(strings.TrimSpace(expr)) == 0 { 90 continue 91 } 92 if _, err := db.Exec(expr); err != nil { 93 panic(err) 94 } 95 } 96 } 97 98 func TestEmptyAccessor(t *testing.T) { 99 a := &Accessor{} 100 ui := spi.UserInfo{} 101 err := a.InsertUser(nil) 102 if err == nil { 103 t.Error("Passing in nil should have resulted in an error") 104 } 105 106 err = a.InsertUser(&ui) 107 if err == nil { 108 t.Error("Empty Accessor InsertUser should have failed") 109 } 110 } 111 112 func TestDBCreation(t *testing.T) { 113 cleanTestSlateSQ(t) 114 defer cleanTestSlateSQ(t) 115 116 os.Mkdir(rootDir, 0755) 117 118 testWithExistingDbAndTablesAndUser(t) 119 testWithExistingDbAndTable(t) 120 testWithExistingDb(t) 121 } 122 123 func createSQLiteDB(path string, t *testing.T) (*sqlx.DB, *TestAccessor) { 124 db, err := sqlx.Open("sqlite3", path) 125 assert.NoError(t, err, "Failed to open SQLite database") 126 127 accessor := NewDBAccessor(db) 128 129 ta := &TestAccessor{ 130 Accessor: accessor, 131 DB: db, 132 } 133 134 return db, ta 135 } 136 137 // Test that an already bootstrapped database properly get inspected and bootstrapped with any new identities on the 138 // next server start 139 func testWithExistingDbAndTablesAndUser(t *testing.T) { 140 var err error 141 142 err = os.RemoveAll(rootDB) 143 if err != nil { 144 t.Errorf("RemoveAll failed: %s", err) 145 } 146 db, acc := createSQLiteDB(rootDB, t) 147 148 _, 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)") 149 assert.NoError(t, err, "Error creating users table") 150 151 srv := TestGetServer2(false, rootPort, rootDir, "", -1, t) 152 srv.CA.Config.DB.Datasource = "fabric_ca.db" 153 154 err = srv.Start() 155 assert.NoError(t, err, "Failed to start server") 156 157 err = srv.Stop() 158 assert.NoError(t, err, "Failed to stop server") 159 160 // Add additional user to registry and start server and confirm that it correctly get added 161 srv.RegisterBootstrapUser("admin2", "admin2pw", "") 162 163 err = srv.Start() 164 assert.NoError(t, err, "Failed to start server") 165 166 _, err = acc.Accessor.GetUser("admin2", nil) 167 assert.NoError(t, err, "Failed to correctly insert 'admin2' during second server bootstrap") 168 169 err = srv.Stop() 170 assert.NoError(t, err, "Failed to stop server") 171 172 err = db.Close() 173 assert.NoError(t, err, "Failed to close DB") 174 } 175 176 // Test starting a server with an already existing database and tables, but not bootstrapped 177 func testWithExistingDbAndTable(t *testing.T) { 178 var err error 179 180 err = os.RemoveAll(rootDB) 181 if err != nil { 182 t.Errorf("RemoveAll failed: %s", err) 183 } 184 db, acc := createSQLiteDB(rootDB, t) 185 186 srv := TestGetServer2(false, rootPort, rootDir, "", -1, t) 187 srv.CA.Config.DB.Datasource = "fabric_ca.db" 188 189 _, 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)") 190 assert.NoError(t, err, "Error creating users table") 191 192 err = srv.Start() 193 assert.NoError(t, err, "Failed to start server") 194 195 _, err = acc.Accessor.GetUser("admin", nil) 196 assert.NoError(t, err, "Failed to correctly insert 'admin' during second server bootstrap") 197 198 err = srv.Stop() 199 assert.NoError(t, err, "Failed to stop server") 200 201 err = db.Close() 202 assert.NoError(t, err, "Failed to close DB") 203 } 204 205 // Test starting a server with an already existing database, but no tables or users 206 func testWithExistingDb(t *testing.T) { 207 var err error 208 209 err = os.RemoveAll(rootDB) 210 if err != nil { 211 t.Errorf("RemoveAll failed: %s", err) 212 } 213 db, acc := createSQLiteDB(rootDB, t) 214 215 srv := TestGetServer2(false, rootPort, rootDir, "", -1, t) 216 srv.CA.Config.DB.Datasource = "fabric_ca.db" 217 218 err = srv.Start() 219 assert.NoError(t, err, "Failed to start server") 220 221 _, err = acc.Accessor.GetUser("admin", nil) 222 assert.NoError(t, err, "Failed to correctly insert 'admin' during second server bootstrap") 223 224 err = srv.Stop() 225 assert.NoError(t, err, "Failed to stop server") 226 227 err = db.Close() 228 assert.NoError(t, err, "Failed to close DB") 229 } 230 231 func cleanTestSlateSQ(t *testing.T) { 232 err := os.RemoveAll(rootDir) 233 if err != nil { 234 t.Errorf("RemoveAll failed: %s", err) 235 } 236 err = os.RemoveAll(dbPath) 237 if err != nil { 238 t.Errorf("RemoveAll failed: %s", err) 239 } 240 } 241 242 func testEverything(ta TestAccessor, t *testing.T) { 243 testInsertAndGetUser(ta, t) 244 testModifyAttribute(ta, t) 245 testDeleteUser(ta, t) 246 testUpdateUser(ta, t) 247 testInsertAndGetAffiliation(ta, t) 248 testDeleteAffiliation(ta, t) 249 } 250 251 func testInsertAndGetUser(ta TestAccessor, t *testing.T) { 252 t.Log("TestInsertAndGetUser") 253 ta.Truncate() 254 255 insert := spi.UserInfo{ 256 Name: "testId", 257 Pass: "123456", 258 Type: "client", 259 Attributes: []api.Attribute{ 260 api.Attribute{ 261 Name: "hf.Registrar.Roles", 262 Value: "peer,client,orderer,user", 263 }, 264 api.Attribute{ 265 Name: "hf.Revoker", 266 Value: "false", 267 }, 268 api.Attribute{ 269 Name: "hf.Registrar.Attributes", 270 Value: "*", 271 }, 272 api.Attribute{ 273 Name: "xyz", 274 Value: "xyz", 275 }, 276 }, 277 } 278 279 err := ta.Accessor.InsertUser(&insert) 280 if err != nil { 281 t.Errorf("Error occured during insert query of ID: %s, error: %s", insert.Name, err) 282 } 283 284 user, err := ta.Accessor.GetUser(insert.Name, nil) 285 if err != nil { 286 t.Errorf("Error occured during querying of id: %s, error: %s", insert.Name, err) 287 } 288 289 if user.GetName() != insert.Name { 290 t.Error("Incorrect ID retrieved") 291 } 292 } 293 294 func testModifyAttribute(ta TestAccessor, t *testing.T) { 295 296 user, err := ta.Accessor.GetUser("testId", nil) 297 assert.NoError(t, err, "Failed to get user") 298 299 err = user.ModifyAttributes([]api.Attribute{ 300 api.Attribute{ 301 Name: "hf.Registrar.Roles", 302 Value: "peer", 303 }, 304 api.Attribute{ 305 Name: "hf.Revoker", 306 Value: "", 307 }, 308 api.Attribute{ 309 Name: "xyz", 310 Value: "", 311 }, 312 api.Attribute{ 313 Name: "hf.IntermediateCA", 314 Value: "true", 315 }, 316 }) 317 assert.NoError(t, err, "Failed to modify user's attributes") 318 319 user, err = ta.Accessor.GetUser("testId", nil) 320 assert.NoError(t, err, "Failed to get user") 321 322 _, err = user.GetAttribute("hf.Revoker") 323 assert.Error(t, err, "Should have returned an error, attribute should have been deleted") 324 325 // Removes last attribute in the slice, should have correctly removed it 326 _, err = user.GetAttribute("xyz") 327 assert.Error(t, err, "Should have returned an error, attribute should have been deleted") 328 329 attr, err := user.GetAttribute("hf.IntermediateCA") 330 assert.NoError(t, err, "Failed to add attribute") 331 assert.Equal(t, "true", attr.Value, "Incorrect value for attribute 'hf.IntermediateCA") 332 333 attr, err = user.GetAttribute("hf.Registrar.Roles") 334 assert.NoError(t, err, "Failed to get attribute") 335 assert.Equal(t, "peer", attr.Value, "Incorrect value for attribute 'hf.Registrar.Roles") 336 337 // Test to make sure that any existing attributes that were not modified continue to exist in there original state 338 attr, err = user.GetAttribute("hf.Registrar.Attributes") 339 assert.NoError(t, err, "Failed to get attribute") 340 assert.Equal(t, "*", attr.Value) 341 } 342 343 func testDeleteUser(ta TestAccessor, t *testing.T) { 344 t.Log("TestDeleteUser") 345 ta.Truncate() 346 347 insert := spi.UserInfo{ 348 Name: "testId", 349 Pass: "123456", 350 Type: "client", 351 Attributes: []api.Attribute{}, 352 } 353 354 err := ta.Accessor.InsertUser(&insert) 355 if err != nil { 356 t.Errorf("Error occured during insert query of id: %s, error: %s", insert.Name, err) 357 } 358 359 _, err = ta.Accessor.DeleteUser(insert.Name) 360 if err != nil { 361 t.Errorf("Error occured during deletion of ID: %s, error: %s", insert.Name, err) 362 } 363 364 _, err = ta.Accessor.GetUser(insert.Name, nil) 365 if err == nil { 366 t.Error("Should have errored, and not returned any results") 367 } 368 } 369 370 func testUpdateUser(ta TestAccessor, t *testing.T) { 371 t.Log("TestUpdateUser") 372 ta.Truncate() 373 374 insert := spi.UserInfo{ 375 Name: "testId", 376 Pass: "123456", 377 Type: "client", 378 Attributes: []api.Attribute{}, 379 MaxEnrollments: 1, 380 } 381 382 err := ta.Accessor.InsertUser(&insert) 383 if err != nil { 384 t.Errorf("Error occured during insert query of ID: %s, error: %s", insert.Name, err) 385 } 386 387 insert.Pass = "654321" 388 389 err = ta.Accessor.UpdateUser(nil, true) 390 if err == nil { 391 t.Error("Passing in nil should have resulted in an error") 392 } 393 394 err = ta.Accessor.UpdateUser(&insert, true) 395 if err != nil { 396 t.Errorf("Error occured during update query of ID: %s, error: %s", insert.Name, err) 397 } 398 399 user, err := ta.Accessor.GetUser(insert.Name, nil) 400 if err != nil { 401 t.Errorf("Error occured during querying of ID: %s, error: %s", insert.Name, err) 402 } 403 404 err = user.Login(insert.Pass, -1) 405 if err != nil { 406 t.Error("Failed to login in user: ", err) 407 } 408 409 } 410 411 func testInsertAndGetAffiliation(ta TestAccessor, t *testing.T) { 412 ta.Truncate() 413 414 err := ta.Accessor.InsertAffiliation("Bank1", "Banks", 0) 415 if err != nil { 416 t.Errorf("Error occured during insert query of group: %s, error: %s", "Bank1", err) 417 } 418 419 group, err := ta.Accessor.GetAffiliation("Bank1") 420 if err != nil { 421 t.Errorf("Error occured during querying of name: %s, error: %s", "Bank1", err) 422 } 423 424 if group.GetName() != "Bank1" { 425 t.Error("Failed to query") 426 } 427 428 } 429 430 func testDeleteAffiliation(ta TestAccessor, t *testing.T) { 431 ta.Truncate() 432 433 err := ta.Accessor.InsertAffiliation("Banks.Bank2", "Banks", 0) 434 if err != nil { 435 t.Errorf("Error occured during insert query of group: %s, error: %s", "Bank2", err) 436 } 437 438 _, err = ta.Accessor.DeleteAffiliation("Banks.Bank2", true, true, true) 439 if err != nil { 440 t.Errorf("Error occured during deletion of group: %s, error: %s", "Bank2", err) 441 } 442 443 _, err = ta.Accessor.GetAffiliation("Banks.Bank2") 444 if err == nil { 445 t.Error("Should have errored, and not returned any results") 446 } 447 } 448 449 func TestDBErrorMessages(t *testing.T) { 450 var err error 451 452 cleanTestSlateSQ(t) 453 defer cleanTestSlateSQ(t) 454 455 if _, err = os.Stat(dbPath); err != nil { 456 if os.IsNotExist(err) { 457 os.MkdirAll(dbPath, 0755) 458 } 459 } else { 460 err = os.RemoveAll(dbPath) 461 if err != nil { 462 t.Errorf("RemoveAll failed: %s", err) 463 } 464 os.MkdirAll(dbPath, 0755) 465 } 466 467 dataSource := dbPath + "/fabric-ca.db" 468 db, err := dbutil.NewUserRegistrySQLLite3(dataSource) 469 if err != nil { 470 t.Error("Failed to open connection to DB") 471 } 472 473 accessor := NewDBAccessor(db) 474 475 ta := TestAccessor{ 476 Accessor: accessor, 477 DB: db, 478 } 479 480 expectedErr := "Failed to get %s" 481 _, err = ta.Accessor.GetAffiliation("hyperledger") 482 if assert.Error(t, err, "Should have errored, and not returned any results") { 483 assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "Affiliation")) 484 } 485 486 _, err = ta.Accessor.GetUser("testuser", []string{}) 487 if assert.Error(t, err, "Should have errored, and not returned any results") { 488 assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "User")) 489 } 490 491 newCertDBAcc := NewCertDBAccessor(db, 0) 492 _, err = newCertDBAcc.GetCertificateWithID("serial", "aki") 493 if assert.Error(t, err, "Should have errored, and not returned any results") { 494 assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "Certificate")) 495 } 496 }