credential_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. package credential
  2. import (
  3. "context"
  4. "testing"
  5. "github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
  6. "github.com/seaweedfs/seaweedfs/weed/util"
  7. )
  8. func TestCredentialStoreInterface(t *testing.T) {
  9. // Note: This test may fail if run without importing store packages
  10. // For full integration testing, see the test/ package
  11. if len(Stores) == 0 {
  12. t.Skip("No credential stores registered - this is expected when testing the base package without store imports")
  13. }
  14. // Check that expected stores are available
  15. storeNames := GetAvailableStores()
  16. expectedStores := []string{string(StoreTypeFilerEtc), string(StoreTypeMemory)}
  17. // Add PostgreSQL if it's available (build tags dependent)
  18. for _, storeName := range storeNames {
  19. found := false
  20. for _, expected := range append(expectedStores, string(StoreTypePostgres)) {
  21. if string(storeName) == expected {
  22. found = true
  23. break
  24. }
  25. }
  26. if !found {
  27. t.Errorf("Unexpected store found: %s", storeName)
  28. }
  29. }
  30. // Test that filer_etc store is always available
  31. filerEtcStoreFound := false
  32. memoryStoreFound := false
  33. for _, storeName := range storeNames {
  34. if string(storeName) == string(StoreTypeFilerEtc) {
  35. filerEtcStoreFound = true
  36. }
  37. if string(storeName) == string(StoreTypeMemory) {
  38. memoryStoreFound = true
  39. }
  40. }
  41. if !filerEtcStoreFound {
  42. t.Error("FilerEtc store should always be available")
  43. }
  44. if !memoryStoreFound {
  45. t.Error("Memory store should always be available")
  46. }
  47. }
  48. func TestCredentialManagerCreation(t *testing.T) {
  49. config := util.GetViper()
  50. // Test creating credential manager with invalid store
  51. _, err := NewCredentialManager(CredentialStoreTypeName("nonexistent"), config, "test.")
  52. if err == nil {
  53. t.Error("Expected error for nonexistent store")
  54. }
  55. // Skip store-specific tests if no stores are registered
  56. if len(Stores) == 0 {
  57. t.Skip("No credential stores registered - skipping store-specific tests")
  58. }
  59. // Test creating credential manager with available stores
  60. availableStores := GetAvailableStores()
  61. if len(availableStores) == 0 {
  62. t.Skip("No stores available for testing")
  63. }
  64. // Test with the first available store
  65. storeName := availableStores[0]
  66. cm, err := NewCredentialManager(storeName, config, "test.")
  67. if err != nil {
  68. t.Fatalf("Failed to create credential manager with store %s: %v", storeName, err)
  69. }
  70. if cm == nil {
  71. t.Error("Credential manager should not be nil")
  72. }
  73. defer cm.Shutdown()
  74. // Test that the store is of the correct type
  75. if cm.GetStore().GetName() != storeName {
  76. t.Errorf("Expected %s store, got %s", storeName, cm.GetStore().GetName())
  77. }
  78. }
  79. func TestCredentialInterface(t *testing.T) {
  80. // Skip if no stores are registered
  81. if len(Stores) == 0 {
  82. t.Skip("No credential stores registered - for full testing see test/ package")
  83. }
  84. // Test the interface with the first available store
  85. availableStores := GetAvailableStores()
  86. if len(availableStores) == 0 {
  87. t.Skip("No stores available for testing")
  88. }
  89. testCredentialInterfaceWithStore(t, availableStores[0])
  90. }
  91. func testCredentialInterfaceWithStore(t *testing.T, storeName CredentialStoreTypeName) {
  92. // Create a test identity
  93. testIdentity := &iam_pb.Identity{
  94. Name: "testuser",
  95. Actions: []string{"Read", "Write"},
  96. Account: &iam_pb.Account{
  97. Id: "123456789012",
  98. DisplayName: "Test User",
  99. EmailAddress: "test@example.com",
  100. },
  101. Credentials: []*iam_pb.Credential{
  102. {
  103. AccessKey: "AKIAIOSFODNN7EXAMPLE",
  104. SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  105. },
  106. },
  107. }
  108. // Test the interface methods exist (compile-time check)
  109. config := util.GetViper()
  110. cm, err := NewCredentialManager(storeName, config, "test.")
  111. if err != nil {
  112. t.Fatalf("Failed to create credential manager: %v", err)
  113. }
  114. defer cm.Shutdown()
  115. ctx := context.Background()
  116. // Test LoadConfiguration
  117. _, err = cm.LoadConfiguration(ctx)
  118. if err != nil {
  119. t.Fatalf("LoadConfiguration failed: %v", err)
  120. }
  121. // Test CreateUser
  122. err = cm.CreateUser(ctx, testIdentity)
  123. if err != nil {
  124. t.Fatalf("CreateUser failed: %v", err)
  125. }
  126. // Test GetUser
  127. user, err := cm.GetUser(ctx, "testuser")
  128. if err != nil {
  129. t.Fatalf("GetUser failed: %v", err)
  130. }
  131. if user.Name != "testuser" {
  132. t.Errorf("Expected user name 'testuser', got %s", user.Name)
  133. }
  134. // Test ListUsers
  135. users, err := cm.ListUsers(ctx)
  136. if err != nil {
  137. t.Fatalf("ListUsers failed: %v", err)
  138. }
  139. if len(users) != 1 || users[0] != "testuser" {
  140. t.Errorf("Expected ['testuser'], got %v", users)
  141. }
  142. // Test GetUserByAccessKey
  143. userByKey, err := cm.GetUserByAccessKey(ctx, "AKIAIOSFODNN7EXAMPLE")
  144. if err != nil {
  145. t.Fatalf("GetUserByAccessKey failed: %v", err)
  146. }
  147. if userByKey.Name != "testuser" {
  148. t.Errorf("Expected user name 'testuser', got %s", userByKey.Name)
  149. }
  150. }
  151. func TestCredentialManagerIntegration(t *testing.T) {
  152. // Skip if no stores are registered
  153. if len(Stores) == 0 {
  154. t.Skip("No credential stores registered - for full testing see test/ package")
  155. }
  156. // Test with the first available store
  157. availableStores := GetAvailableStores()
  158. if len(availableStores) == 0 {
  159. t.Skip("No stores available for testing")
  160. }
  161. storeName := availableStores[0]
  162. config := util.GetViper()
  163. cm, err := NewCredentialManager(storeName, config, "test.")
  164. if err != nil {
  165. t.Fatalf("Failed to create credential manager: %v", err)
  166. }
  167. defer cm.Shutdown()
  168. ctx := context.Background()
  169. // Test complete workflow
  170. user1 := &iam_pb.Identity{
  171. Name: "user1",
  172. Actions: []string{"Read"},
  173. Account: &iam_pb.Account{
  174. Id: "111111111111",
  175. DisplayName: "User One",
  176. EmailAddress: "user1@example.com",
  177. },
  178. Credentials: []*iam_pb.Credential{
  179. {
  180. AccessKey: "AKIAUSER1",
  181. SecretKey: "secret1",
  182. },
  183. },
  184. }
  185. user2 := &iam_pb.Identity{
  186. Name: "user2",
  187. Actions: []string{"Write"},
  188. Account: &iam_pb.Account{
  189. Id: "222222222222",
  190. DisplayName: "User Two",
  191. EmailAddress: "user2@example.com",
  192. },
  193. Credentials: []*iam_pb.Credential{
  194. {
  195. AccessKey: "AKIAUSER2",
  196. SecretKey: "secret2",
  197. },
  198. },
  199. }
  200. // Create users
  201. err = cm.CreateUser(ctx, user1)
  202. if err != nil {
  203. t.Fatalf("Failed to create user1: %v", err)
  204. }
  205. err = cm.CreateUser(ctx, user2)
  206. if err != nil {
  207. t.Fatalf("Failed to create user2: %v", err)
  208. }
  209. // List users
  210. users, err := cm.ListUsers(ctx)
  211. if err != nil {
  212. t.Fatalf("Failed to list users: %v", err)
  213. }
  214. if len(users) != 2 {
  215. t.Errorf("Expected 2 users, got %d", len(users))
  216. }
  217. // Test access key lookup
  218. foundUser, err := cm.GetUserByAccessKey(ctx, "AKIAUSER1")
  219. if err != nil {
  220. t.Fatalf("Failed to get user by access key: %v", err)
  221. }
  222. if foundUser.Name != "user1" {
  223. t.Errorf("Expected user1, got %s", foundUser.Name)
  224. }
  225. // Delete user
  226. err = cm.DeleteUser(ctx, "user1")
  227. if err != nil {
  228. t.Fatalf("Failed to delete user: %v", err)
  229. }
  230. // Verify user is deleted
  231. _, err = cm.GetUser(ctx, "user1")
  232. if err != ErrUserNotFound {
  233. t.Errorf("Expected ErrUserNotFound, got %v", err)
  234. }
  235. // Clean up
  236. err = cm.DeleteUser(ctx, "user2")
  237. if err != nil {
  238. t.Fatalf("Failed to delete user2: %v", err)
  239. }
  240. }
  241. // TestErrorTypes tests that the custom error types are defined correctly
  242. func TestErrorTypes(t *testing.T) {
  243. // Test that error types are defined
  244. if ErrUserNotFound == nil {
  245. t.Error("ErrUserNotFound should be defined")
  246. }
  247. if ErrUserAlreadyExists == nil {
  248. t.Error("ErrUserAlreadyExists should be defined")
  249. }
  250. if ErrAccessKeyNotFound == nil {
  251. t.Error("ErrAccessKeyNotFound should be defined")
  252. }
  253. // Test error messages
  254. if ErrUserNotFound.Error() != "user not found" {
  255. t.Errorf("Expected 'user not found', got '%s'", ErrUserNotFound.Error())
  256. }
  257. if ErrUserAlreadyExists.Error() != "user already exists" {
  258. t.Errorf("Expected 'user already exists', got '%s'", ErrUserAlreadyExists.Error())
  259. }
  260. if ErrAccessKeyNotFound.Error() != "access key not found" {
  261. t.Errorf("Expected 'access key not found', got '%s'", ErrAccessKeyNotFound.Error())
  262. }
  263. }
  264. // TestGetAvailableStores tests the store discovery function
  265. func TestGetAvailableStores(t *testing.T) {
  266. stores := GetAvailableStores()
  267. if len(stores) == 0 {
  268. t.Skip("No stores available for testing")
  269. }
  270. // Convert to strings for comparison
  271. storeNames := make([]string, len(stores))
  272. for i, store := range stores {
  273. storeNames[i] = string(store)
  274. }
  275. t.Logf("Available stores: %v (count: %d)", storeNames, len(storeNames))
  276. // We expect at least memory and filer_etc stores to be available
  277. expectedStores := []string{string(StoreTypeFilerEtc), string(StoreTypeMemory)}
  278. // Add PostgreSQL if it's available (build tags dependent)
  279. for _, storeName := range storeNames {
  280. found := false
  281. for _, expected := range append(expectedStores, string(StoreTypePostgres)) {
  282. if storeName == expected {
  283. found = true
  284. break
  285. }
  286. }
  287. if !found {
  288. t.Errorf("Unexpected store found: %s", storeName)
  289. }
  290. }
  291. // Test that filer_etc store is always available
  292. filerEtcStoreFound := false
  293. memoryStoreFound := false
  294. for _, storeName := range storeNames {
  295. if storeName == string(StoreTypeFilerEtc) {
  296. filerEtcStoreFound = true
  297. }
  298. if storeName == string(StoreTypeMemory) {
  299. memoryStoreFound = true
  300. }
  301. }
  302. if !filerEtcStoreFound {
  303. t.Error("FilerEtc store should always be available")
  304. }
  305. if !memoryStoreFound {
  306. t.Error("Memory store should always be available")
  307. }
  308. }