aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/auth_credentials.go
diff options
context:
space:
mode:
authorKonstantin Lebedev <9497591+kmlebedev@users.noreply.github.com>2023-09-25 20:34:12 +0500
committerGitHub <noreply@github.com>2023-09-25 08:34:12 -0700
commitf8b94cac0e91660ff4dc33bb458e973b4de6523b (patch)
tree46226e5a964b65546ac299b4ad2e8cb5b7b81d0b /weed/s3api/auth_credentials.go
parentc9177c92e5b6459d15d112738b7a3862655a853f (diff)
downloadseaweedfs-f8b94cac0e91660ff4dc33bb458e973b4de6523b.tar.xz
seaweedfs-f8b94cac0e91660ff4dc33bb458e973b4de6523b.zip
[s3acl] Step1: move s3account.AccountManager into to iam.S3ApiConfiguration (#4859)
* move s3account.AccountManager into to iam.S3ApiConfiguration and switch to Interface https://github.com/seaweedfs/seaweedfs/issues/4519 * fix: test bucket acl default and adjust the variable names * fix: s3 api config test --------- Co-authored-by: Konstantin Lebedev <9497591+kmlebedev@users.noreply.github.co> Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>
Diffstat (limited to 'weed/s3api/auth_credentials.go')
-rw-r--r--weed/s3api/auth_credentials.go137
1 files changed, 118 insertions, 19 deletions
diff --git a/weed/s3api/auth_credentials.go b/weed/s3api/auth_credentials.go
index 38ff2b5ca..a2b1fd90f 100644
--- a/weed/s3api/auth_credentials.go
+++ b/weed/s3api/auth_credentials.go
@@ -7,8 +7,6 @@ import (
"strings"
"sync"
- "github.com/seaweedfs/seaweedfs/weed/s3api/s3account"
-
"github.com/seaweedfs/seaweedfs/weed/filer"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb"
@@ -29,6 +27,8 @@ type IdentityAccessManagement struct {
identities []*Identity
accessKeyIdent map[string]*Identity
+ accounts map[string]*Account
+ emailAccount map[string]*Account
hashes map[string]*sync.Pool
hashCounters map[string]*int32
identityAnonymous *Identity
@@ -39,20 +39,50 @@ type IdentityAccessManagement struct {
type Identity struct {
Name string
- AccountId string
+ Account *Account
Credentials []*Credential
Actions []Action
}
-func (i *Identity) isAnonymous() bool {
- return i.Name == s3account.AccountAnonymous.Name
+// Account represents a system user, a system user can
+// configure multiple IAM-Users, IAM-Users can configure
+// permissions respectively, and each IAM-User can
+// configure multiple security credentials
+type Account struct {
+ //Name is also used to display the "DisplayName" as the owner of the bucket or object
+ DisplayName string
+ EmailAddress string
+
+ //Id is used to identify an Account when granting cross-account access(ACLs) to buckets and objects
+ Id string
}
+// Predefined Accounts
+var (
+ // AccountAdmin is used as the default account for IAM-Credentials access without Account configured
+ AccountAdmin = Account{
+ DisplayName: "admin",
+ EmailAddress: "admin@example.com",
+ Id: s3_constants.AccountAdminId,
+ }
+
+ // AccountAnonymous is used to represent the account for anonymous access
+ AccountAnonymous = Account{
+ DisplayName: "anonymous",
+ EmailAddress: "anonymous@example.com",
+ Id: s3_constants.AccountAnonymousId,
+ }
+)
+
type Credential struct {
AccessKey string
SecretKey string
}
+func (i *Identity) isAnonymous() bool {
+ return i.Account.Id == s3_constants.AccountAnonymousId
+}
+
func (action Action) isAdmin() bool {
return strings.HasPrefix(string(action), s3_constants.ACTION_ADMIN)
}
@@ -65,14 +95,19 @@ func (action Action) overBucket(bucket string) bool {
return strings.HasSuffix(string(action), ":"+bucket) || strings.HasSuffix(string(action), ":*")
}
+// "Permission": "FULL_CONTROL"|"WRITE"|"WRITE_ACP"|"READ"|"READ_ACP"
func (action Action) getPermission() Permission {
switch act := strings.Split(string(action), ":")[0]; act {
case s3_constants.ACTION_ADMIN:
return Permission("FULL_CONTROL")
case s3_constants.ACTION_WRITE:
return Permission("WRITE")
+ case s3_constants.ACTION_WRITE_ACP:
+ return Permission("WRITE_ACP")
case s3_constants.ACTION_READ:
return Permission("READ")
+ case s3_constants.ACTION_READ_ACP:
+ return Permission("READ_ACP")
default:
return Permission("")
}
@@ -138,26 +173,69 @@ func (iam *IdentityAccessManagement) loadS3ApiConfiguration(config *iam_pb.S3Api
var identities []*Identity
var identityAnonymous *Identity
accessKeyIdent := make(map[string]*Identity)
+ accounts := make(map[string]*Account)
+ emailAccount := make(map[string]*Account)
+ foundAccountAdmin := false
+ foundAccountAnonymous := false
+
+ for _, account := range config.Accounts {
+ switch account.Id {
+ case AccountAdmin.Id:
+ AccountAdmin = Account{
+ Id: account.Id,
+ DisplayName: account.DisplayName,
+ EmailAddress: account.EmailAddress,
+ }
+ accounts[account.Id] = &AccountAdmin
+ foundAccountAdmin = true
+ case AccountAnonymous.Id:
+ AccountAnonymous = Account{
+ Id: account.Id,
+ DisplayName: account.DisplayName,
+ EmailAddress: account.EmailAddress,
+ }
+ accounts[account.Id] = &AccountAnonymous
+ foundAccountAnonymous = true
+ default:
+ t := Account{
+ Id: account.Id,
+ DisplayName: account.DisplayName,
+ EmailAddress: account.EmailAddress,
+ }
+ accounts[account.Id] = &t
+ }
+ if account.EmailAddress != "" {
+ emailAccount[account.EmailAddress] = accounts[account.Id]
+ }
+ }
+ if !foundAccountAdmin {
+ accounts[AccountAdmin.Id] = &AccountAdmin
+ emailAccount[AccountAdmin.EmailAddress] = &AccountAdmin
+ }
+ if !foundAccountAnonymous {
+ accounts[AccountAnonymous.Id] = &AccountAnonymous
+ emailAccount[AccountAnonymous.EmailAddress] = &AccountAnonymous
+ }
for _, ident := range config.Identities {
t := &Identity{
Name: ident.Name,
- AccountId: s3account.AccountAdmin.Id,
Credentials: nil,
Actions: nil,
}
-
- if ident.Name == s3account.AccountAnonymous.Name {
- if ident.AccountId != "" && ident.AccountId != s3account.AccountAnonymous.Id {
- glog.Warningf("anonymous identity is associated with a non-anonymous account ID, the association is invalid")
- }
- t.AccountId = s3account.AccountAnonymous.Id
+ switch {
+ case ident.Name == AccountAnonymous.Id:
+ t.Account = &AccountAnonymous
identityAnonymous = t
- } else {
- if len(ident.AccountId) > 0 {
- t.AccountId = ident.AccountId
+ case ident.Account == nil:
+ t.Account = &AccountAdmin
+ default:
+ if account, ok := accounts[ident.Account.Id]; ok {
+ t.Account = account
+ } else {
+ t.Account = &AccountAdmin
+ glog.Warningf("identity %s is associated with a non exist account ID, the association is invalid", ident.Name)
}
}
-
for _, action := range ident.Actions {
t.Actions = append(t.Actions, Action(action))
}
@@ -170,15 +248,19 @@ func (iam *IdentityAccessManagement) loadS3ApiConfiguration(config *iam_pb.S3Api
}
identities = append(identities, t)
}
+
iam.m.Lock()
// atomically switch
iam.identities = identities
iam.identityAnonymous = identityAnonymous
+ iam.accounts = accounts
+ iam.emailAccount = emailAccount
iam.accessKeyIdent = accessKeyIdent
if !iam.isAuthEnabled { // one-directional, no toggling
iam.isAuthEnabled = len(identities) > 0
}
iam.m.Unlock()
+
return nil
}
@@ -209,6 +291,24 @@ func (iam *IdentityAccessManagement) lookupAnonymous() (identity *Identity, foun
return nil, false
}
+func (iam *IdentityAccessManagement) GetAccountNameById(canonicalId string) string {
+ iam.m.RLock()
+ defer iam.m.RUnlock()
+ if account, ok := iam.accounts[canonicalId]; ok {
+ return account.DisplayName
+ }
+ return ""
+}
+
+func (iam *IdentityAccessManagement) GetAccountIdByEmail(email string) string {
+ iam.m.RLock()
+ defer iam.m.RUnlock()
+ if account, ok := iam.emailAccount[email]; ok {
+ return account.Id
+ }
+ return ""
+}
+
func (iam *IdentityAccessManagement) Auth(f http.HandlerFunc, action Action) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !iam.isEnabled() {
@@ -287,9 +387,8 @@ func (iam *IdentityAccessManagement) authRequest(r *http.Request, action Action)
return identity, s3err.ErrAccessDenied
}
- if !identity.isAnonymous() {
- r.Header.Set(s3_constants.AmzAccountId, identity.AccountId)
- }
+ r.Header.Set(s3_constants.AmzAccountId, identity.Account.Id)
+
return identity, s3err.ErrNone
}