Skip to content

[Enhancement] Implement Session Management with Session Cookies #77

@bsimonWallix

Description

@bsimonWallix

Issue Summary

The current Terraform provider implementation uses per-request authentication (API keys or Basic Auth) which results in unnecessary authentication overhead, large log creation on bastion and potential performance issues. This enhancement proposes implementing session management using the native Wallix Bastion session cookies to improve performance and reduce API load.

Current Problem

Authentication Overhead

Currently, the provider authenticates every single API request independently using either:

  1. API Key Authentication: X-Auth-User + X-Auth-Key headers on each request
  2. Basic Authentication: HTTP Basic Auth on each request

Code Example (Current Implementation)

// bastion/client.go - Current per-request authentication
func (c *Client) newRequest(ctx context.Context, uri string, method string, jsonBody interface{}) (string, int, error) {
    req, err := http.NewRequestWithContext(ctx, method, url, body)
    req.Header.Add("Content-Type", "application/json; charset=utf-8")
    req.Header.Add("User-Agent", "terraform-provider-wallix-bastion")
    
    if c.bastionToken != "" {
        req.Header.Add("X-Auth-Key", c.bastionToken)      // Every request
        req.Header.Add("X-Auth-User", c.bastionUser)      // Every request
    } else {
        rawcreds := c.bastionUser + ":" + c.bastionPwd
        encodedcreds := base64.StdEncoding.EncodeToString([]byte(rawcreds))
        req.Header.Add("Authorization", "Basic "+encodedcreds)  // Every request
    }
    
    resp, err := defaultHTTPClient.Do(req)
    // ...
}

Impact & Issues

Performance Issues

  • Authentication overhead: Every API call requires authentication processing
  • Credential validation: Server validates credentials on each request
  • Network overhead: Authentication headers sent with every request
  • Scalability concerns: High authentication load on Bastion servers

Security Considerations

  • Credential exposure: API keys/passwords transmitted with every request
  • Session hijacking: No session-based security benefits
  • Audit trail: Harder to track session-based activities

Operational Issues

  • Connection efficiency: No connection reuse benefits
  • Rate limiting: Each request counts against authentication limits
  • Debugging complexity: Harder to correlate related operations

Proposed Solution

Session Management Implementation

Based on the official Wallix Bastion API documentation, implement session management using:

  1. Session Creation: POST to /api creates a session and returns wab_session_id cookie
  2. Session Reuse: Use session cookie for subsequent requests (no re-authentication)
  3. CSRF Protection: Handle X-CSRF-Token header when required
  4. Session Cleanup: Explicit logout via POST to /api/logout

Architecture Overview

bastion/
├── client/
│   ├── client.go           # Enhanced HTTP client
│   ├── session.go          # Session management
│   └── csrf.go             # CSRF token handling
├── session/
│   ├── manager.go          # Session lifecycle management
│   ├── cache.go            # Session caching and renewal
│   └── auth.go             # Authentication strategies
└── provider.go             # Integration with Terraform provider

Key Components

1. Session Manager

type SessionManager struct {
    client         *http.Client
    baseURL        string
    credentials    AuthConfig
    sessionActive  bool
    sessionExpiry  time.Time
    csrfToken      string
    sessionCookie  *http.Cookie
    mutex          sync.RWMutex
}

type AuthConfig struct {
    Method    string // "api_key", "basic", "x509", "kerberos"
    User      string
    Token     string
    Password  string
    CertPath  string
}

2. Session Lifecycle Management

func (sm *SessionManager) EnsureSession(ctx context.Context) error {
    sm.mutex.Lock()
    defer sm.mutex.Unlock()

    // Check if session is still valid (2-minute timeout)
    if sm.sessionActive && time.Now().Before(sm.sessionExpiry) {
        return nil
    }

    return sm.createSession(ctx)
}

func (sm *SessionManager) createSession(ctx context.Context) error {
    sessionURL := fmt.Sprintf("%s/api", sm.baseURL)
    
    req, err := http.NewRequestWithContext(ctx, "POST", sessionURL, nil)
    if err != nil {
        return err
    }

    // Apply authentication method
    switch sm.credentials.Method {
    case "api_key":
        req.Header.Set("X-Auth-User", sm.credentials.User)
        req.Header.Set("X-Auth-Key", sm.credentials.Token)
    case "basic":
        req.SetBasicAuth(sm.credentials.User, sm.credentials.Password)
    }

    resp, err := sm.client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode == 204 {
        // Extract session cookie and CSRF token
        sm.sessionActive = true
        sm.sessionExpiry = time.Now().Add(2 * time.Minute)
        sm.extractSessionData(resp)
        return nil
    }

    return fmt.Errorf("failed to create session: %d", resp.StatusCode)
}

3. CSRF Token Management

func (sm *SessionManager) handleCSRF(req *http.Request) {
    sm.mutex.RLock()
    defer sm.mutex.RUnlock()
    
    if sm.csrfToken != "" {
        req.Header.Set("X-CSRF-Token", sm.csrfToken)
    }
}

func (sm *SessionManager) extractSessionData(resp *http.Response) {
    // Extract wab_session_id cookie
    for _, cookie := range resp.Cookies() {
        if cookie.Name == "wab_session_id" {
            sm.sessionCookie = cookie
            break
        }
    }
    
    // Extract CSRF token
    if csrfToken := resp.Header.Get("X-CSRF-Token"); csrfToken != "" {
        sm.csrfToken = csrfToken
    }
}

