Browse Source
test: Add comprehensive STS session claims validation tests
test: Add comprehensive STS session claims validation tests
- TestSTSSessionClaimsToSessionInfo: Validates basic claims conversion - TestSTSSessionClaimsToSessionInfoCredentialGeneration: Verifies credential generation - TestSTSSessionClaimsToSessionInfoPreservesAllFields: Ensures all fields are preserved - TestSTSSessionClaimsToSessionInfoEmptyFields: Tests handling of empty/nil fields - TestSTSSessionClaimsToSessionInfoCredentialExpiration: Validates expiration handling All tests pass with proper timing tolerance for credential generation.pull/7944/head
1 changed files with 211 additions and 0 deletions
@ -0,0 +1,211 @@ |
|||
package sts |
|||
|
|||
import ( |
|||
"testing" |
|||
"time" |
|||
|
|||
"github.com/stretchr/testify/assert" |
|||
"github.com/stretchr/testify/require" |
|||
) |
|||
|
|||
// TestSTSSessionClaimsToSessionInfo tests the ToSessionInfo conversion
|
|||
func TestSTSSessionClaimsToSessionInfo(t *testing.T) { |
|||
sessionId := "test-session-123" |
|||
issuer := "test-issuer" |
|||
expiresAt := time.Now().Add(time.Hour) |
|||
|
|||
claims := NewSTSSessionClaims(sessionId, issuer, expiresAt). |
|||
WithSessionName("test-session-name"). |
|||
WithRoleInfo( |
|||
"arn:aws:iam::123456789012:role/test-role", |
|||
"arn:aws:iam::123456789012:assumed-role/test-role/session", |
|||
"arn:aws:iam::123456789012:assumed-role/test-role/session", |
|||
). |
|||
WithIdentityProvider("oidc", "user-123", "https://issuer.example.com"). |
|||
WithMaxDuration(time.Hour) |
|||
|
|||
sessionInfo := claims.ToSessionInfo() |
|||
|
|||
// Verify basic claims are converted
|
|||
assert.Equal(t, sessionId, sessionInfo.SessionId) |
|||
assert.Equal(t, "test-session-name", sessionInfo.SessionName) |
|||
assert.Equal(t, "arn:aws:iam::123456789012:role/test-role", sessionInfo.RoleArn) |
|||
assert.Equal(t, "arn:aws:iam::123456789012:assumed-role/test-role/session", sessionInfo.AssumedRoleUser) |
|||
assert.Equal(t, "oidc", sessionInfo.IdentityProvider) |
|||
assert.Equal(t, "user-123", sessionInfo.ExternalUserId) |
|||
|
|||
// Verify credentials are generated
|
|||
assert.NotNil(t, sessionInfo.Credentials, "credentials should be populated") |
|||
assert.NotEmpty(t, sessionInfo.Credentials.AccessKeyId, "access key should be generated") |
|||
assert.NotEmpty(t, sessionInfo.Credentials.SecretAccessKey, "secret key should be generated") |
|||
// Credential expiration may have sub-second differences, so just check they're close
|
|||
assert.True(t, sessionInfo.Credentials.Expiration.Sub(expiresAt) < time.Second, "credential expiration should match session expiration") |
|||
|
|||
// Verify expiration is preserved (within 1 second tolerance for timing differences)
|
|||
assert.WithinDuration(t, expiresAt, sessionInfo.ExpiresAt, 1*time.Second) |
|||
} |
|||
|
|||
// TestSTSSessionClaimsToSessionInfoCredentialGeneration tests that credentials are properly generated
|
|||
func TestSTSSessionClaimsToSessionInfoCredentialGeneration(t *testing.T) { |
|||
sessionId := "deterministic-session-id" |
|||
issuer := "test-issuer" |
|||
expiresAt := time.Now().Add(time.Hour) |
|||
|
|||
claims1 := NewSTSSessionClaims(sessionId, issuer, expiresAt) |
|||
sessionInfo1 := claims1.ToSessionInfo() |
|||
|
|||
// Create another claims object with the same session ID
|
|||
claims2 := NewSTSSessionClaims(sessionId, issuer, expiresAt) |
|||
sessionInfo2 := claims2.ToSessionInfo() |
|||
|
|||
// Verify that both have valid credentials (may not be the same due to randomness, but same structure)
|
|||
assert.NotNil(t, sessionInfo1.Credentials, "credentials should be populated") |
|||
assert.NotNil(t, sessionInfo2.Credentials, "credentials should be populated") |
|||
|
|||
// Both should have the same access key and secret key patterns
|
|||
assert.NotEmpty(t, sessionInfo1.Credentials.AccessKeyId) |
|||
assert.NotEmpty(t, sessionInfo1.Credentials.SecretAccessKey) |
|||
assert.NotEmpty(t, sessionInfo2.Credentials.AccessKeyId) |
|||
assert.NotEmpty(t, sessionInfo2.Credentials.SecretAccessKey) |
|||
} |
|||
|
|||
// TestSTSSessionClaimsToSessionInfoPreservesAllFields tests that all fields are preserved
|
|||
func TestSTSSessionClaimsToSessionInfoPreservesAllFields(t *testing.T) { |
|||
sessionId := "test-session-id" |
|||
issuer := "test-issuer" |
|||
expiresAt := time.Now().Add(2 * time.Hour) |
|||
|
|||
policies := []string{"policy1", "policy2"} |
|||
requestContext := map[string]interface{}{ |
|||
"sourceIp": "192.168.1.1", |
|||
"userAgent": "test-agent", |
|||
} |
|||
|
|||
claims := NewSTSSessionClaims(sessionId, issuer, expiresAt). |
|||
WithSessionName("session-name"). |
|||
WithRoleInfo("role-arn", "assumed-role", "principal"). |
|||
WithIdentityProvider("provider", "external-id", "issuer"). |
|||
WithPolicies(policies). |
|||
WithRequestContext(requestContext). |
|||
WithMaxDuration(2 * time.Hour) |
|||
|
|||
sessionInfo := claims.ToSessionInfo() |
|||
|
|||
// Verify all fields are preserved
|
|||
assert.Equal(t, sessionId, sessionInfo.SessionId) |
|||
assert.Equal(t, "session-name", sessionInfo.SessionName) |
|||
assert.Equal(t, "role-arn", sessionInfo.RoleArn) |
|||
assert.Equal(t, "assumed-role", sessionInfo.AssumedRoleUser) |
|||
assert.Equal(t, "principal", sessionInfo.Principal) |
|||
assert.Equal(t, "provider", sessionInfo.IdentityProvider) |
|||
assert.Equal(t, "external-id", sessionInfo.ExternalUserId) |
|||
assert.Equal(t, "issuer", sessionInfo.ProviderIssuer) |
|||
assert.Equal(t, policies, sessionInfo.Policies) |
|||
assert.Equal(t, requestContext, sessionInfo.RequestContext) |
|||
assert.WithinDuration(t, expiresAt, sessionInfo.ExpiresAt, 1*time.Second) |
|||
} |
|||
|
|||
// TestSTSSessionClaimsToSessionInfoEmptyFields tests handling of empty/nil fields
|
|||
func TestSTSSessionClaimsToSessionInfoEmptyFields(t *testing.T) { |
|||
sessionId := "minimal-session" |
|||
issuer := "issuer" |
|||
expiresAt := time.Now().Add(time.Hour) |
|||
|
|||
// Create claims with minimal fields
|
|||
claims := NewSTSSessionClaims(sessionId, issuer, expiresAt) |
|||
|
|||
sessionInfo := claims.ToSessionInfo() |
|||
|
|||
// Verify basic fields are preserved
|
|||
assert.Equal(t, sessionId, sessionInfo.SessionId) |
|||
assert.Empty(t, sessionInfo.SessionName) |
|||
assert.Empty(t, sessionInfo.RoleArn) |
|||
|
|||
// Verify credentials are still generated even with minimal fields
|
|||
assert.NotNil(t, sessionInfo.Credentials) |
|||
assert.NotEmpty(t, sessionInfo.Credentials.AccessKeyId) |
|||
assert.NotEmpty(t, sessionInfo.Credentials.SecretAccessKey) |
|||
} |
|||
|
|||
// TestSTSSessionClaimsToSessionInfoCredentialExpiration tests credential expiration
|
|||
func TestSTSSessionClaimsToSessionInfoCredentialExpiration(t *testing.T) { |
|||
sessionId := "test-session" |
|||
issuer := "issuer" |
|||
|
|||
tests := []struct { |
|||
name string |
|||
expiresAt time.Time |
|||
expectNotExpired bool |
|||
description string |
|||
}{ |
|||
{ |
|||
name: "future_expiration", |
|||
expiresAt: time.Now().Add(time.Hour), |
|||
expectNotExpired: true, |
|||
description: "Credentials should not be expired if ExpiresAt is in the future", |
|||
}, |
|||
{ |
|||
name: "past_expiration", |
|||
expiresAt: time.Now().Add(-time.Hour), |
|||
expectNotExpired: false, |
|||
description: "Credentials should be expired if ExpiresAt is in the past", |
|||
}, |
|||
{ |
|||
name: "near_future_expiration", |
|||
expiresAt: time.Now().Add(time.Minute), |
|||
expectNotExpired: true, |
|||
description: "Credentials should not be expired even if close to expiration", |
|||
}, |
|||
} |
|||
|
|||
for _, tc := range tests { |
|||
t.Run(tc.name, func(t *testing.T) { |
|||
claims := NewSTSSessionClaims(sessionId, issuer, tc.expiresAt) |
|||
sessionInfo := claims.ToSessionInfo() |
|||
|
|||
assert.NotNil(t, sessionInfo.Credentials) |
|||
// Check expiration within 1 second due to timing precision
|
|||
assert.True(t, sessionInfo.Credentials.Expiration.Sub(tc.expiresAt) < time.Second) |
|||
|
|||
if tc.expectNotExpired { |
|||
assert.False(t, time.Now().After(tc.expiresAt), tc.description) |
|||
} else { |
|||
assert.True(t, time.Now().After(tc.expiresAt), tc.description) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
|
|||
// TestSessionInfoIntegration tests the full integration of session info flow
|
|||
func TestSessionInfoIntegration(t *testing.T) { |
|||
// Create a session claim
|
|||
sessionId, err := GenerateSessionId() |
|||
require.NoError(t, err) |
|||
|
|||
expiresAt := time.Now().Add(time.Hour) |
|||
claims := NewSTSSessionClaims(sessionId, "test-issuer", expiresAt). |
|||
WithSessionName("integration-test"). |
|||
WithRoleInfo( |
|||
"arn:aws:iam::123456789012:role/integration", |
|||
"arn:aws:iam::123456789012:assumed-role/integration/test", |
|||
"arn:aws:iam::123456789012:assumed-role/integration/test", |
|||
). |
|||
WithIdentityProvider("test-provider", "user-id", "https://test.example.com") |
|||
|
|||
// Convert to SessionInfo
|
|||
sessionInfo := claims.ToSessionInfo() |
|||
|
|||
// Verify the session info has valid credentials
|
|||
assert.NotNil(t, sessionInfo.Credentials) |
|||
assert.NotEmpty(t, sessionInfo.Credentials.AccessKeyId) |
|||
assert.NotEmpty(t, sessionInfo.Credentials.SecretAccessKey) |
|||
|
|||
// Verify basic session properties
|
|||
assert.Equal(t, sessionId, sessionInfo.SessionId) |
|||
assert.Equal(t, "integration-test", sessionInfo.SessionName) |
|||
assert.False(t, sessionInfo.ExpiresAt.IsZero()) |
|||
|
|||
// Verify that the session is valid
|
|||
assert.True(t, sessionInfo.ExpiresAt.After(time.Now()), "session should not be expired") |
|||
assert.False(t, sessionInfo.Credentials.Expiration.Before(time.Now()), "credentials should not be expired") |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue