memory_identity.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. package memory
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/seaweedfs/seaweedfs/weed/credential"
  7. "github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
  8. )
  9. func (store *MemoryStore) LoadConfiguration(ctx context.Context) (*iam_pb.S3ApiConfiguration, error) {
  10. store.mu.RLock()
  11. defer store.mu.RUnlock()
  12. if !store.initialized {
  13. return nil, fmt.Errorf("store not initialized")
  14. }
  15. config := &iam_pb.S3ApiConfiguration{}
  16. // Convert all users to identities
  17. for _, user := range store.users {
  18. // Deep copy the identity to avoid mutation issues
  19. identityCopy := store.deepCopyIdentity(user)
  20. config.Identities = append(config.Identities, identityCopy)
  21. }
  22. return config, nil
  23. }
  24. func (store *MemoryStore) SaveConfiguration(ctx context.Context, config *iam_pb.S3ApiConfiguration) error {
  25. store.mu.Lock()
  26. defer store.mu.Unlock()
  27. if !store.initialized {
  28. return fmt.Errorf("store not initialized")
  29. }
  30. // Clear existing data
  31. store.users = make(map[string]*iam_pb.Identity)
  32. store.accessKeys = make(map[string]string)
  33. // Add all identities
  34. for _, identity := range config.Identities {
  35. // Deep copy to avoid mutation issues
  36. identityCopy := store.deepCopyIdentity(identity)
  37. store.users[identity.Name] = identityCopy
  38. // Index access keys
  39. for _, credential := range identity.Credentials {
  40. store.accessKeys[credential.AccessKey] = identity.Name
  41. }
  42. }
  43. return nil
  44. }
  45. func (store *MemoryStore) CreateUser(ctx context.Context, identity *iam_pb.Identity) error {
  46. store.mu.Lock()
  47. defer store.mu.Unlock()
  48. if !store.initialized {
  49. return fmt.Errorf("store not initialized")
  50. }
  51. if _, exists := store.users[identity.Name]; exists {
  52. return credential.ErrUserAlreadyExists
  53. }
  54. // Check for duplicate access keys
  55. for _, cred := range identity.Credentials {
  56. if _, exists := store.accessKeys[cred.AccessKey]; exists {
  57. return fmt.Errorf("access key %s already exists", cred.AccessKey)
  58. }
  59. }
  60. // Deep copy to avoid mutation issues
  61. identityCopy := store.deepCopyIdentity(identity)
  62. store.users[identity.Name] = identityCopy
  63. // Index access keys
  64. for _, cred := range identity.Credentials {
  65. store.accessKeys[cred.AccessKey] = identity.Name
  66. }
  67. return nil
  68. }
  69. func (store *MemoryStore) GetUser(ctx context.Context, username string) (*iam_pb.Identity, error) {
  70. store.mu.RLock()
  71. defer store.mu.RUnlock()
  72. if !store.initialized {
  73. return nil, fmt.Errorf("store not initialized")
  74. }
  75. user, exists := store.users[username]
  76. if !exists {
  77. return nil, credential.ErrUserNotFound
  78. }
  79. // Return a deep copy to avoid mutation issues
  80. return store.deepCopyIdentity(user), nil
  81. }
  82. func (store *MemoryStore) UpdateUser(ctx context.Context, username string, identity *iam_pb.Identity) error {
  83. store.mu.Lock()
  84. defer store.mu.Unlock()
  85. if !store.initialized {
  86. return fmt.Errorf("store not initialized")
  87. }
  88. existingUser, exists := store.users[username]
  89. if !exists {
  90. return credential.ErrUserNotFound
  91. }
  92. // Remove old access keys from index
  93. for _, cred := range existingUser.Credentials {
  94. delete(store.accessKeys, cred.AccessKey)
  95. }
  96. // Check for duplicate access keys (excluding current user)
  97. for _, cred := range identity.Credentials {
  98. if existingUsername, exists := store.accessKeys[cred.AccessKey]; exists && existingUsername != username {
  99. return fmt.Errorf("access key %s already exists", cred.AccessKey)
  100. }
  101. }
  102. // Deep copy to avoid mutation issues
  103. identityCopy := store.deepCopyIdentity(identity)
  104. store.users[username] = identityCopy
  105. // Re-index access keys
  106. for _, cred := range identity.Credentials {
  107. store.accessKeys[cred.AccessKey] = username
  108. }
  109. return nil
  110. }
  111. func (store *MemoryStore) DeleteUser(ctx context.Context, username string) error {
  112. store.mu.Lock()
  113. defer store.mu.Unlock()
  114. if !store.initialized {
  115. return fmt.Errorf("store not initialized")
  116. }
  117. user, exists := store.users[username]
  118. if !exists {
  119. return credential.ErrUserNotFound
  120. }
  121. // Remove access keys from index
  122. for _, cred := range user.Credentials {
  123. delete(store.accessKeys, cred.AccessKey)
  124. }
  125. // Remove user
  126. delete(store.users, username)
  127. return nil
  128. }
  129. func (store *MemoryStore) ListUsers(ctx context.Context) ([]string, error) {
  130. store.mu.RLock()
  131. defer store.mu.RUnlock()
  132. if !store.initialized {
  133. return nil, fmt.Errorf("store not initialized")
  134. }
  135. var usernames []string
  136. for username := range store.users {
  137. usernames = append(usernames, username)
  138. }
  139. return usernames, nil
  140. }
  141. func (store *MemoryStore) GetUserByAccessKey(ctx context.Context, accessKey string) (*iam_pb.Identity, error) {
  142. store.mu.RLock()
  143. defer store.mu.RUnlock()
  144. if !store.initialized {
  145. return nil, fmt.Errorf("store not initialized")
  146. }
  147. username, exists := store.accessKeys[accessKey]
  148. if !exists {
  149. return nil, credential.ErrAccessKeyNotFound
  150. }
  151. user, exists := store.users[username]
  152. if !exists {
  153. // This should not happen, but handle it gracefully
  154. return nil, credential.ErrUserNotFound
  155. }
  156. // Return a deep copy to avoid mutation issues
  157. return store.deepCopyIdentity(user), nil
  158. }
  159. func (store *MemoryStore) CreateAccessKey(ctx context.Context, username string, cred *iam_pb.Credential) error {
  160. store.mu.Lock()
  161. defer store.mu.Unlock()
  162. if !store.initialized {
  163. return fmt.Errorf("store not initialized")
  164. }
  165. user, exists := store.users[username]
  166. if !exists {
  167. return credential.ErrUserNotFound
  168. }
  169. // Check if access key already exists
  170. if _, exists := store.accessKeys[cred.AccessKey]; exists {
  171. return fmt.Errorf("access key %s already exists", cred.AccessKey)
  172. }
  173. // Add credential to user
  174. user.Credentials = append(user.Credentials, &iam_pb.Credential{
  175. AccessKey: cred.AccessKey,
  176. SecretKey: cred.SecretKey,
  177. })
  178. // Index the access key
  179. store.accessKeys[cred.AccessKey] = username
  180. return nil
  181. }
  182. func (store *MemoryStore) DeleteAccessKey(ctx context.Context, username string, accessKey string) error {
  183. store.mu.Lock()
  184. defer store.mu.Unlock()
  185. if !store.initialized {
  186. return fmt.Errorf("store not initialized")
  187. }
  188. user, exists := store.users[username]
  189. if !exists {
  190. return credential.ErrUserNotFound
  191. }
  192. // Find and remove the credential
  193. var newCredentials []*iam_pb.Credential
  194. found := false
  195. for _, cred := range user.Credentials {
  196. if cred.AccessKey == accessKey {
  197. found = true
  198. // Remove from access key index
  199. delete(store.accessKeys, accessKey)
  200. } else {
  201. newCredentials = append(newCredentials, cred)
  202. }
  203. }
  204. if !found {
  205. return credential.ErrAccessKeyNotFound
  206. }
  207. user.Credentials = newCredentials
  208. return nil
  209. }
  210. // deepCopyIdentity creates a deep copy of an identity to avoid mutation issues
  211. func (store *MemoryStore) deepCopyIdentity(identity *iam_pb.Identity) *iam_pb.Identity {
  212. if identity == nil {
  213. return nil
  214. }
  215. // Use JSON marshaling/unmarshaling for deep copy
  216. // This is simple and safe for protobuf messages
  217. data, err := json.Marshal(identity)
  218. if err != nil {
  219. // Fallback to shallow copy if JSON fails
  220. return &iam_pb.Identity{
  221. Name: identity.Name,
  222. Account: identity.Account,
  223. Credentials: identity.Credentials,
  224. Actions: identity.Actions,
  225. }
  226. }
  227. var copy iam_pb.Identity
  228. if err := json.Unmarshal(data, &copy); err != nil {
  229. // Fallback to shallow copy if JSON fails
  230. return &iam_pb.Identity{
  231. Name: identity.Name,
  232. Account: identity.Account,
  233. Credentials: identity.Credentials,
  234. Actions: identity.Actions,
  235. }
  236. }
  237. return &copy
  238. }