4. Enhanced Client Integration

func (sm *SessionManager) DoRequest(ctx context.Context, method, path string, body interface{}) (*http.Response, error) {
    // Ensure session is active
    if err := sm.EnsureSession(ctx); err != nil {
        return nil, err
    }

    req, err := http.NewRequestWithContext(ctx, method, sm.baseURL+path, nil)
    if err != nil {
        return nil, err
    }

    // Add session cookie instead of auth headers
    if sm.sessionCookie != nil {
        req.AddCookie(sm.sessionCookie)
    }
    
    // Add CSRF token if available
    sm.handleCSRF(req)

    return sm.client.Do(req)
}

Expected Benefits

Performance Improvements

  • -80% authentication overhead: Authentication only once per session
  • -30% request size: No authentication headers on each request
  • +50% throughput: Reduced server-side authentication processing
  • Session reuse: 2-minute session lifetime reduces auth calls

Security Improvements

  • Reduced credential exposure: Credentials only sent during session creation
  • CSRF protection: Built-in CSRF token support
  • Session tracking: Better audit trail for session-based operations
  • Secure logout: Explicit session termination

Operational Improvements

  • Connection efficiency: HTTP keep-alive with session cookies
  • Better debugging: Session-based request correlation
  • Rate limiting: Sessions not subject to per-request auth limits
  • Scalability: Reduced load on authentication systems

Implementation Plan

Phase 1: Core Session Management

  • Create bastion/session/ package
  • Implement SessionManager with basic session lifecycle
  • Add unit tests for session creation and management
  • Test session expiry and renewal logic

Phase 2: CSRF and Security

  • Implement CSRF token extraction and management
  • Add support for X-Use-CSRF-Token header
  • Handle api_csrf_token cookie (Bastion 12.0.3+)
  • Test CSRF token rotation and validation

Phase 3: Authentication Methods

  • Implement API key authentication for sessions
  • Implement Basic authentication for sessions
  • Add X.509 certificate authentication support
  • Add Kerberos authentication support

Phase 4: Client Integration

  • Modify bastion/client.go to use session manager
  • Update all resource operations to use session-based requests
  • Implement graceful fallback to per-request auth if needed
  • Add configuration options for session management

Phase 5: Testing and Optimization (Week 6)

  • Comprehensive integration tests
  • Performance benchmarks (before/after comparison)
  • Concurrent session handling tests
  • Error handling and recovery scenarios

Configuration Options

Provider Configuration

provider "wallix-bastion" {
  ip              = "192.168.1.100"
  user            = "admin"
  token           = "your-api-token"
  api_version     = "v3.12"
  
  # New session management options
  session_enabled = true        # Enable session management
  session_timeout = 120         # Session timeout in seconds (default: 120)
  csrf_enabled    = true        # Enable CSRF protection
  auth_method     = "api_key"   # api_key, basic, x509, kerberos
}

Environment Variables

# Session management settings
export WALLIX_SESSION_ENABLED=true
export WALLIX_SESSION_TIMEOUT=120
export WALLIX_CSRF_ENABLED=true
export WALLIX_AUTH_METHOD=api_key

Testing Strategy

Unit Tests

  • Session creation and lifecycle management
  • CSRF token extraction and handling
  • Authentication method implementations
  • Session expiry and renewal logic

Integration Tests

  • End-to-end session-based resource operations
  • Multi-resource operations within single session
  • Session timeout and recovery scenarios
  • CSRF token validation

Performance Tests

  • Benchmark authentication overhead reduction
  • Concurrent session handling capacity
  • Memory usage for session management
  • Network efficiency improvements

Success Metrics

Performance Metrics

  • Authentication calls reduction: Target 80% reduction
  • Request latency improvement: Target 20% faster requests
  • Throughput increase: Target 50% more operations per minute
  • Memory efficiency: Session cache memory usage

Reliability Metrics

  • Session success rate: Target 99.9% successful session creation
  • Session renewal success: Target 99.9% successful renewals
  • CSRF validation rate: 100% CSRF token handling
  • Fallback reliability: Graceful degradation when sessions fail

Backward Compatibility

  • Optional feature: Session management disabled by default initially
  • Graceful fallback: Per-request authentication if session fails
  • Configuration compatibility: No breaking changes to existing configs
  • Migration path: Gradual rollout with feature flags

Security Considerations

Session Security

  • Session timeout: Respect 2-minute Bastion timeout
  • Secure storage: Session data stored securely in memory only
  • Session cleanup: Explicit logout on provider destruction
  • CSRF protection: Full CSRF token lifecycle management

Authentication Security

  • Credential handling: Credentials only used for session creation
  • Token management: Secure CSRF token storage and rotation
  • Session isolation: No session sharing between provider instances
  • Audit compliance: Maintain audit trail for session operations

Risk Mitigation

  • Feature flags: Enable/disable session management per environment
  • Comprehensive testing: Extensive testing before production deployment
  • Monitoring: Track session creation and failure rates
  • Rollback plan: Quick revert to per-request authentication
  • Documentation: Clear migration guide and troubleshooting

Priority: Medium
Complexity: Medium
Impact: High
Type: Enhancement

This enhancement will significantly improve provider performance and scalability while maintaining security and reliability standards. The session-based approach aligns with modern API client best practices and leverages native Bastion session management capabilities.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions