added s3 iam DeleteBucket permission management (#5599)

This commit is contained in:
Riccardo Bertossa
2024-05-17 13:54:09 +02:00
committed by GitHub
parent 54f3913bed
commit f6e8a9bf9c
7 changed files with 41 additions and 14 deletions

View File

@@ -33,6 +33,7 @@ const (
StatementActionReadAcp = "GetBucketAcl" StatementActionReadAcp = "GetBucketAcl"
StatementActionList = "List*" StatementActionList = "List*"
StatementActionTagging = "Tagging*" StatementActionTagging = "Tagging*"
StatementActionDelete = "DeleteBucket*"
) )
var ( var (
@@ -58,6 +59,8 @@ func MapToStatementAction(action string) string {
return s3_constants.ACTION_LIST return s3_constants.ACTION_LIST
case StatementActionTagging: case StatementActionTagging:
return s3_constants.ACTION_TAGGING return s3_constants.ACTION_TAGGING
case StatementActionDelete:
return s3_constants.ACTION_DELETE_BUCKET
default: default:
return "" return ""
} }
@@ -79,6 +82,8 @@ func MapToIdentitiesAction(action string) string {
return StatementActionList return StatementActionList
case s3_constants.ACTION_TAGGING: case s3_constants.ACTION_TAGGING:
return StatementActionTagging return StatementActionTagging
case s3_constants.ACTION_DELETE_BUCKET:
return StatementActionDelete
default: default:
return "" return ""
} }

View File

@@ -317,6 +317,7 @@ func (iam *IdentityAccessManagement) Auth(f http.HandlerFunc, action Action) htt
} }
identity, errCode := iam.authRequest(r, action) identity, errCode := iam.authRequest(r, action)
glog.V(3).Infof("auth error: %v", errCode)
if errCode == s3err.ErrNone { if errCode == s3err.ErrNone {
if identity != nil && identity.Name != "" { if identity != nil && identity.Name != "" {
r.Header.Set(s3_constants.AmzIdentityId, identity.Name) r.Header.Set(s3_constants.AmzIdentityId, identity.Name)
@@ -453,6 +454,7 @@ func (identity *Identity) canDo(action Action, bucket string, objectKey string)
} }
} }
if bucket == "" { if bucket == "" {
glog.V(3).Infof("identity %s is not allowed to perform action %s on %s -- bucket is empty", identity.Name, action, bucket+objectKey)
return false return false
} }
target := string(action) + ":" + bucket + objectKey target := string(action) + ":" + bucket + objectKey
@@ -477,6 +479,8 @@ func (identity *Identity) canDo(action Action, bucket string, objectKey string)
} }
} }
} }
//log error
glog.V(3).Infof("identity %s is not allowed to perform action %s on %s", identity.Name, action, bucket+objectKey)
return false return false
} }

View File

