added s3 iam DeleteBucket permission management (#5599)
This commit is contained in:
committed by
GitHub
parent
54f3913bed
commit
f6e8a9bf9c
@@ -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 ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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 = ":"
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
Reference in New Issue
Block a user