Add session policy support to IAM (#8338)

* Add session policy support to IAM

- Implement policy evaluation for session tokens in policy_engine.go
- Add session_policy field to session claims for tracking applied policies
- Update STS service to include session policies in token generation
- Add IAM integration tests for session policy validation
- Update IAM manager to support policy attachment to sessions
- Extend S3 API STS endpoint to handle session policy restrictions

* fix: optimize session policy evaluation and add documentation

* sts: add NormalizeSessionPolicy helper for inline session policies

* sts: support inline session policies for AssumeRoleWithWebIdentity and credential-based flows

* s3api: parse and normalize Policy parameter for STS HTTP handlers

* tests: add session policy unit tests and integration tests for inline policy downscoping

* tests: add s3tables STS inline policy integration

* iam: handle user principals and validate tokens

* sts: enforce inline session policy size limit

* tests: harden s3tables STS integration config

* iam: clarify principal policy resolution errors

* tests: improve STS integration endpoint selection
This commit is contained in:
Chris Lu
2026-02-13 13:58:22 -08:00
committed by GitHub
parent beeb375a88
commit 49a64f50f1
12 changed files with 682 additions and 275 deletions

View File

@@ -161,6 +161,9 @@ type AssumeRoleWithCredentialsRequest struct {
// DurationSeconds is the duration of the role session (optional)
DurationSeconds *int64 `json:"DurationSeconds,omitempty"`
// Policy is an optional session policy (optional)
Policy *string `json:"Policy,omitempty"`
}
// AssumeRoleResponse represents the response from assume role operations
@@ -237,6 +240,9 @@ type SessionInfo struct {
// Policies are the policies associated with this session
Policies []string `json:"policies"`
// SessionPolicy is the inline session policy JSON (optional)
SessionPolicy string `json:"sessionPolicy,omitempty"`
// RequestContext contains additional request context for policy evaluation
RequestContext map[string]interface{} `json:"requestContext,omitempty"`
@@ -418,9 +424,13 @@ func (s *STSService) AssumeRoleWithWebIdentity(ctx context.Context, request *Ass
return nil, fmt.Errorf("invalid request: %w", err)
}
// Check for unsupported session policy
sessionPolicy := ""
if request.Policy != nil {
return nil, fmt.Errorf("session policies are not currently supported - Policy parameter must be omitted")
normalized, err := NormalizeSessionPolicy(*request.Policy)
if err != nil {
return nil, fmt.Errorf("invalid session policy: %w", err)
}
sessionPolicy = normalized
}
// 1. Validate the web identity token with appropriate provider
@@ -485,6 +495,9 @@ func (s *STSService) AssumeRoleWithWebIdentity(ctx context.Context, request *Ass
WithIdentityProvider(provider.Name(), externalIdentity.UserID, "").
WithMaxDuration(sessionDuration).
WithRequestContext(requestContext)
if sessionPolicy != "" {
sessionClaims.WithSessionPolicy(sessionPolicy)
}
// Generate self-contained JWT token with all session information
jwtToken, err := s.tokenGenerator.GenerateJWTWithClaims(sessionClaims)
@@ -517,6 +530,15 @@ func (s *STSService) AssumeRoleWithCredentials(ctx context.Context, request *Ass
return nil, fmt.Errorf("invalid request: %w", err)
}
sessionPolicy := ""
if request.Policy != nil {
normalized, err := NormalizeSessionPolicy(*request.Policy)
if err != nil {
return nil, fmt.Errorf("invalid session policy: %w", err)
}
sessionPolicy = normalized
}
// 1. Get the specified provider
provider, exists := s.providers[request.ProviderName]
if !exists {
@@ -565,6 +587,9 @@ func (s *STSService) AssumeRoleWithCredentials(ctx context.Context, request *Ass
WithRoleInfo(request.RoleArn, assumedRoleUser.Arn, assumedRoleUser.Arn).
WithIdentityProvider(provider.Name(), externalIdentity.UserID, "").
WithMaxDuration(sessionDuration)
if sessionPolicy != "" {
sessionClaims.WithSessionPolicy(sessionPolicy)
}
// Generate self-contained JWT token with all session information
jwtToken, err := s.tokenGenerator.GenerateJWTWithClaims(sessionClaims)