You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
5.4 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package shell
  2. import (
  3. "bytes"
  4. "errors"
  5. "flag"
  6. "fmt"
  7. "github.com/chrislusf/seaweedfs/weed/filer"
  8. "io"
  9. "sort"
  10. "strings"
  11. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  12. "github.com/chrislusf/seaweedfs/weed/pb/iam_pb"
  13. )
  14. func init() {
  15. Commands = append(Commands, &commandS3Configure{})
  16. }
  17. type commandS3Configure struct {
  18. }
  19. func (c *commandS3Configure) Name() string {
  20. return "s3.configure"
  21. }
  22. func (c *commandS3Configure) Help() string {
  23. return `configure and apply s3 options for each bucket
  24. # see the current configuration file content
  25. s3.configure
  26. `
  27. }
  28. func (c *commandS3Configure) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
  29. s3ConfigureCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  30. actions := s3ConfigureCommand.String("actions", "", "comma separated actions names: Read,Write,List,Tagging,Admin")
  31. user := s3ConfigureCommand.String("user", "", "user name")
  32. buckets := s3ConfigureCommand.String("buckets", "", "bucket name")
  33. accessKey := s3ConfigureCommand.String("access_key", "", "specify the access key")
  34. secretKey := s3ConfigureCommand.String("secret_key", "", "specify the secret key")
  35. isDelete := s3ConfigureCommand.Bool("delete", false, "delete users, actions or access keys")
  36. apply := s3ConfigureCommand.Bool("apply", false, "update and apply s3 configuration")
  37. if err = s3ConfigureCommand.Parse(args); err != nil {
  38. return nil
  39. }
  40. var buf bytes.Buffer
  41. if err = commandEnv.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
  42. return filer.ReadEntry(commandEnv.MasterClient, client, filer.IamConfigDirecotry, filer.IamIdentityFile, &buf)
  43. }); err != nil && err != filer_pb.ErrNotFound {
  44. return err
  45. }
  46. s3cfg := &iam_pb.S3ApiConfiguration{}
  47. if buf.Len() > 0 {
  48. if err = filer.ParseS3ConfigurationFromBytes(buf.Bytes(), s3cfg); err != nil {
  49. return err
  50. }
  51. }
  52. idx := 0
  53. changed := false
  54. if *user != "" {
  55. for i, identity := range s3cfg.Identities {
  56. if *user == identity.Name {
  57. idx = i
  58. changed = true
  59. break
  60. }
  61. }
  62. }
  63. var cmdActions []string
  64. for _, action := range strings.Split(*actions, ",") {
  65. if *buckets == "" {
  66. cmdActions = append(cmdActions, action)
  67. } else {
  68. for _, bucket := range strings.Split(*buckets, ",") {
  69. cmdActions = append(cmdActions, fmt.Sprintf("%s:%s", action, bucket))
  70. }
  71. }
  72. }
  73. if changed {
  74. infoAboutSimulationMode(writer, *apply, "-apply")
  75. if *isDelete {
  76. var exists []int
  77. for _, cmdAction := range cmdActions {
  78. for i, currentAction := range s3cfg.Identities[idx].Actions {
  79. if cmdAction == currentAction {
  80. exists = append(exists, i)
  81. }
  82. }
  83. }
  84. sort.Sort(sort.Reverse(sort.IntSlice(exists)))
  85. for _, i := range exists {
  86. s3cfg.Identities[idx].Actions = append(
  87. s3cfg.Identities[idx].Actions[:i],
  88. s3cfg.Identities[idx].Actions[i+1:]...,
  89. )
  90. }
  91. if *accessKey != "" {
  92. exists = []int{}
  93. for i, credential := range s3cfg.Identities[idx].Credentials {
  94. if credential.AccessKey == *accessKey {
  95. exists = append(exists, i)
  96. }
  97. }
  98. sort.Sort(sort.Reverse(sort.IntSlice(exists)))
  99. for _, i := range exists {
  100. s3cfg.Identities[idx].Credentials = append(
  101. s3cfg.Identities[idx].Credentials[:i],
  102. s3cfg.Identities[idx].Credentials[:i+1]...,
  103. )
  104. }
  105. }
  106. if *actions == "" && *accessKey == "" && *buckets == "" {
  107. s3cfg.Identities = append(s3cfg.Identities[:idx], s3cfg.Identities[idx+1:]...)
  108. }
  109. } else {
  110. if *actions != "" {
  111. for _, cmdAction := range cmdActions {
  112. found := false
  113. for _, action := range s3cfg.Identities[idx].Actions {
  114. if cmdAction == action {
  115. found = true
  116. break
  117. }
  118. }
  119. if !found {
  120. s3cfg.Identities[idx].Actions = append(s3cfg.Identities[idx].Actions, cmdAction)
  121. }
  122. }
  123. }
  124. if *accessKey != "" && *user != "anonymous" {
  125. found := false
  126. for _, credential := range s3cfg.Identities[idx].Credentials {
  127. if credential.AccessKey == *accessKey {
  128. found = true
  129. credential.SecretKey = *secretKey
  130. break
  131. }
  132. }
  133. if !found {
  134. s3cfg.Identities[idx].Credentials = append(s3cfg.Identities[idx].Credentials, &iam_pb.Credential{
  135. AccessKey: *accessKey,
  136. SecretKey: *secretKey,
  137. })
  138. }
  139. }
  140. }
  141. } else if *user != "" && *actions != "" {
  142. infoAboutSimulationMode(writer, *apply, "-apply")
  143. identity := iam_pb.Identity{
  144. Name: *user,
  145. Actions: cmdActions,
  146. Credentials: []*iam_pb.Credential{},
  147. }
  148. if *user != "anonymous" {
  149. identity.Credentials = append(identity.Credentials,
  150. &iam_pb.Credential{AccessKey: *accessKey, SecretKey: *secretKey})
  151. }
  152. s3cfg.Identities = append(s3cfg.Identities, &identity)
  153. }
  154. accessKeySet := make(map[string]string)
  155. for _, ident := range s3cfg.Identities {
  156. for _, cred := range ident.Credentials {
  157. if userName, found := accessKeySet[cred.AccessKey]; !found {
  158. accessKeySet[cred.AccessKey] = ident.Name
  159. } else {
  160. return errors.New(fmt.Sprintf("duplicate accessKey[%s], already configured in user[%s]", cred.AccessKey, userName))
  161. }
  162. }
  163. }
  164. buf.Reset()
  165. filer.ProtoToText(&buf, s3cfg)
  166. fmt.Fprintf(writer, string(buf.Bytes()))
  167. fmt.Fprintln(writer)
  168. if *apply {
  169. if err := commandEnv.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
  170. return filer.SaveInsideFiler(client, filer.IamConfigDirecotry, filer.IamIdentityFile, buf.Bytes())
  171. }); err != nil {
  172. return err
  173. }
  174. }
  175. return nil
  176. }