Browse Source

fix: Update IAM config field name for role store configuration

- Change JSON field from 'roles' to 'roleStore' for clarity
- Prevents confusion with the actual role definitions array
- Matches the new distributed configuration schema

This ensures the JSON configuration properly maps to the
RoleStoreConfig struct for distributed IAM deployments.
pull/7160/head
chrislu 2 months ago
parent
commit
88ee23d210
  1. 96
      weed/iam/integration/iam_manager.go

96
weed/iam/integration/iam_manager.go

@ -11,20 +11,20 @@ import (
// IAMManager orchestrates all IAM components // IAMManager orchestrates all IAM components
type IAMManager struct { type IAMManager struct {
stsService *sts.STSService
policyEngine *policy.PolicyEngine
roleStore RoleStore
initialized bool
stsService *sts.STSService
policyEngine *policy.PolicyEngine
roleStore RoleStore
initialized bool
} }
// IAMConfig holds configuration for all IAM components // IAMConfig holds configuration for all IAM components
type IAMConfig struct { type IAMConfig struct {
// STS service configuration // STS service configuration
STS *sts.STSConfig `json:"sts"` STS *sts.STSConfig `json:"sts"`
// Policy engine configuration // Policy engine configuration
Policy *policy.PolicyEngineConfig `json:"policy"` Policy *policy.PolicyEngineConfig `json:"policy"`
// Role store configuration // Role store configuration
Roles *RoleStoreConfig `json:"roleStore"` Roles *RoleStoreConfig `json:"roleStore"`
} }
@ -42,16 +42,16 @@ type RoleStoreConfig struct {
type RoleDefinition struct { type RoleDefinition struct {
// RoleName is the name of the role // RoleName is the name of the role
RoleName string `json:"roleName"` RoleName string `json:"roleName"`
// RoleArn is the full ARN of the role // RoleArn is the full ARN of the role
RoleArn string `json:"roleArn"` RoleArn string `json:"roleArn"`
// TrustPolicy defines who can assume this role // TrustPolicy defines who can assume this role
TrustPolicy *policy.PolicyDocument `json:"trustPolicy"` TrustPolicy *policy.PolicyDocument `json:"trustPolicy"`
// AttachedPolicies lists the policy names attached to this role // AttachedPolicies lists the policy names attached to this role
AttachedPolicies []string `json:"attachedPolicies"` AttachedPolicies []string `json:"attachedPolicies"`
// Description is an optional description of the role // Description is an optional description of the role
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
} }
@ -60,16 +60,16 @@ type RoleDefinition struct {
type ActionRequest struct { type ActionRequest struct {
// Principal is the entity performing the action // Principal is the entity performing the action
Principal string `json:"principal"` Principal string `json:"principal"`
// Action is the action being requested // Action is the action being requested
Action string `json:"action"` Action string `json:"action"`
// Resource is the resource being accessed // Resource is the resource being accessed
Resource string `json:"resource"` Resource string `json:"resource"`
// SessionToken for temporary credential validation // SessionToken for temporary credential validation
SessionToken string `json:"sessionToken"` SessionToken string `json:"sessionToken"`
// RequestContext contains additional request information // RequestContext contains additional request information
RequestContext map[string]interface{} `json:"requestContext,omitempty"` RequestContext map[string]interface{} `json:"requestContext,omitempty"`
} }
@ -84,26 +84,26 @@ func (m *IAMManager) Initialize(config *IAMConfig) error {
if config == nil { if config == nil {
return fmt.Errorf("config cannot be nil") return fmt.Errorf("config cannot be nil")
} }
// Initialize STS service // Initialize STS service
m.stsService = sts.NewSTSService() m.stsService = sts.NewSTSService()
if err := m.stsService.Initialize(config.STS); err != nil { if err := m.stsService.Initialize(config.STS); err != nil {
return fmt.Errorf("failed to initialize STS service: %w", err) return fmt.Errorf("failed to initialize STS service: %w", err)
} }
// Initialize policy engine // Initialize policy engine
m.policyEngine = policy.NewPolicyEngine() m.policyEngine = policy.NewPolicyEngine()
if err := m.policyEngine.Initialize(config.Policy); err != nil { if err := m.policyEngine.Initialize(config.Policy); err != nil {
return fmt.Errorf("failed to initialize policy engine: %w", err) return fmt.Errorf("failed to initialize policy engine: %w", err)
} }
// Initialize role store // Initialize role store
roleStore, err := m.createRoleStore(config.Roles) roleStore, err := m.createRoleStore(config.Roles)
if err != nil { if err != nil {
return fmt.Errorf("failed to initialize role store: %w", err) return fmt.Errorf("failed to initialize role store: %w", err)
} }
m.roleStore = roleStore m.roleStore = roleStore
m.initialized = true m.initialized = true
return nil return nil
} }
@ -114,7 +114,7 @@ func (m *IAMManager) createRoleStore(config *RoleStoreConfig) (RoleStore, error)
// Default to memory role store // Default to memory role store
return NewMemoryRoleStore(), nil return NewMemoryRoleStore(), nil
} }
switch config.StoreType { switch config.StoreType {
case "", "memory": case "", "memory":
return NewMemoryRoleStore(), nil return NewMemoryRoleStore(), nil
@ -130,7 +130,7 @@ func (m *IAMManager) RegisterIdentityProvider(provider providers.IdentityProvide
if !m.initialized { if !m.initialized {
return fmt.Errorf("IAM manager not initialized") return fmt.Errorf("IAM manager not initialized")
} }
return m.stsService.RegisterProvider(provider) return m.stsService.RegisterProvider(provider)
} }
@ -139,7 +139,7 @@ func (m *IAMManager) CreatePolicy(ctx context.Context, name string, policyDoc *p
if !m.initialized { if !m.initialized {
return fmt.Errorf("IAM manager not initialized") return fmt.Errorf("IAM manager not initialized")
} }
return m.policyEngine.AddPolicy(name, policyDoc) return m.policyEngine.AddPolicy(name, policyDoc)
} }
@ -148,27 +148,27 @@ func (m *IAMManager) CreateRole(ctx context.Context, roleName string, roleDef *R
if !m.initialized { if !m.initialized {
return fmt.Errorf("IAM manager not initialized") return fmt.Errorf("IAM manager not initialized")
} }
if roleName == "" { if roleName == "" {
return fmt.Errorf("role name cannot be empty") return fmt.Errorf("role name cannot be empty")
} }
if roleDef == nil { if roleDef == nil {
return fmt.Errorf("role definition cannot be nil") return fmt.Errorf("role definition cannot be nil")
} }
// Set role ARN if not provided // Set role ARN if not provided
if roleDef.RoleArn == "" { if roleDef.RoleArn == "" {
roleDef.RoleArn = fmt.Sprintf("arn:seaweed:iam::role/%s", roleName) roleDef.RoleArn = fmt.Sprintf("arn:seaweed:iam::role/%s", roleName)
} }
// Validate trust policy // Validate trust policy
if roleDef.TrustPolicy != nil { if roleDef.TrustPolicy != nil {
if err := policy.ValidateTrustPolicyDocument(roleDef.TrustPolicy); err != nil { if err := policy.ValidateTrustPolicyDocument(roleDef.TrustPolicy); err != nil {
return fmt.Errorf("invalid trust policy: %w", err) return fmt.Errorf("invalid trust policy: %w", err)
} }
} }
// Store role definition // Store role definition
return m.roleStore.StoreRole(ctx, roleName, roleDef) return m.roleStore.StoreRole(ctx, roleName, roleDef)
} }
@ -178,21 +178,21 @@ func (m *IAMManager) AssumeRoleWithWebIdentity(ctx context.Context, request *sts
if !m.initialized { if !m.initialized {
return nil, fmt.Errorf("IAM manager not initialized") return nil, fmt.Errorf("IAM manager not initialized")
} }
// Extract role name from ARN // Extract role name from ARN
roleName := extractRoleNameFromArn(request.RoleArn) roleName := extractRoleNameFromArn(request.RoleArn)
// Get role definition // Get role definition
roleDef, err := m.roleStore.GetRole(ctx, roleName) roleDef, err := m.roleStore.GetRole(ctx, roleName)
if err != nil { if err != nil {
return nil, fmt.Errorf("role not found: %s", roleName) return nil, fmt.Errorf("role not found: %s", roleName)
} }
// Validate trust policy before allowing STS to assume the role // Validate trust policy before allowing STS to assume the role
if err := m.validateTrustPolicyForWebIdentity(ctx, roleDef, request.WebIdentityToken); err != nil { if err := m.validateTrustPolicyForWebIdentity(ctx, roleDef, request.WebIdentityToken); err != nil {
return nil, fmt.Errorf("trust policy validation failed: %w", err) return nil, fmt.Errorf("trust policy validation failed: %w", err)
} }
// Use STS service to assume the role // Use STS service to assume the role
return m.stsService.AssumeRoleWithWebIdentity(ctx, request) return m.stsService.AssumeRoleWithWebIdentity(ctx, request)
} }
@ -202,21 +202,21 @@ func (m *IAMManager) AssumeRoleWithCredentials(ctx context.Context, request *sts
if !m.initialized { if !m.initialized {
return nil, fmt.Errorf("IAM manager not initialized") return nil, fmt.Errorf("IAM manager not initialized")
} }
// Extract role name from ARN // Extract role name from ARN
roleName := extractRoleNameFromArn(request.RoleArn) roleName := extractRoleNameFromArn(request.RoleArn)
// Get role definition // Get role definition
roleDef, err := m.roleStore.GetRole(ctx, roleName) roleDef, err := m.roleStore.GetRole(ctx, roleName)
if err != nil { if err != nil {
return nil, fmt.Errorf("role not found: %s", roleName) return nil, fmt.Errorf("role not found: %s", roleName)
} }
// Validate trust policy // Validate trust policy
if err := m.validateTrustPolicyForCredentials(ctx, roleDef, request); err != nil { if err := m.validateTrustPolicyForCredentials(ctx, roleDef, request); err != nil {
return nil, fmt.Errorf("trust policy validation failed: %w", err) return nil, fmt.Errorf("trust policy validation failed: %w", err)
} }
// Use STS service to assume the role // Use STS service to assume the role
return m.stsService.AssumeRoleWithCredentials(ctx, request) return m.stsService.AssumeRoleWithCredentials(ctx, request)
} }
@ -226,25 +226,25 @@ func (m *IAMManager) IsActionAllowed(ctx context.Context, request *ActionRequest
if !m.initialized { if !m.initialized {
return false, fmt.Errorf("IAM manager not initialized") return false, fmt.Errorf("IAM manager not initialized")
} }
// Validate session token first // Validate session token first
_, err := m.stsService.ValidateSessionToken(ctx, request.SessionToken) _, err := m.stsService.ValidateSessionToken(ctx, request.SessionToken)
if err != nil { if err != nil {
return false, fmt.Errorf("invalid session: %w", err) return false, fmt.Errorf("invalid session: %w", err)
} }
// Extract role name from principal ARN // Extract role name from principal ARN
roleName := extractRoleNameFromPrincipal(request.Principal) roleName := extractRoleNameFromPrincipal(request.Principal)
if roleName == "" { if roleName == "" {
return false, fmt.Errorf("could not extract role from principal: %s", request.Principal) return false, fmt.Errorf("could not extract role from principal: %s", request.Principal)
} }
// Get role definition // Get role definition
roleDef, err := m.roleStore.GetRole(ctx, roleName) roleDef, err := m.roleStore.GetRole(ctx, roleName)
if err != nil { if err != nil {
return false, fmt.Errorf("role not found: %s", roleName) return false, fmt.Errorf("role not found: %s", roleName)
} }
// Create evaluation context // Create evaluation context
evalCtx := &policy.EvaluationContext{ evalCtx := &policy.EvaluationContext{
Principal: request.Principal, Principal: request.Principal,
@ -252,13 +252,13 @@ func (m *IAMManager) IsActionAllowed(ctx context.Context, request *ActionRequest
Resource: request.Resource, Resource: request.Resource,
RequestContext: request.RequestContext, RequestContext: request.RequestContext,
} }
// Evaluate policies attached to the role // 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 { if err != nil {
return false, fmt.Errorf("policy evaluation failed: %w", err) return false, fmt.Errorf("policy evaluation failed: %w", err)
} }
return result.Effect == policy.EffectAllow, nil return result.Effect == policy.EffectAllow, nil
} }
@ -269,7 +269,7 @@ func (m *IAMManager) ValidateTrustPolicy(ctx context.Context, roleArn, provider,
if err != nil { if err != nil {
return false return false
} }
// Simple validation based on provider in trust policy // Simple validation based on provider in trust policy
if roleDef.TrustPolicy != nil { if roleDef.TrustPolicy != nil {
for _, statement := range roleDef.TrustPolicy.Statement { for _, statement := range roleDef.TrustPolicy.Statement {
@ -284,7 +284,7 @@ func (m *IAMManager) ValidateTrustPolicy(ctx context.Context, roleArn, provider,
} }
} }
} }
return false return false
} }
@ -293,13 +293,13 @@ func (m *IAMManager) validateTrustPolicyForWebIdentity(ctx context.Context, role
if roleDef.TrustPolicy == nil { if roleDef.TrustPolicy == nil {
return fmt.Errorf("role has no trust policy") return fmt.Errorf("role has no trust policy")
} }
// For simplified implementation, we'll do basic validation // For simplified implementation, we'll do basic validation
// In a full implementation, this would: // In a full implementation, this would:
// 1. Parse the web identity token // 1. Parse the web identity token
// 2. Check issuer against trust policy // 2. Check issuer against trust policy
// 3. Validate conditions in trust policy // 3. Validate conditions in trust policy
// Check if trust policy allows web identity assumption // Check if trust policy allows web identity assumption
for _, statement := range roleDef.TrustPolicy.Statement { for _, statement := range roleDef.TrustPolicy.Statement {
if statement.Effect == "Allow" { if statement.Effect == "Allow" {
@ -315,7 +315,7 @@ func (m *IAMManager) validateTrustPolicyForWebIdentity(ctx context.Context, role
} }
} }
} }
return fmt.Errorf("trust policy does not allow web identity assumption") return fmt.Errorf("trust policy does not allow web identity assumption")
} }
@ -324,7 +324,7 @@ func (m *IAMManager) validateTrustPolicyForCredentials(ctx context.Context, role
if roleDef.TrustPolicy == nil { if roleDef.TrustPolicy == nil {
return fmt.Errorf("role has no trust policy") return fmt.Errorf("role has no trust policy")
} }
// Check if trust policy allows credential assumption for the specific provider // Check if trust policy allows credential assumption for the specific provider
for _, statement := range roleDef.TrustPolicy.Statement { for _, statement := range roleDef.TrustPolicy.Statement {
if statement.Effect == "Allow" { if statement.Effect == "Allow" {
@ -341,7 +341,7 @@ func (m *IAMManager) validateTrustPolicyForCredentials(ctx context.Context, role
} }
} }
} }
return fmt.Errorf("trust policy does not allow credential assumption for provider: %s", request.ProviderName) return fmt.Errorf("trust policy does not allow credential assumption for provider: %s", request.ProviderName)
} }
@ -385,6 +385,6 @@ func (m *IAMManager) ExpireSessionForTesting(ctx context.Context, sessionToken s
if !m.initialized { if !m.initialized {
return fmt.Errorf("IAM manager not initialized") return fmt.Errorf("IAM manager not initialized")
} }
return m.stsService.ExpireSessionForTesting(ctx, sessionToken) return m.stsService.ExpireSessionForTesting(ctx, sessionToken)
} }
Loading…
Cancel
Save