2020-11-26 00:02:31 +08:00
|
|
|
package shell
|
|
|
|
|
|
|
|
import (
|
2020-12-07 15:16:20 +08:00
|
|
|
"bytes"
|
2020-11-26 00:02:31 +08:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
|
2022-07-29 15:17:28 +08:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/filer"
|
2022-07-13 17:28:20 +08:00
|
|
|
|
2022-07-29 15:17:28 +08:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
|
2020-11-26 00:02:31 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
Commands = append(Commands, &commandS3Configure{})
|
|
|
|
}
|
|
|
|
|
|
|
|
type commandS3Configure struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *commandS3Configure) Name() string {
|
|
|
|
return "s3.configure"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *commandS3Configure) Help() string {
|
2021-01-14 14:21:34 +08:00
|
|
|
return `configure and apply s3 options for each bucket
|
2020-12-07 10:56:58 +08:00
|
|
|
|
2020-11-26 00:02:31 +08:00
|
|
|
# see the current configuration file content
|
|
|
|
s3.configure
|
|
|
|
`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *commandS3Configure) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
|
2020-12-07 15:16:20 +08:00
|
|
|
|
2020-11-26 00:02:31 +08:00
|
|
|
s3ConfigureCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
2020-12-07 13:54:55 +08:00
|
|
|
actions := s3ConfigureCommand.String("actions", "", "comma separated actions names: Read,Write,List,Tagging,Admin")
|
2020-11-26 00:02:31 +08:00
|
|
|
user := s3ConfigureCommand.String("user", "", "user name")
|
|
|
|
buckets := s3ConfigureCommand.String("buckets", "", "bucket name")
|
|
|
|
accessKey := s3ConfigureCommand.String("access_key", "", "specify the access key")
|
|
|
|
secretKey := s3ConfigureCommand.String("secret_key", "", "specify the secret key")
|
|
|
|
isDelete := s3ConfigureCommand.Bool("delete", false, "delete users, actions or access keys")
|
|
|
|
apply := s3ConfigureCommand.Bool("apply", false, "update and apply s3 configuration")
|
|
|
|
if err = s3ConfigureCommand.Parse(args); err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-07 15:16:20 +08:00
|
|
|
var buf bytes.Buffer
|
2021-12-26 16:15:03 +08:00
|
|
|
if err = commandEnv.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
|
2022-09-15 01:11:31 +08:00
|
|
|
return filer.ReadEntry(commandEnv.MasterClient, client, filer.IamConfigDirectory, filer.IamIdentityFile, &buf)
|
2020-12-07 15:16:20 +08:00
|
|
|
}); err != nil && err != filer_pb.ErrNotFound {
|
2020-11-26 00:02:31 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-12-07 15:16:20 +08:00
|
|
|
s3cfg := &iam_pb.S3ApiConfiguration{}
|
|
|
|
if buf.Len() > 0 {
|
|
|
|
if err = filer.ParseS3ConfigurationFromBytes(buf.Bytes(), s3cfg); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 00:02:31 +08:00
|
|
|
idx := 0
|
|
|
|
changed := false
|
2020-11-26 06:50:53 +08:00
|
|
|
if *user != "" {
|
2020-11-26 04:30:11 +08:00
|
|
|
for i, identity := range s3cfg.Identities {
|
2020-11-26 00:02:31 +08:00
|
|
|
if *user == identity.Name {
|
|
|
|
idx = i
|
|
|
|
changed = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-26 04:30:11 +08:00
|
|
|
var cmdActions []string
|
2020-11-26 06:50:53 +08:00
|
|
|
for _, action := range strings.Split(*actions, ",") {
|
|
|
|
if *buckets == "" {
|
|
|
|
cmdActions = append(cmdActions, action)
|
|
|
|
} else {
|
|
|
|
for _, bucket := range strings.Split(*buckets, ",") {
|
|
|
|
cmdActions = append(cmdActions, fmt.Sprintf("%s:%s", action, bucket))
|
|
|
|
}
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if changed {
|
2022-06-01 05:48:46 +08:00
|
|
|
infoAboutSimulationMode(writer, *apply, "-apply")
|
2020-11-26 00:02:31 +08:00
|
|
|
if *isDelete {
|
2020-11-26 04:30:11 +08:00
|
|
|
var exists []int
|
2020-11-26 00:02:31 +08:00
|
|
|
for _, cmdAction := range cmdActions {
|
2020-11-26 04:30:11 +08:00
|
|
|
for i, currentAction := range s3cfg.Identities[idx].Actions {
|
2020-11-26 00:02:31 +08:00
|
|
|
if cmdAction == currentAction {
|
|
|
|
exists = append(exists, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(sort.IntSlice(exists)))
|
|
|
|
for _, i := range exists {
|
2020-11-26 04:30:11 +08:00
|
|
|
s3cfg.Identities[idx].Actions = append(
|
|
|
|
s3cfg.Identities[idx].Actions[:i],
|
|
|
|
s3cfg.Identities[idx].Actions[i+1:]...,
|
|
|
|
)
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
|
|
|
if *accessKey != "" {
|
|
|
|
exists = []int{}
|
2020-11-26 04:30:11 +08:00
|
|
|
for i, credential := range s3cfg.Identities[idx].Credentials {
|
2020-11-26 00:02:31 +08:00
|
|
|
if credential.AccessKey == *accessKey {
|
|
|
|
exists = append(exists, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(sort.IntSlice(exists)))
|
|
|
|
for _, i := range exists {
|
2020-11-26 04:30:11 +08:00
|
|
|
s3cfg.Identities[idx].Credentials = append(
|
|
|
|
s3cfg.Identities[idx].Credentials[:i],
|
|
|
|
s3cfg.Identities[idx].Credentials[:i+1]...,
|
|
|
|
)
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2020-11-26 06:50:53 +08:00
|
|
|
if *actions == "" && *accessKey == "" && *buckets == "" {
|
2020-11-26 04:30:11 +08:00
|
|
|
s3cfg.Identities = append(s3cfg.Identities[:idx], s3cfg.Identities[idx+1:]...)
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
|
|
|
} else {
|
2020-11-26 06:50:53 +08:00
|
|
|
if *actions != "" {
|
|
|
|
for _, cmdAction := range cmdActions {
|
|
|
|
found := false
|
|
|
|
for _, action := range s3cfg.Identities[idx].Actions {
|
|
|
|
if cmdAction == action {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
s3cfg.Identities[idx].Actions = append(s3cfg.Identities[idx].Actions, cmdAction)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if *accessKey != "" && *user != "anonymous" {
|
|
|
|
found := false
|
|
|
|
for _, credential := range s3cfg.Identities[idx].Credentials {
|
|
|
|
if credential.AccessKey == *accessKey {
|
|
|
|
found = true
|
|
|
|
credential.SecretKey = *secretKey
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
s3cfg.Identities[idx].Credentials = append(s3cfg.Identities[idx].Credentials, &iam_pb.Credential{
|
|
|
|
AccessKey: *accessKey,
|
|
|
|
SecretKey: *secretKey,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
2020-11-26 06:50:53 +08:00
|
|
|
} else if *user != "" && *actions != "" {
|
2022-06-01 05:48:46 +08:00
|
|
|
infoAboutSimulationMode(writer, *apply, "-apply")
|
2020-11-26 04:30:11 +08:00
|
|
|
identity := iam_pb.Identity{
|
2020-11-26 06:50:53 +08:00
|
|
|
Name: *user,
|
|
|
|
Actions: cmdActions,
|
|
|
|
Credentials: []*iam_pb.Credential{},
|
|
|
|
}
|
|
|
|
if *user != "anonymous" {
|
|
|
|
identity.Credentials = append(identity.Credentials,
|
|
|
|
&iam_pb.Credential{AccessKey: *accessKey, SecretKey: *secretKey})
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
2020-11-26 04:30:11 +08:00
|
|
|
s3cfg.Identities = append(s3cfg.Identities, &identity)
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
|
|
|
|
2022-07-13 17:28:20 +08:00
|
|
|
if err = filer.CheckDuplicateAccessKey(s3cfg); err != nil {
|
|
|
|
return err
|
2022-07-13 11:36:11 +08:00
|
|
|
}
|
|
|
|
|
2020-12-07 15:16:20 +08:00
|
|
|
buf.Reset()
|
2021-07-09 18:19:21 +08:00
|
|
|
filer.ProtoToText(&buf, s3cfg)
|
2020-11-26 06:50:53 +08:00
|
|
|
|
2020-12-07 15:16:20 +08:00
|
|
|
fmt.Fprintf(writer, string(buf.Bytes()))
|
2020-11-26 00:02:31 +08:00
|
|
|
fmt.Fprintln(writer)
|
|
|
|
|
2020-11-26 04:30:11 +08:00
|
|
|
if *apply {
|
2020-12-07 15:16:20 +08:00
|
|
|
|
2021-12-26 16:15:03 +08:00
|
|
|
if err := commandEnv.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
|
2022-09-15 01:11:31 +08:00
|
|
|
return filer.SaveInsideFiler(client, filer.IamConfigDirectory, filer.IamIdentityFile, buf.Bytes())
|
2020-12-10 16:15:22 +08:00
|
|
|
}); err != nil {
|
2020-11-26 00:02:31 +08:00
|
|
|
return err
|
|
|
|
}
|
2020-12-07 15:16:20 +08:00
|
|
|
|
2020-11-26 00:02:31 +08:00
|
|
|
}
|
2020-11-26 04:30:11 +08:00
|
|
|
|
2020-11-26 00:02:31 +08:00
|
|
|
return nil
|
|
|
|
}
|