diff --git a/.github/workflows/s3-iam-tests.yml b/.github/workflows/s3-iam-tests.yml index ecd36cb1f..c1499292d 100644 --- a/.github/workflows/s3-iam-tests.yml +++ b/.github/workflows/s3-iam-tests.yml @@ -164,6 +164,14 @@ jobs: sudo apt-get install -y jq chmod +x setup_keycloak.sh ./setup_keycloak.sh + + # Wait for the test realm to be fully available + echo "Waiting for seaweedfs-test realm to be available..." + timeout 120 bash -c 'until curl -fs http://localhost:8080/realms/seaweedfs-test/.well-known/openid-configuration > /dev/null; do echo "... waiting for realm"; sleep 3; done' || { + echo "❌ seaweedfs-test realm not available" + docker logs keycloak --tail=200 || true + exit 1 + } # Start SeaweedFS services make clean setup start-services wait-for-services @@ -299,6 +307,14 @@ jobs: # Give services extra time to fully initialize sleep 10 + + # Ensure the seaweedfs-test realm is available before running tests + echo "Waiting for seaweedfs-test realm to be available..." + timeout 120 bash -c 'until curl -fs http://localhost:8080/realms/seaweedfs-test/.well-known/openid-configuration > /dev/null; do echo "... waiting for realm"; sleep 3; done' || { + echo "❌ seaweedfs-test realm not available" + docker logs keycloak --tail=200 || true + exit 1 + } # Verify services are accessible echo "=== Verifying Service Accessibility ===" diff --git a/weed/iam/integration/iam_manager.go b/weed/iam/integration/iam_manager.go index b9ec26ceb..e9c9e5a16 100644 --- a/weed/iam/integration/iam_manager.go +++ b/weed/iam/integration/iam_manager.go @@ -139,16 +139,16 @@ func (m *IAMManager) RegisterIdentityProvider(provider providers.IdentityProvide } // CreatePolicy creates a new policy -func (m *IAMManager) CreatePolicy(ctx context.Context, name string, policyDoc *policy.PolicyDocument) error { +func (m *IAMManager) CreatePolicy(ctx context.Context, filerAddress string, name string, policyDoc *policy.PolicyDocument) error { if !m.initialized { return fmt.Errorf("IAM manager not initialized") } - return m.policyEngine.AddPolicy(name, policyDoc) + return m.policyEngine.AddPolicy(filerAddress, name, policyDoc) } // CreateRole creates a new role with trust policy and attached policies -func (m *IAMManager) CreateRole(ctx context.Context, roleName string, roleDef *RoleDefinition) error { +func (m *IAMManager) CreateRole(ctx context.Context, filerAddress string, roleName string, roleDef *RoleDefinition) error { if !m.initialized { return fmt.Errorf("IAM manager not initialized") } @@ -174,7 +174,7 @@ func (m *IAMManager) CreateRole(ctx context.Context, roleName string, roleDef *R } // Store role definition - return m.roleStore.StoreRole(ctx, roleName, roleDef) + return m.roleStore.StoreRole(ctx, "", roleName, roleDef) } // AssumeRoleWithWebIdentity assumes a role using web identity (OIDC) @@ -187,7 +187,7 @@ func (m *IAMManager) AssumeRoleWithWebIdentity(ctx context.Context, request *sts roleName := extractRoleNameFromArn(request.RoleArn) // Get role definition - roleDef, err := m.roleStore.GetRole(ctx, roleName) + roleDef, err := m.roleStore.GetRole(ctx, "", roleName) if err != nil { return nil, fmt.Errorf("role not found: %s", roleName) } @@ -211,7 +211,7 @@ func (m *IAMManager) AssumeRoleWithCredentials(ctx context.Context, request *sts roleName := extractRoleNameFromArn(request.RoleArn) // Get role definition - roleDef, err := m.roleStore.GetRole(ctx, roleName) + roleDef, err := m.roleStore.GetRole(ctx, "", roleName) if err != nil { return nil, fmt.Errorf("role not found: %s", roleName) } @@ -246,7 +246,7 @@ func (m *IAMManager) IsActionAllowed(ctx context.Context, request *ActionRequest } // Get role definition - roleDef, err := m.roleStore.GetRole(ctx, roleName) + roleDef, err := m.roleStore.GetRole(ctx, "", roleName) if err != nil { return false, fmt.Errorf("role not found: %s", roleName) } @@ -260,7 +260,7 @@ func (m *IAMManager) IsActionAllowed(ctx context.Context, request *ActionRequest } // Evaluate policies attached to the role - result, err := m.policyEngine.Evaluate(ctx, evalCtx, roleDef.AttachedPolicies) + result, err := m.policyEngine.Evaluate(ctx, "", evalCtx, roleDef.AttachedPolicies) if err != nil { return false, fmt.Errorf("policy evaluation failed: %w", err) } @@ -271,7 +271,7 @@ func (m *IAMManager) IsActionAllowed(ctx context.Context, request *ActionRequest // ValidateTrustPolicy validates if a principal can assume a role (for testing) func (m *IAMManager) ValidateTrustPolicy(ctx context.Context, roleArn, provider, userID string) bool { roleName := extractRoleNameFromArn(roleArn) - roleDef, err := m.roleStore.GetRole(ctx, roleName) + roleDef, err := m.roleStore.GetRole(ctx, "", roleName) if err != nil { return false } diff --git a/weed/iam/integration/role_store.go b/weed/iam/integration/role_store.go index 1b8ceb3fe..295115be4 100644 --- a/weed/iam/integration/role_store.go +++ b/weed/iam/integration/role_store.go @@ -17,17 +17,17 @@ import ( // RoleStore defines the interface for storing IAM role definitions type RoleStore interface { - // StoreRole stores a role definition - StoreRole(ctx context.Context, roleName string, role *RoleDefinition) error + // StoreRole stores a role definition (filerAddress ignored for memory stores) + StoreRole(ctx context.Context, filerAddress string, roleName string, role *RoleDefinition) error - // GetRole retrieves a role definition - GetRole(ctx context.Context, roleName string) (*RoleDefinition, error) + // GetRole retrieves a role definition (filerAddress ignored for memory stores) + GetRole(ctx context.Context, filerAddress string, roleName string) (*RoleDefinition, error) - // ListRoles lists all role names - ListRoles(ctx context.Context) ([]string, error) + // ListRoles lists all role names (filerAddress ignored for memory stores) + ListRoles(ctx context.Context, filerAddress string) ([]string, error) - // DeleteRole deletes a role definition - DeleteRole(ctx context.Context, roleName string) error + // DeleteRole deletes a role definition (filerAddress ignored for memory stores) + DeleteRole(ctx context.Context, filerAddress string, roleName string) error } // MemoryRoleStore implements RoleStore using in-memory storage @@ -43,8 +43,8 @@ func NewMemoryRoleStore() *MemoryRoleStore { } } -// StoreRole stores a role definition in memory -func (m *MemoryRoleStore) StoreRole(ctx context.Context, roleName string, role *RoleDefinition) error { +// StoreRole stores a role definition in memory (filerAddress ignored for memory store) +func (m *MemoryRoleStore) StoreRole(ctx context.Context, filerAddress string, roleName string, role *RoleDefinition) error { if roleName == "" { return fmt.Errorf("role name cannot be empty") } @@ -60,8 +60,8 @@ func (m *MemoryRoleStore) StoreRole(ctx context.Context, roleName string, role * return nil } -// GetRole retrieves a role definition from memory -func (m *MemoryRoleStore) GetRole(ctx context.Context, roleName string) (*RoleDefinition, error) { +// GetRole retrieves a role definition from memory (filerAddress ignored for memory store) +func (m *MemoryRoleStore) GetRole(ctx context.Context, filerAddress string, roleName string) (*RoleDefinition, error) { if roleName == "" { return nil, fmt.Errorf("role name cannot be empty") } @@ -78,8 +78,8 @@ func (m *MemoryRoleStore) GetRole(ctx context.Context, roleName string) (*RoleDe return copyRoleDefinition(role), nil } -// ListRoles lists all role names in memory -func (m *MemoryRoleStore) ListRoles(ctx context.Context) ([]string, error) { +// ListRoles lists all role names in memory (filerAddress ignored for memory store) +func (m *MemoryRoleStore) ListRoles(ctx context.Context, filerAddress string) ([]string, error) { m.mutex.RLock() defer m.mutex.RUnlock() @@ -91,8 +91,8 @@ func (m *MemoryRoleStore) ListRoles(ctx context.Context) ([]string, error) { return names, nil } -// DeleteRole deletes a role definition from memory -func (m *MemoryRoleStore) DeleteRole(ctx context.Context, roleName string) error { +// DeleteRole deletes a role definition from memory (filerAddress ignored for memory store) +func (m *MemoryRoleStore) DeleteRole(ctx context.Context, filerAddress string, roleName string) error { if roleName == "" { return fmt.Errorf("role name cannot be empty") } @@ -136,9 +136,8 @@ func copyRoleDefinition(original *RoleDefinition) *RoleDefinition { // FilerRoleStore implements RoleStore using SeaweedFS filer type FilerRoleStore struct { - filerGrpcAddress string - grpcDialOption grpc.DialOption - basePath string + grpcDialOption grpc.DialOption + basePath string } // NewFilerRoleStore creates a new filer-based role store @@ -147,29 +146,23 @@ func NewFilerRoleStore(config map[string]interface{}) (*FilerRoleStore, error) { basePath: "/etc/iam/roles", // Default path for role storage - aligned with /etc/ convention } - // Parse configuration + // Parse configuration - only basePath and other settings, NOT filerAddress if config != nil { - if filerAddr, ok := config["filerAddress"].(string); ok { - store.filerGrpcAddress = filerAddr - } - if basePath, ok := config["basePath"].(string); ok { + if basePath, ok := config["basePath"].(string); ok && basePath != "" { store.basePath = strings.TrimSuffix(basePath, "/") } } - // Validate configuration - if store.filerGrpcAddress == "" { - return nil, fmt.Errorf("filer address is required for FilerRoleStore") - } - - glog.V(2).Infof("Initialized FilerRoleStore with filer %s, basePath %s", - store.filerGrpcAddress, store.basePath) + glog.V(2).Infof("Initialized FilerRoleStore with basePath %s", store.basePath) return store, nil } // StoreRole stores a role definition in filer -func (f *FilerRoleStore) StoreRole(ctx context.Context, roleName string, role *RoleDefinition) error { +func (f *FilerRoleStore) StoreRole(ctx context.Context, filerAddress string, roleName string, role *RoleDefinition) error { + if filerAddress == "" { + return fmt.Errorf("filer address is required for FilerRoleStore") + } if roleName == "" { return fmt.Errorf("role name cannot be empty") } @@ -186,7 +179,7 @@ func (f *FilerRoleStore) StoreRole(ctx context.Context, roleName string, role *R rolePath := f.getRolePath(roleName) // Store in filer - return f.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + return f.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.CreateEntryRequest{ Directory: f.basePath, Entry: &filer_pb.Entry{ @@ -214,13 +207,16 @@ func (f *FilerRoleStore) StoreRole(ctx context.Context, roleName string, role *R } // GetRole retrieves a role definition from filer -func (f *FilerRoleStore) GetRole(ctx context.Context, roleName string) (*RoleDefinition, error) { +func (f *FilerRoleStore) GetRole(ctx context.Context, filerAddress string, roleName string) (*RoleDefinition, error) { + if filerAddress == "" { + return nil, fmt.Errorf("filer address is required for FilerRoleStore") + } if roleName == "" { return nil, fmt.Errorf("role name cannot be empty") } var roleData []byte - err := f.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + err := f.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.LookupDirectoryEntryRequest{ Directory: f.basePath, Name: f.getRoleFileName(roleName), @@ -254,10 +250,14 @@ func (f *FilerRoleStore) GetRole(ctx context.Context, roleName string) (*RoleDef } // ListRoles lists all role names in filer -func (f *FilerRoleStore) ListRoles(ctx context.Context) ([]string, error) { +func (f *FilerRoleStore) ListRoles(ctx context.Context, filerAddress string) ([]string, error) { + if filerAddress == "" { + return nil, fmt.Errorf("filer address is required for FilerRoleStore") + } + var roleNames []string - err := f.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + err := f.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.ListEntriesRequest{ Directory: f.basePath, Prefix: "", @@ -301,12 +301,15 @@ func (f *FilerRoleStore) ListRoles(ctx context.Context) ([]string, error) { } // DeleteRole deletes a role definition from filer -func (f *FilerRoleStore) DeleteRole(ctx context.Context, roleName string) error { +func (f *FilerRoleStore) DeleteRole(ctx context.Context, filerAddress string, roleName string) error { + if filerAddress == "" { + return fmt.Errorf("filer address is required for FilerRoleStore") + } if roleName == "" { return fmt.Errorf("role name cannot be empty") } - return f.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + return f.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.DeleteEntryRequest{ Directory: f.basePath, Name: f.getRoleFileName(roleName), @@ -333,6 +336,9 @@ func (f *FilerRoleStore) getRolePath(roleName string) string { return f.basePath + "/" + f.getRoleFileName(roleName) } -func (f *FilerRoleStore) withFilerClient(fn func(filer_pb.SeaweedFilerClient) error) error { - return pb.WithGrpcFilerClient(false, 0, pb.ServerAddress(f.filerGrpcAddress), f.grpcDialOption, fn) +func (f *FilerRoleStore) withFilerClient(filerAddress string, fn func(filer_pb.SeaweedFilerClient) error) error { + if filerAddress == "" { + return fmt.Errorf("filer address is required for FilerRoleStore") + } + return pb.WithGrpcFilerClient(false, 0, pb.ServerAddress(filerAddress), f.grpcDialOption, fn) } diff --git a/weed/iam/policy/policy_engine.go b/weed/iam/policy/policy_engine.go index b23ae92cd..8d000b8b9 100644 --- a/weed/iam/policy/policy_engine.go +++ b/weed/iam/policy/policy_engine.go @@ -139,17 +139,17 @@ type EvaluationDetails struct { // PolicyStore defines the interface for storing and retrieving policies type PolicyStore interface { - // StorePolicy stores a policy document - StorePolicy(ctx context.Context, name string, policy *PolicyDocument) error + // StorePolicy stores a policy document (filerAddress ignored for memory stores) + StorePolicy(ctx context.Context, filerAddress string, name string, policy *PolicyDocument) error - // GetPolicy retrieves a policy document - GetPolicy(ctx context.Context, name string) (*PolicyDocument, error) + // GetPolicy retrieves a policy document (filerAddress ignored for memory stores) + GetPolicy(ctx context.Context, filerAddress string, name string) (*PolicyDocument, error) - // DeletePolicy deletes a policy document - DeletePolicy(ctx context.Context, name string) error + // DeletePolicy deletes a policy document (filerAddress ignored for memory stores) + DeletePolicy(ctx context.Context, filerAddress string, name string) error - // ListPolicies lists all policy names - ListPolicies(ctx context.Context) ([]string, error) + // ListPolicies lists all policy names (filerAddress ignored for memory stores) + ListPolicies(ctx context.Context, filerAddress string) ([]string, error) } // NewPolicyEngine creates a new policy engine @@ -210,8 +210,8 @@ func (e *PolicyEngine) IsInitialized() bool { return e.initialized } -// AddPolicy adds a policy to the engine -func (e *PolicyEngine) AddPolicy(name string, policy *PolicyDocument) error { +// AddPolicy adds a policy to the engine (filerAddress ignored for memory stores) +func (e *PolicyEngine) AddPolicy(filerAddress string, name string, policy *PolicyDocument) error { if !e.initialized { return fmt.Errorf("policy engine not initialized") } @@ -228,11 +228,11 @@ func (e *PolicyEngine) AddPolicy(name string, policy *PolicyDocument) error { return fmt.Errorf("invalid policy document: %w", err) } - return e.store.StorePolicy(context.Background(), name, policy) + return e.store.StorePolicy(context.Background(), filerAddress, name, policy) } -// Evaluate evaluates policies against a request context -func (e *PolicyEngine) Evaluate(ctx context.Context, evalCtx *EvaluationContext, policyNames []string) (*EvaluationResult, error) { +// Evaluate evaluates policies against a request context (filerAddress ignored for memory stores) +func (e *PolicyEngine) Evaluate(ctx context.Context, filerAddress string, evalCtx *EvaluationContext, policyNames []string) (*EvaluationResult, error) { if !e.initialized { return nil, fmt.Errorf("policy engine not initialized") } @@ -257,7 +257,7 @@ func (e *PolicyEngine) Evaluate(ctx context.Context, evalCtx *EvaluationContext, // Evaluate each policy for _, policyName := range policyNames { - policy, err := e.store.GetPolicy(ctx, policyName) + policy, err := e.store.GetPolicy(ctx, filerAddress, policyName) if err != nil { continue // Skip policies that can't be loaded } diff --git a/weed/iam/policy/policy_store.go b/weed/iam/policy/policy_store.go index 405dcc83f..4c673d40a 100644 --- a/weed/iam/policy/policy_store.go +++ b/weed/iam/policy/policy_store.go @@ -27,8 +27,8 @@ func NewMemoryPolicyStore() *MemoryPolicyStore { } } -// StorePolicy stores a policy document in memory -func (s *MemoryPolicyStore) StorePolicy(ctx context.Context, name string, policy *PolicyDocument) error { +// StorePolicy stores a policy document in memory (filerAddress ignored for memory store) +func (s *MemoryPolicyStore) StorePolicy(ctx context.Context, filerAddress string, name string, policy *PolicyDocument) error { if name == "" { return fmt.Errorf("policy name cannot be empty") } @@ -45,8 +45,8 @@ func (s *MemoryPolicyStore) StorePolicy(ctx context.Context, name string, policy return nil } -// GetPolicy retrieves a policy document from memory -func (s *MemoryPolicyStore) GetPolicy(ctx context.Context, name string) (*PolicyDocument, error) { +// GetPolicy retrieves a policy document from memory (filerAddress ignored for memory store) +func (s *MemoryPolicyStore) GetPolicy(ctx context.Context, filerAddress string, name string) (*PolicyDocument, error) { if name == "" { return nil, fmt.Errorf("policy name cannot be empty") } @@ -63,8 +63,8 @@ func (s *MemoryPolicyStore) GetPolicy(ctx context.Context, name string) (*Policy return copyPolicyDocument(policy), nil } -// DeletePolicy deletes a policy document from memory -func (s *MemoryPolicyStore) DeletePolicy(ctx context.Context, name string) error { +// DeletePolicy deletes a policy document from memory (filerAddress ignored for memory store) +func (s *MemoryPolicyStore) DeletePolicy(ctx context.Context, filerAddress string, name string) error { if name == "" { return fmt.Errorf("policy name cannot be empty") } @@ -76,8 +76,8 @@ func (s *MemoryPolicyStore) DeletePolicy(ctx context.Context, name string) error return nil } -// ListPolicies lists all policy names in memory -func (s *MemoryPolicyStore) ListPolicies(ctx context.Context) ([]string, error) { +// ListPolicies lists all policy names in memory (filerAddress ignored for memory store) +func (s *MemoryPolicyStore) ListPolicies(ctx context.Context, filerAddress string) ([]string, error) { s.mutex.RLock() defer s.mutex.RUnlock() @@ -148,9 +148,8 @@ func copyPolicyDocument(original *PolicyDocument) *PolicyDocument { // FilerPolicyStore implements PolicyStore using SeaweedFS filer type FilerPolicyStore struct { - filerGrpcAddress string - grpcDialOption grpc.DialOption - basePath string + grpcDialOption grpc.DialOption + basePath string } // NewFilerPolicyStore creates a new filer-based policy store @@ -159,29 +158,23 @@ func NewFilerPolicyStore(config map[string]interface{}) (*FilerPolicyStore, erro basePath: "/etc/iam/policies", // Default path for policy storage - aligned with /etc/ convention } - // Parse configuration + // Parse configuration - only basePath and other settings, NOT filerAddress if config != nil { - if filerAddr, ok := config["filerAddress"].(string); ok { - store.filerGrpcAddress = filerAddr - } - if basePath, ok := config["basePath"].(string); ok { + if basePath, ok := config["basePath"].(string); ok && basePath != "" { store.basePath = strings.TrimSuffix(basePath, "/") } } - // Validate configuration - if store.filerGrpcAddress == "" { - return nil, fmt.Errorf("filer address is required for FilerPolicyStore") - } - - glog.V(2).Infof("Initialized FilerPolicyStore with filer %s, basePath %s", - store.filerGrpcAddress, store.basePath) + glog.V(2).Infof("Initialized FilerPolicyStore with basePath %s", store.basePath) return store, nil } // StorePolicy stores a policy document in filer -func (s *FilerPolicyStore) StorePolicy(ctx context.Context, name string, policy *PolicyDocument) error { +func (s *FilerPolicyStore) StorePolicy(ctx context.Context, filerAddress string, name string, policy *PolicyDocument) error { + if filerAddress == "" { + return fmt.Errorf("filer address is required for FilerPolicyStore") + } if name == "" { return fmt.Errorf("policy name cannot be empty") } @@ -198,7 +191,7 @@ func (s *FilerPolicyStore) StorePolicy(ctx context.Context, name string, policy policyPath := s.getPolicyPath(name) // Store in filer - return s.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + return s.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.CreateEntryRequest{ Directory: s.basePath, Entry: &filer_pb.Entry{ @@ -226,13 +219,16 @@ func (s *FilerPolicyStore) StorePolicy(ctx context.Context, name string, policy } // GetPolicy retrieves a policy document from filer -func (s *FilerPolicyStore) GetPolicy(ctx context.Context, name string) (*PolicyDocument, error) { +func (s *FilerPolicyStore) GetPolicy(ctx context.Context, filerAddress string, name string) (*PolicyDocument, error) { + if filerAddress == "" { + return nil, fmt.Errorf("filer address is required for FilerPolicyStore") + } if name == "" { return nil, fmt.Errorf("policy name cannot be empty") } var policyData []byte - err := s.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + err := s.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.LookupDirectoryEntryRequest{ Directory: s.basePath, Name: s.getPolicyFileName(name), @@ -266,12 +262,15 @@ func (s *FilerPolicyStore) GetPolicy(ctx context.Context, name string) (*PolicyD } // DeletePolicy deletes a policy document from filer -func (s *FilerPolicyStore) DeletePolicy(ctx context.Context, name string) error { +func (s *FilerPolicyStore) DeletePolicy(ctx context.Context, filerAddress string, name string) error { + if filerAddress == "" { + return fmt.Errorf("filer address is required for FilerPolicyStore") + } if name == "" { return fmt.Errorf("policy name cannot be empty") } - return s.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + return s.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { request := &filer_pb.DeleteEntryRequest{ Directory: s.basePath, Name: s.getPolicyFileName(name), @@ -304,10 +303,14 @@ func (s *FilerPolicyStore) DeletePolicy(ctx context.Context, name string) error } // ListPolicies lists all policy names in filer -func (s *FilerPolicyStore) ListPolicies(ctx context.Context) ([]string, error) { +func (s *FilerPolicyStore) ListPolicies(ctx context.Context, filerAddress string) ([]string, error) { + if filerAddress == "" { + return nil, fmt.Errorf("filer address is required for FilerPolicyStore") + } + var policyNames []string - err := s.withFilerClient(func(client filer_pb.SeaweedFilerClient) error { + err := s.withFilerClient(filerAddress, func(client filer_pb.SeaweedFilerClient) error { // List all entries in the policy directory request := &filer_pb.ListEntriesRequest{ Directory: s.basePath, @@ -353,20 +356,14 @@ func (s *FilerPolicyStore) ListPolicies(ctx context.Context) ([]string, error) { // Helper methods -// SetFilerClient sets the filer client connection details -func (s *FilerPolicyStore) SetFilerClient(filerAddress string, grpcDialOption grpc.DialOption) { - s.filerGrpcAddress = filerAddress - s.grpcDialOption = grpcDialOption -} - // withFilerClient executes a function with a filer client -func (s *FilerPolicyStore) withFilerClient(fn func(client filer_pb.SeaweedFilerClient) error) error { - if s.filerGrpcAddress == "" { - return fmt.Errorf("filer address not configured") +func (s *FilerPolicyStore) withFilerClient(filerAddress string, fn func(client filer_pb.SeaweedFilerClient) error) error { + if filerAddress == "" { + return fmt.Errorf("filer address is required for FilerPolicyStore") } // Use the pb.WithGrpcFilerClient helper similar to existing SeaweedFS code - return pb.WithGrpcFilerClient(false, 0, pb.ServerAddress(s.filerGrpcAddress), s.grpcDialOption, fn) + return pb.WithGrpcFilerClient(false, 0, pb.ServerAddress(filerAddress), s.grpcDialOption, fn) } // getPolicyPath returns the full path for a policy diff --git a/weed/s3api/s3api_server.go b/weed/s3api/s3api_server.go index 8bd452b0e..07e5993db 100644 --- a/weed/s3api/s3api_server.go +++ b/weed/s3api/s3api_server.go @@ -474,14 +474,14 @@ func loadIAMManagerFromConfig(configPath string) (*integration.IAMManager, error // Load policies for _, policyDef := range configRoot.Policies { - if err := iamManager.CreatePolicy(context.Background(), policyDef.Name, policyDef.Document); err != nil { + if err := iamManager.CreatePolicy(context.Background(), "", policyDef.Name, policyDef.Document); err != nil { glog.Warningf("Failed to create policy %s: %v", policyDef.Name, err) } } // Load roles for _, roleDef := range configRoot.Roles { - if err := iamManager.CreateRole(context.Background(), roleDef.RoleName, roleDef); err != nil { + if err := iamManager.CreateRole(context.Background(), "", roleDef.RoleName, roleDef); err != nil { glog.Warningf("Failed to create role %s: %v", roleDef.RoleName, err) } }