@@ -1,11 +1,12 @@
package s3api package s3api
import ( import (
. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/stretchr/testify/assert"
"reflect" "reflect"
"testing" "testing"
. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/stretchr/testify/assert"
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb" "github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
jsonpb "google.golang.org/protobuf/encoding/protojson" jsonpb "google.golang.org/protobuf/encoding/protojson"
) )
@@ -79,6 +80,7 @@ func TestCanDo(t *testing.T) {
} }
// object specific // object specific
assert.Equal(t, true, ident1.canDo(ACTION_WRITE, "bucket1", "/a/b/c/d.txt")) assert.Equal(t, true, ident1.canDo(ACTION_WRITE, "bucket1", "/a/b/c/d.txt"))
assert.Equal(t, false, ident1.canDo(ACTION_DELETE_BUCKET, "bucket1", ""))
assert.Equal(t, false, ident1.canDo(ACTION_WRITE, "bucket1", "/a/b/other/some"), "action without *") assert.Equal(t, false, ident1.canDo(ACTION_WRITE, "bucket1", "/a/b/other/some"), "action without *")
// bucket specific // bucket specific
@@ -141,6 +143,15 @@ func TestCanDo(t *testing.T) {
}, },
} }
assert.Equal(t, true, ident6.canDo(ACTION_READ, "anything_bucket", "/a/b/c/d.txt")) assert.Equal(t, true, ident6.canDo(ACTION_READ, "anything_bucket", "/a/b/c/d.txt"))
//test deleteBucket operation
ident7 := &Identity{
Name: "anything",
Actions: []Action{
"DeleteBucket:bucket1",
},
}
assert.Equal(t, true, ident7.canDo(ACTION_DELETE_BUCKET, "bucket1", ""))
} }
type LoadS3ApiConfigurationTestCase struct { type LoadS3ApiConfigurationTestCase struct {

View File

@@ -1,13 +1,14 @@
package s3_constants package s3_constants
const ( const (
ACTION_READ = "Read" ACTION_READ = "Read"
ACTION_READ_ACP = "ReadAcp" ACTION_READ_ACP = "ReadAcp"
ACTION_WRITE = "Write" ACTION_WRITE = "Write"
ACTION_WRITE_ACP = "WriteAcp" ACTION_WRITE_ACP = "WriteAcp"
ACTION_ADMIN = "Admin" ACTION_ADMIN = "Admin"
ACTION_TAGGING = "Tagging" ACTION_TAGGING = "Tagging"
ACTION_LIST = "List" ACTION_LIST = "List"
ACTION_DELETE_BUCKET = "DeleteBucket"
SeaweedStorageDestinationHeader = "x-seaweedfs-destination" SeaweedStorageDestinationHeader = "x-seaweedfs-destination"
MultipartUploadsFolder = ".uploads" MultipartUploadsFolder = ".uploads"

View File

@@ -7,7 +7,7 @@ import (
var ( var (
CircuitBreakerConfigDir = "/etc/s3" CircuitBreakerConfigDir = "/etc/s3"
CircuitBreakerConfigFile = "circuit_breaker.json" CircuitBreakerConfigFile = "circuit_breaker.json"
AllowedActions = []string{ACTION_READ, ACTION_READ_ACP, ACTION_WRITE, ACTION_WRITE_ACP, ACTION_LIST, ACTION_TAGGING, ACTION_ADMIN} AllowedActions = []string{ACTION_READ, ACTION_READ_ACP, ACTION_WRITE, ACTION_WRITE_ACP, ACTION_LIST, ACTION_TAGGING, ACTION_ADMIN, ACTION_DELETE_BUCKET}
LimitTypeCount = "Count" LimitTypeCount = "Count"
LimitTypeBytes = "MB" LimitTypeBytes = "MB"
Separator = ":" Separator = ":"

View File

@@ -6,14 +6,15 @@ import (
"encoding/xml" "encoding/xml"
"errors" "errors"
"fmt" "fmt"
"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3bucket"
"github.com/seaweedfs/seaweedfs/weed/util"
"math" "math"
"net/http" "net/http"
"strings" "strings"
"time" "time"
"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3bucket"
"github.com/seaweedfs/seaweedfs/weed/util"
"github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/filer"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/storage/needle" "github.com/seaweedfs/seaweedfs/weed/storage/needle"
@@ -218,6 +219,10 @@ func (s3a *S3ApiServer) checkBucket(r *http.Request, bucket string) s3err.ErrorC
return s3err.ErrNoSuchBucket return s3err.ErrNoSuchBucket
} }
//if iam is enabled, the access was already checked before
if s3a.iam.isEnabled() {
return s3err.ErrNone
}
if !s3a.hasAccess(r, entry) { if !s3a.hasAccess(r, entry) {
return s3err.ErrAccessDenied return s3err.ErrAccessDenied
} }
@@ -236,6 +241,7 @@ func (s3a *S3ApiServer) hasAccess(r *http.Request, entry *filer_pb.Entry) bool {
identityId := r.Header.Get(s3_constants.AmzIdentityId) identityId := r.Header.Get(s3_constants.AmzIdentityId)
if id, ok := entry.Extended[s3_constants.AmzIdentityId]; ok { if id, ok := entry.Extended[s3_constants.AmzIdentityId]; ok {
if identityId != string(id) { if identityId != string(id) {
glog.V(3).Infof("hasAccess: %s != %s (entry.Extended = %v)", identityId, id, entry.Extended)
return false return false
} }
} }

View File

@@ -279,7 +279,7 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) {
bucket.Methods("PUT").HandlerFunc(track(s3a.iam.Auth(s3a.cb.Limit(s3a.PutBucketHandler, ACTION_ADMIN)), "PUT")) bucket.Methods("PUT").HandlerFunc(track(s3a.iam.Auth(s3a.cb.Limit(s3a.PutBucketHandler, ACTION_ADMIN)), "PUT"))
// DeleteBucket // DeleteBucket
bucket.Methods("DELETE").HandlerFunc(track(s3a.iam.Auth(s3a.cb.Limit(s3a.DeleteBucketHandler, ACTION_ADMIN)), "DELETE")) bucket.Methods("DELETE").HandlerFunc(track(s3a.iam.Auth(s3a.cb.Limit(s3a.DeleteBucketHandler, ACTION_DELETE_BUCKET)), "DELETE"))
// ListObjectsV1 (Legacy) // ListObjectsV1 (Legacy)
bucket.Methods("GET").HandlerFunc(track(s3a.iam.Auth(s3a.cb.Limit(s3a.ListObjectsV1Handler, ACTION_LIST)), "LIST")) bucket.Methods("GET").HandlerFunc(track(s3a.iam.Auth(s3a.cb.Limit(s3a.ListObjectsV1Handler, ACTION_LIST)), "LIST"))