mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-25 22:40:44 +01:00
s3: keep dynamic IAM live when -iam.config is set (#9817)
* s3: keep dynamic IAM live when -iam.config is set -iam.config was treated like a static -config identity file: it set useStaticConfig, which makes the filer metadata subscription skip reloads. Identities and policies created at runtime (the IAM gRPC API) then never took effect, so advanced IAM (OIDC/STS) and dynamic IAM were mutually exclusive. Gate useStaticConfig on whether inline identities were actually loaded. An OIDC/STS-only config carries none, so it keeps the dynamic credential store live; a -config identity file still freezes its identities as before. * s3: mark static identities on config reload too A -config reload (grace.OnReload) re-reads the file, but only the startup path marked its identities static, so identities added to the file and reloaded were left unprotected from dynamic filer updates. Move the marking into loadS3ApiConfigurationFromFile and make it additive and scoped to the file's identities, so a reload protects newly added ones without freezing dynamic filer-managed identities. * s3: sync reloaded static identities into the credential manager After marking a (re)loaded config file's identities static, push the updated set into the credential manager so reloaded identities still appear in listings and survive later dynamic merges. Centralize the sync in loadS3ApiConfigurationFromFile and drop the now-redundant call in the reload hook.
This commit is contained in:
1 parent
ce6a51468a
commit
3e8ec879c4
3 files changed
+170
-17
No files matched your search
@@ -267,17 +267,6 @@ func NewIdentityAccessManagementWithStore(option *S3ApiServerOption, filerClient
|
||||
if err := iam.loadS3ApiConfigurationFromFile(startConfigFile); err != nil {
|
||||
glog.Fatalf("fail to load config file %s: %v", startConfigFile, err)
|
||||
}
|
||||
|
||||
// Track identity names from static config to protect them from dynamic updates
|
||||
// Must be done under lock to avoid race conditions
|
||||
iam.m.Lock()
|
||||
iam.useStaticConfig = true
|
||||
iam.staticIdentityNames = make(map[string]bool)
|
||||
for _, identity := range iam.identities {
|
||||
iam.staticIdentityNames[identity.Name] = true
|
||||
identity.IsStatic = true
|
||||
}
|
||||
iam.m.Unlock()
|
||||
}
|
||||
|
||||
// Always try to load/merge config from credential manager (filer/db)
|
||||
@@ -332,6 +321,30 @@ func NewIdentityAccessManagementWithStore(option *S3ApiServerOption, filerClient
|
||||
return iam
|
||||
}
|
||||
|
||||
// markStaticIdentities marks the identities declared in a static config file
|
||||
// (-config, or -iam.config when it carries inline identities) as immutable, so
|
||||
// dynamic filer reloads can't overwrite them. It is additive and scoped to the
|
||||
// file's identities: a reload protects newly added ones without un-protecting
|
||||
// the existing set or freezing dynamic filer-managed identities. useStaticConfig
|
||||
// stays gated on whether any static identity exists, so an advanced-IAM file
|
||||
// with no inline identities (OIDC/STS only) keeps the dynamic store live.
|
||||
func (iam *IdentityAccessManagement) markStaticIdentities(config *iam_pb.S3ApiConfiguration) {
|
||||
iam.m.Lock()
|
||||
defer iam.m.Unlock()
|
||||
if iam.staticIdentityNames == nil {
|
||||
iam.staticIdentityNames = make(map[string]bool)
|
||||
}
|
||||
for _, ident := range config.Identities {
|
||||
iam.staticIdentityNames[ident.Name] = true
|
||||
}
|
||||
for _, identity := range iam.identities {
|
||||
if iam.staticIdentityNames[identity.Name] {
|
||||
identity.IsStatic = true
|
||||
}
|
||||
}
|
||||
iam.useStaticConfig = len(iam.staticIdentityNames) > 0
|
||||
}
|
||||
|
||||
func (iam *IdentityAccessManagement) pollIamConfigChanges(interval time.Duration) {
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
@@ -477,24 +490,40 @@ func (iam *IdentityAccessManagement) loadS3ApiConfigurationFromFile(fileName str
|
||||
glog.Warningf("KMS initialization failed: %v", err)
|
||||
}
|
||||
|
||||
return iam.LoadS3ApiConfigurationFromBytes(content)
|
||||
config, err := iam.loadS3ApiConfigurationFromBytes(content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Identities listed in a config file are static (immutable). Mark them on
|
||||
// every load so a reload protects newly added identities too, not just the
|
||||
// set present at startup, and push the updated set into the credential
|
||||
// manager so reloaded identities still show up in listings and survive
|
||||
// later dynamic merges.
|
||||
iam.markStaticIdentities(config)
|
||||
iam.updateCredentialManagerStaticIdentities()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (iam *IdentityAccessManagement) LoadS3ApiConfigurationFromBytes(content []byte) error {
|
||||
_, err := iam.loadS3ApiConfigurationFromBytes(content)
|
||||
return err
|
||||
}
|
||||
|
||||
func (iam *IdentityAccessManagement) loadS3ApiConfigurationFromBytes(content []byte) (*iam_pb.S3ApiConfiguration, error) {
|
||||
s3ApiConfiguration := &iam_pb.S3ApiConfiguration{}
|
||||
if err := filer.ParseS3ConfigurationFromBytes(content, s3ApiConfiguration); err != nil {
|
||||
glog.Warningf("unmarshal error: %v", err)
|
||||
return fmt.Errorf("unmarshal error: %w", err)
|
||||
return nil, fmt.Errorf("unmarshal error: %w", err)
|
||||
}
|
||||
|
||||
if err := filer.CheckDuplicateAccessKey(s3ApiConfiguration); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := iam.loadS3ApiConfiguration(s3ApiConfiguration); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return s3ApiConfiguration, nil
|
||||
}
|
||||
|
||||
func (iam *IdentityAccessManagement) loadS3ApiConfiguration(config *iam_pb.S3ApiConfiguration) error {
|
||||
|
||||
Reference in new issue
Block a user