aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/auth_credentials.go
diff options
context:
space:
mode:
authorchrislu <chris.lu@gmail.com>2025-12-14 16:31:06 -0800
committerchrislu <chris.lu@gmail.com>2025-12-14 17:43:57 -0800
commite03b2ee8bbeb6e23bf46bcc26cb72ada615a24c2 (patch)
tree2688ad5cb600bbeef7f760184cfa5044711930a6 /weed/s3api/auth_credentials.go
parent8bdc4390a04604af79f91c7dce94e3b2b58442f7 (diff)
downloadseaweedfs-origin/feature/iam-user-status-management-7745.tar.xz
seaweedfs-origin/feature/iam-user-status-management-7745.zip
feat(iam): add SetUserStatus and UpdateAccessKey actions (#7745)origin/feature/iam-user-status-management-7745
Add ability to enable/disable users and access keys without deleting them. ## Changes ### Protocol Buffer Updates - Add `disabled` field (bool) to Identity message for user status - false (default) = enabled, true = disabled - No backward compatibility hack needed since zero value is correct - Add `status` field (string: Active/Inactive) to Credential message ### New IAM Actions - SetUserStatus: Enable or disable a user (requires admin) - UpdateAccessKey: Change access key status (self-service or admin) ### Behavior - Disabled users: All API requests return AccessDenied - Inactive access keys: Signature validation fails - Status check happens early in auth flow for performance - Backward compatible: existing configs default to enabled (disabled=false) ### Use Cases 1. Temporary suspension: Disable user access during investigation 2. Key rotation: Deactivate old key before deletion 3. Offboarding: Disable rather than delete for audit purposes 4. Emergency response: Quickly disable compromised credentials Fixes #7745
Diffstat (limited to 'weed/s3api/auth_credentials.go')
-rw-r--r--weed/s3api/auth_credentials.go17
1 files changed, 16 insertions, 1 deletions
diff --git a/weed/s3api/auth_credentials.go b/weed/s3api/auth_credentials.go
index c81fb3a88..5acd711cd 100644
--- a/weed/s3api/auth_credentials.go
+++ b/weed/s3api/auth_credentials.go
@@ -66,6 +66,7 @@ type Identity struct {
Credentials []*Credential
Actions []Action
PrincipalArn string // ARN for IAM authorization (e.g., "arn:aws:iam::account-id:user/username")
+ Disabled bool // User status: false = enabled (default), true = disabled
}
// Account represents a system user, a system user can
@@ -101,6 +102,7 @@ var (
type Credential struct {
AccessKey string
SecretKey string
+ Status string // Access key status: "Active" or "Inactive" (empty treated as "Active")
}
// "Permission": "FULL_CONTROL"|"WRITE"|"WRITE_ACP"|"READ"|"READ_ACP"
@@ -318,12 +320,13 @@ func (iam *IdentityAccessManagement) loadS3ApiConfiguration(config *iam_pb.S3Api
emailAccount[AccountAnonymous.EmailAddress] = &AccountAnonymous
}
for _, ident := range config.Identities {
- glog.V(3).Infof("loading identity %s", ident.Name)
+ glog.V(3).Infof("loading identity %s (disabled=%v)", ident.Name, ident.Disabled)
t := &Identity{
Name: ident.Name,
Credentials: nil,
Actions: nil,
PrincipalArn: generatePrincipalArn(ident.Name),
+ Disabled: ident.Disabled, // false (default) = enabled, true = disabled
}
switch {
case ident.Name == AccountAnonymous.Id:
@@ -347,6 +350,7 @@ func (iam *IdentityAccessManagement) loadS3ApiConfiguration(config *iam_pb.S3Api
t.Credentials = append(t.Credentials, &Credential{
AccessKey: cred.AccessKey,
SecretKey: cred.SecretKey,
+ Status: cred.Status, // Load access key status
})
accessKeyIdent[cred.AccessKey] = t
}
@@ -405,8 +409,19 @@ func (iam *IdentityAccessManagement) lookupByAccessKey(accessKey string) (identi
truncatedKey, len(accessKey), len(iam.accessKeyIdent))
if ident, ok := iam.accessKeyIdent[accessKey]; ok {
+ // Check if user is disabled
+ if ident.Disabled {
+ glog.V(2).Infof("User %s is disabled, rejecting access key %s", ident.Name, truncatedKey)
+ return nil, nil, false
+ }
+
for _, credential := range ident.Credentials {
if credential.AccessKey == accessKey {
+ // Check if access key is inactive (empty Status treated as Active for backward compatibility)
+ if credential.Status == iamAccessKeyStatusInactive {
+ glog.V(2).Infof("Access key %s for identity %s is inactive", truncatedKey, ident.Name)
+ return nil, nil, false
+ }
glog.V(2).Infof("Found access key %s for identity %s", truncatedKey, ident.Name)
return ident, credential, true
}