shell: address review feedback for s3.iam.*, s3.config.show, s3.user.provision

- Simplify joinMax using strings.Join
- Fix rolePolicies: remove s3:ListBucket from object-level actions
  (already covered by bucket-level statement)
- Fix admin role: grant s3:* on bucket resource too
- Return flag parse errors instead of swallowing them
This commit is contained in:
Chris Lu
2026-04-07 12:24:00 -07:00
parent eee884db35
commit 99cf9fadca
4 changed files with 14 additions and 22 deletions
+4 -16
View File
@@ -1,23 +1,11 @@
package shell
import "strings"
// joinMax joins up to max strings with ", " and appends "..." if truncated.
func joinMax(items []string, max int) string {
if len(items) <= max {
result := ""
for i, s := range items {
if i > 0 {
result += ", "
}
result += s
}
return result
return strings.Join(items, ", ")
}
result := ""
for i := 0; i < max; i++ {
if i > 0 {
result += ", "
}
result += items[i]
}
return result + "..."
return strings.Join(items[:max], ", ") + "..."
}
+1 -1
View File
@@ -44,7 +44,7 @@ func (c *commandS3IAMExport) Do(args []string, commandEnv *CommandEnv, writer io
f := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
file := f.String("file", "", "output file path (stdout if omitted)")
if err := f.Parse(args); err != nil {
return nil
return err
}
return pb.WithGrpcClient(false, 0, func(conn *grpc.ClientConn) error {
+1 -1
View File
@@ -45,7 +45,7 @@ func (c *commandS3IAMImport) Do(args []string, commandEnv *CommandEnv, writer io
f := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
file := f.String("file", "", "input JSON file")
if err := f.Parse(args); err != nil {
return nil
return err
}
if *file == "" {
+8 -4
View File
@@ -48,8 +48,8 @@ func (c *commandS3UserProvision) HasTag(CommandTag) bool {
}
var rolePolicies = map[string][]string{
"readonly": {"s3:GetObject", "s3:ListBucket"},
"readwrite": {"s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket"},
"readonly": {"s3:GetObject"},
"readwrite": {"s3:GetObject", "s3:PutObject", "s3:DeleteObject"},
"admin": {"s3:*"},
}
@@ -59,7 +59,7 @@ func (c *commandS3UserProvision) Do(args []string, commandEnv *CommandEnv, write
bucket := f.String("bucket", "", "bucket name")
role := f.String("role", "", "role: readonly, readwrite, or admin")
if err := f.Parse(args); err != nil {
return nil
return err
}
if *name == "" {
@@ -80,6 +80,10 @@ func (c *commandS3UserProvision) Do(args []string, commandEnv *CommandEnv, write
policyName := fmt.Sprintf("%s-%s-%s", *bucket, *name, *role)
// Build the policy document
bucketActions := []string{"s3:ListBucket"}
if *role == "admin" {
bucketActions = []string{"s3:*"}
}
policyDoc := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
@@ -90,7 +94,7 @@ func (c *commandS3UserProvision) Do(args []string, commandEnv *CommandEnv, write
},
{
"Effect": "Allow",
"Action": []string{"s3:ListBucket"},
"Action": bucketActions,
"Resource": []string{fmt.Sprintf("arn:aws:s3:::%s", *bucket)},
},
},