CargoWise Security Best Practices: API Keys, Authentication & Data Protection (2025)

Jan 19, 2025
cargowisesecurityapi-keysauthentication
0

CargoWise security is paramount for protecting sensitive freight forwarding data, ensuring regulatory compliance, and maintaining customer trust. With increasing cyber threats and stringent data protection regulations, implementing robust security measures is not just a best practice—it's a business necessity.

This comprehensive guide covers everything you need to know about CargoWise security, from API key management and authentication to data encryption and compliance. Whether you're securing a new CargoWise implementation or enhancing an existing system, this guide will provide the security framework and best practices you need.

Understanding CargoWise Security

Security Threats and Risks

Common Security Threats:

  • Data Breaches: Unauthorized access to sensitive customer and shipment data
  • API Attacks: Exploitation of API vulnerabilities and unauthorized access
  • Insider Threats: Malicious or negligent actions by internal users
  • Phishing Attacks: Social engineering attempts to gain credentials
  • Malware and Ransomware: Malicious software targeting freight forwarding systems
  • DDoS Attacks: Distributed denial-of-service attacks disrupting operations

Data Protection Requirements:

  • Customer Data: Personal information, contact details, and preferences
  • Shipment Data: Cargo details, routing information, and tracking data
  • Financial Data: Billing information, payment details, and transaction records
  • Operational Data: Business processes, workflows, and internal communications
  • Compliance Data: Regulatory information, customs data, and audit trails

Security Framework

CargoWise Security Pillars:

  1. Authentication: Verifying user identity
  2. Authorization: Controlling access to resources
  3. Data Protection: Encrypting and securing data
  4. Network Security: Protecting communication channels
  5. Monitoring: Detecting and responding to threats
  6. Compliance: Meeting regulatory requirements

API Key Management

API Key Security Best Practices

C# API Key Management System:

public class CargoWiseApiKeyManager
{
    private readonly ILogger<CargoWiseApiKeyManager> _logger;
    private readonly IApiKeyRepository _apiKeyRepository;
    private readonly IEncryptionService _encryptionService;
    private readonly IAuditService _auditService;
    
    public CargoWiseApiKeyManager(
        ILogger<CargoWiseApiKeyManager> logger,
        IApiKeyRepository apiKeyRepository,
        IEncryptionService encryptionService,
        IAuditService auditService)
    {
        _logger = logger;
        _apiKeyRepository = apiKeyRepository;
        _encryptionService = encryptionService;
        _auditService = auditService;
    }
    
    public async Task<ApiKeyResult> CreateApiKey(CreateApiKeyRequest request)
    {
        var result = new ApiKeyResult
        {
            StartTime = DateTime.UtcNow,
            Status = ApiKeyStatus.InProgress
        };
        
        try
        {
            _logger.LogInformation("Creating API key for user: {UserId}", request.UserId);
            
            // Generate secure API key
            var apiKey = GenerateSecureApiKey();
            var hashedKey = await _encryptionService.HashAsync(apiKey);
            
            // Create API key record
            var apiKeyRecord = new ApiKeyRecord
            {
                Id = Guid.NewGuid().ToString(),
                UserId = request.UserId,
                Name = request.Name,
                Description = request.Description,
                HashedKey = hashedKey,
                Permissions = request.Permissions,
                ExpiresAt = request.ExpiresAt,
                IsActive = true,
                CreatedAt = DateTime.UtcNow,
                LastUsedAt = null
            };
            
            // Store API key
            await _apiKeyRepository.CreateAsync(apiKeyRecord);
            
            // Log audit event
            await _auditService.LogEventAsync(new AuditEvent
            {
                EventType = "API_KEY_CREATED",
                UserId = request.UserId,
                Details = new { ApiKeyId = apiKeyRecord.Id, Name = request.Name },
                Timestamp = DateTime.UtcNow
            });
            
            result.Status = ApiKeyStatus.Created;
            result.ApiKey = apiKey;
            result.ApiKeyId = apiKeyRecord.Id;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogInformation("API key created successfully: {ApiKeyId}", apiKeyRecord.Id);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating API key for user: {UserId}", request.UserId);
            
            result.Status = ApiKeyStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    public async Task<ApiKeyValidationResult> ValidateApiKey(string apiKey)
    {
        var result = new ApiKeyValidationResult
        {
            StartTime = DateTime.UtcNow,
            Status = ApiKeyValidationStatus.InProgress
        };
        
        try
        {
            _logger.LogDebug("Validating API key");
            
            // Hash the provided API key
            var hashedKey = await _encryptionService.HashAsync(apiKey);
            
            // Find API key record
            var apiKeyRecord = await _apiKeyRepository.GetByHashedKeyAsync(hashedKey);
            
            if (apiKeyRecord == null)
            {
                result.Status = ApiKeyValidationStatus.Invalid;
                result.ErrorMessage = "API key not found";
                return result;
            }
            
            // Check if API key is active
            if (!apiKeyRecord.IsActive)
            {
                result.Status = ApiKeyValidationStatus.Inactive;
                result.ErrorMessage = "API key is inactive";
                return result;
            }
            
            // Check if API key has expired
            if (apiKeyRecord.ExpiresAt.HasValue && apiKeyRecord.ExpiresAt.Value < DateTime.UtcNow)
            {
                result.Status = ApiKeyValidationStatus.Expired;
                result.ErrorMessage = "API key has expired";
                return result;
            }
            
            // Update last used timestamp
            apiKeyRecord.LastUsedAt = DateTime.UtcNow;
            await _apiKeyRepository.UpdateAsync(apiKeyRecord);
            
            // Log audit event
            await _auditService.LogEventAsync(new AuditEvent
            {
                EventType = "API_KEY_VALIDATED",
                UserId = apiKeyRecord.UserId,
                Details = new { ApiKeyId = apiKeyRecord.Id },
                Timestamp = DateTime.UtcNow
            });
            
            result.Status = ApiKeyValidationStatus.Valid;
            result.UserId = apiKeyRecord.UserId;
            result.Permissions = apiKeyRecord.Permissions;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogDebug("API key validated successfully: {ApiKeyId}", apiKeyRecord.Id);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error validating API key");
            
            result.Status = ApiKeyValidationStatus.Error;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    private string GenerateSecureApiKey()
    {
        // Generate a cryptographically secure random API key
        var bytes = new byte[32];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(bytes);
        }
        
        return Convert.ToBase64String(bytes);
    }
}

API Key Rotation and Management

C# API Key Rotation System:

public class CargoWiseApiKeyRotationService
{
    private readonly ILogger<CargoWiseApiKeyRotationService> _logger;
    private readonly IApiKeyRepository _apiKeyRepository;
    private readonly IEncryptionService _encryptionService;
    private readonly INotificationService _notificationService;
    private readonly Timer _rotationTimer;
    
    public CargoWiseApiKeyRotationService(
        ILogger<CargoWiseApiKeyRotationService> logger,
        IApiKeyRepository apiKeyRepository,
        IEncryptionService encryptionService,
        INotificationService notificationService)
    {
        _logger = logger;
        _apiKeyRepository = apiKeyRepository;
        _encryptionService = encryptionService;
        _notificationService = notificationService;
        
        // Set up automatic rotation timer (daily check)
        _rotationTimer = new Timer(CheckForRotation, null, TimeSpan.Zero, TimeSpan.FromDays(1));
    }
    
    private async void CheckForRotation(object state)
    {
        try
        {
            await RotateExpiredKeys();
            await RotateKeysNearExpiration();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error during API key rotation check");
        }
    }
    
    public async Task<ApiKeyRotationResult> RotateApiKey(string apiKeyId, string userId)
    {
        var result = new ApiKeyRotationResult
        {
            ApiKeyId = apiKeyId,
            StartTime = DateTime.UtcNow,
            Status = ApiKeyRotationStatus.InProgress
        };
        
        try
        {
            _logger.LogInformation("Rotating API key: {ApiKeyId}", apiKeyId);
            
            // Get current API key
            var currentApiKey = await _apiKeyRepository.GetByIdAsync(apiKeyId);
            if (currentApiKey == null)
            {
                result.Status = ApiKeyRotationStatus.NotFound;
                result.ErrorMessage = "API key not found";
                return result;
            }
            
            // Generate new API key
            var newApiKey = GenerateSecureApiKey();
            var newHashedKey = await _encryptionService.HashAsync(newApiKey);
            
            // Create new API key record
            var newApiKeyRecord = new ApiKeyRecord
            {
                Id = Guid.NewGuid().ToString(),
                UserId = currentApiKey.UserId,
                Name = currentApiKey.Name,
                Description = currentApiKey.Description,
                HashedKey = newHashedKey,
                Permissions = currentApiKey.Permissions,
                ExpiresAt = currentApiKey.ExpiresAt,
                IsActive = true,
                CreatedAt = DateTime.UtcNow,
                LastUsedAt = null
            };
            
            // Store new API key
            await _apiKeyRepository.CreateAsync(newApiKeyRecord);
            
            // Deactivate old API key
            currentApiKey.IsActive = false;
            currentApiKey.DeactivatedAt = DateTime.UtcNow;
            await _apiKeyRepository.UpdateAsync(currentApiKey);
            
            // Notify user
            await _notificationService.SendNotificationAsync(userId, new ApiKeyRotationNotification
            {
                OldApiKeyId = apiKeyId,
                NewApiKeyId = newApiKeyRecord.Id,
                NewApiKey = newApiKey,
                RotationDate = DateTime.UtcNow
            });
            
            result.Status = ApiKeyRotationStatus.Completed;
            result.NewApiKey = newApiKey;
            result.NewApiKeyId = newApiKeyRecord.Id;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogInformation("API key rotated successfully: {ApiKeyId} -> {NewApiKeyId}", 
                apiKeyId, newApiKeyRecord.Id);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error rotating API key: {ApiKeyId}", apiKeyId);
            
            result.Status = ApiKeyRotationStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    private async Task RotateExpiredKeys()
    {
        var expiredKeys = await _apiKeyRepository.GetExpiredKeysAsync();
        
        foreach (var key in expiredKeys)
        {
            if (key.IsActive)
            {
                key.IsActive = false;
                key.DeactivatedAt = DateTime.UtcNow;
                await _apiKeyRepository.UpdateAsync(key);
                
                _logger.LogInformation("Deactivated expired API key: {ApiKeyId}", key.Id);
            }
        }
    }
    
    private async Task RotateKeysNearExpiration()
    {
        var keysNearExpiration = await _apiKeyRepository.GetKeysNearExpirationAsync(TimeSpan.FromDays(7));
        
        foreach (var key in keysNearExpiration)
        {
            await _notificationService.SendNotificationAsync(key.UserId, new ApiKeyExpirationNotification
            {
                ApiKeyId = key.Id,
                ExpiresAt = key.ExpiresAt.Value,
                DaysUntilExpiration = (key.ExpiresAt.Value - DateTime.UtcNow).Days
            });
        }
    }
}

Authentication Methods

Multi-Factor Authentication

C# MFA Implementation:

public class CargoWiseMfaService
{
    private readonly ILogger<CargoWiseMfaService> _logger;
    private readonly IUserRepository _userRepository;
    private readonly IEncryptionService _encryptionService;
    private readonly ITotpService _totpService;
    private readonly ISmsService _smsService;
    private readonly IEmailService _emailService;
    
    public CargoWiseMfaService(
        ILogger<CargoWiseMfaService> logger,
        IUserRepository userRepository,
        IEncryptionService encryptionService,
        ITotpService totpService,
        ISmsService smsService,
        IEmailService emailService)
    {
        _logger = logger;
        _userRepository = userRepository;
        _encryptionService = encryptionService;
        _totpService = totpService;
        _smsService = smsService;
        _emailService = emailService;
    }
    
    public async Task<MfaSetupResult> SetupMfa(string userId, MfaMethod method)
    {
        var result = new MfaSetupResult
        {
            UserId = userId,
            Method = method,
            StartTime = DateTime.UtcNow,
            Status = MfaSetupStatus.InProgress
        };
        
        try
        {
            _logger.LogInformation("Setting up MFA for user: {UserId}, method: {Method}", userId, method);
            
            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null)
            {
                result.Status = MfaSetupStatus.UserNotFound;
                result.ErrorMessage = "User not found";
                return result;
            }
            
            switch (method)
            {
                case MfaMethod.Totp:
                    result = await SetupTotpMfa(user);
                    break;
                case MfaMethod.Sms:
                    result = await SetupSmsMfa(user);
                    break;
                case MfaMethod.Email:
                    result = await SetupEmailMfa(user);
                    break;
                default:
                    result.Status = MfaSetupStatus.InvalidMethod;
                    result.ErrorMessage = "Invalid MFA method";
                    return result;
            }
            
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogInformation("MFA setup completed for user: {UserId}, method: {Method}, status: {Status}", 
                userId, method, result.Status);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error setting up MFA for user: {UserId}, method: {Method}", userId, method);
            
            result.Status = MfaSetupStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    private async Task<MfaSetupResult> SetupTotpMfa(User user)
    {
        var result = new MfaSetupResult
        {
            UserId = user.Id,
            Method = MfaMethod.Totp,
            StartTime = DateTime.UtcNow,
            Status = MfaSetupStatus.InProgress
        };
        
        try
        {
            // Generate TOTP secret
            var secret = _totpService.GenerateSecret();
            
            // Encrypt and store secret
            var encryptedSecret = await _encryptionService.EncryptAsync(secret);
            user.MfaSecret = encryptedSecret;
            user.MfaMethod = MfaMethod.Totp;
            user.MfaEnabled = true;
            
            await _userRepository.UpdateAsync(user);
            
            // Generate QR code for authenticator app
            var qrCodeUrl = _totpService.GenerateQrCodeUrl(user.Email, secret);
            
            result.Status = MfaSetupStatus.Completed;
            result.QrCodeUrl = qrCodeUrl;
            result.Secret = secret;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error setting up TOTP MFA for user: {UserId}", user.Id);
            
            result.Status = MfaSetupStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    private async Task<MfaSetupResult> SetupSmsMfa(User user)
    {
        var result = new MfaSetupResult
        {
            UserId = user.Id,
            Method = MfaMethod.Sms,
            StartTime = DateTime.UtcNow,
            Status = MfaSetupStatus.InProgress
        };
        
        try
        {
            // Validate phone number
            if (string.IsNullOrEmpty(user.PhoneNumber))
            {
                result.Status = MfaSetupStatus.PhoneNumberRequired;
                result.ErrorMessage = "Phone number is required for SMS MFA";
                return result;
            }
            
            // Send verification code
            var verificationCode = GenerateVerificationCode();
            await _smsService.SendSmsAsync(user.PhoneNumber, $"Your CargoWise verification code is: {verificationCode}");
            
            // Store verification code temporarily
            user.MfaVerificationCode = await _encryptionService.EncryptAsync(verificationCode);
            user.MfaVerificationCodeExpiresAt = DateTime.UtcNow.AddMinutes(5);
            user.MfaMethod = MfaMethod.Sms;
            user.MfaEnabled = false; // Will be enabled after verification
            
            await _userRepository.UpdateAsync(user);
            
            result.Status = MfaSetupStatus.PendingVerification;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error setting up SMS MFA for user: {UserId}", user.Id);
            
            result.Status = MfaSetupStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    public async Task<MfaVerificationResult> VerifyMfa(string userId, string code)
    {
        var result = new MfaVerificationResult
        {
            UserId = userId,
            StartTime = DateTime.UtcNow,
            Status = MfaVerificationStatus.InProgress
        };
        
        try
        {
            _logger.LogInformation("Verifying MFA for user: {UserId}", userId);
            
            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null)
            {
                result.Status = MfaVerificationStatus.UserNotFound;
                result.ErrorMessage = "User not found";
                return result;
            }
            
            if (!user.MfaEnabled)
            {
                result.Status = MfaVerificationStatus.MfaNotEnabled;
                result.ErrorMessage = "MFA is not enabled for this user";
                return result;
            }
            
            bool isValid = false;
            
            switch (user.MfaMethod)
            {
                case MfaMethod.Totp:
                    isValid = await VerifyTotpCode(user, code);
                    break;
                case MfaMethod.Sms:
                    isValid = await VerifySmsCode(user, code);
                    break;
                case MfaMethod.Email:
                    isValid = await VerifyEmailCode(user, code);
                    break;
                default:
                    result.Status = MfaVerificationStatus.InvalidMethod;
                    result.ErrorMessage = "Invalid MFA method";
                    return result;
            }
            
            if (isValid)
            {
                result.Status = MfaVerificationStatus.Valid;
                result.IsValid = true;
            }
            else
            {
                result.Status = MfaVerificationStatus.Invalid;
                result.ErrorMessage = "Invalid verification code";
            }
            
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogInformation("MFA verification completed for user: {UserId}, status: {Status}", 
                userId, result.Status);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error verifying MFA for user: {UserId}", userId);
            
            result.Status = MfaVerificationStatus.Error;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
}

Data Encryption

Encryption at Rest

C# Data Encryption Service:

public class CargoWiseDataEncryptionService
{
    private readonly ILogger<CargoWiseDataEncryptionService> _logger;
    private readonly IEncryptionKeyRepository _keyRepository;
    private readonly IConfiguration _configuration;
    
    public CargoWiseDataEncryptionService(
        ILogger<CargoWiseDataEncryptionService> logger,
        IEncryptionKeyRepository keyRepository,
        IConfiguration configuration)
    {
        _logger = logger;
        _keyRepository = keyRepository;
        _configuration = configuration;
    }
    
    public async Task<EncryptionResult> EncryptDataAsync(string data, string keyId = null)
    {
        var result = new EncryptionResult
        {
            StartTime = DateTime.UtcNow,
            Status = EncryptionStatus.InProgress
        };
        
        try
        {
            _logger.LogDebug("Encrypting data with key: {KeyId}", keyId ?? "default");
            
            // Get encryption key
            var encryptionKey = await GetEncryptionKeyAsync(keyId);
            
            // Encrypt data
            var encryptedData = await EncryptStringAsync(data, encryptionKey);
            
            result.Status = EncryptionStatus.Completed;
            result.EncryptedData = encryptedData;
            result.KeyId = encryptionKey.Id;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogDebug("Data encrypted successfully with key: {KeyId}", encryptionKey.Id);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error encrypting data with key: {KeyId}", keyId);
            
            result.Status = EncryptionStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    public async Task<DecryptionResult> DecryptDataAsync(string encryptedData, string keyId)
    {
        var result = new DecryptionResult
        {
            StartTime = DateTime.UtcNow,
            Status = DecryptionStatus.InProgress
        };
        
        try
        {
            _logger.LogDebug("Decrypting data with key: {KeyId}", keyId);
            
            // Get encryption key
            var encryptionKey = await GetEncryptionKeyAsync(keyId);
            
            // Decrypt data
            var decryptedData = await DecryptStringAsync(encryptedData, encryptionKey);
            
            result.Status = DecryptionStatus.Completed;
            result.DecryptedData = decryptedData;
            result.KeyId = encryptionKey.Id;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogDebug("Data decrypted successfully with key: {KeyId}", encryptionKey.Id);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error decrypting data with key: {KeyId}", keyId);
            
            result.Status = DecryptionStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    private async Task<EncryptionKey> GetEncryptionKeyAsync(string keyId)
    {
        if (string.IsNullOrEmpty(keyId))
        {
            keyId = _configuration["Encryption:DefaultKeyId"];
        }
        
        var key = await _keyRepository.GetByIdAsync(keyId);
        if (key == null)
        {
            throw new EncryptionKeyNotFoundException($"Encryption key not found: {keyId}");
        }
        
        return key;
    }
    
    private async Task<string> EncryptStringAsync(string plainText, EncryptionKey key)
    {
        using (var aes = Aes.Create())
        {
            aes.Key = Convert.FromBase64String(key.Key);
            aes.IV = Convert.FromBase64String(key.IV);
            
            using (var encryptor = aes.CreateEncryptor())
            using (var msEncrypt = new MemoryStream())
            using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            using (var swEncrypt = new StreamWriter(csEncrypt))
            {
                await swEncrypt.WriteAsync(plainText);
                await swEncrypt.FlushAsync();
                csEncrypt.FlushFinalBlock();
                
                return Convert.ToBase64String(msEncrypt.ToArray());
            }
        }
    }
    
    private async Task<string> DecryptStringAsync(string cipherText, EncryptionKey key)
    {
        using (var aes = Aes.Create())
        {
            aes.Key = Convert.FromBase64String(key.Key);
            aes.IV = Convert.FromBase64String(key.IV);
            
            using (var decryptor = aes.CreateDecryptor())
            using (var msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
            using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            using (var srDecrypt = new StreamReader(csDecrypt))
            {
                return await srDecrypt.ReadToEndAsync();
            }
        }
    }
}

Encryption in Transit

C# TLS Configuration:

public class CargoWiseTlsConfiguration
{
    private readonly ILogger<CargoWiseTlsConfiguration> _logger;
    private readonly IConfiguration _configuration;
    
    public CargoWiseTlsConfiguration(ILogger<CargoWiseTlsConfiguration> logger, IConfiguration configuration)
    {
        _logger = logger;
        _configuration = configuration;
    }
    
    public void ConfigureTls(IServiceCollection services)
    {
        // Configure HTTP client with TLS
        services.AddHttpClient<CargoWiseApiClient>(client =>
        {
            client.DefaultRequestHeaders.Add("User-Agent", "CargoWise-Client/1.0");
            client.Timeout = TimeSpan.FromSeconds(30);
        })
        .ConfigurePrimaryHttpMessageHandler(() =>
        {
            var handler = new HttpClientHandler();
            
            // Configure TLS settings
            handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
            handler.CheckCertificateRevocationList = true;
            handler.ServerCertificateCustomValidationCallback = ValidateServerCertificate;
            
            return handler;
        });
    }
    
    private bool ValidateServerCertificate(HttpRequestMessage request, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        // Log certificate validation
        _logger.LogDebug("Validating server certificate for: {Host}", request.RequestUri.Host);
        
        // Check for SSL policy errors
        if (sslPolicyErrors != SslPolicyErrors.None)
        {
            _logger.LogWarning("SSL policy errors detected: {Errors}", sslPolicyErrors);
            
            // Allow specific hosts for development
            if (IsDevelopmentHost(request.RequestUri.Host))
            {
                _logger.LogWarning("Allowing development host despite SSL errors: {Host}", request.RequestUri.Host);
                return true;
            }
            
            return false;
        }
        
        // Validate certificate chain
        if (chain != null)
        {
            var chainStatus = chain.ChainStatus;
            foreach (var status in chainStatus)
            {
                if (status.Status != X509ChainStatusFlags.NoError)
                {
                    _logger.LogWarning("Certificate chain error: {Status}", status.Status);
                    return false;
                }
            }
        }
        
        // Validate certificate expiration
        if (certificate.NotAfter < DateTime.UtcNow)
        {
            _logger.LogWarning("Certificate has expired: {NotAfter}", certificate.NotAfter);
            return false;
        }
        
        // Validate certificate not before date
        if (certificate.NotBefore > DateTime.UtcNow)
        {
            _logger.LogWarning("Certificate is not yet valid: {NotBefore}", certificate.NotBefore);
            return false;
        }
        
        _logger.LogDebug("Server certificate validation successful for: {Host}", request.RequestUri.Host);
        return true;
    }
    
    private bool IsDevelopmentHost(string host)
    {
        var developmentHosts = _configuration.GetSection("Security:DevelopmentHosts").Get<string[]>();
        return developmentHosts?.Contains(host) ?? false;
    }
}

Compliance and Audit

Audit Logging

C# Audit Service:

public class CargoWiseAuditService
{
    private readonly ILogger<CargoWiseAuditService> _logger;
    private readonly IAuditRepository _auditRepository;
    private readonly IEncryptionService _encryptionService;
    
    public CargoWiseAuditService(
        ILogger<CargoWiseAuditService> logger,
        IAuditRepository auditRepository,
        IEncryptionService encryptionService)
    {
        _logger = logger;
        _auditRepository = auditRepository;
        _encryptionService = encryptionService;
    }
    
    public async Task<AuditResult> LogEventAsync(AuditEvent auditEvent)
    {
        var result = new AuditResult
        {
            StartTime = DateTime.UtcNow,
            Status = AuditStatus.InProgress
        };
        
        try
        {
            _logger.LogDebug("Logging audit event: {EventType}", auditEvent.EventType);
            
            // Encrypt sensitive data
            var encryptedDetails = await EncryptSensitiveData(auditEvent.Details);
            
            // Create audit record
            var auditRecord = new AuditRecord
            {
                Id = Guid.NewGuid().ToString(),
                EventType = auditEvent.EventType,
                UserId = auditEvent.UserId,
                SessionId = auditEvent.SessionId,
                IpAddress = auditEvent.IpAddress,
                UserAgent = auditEvent.UserAgent,
                Details = encryptedDetails,
                Timestamp = auditEvent.Timestamp,
                Severity = auditEvent.Severity
            };
            
            // Store audit record
            await _auditRepository.CreateAsync(auditRecord);
            
            result.Status = AuditStatus.Completed;
            result.AuditId = auditRecord.Id;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            _logger.LogDebug("Audit event logged successfully: {AuditId}", auditRecord.Id);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error logging audit event: {EventType}", auditEvent.EventType);
            
            result.Status = AuditStatus.Failed;
            result.ErrorMessage = ex.Message;
            result.EndTime = DateTime.UtcNow;
            result.Duration = result.EndTime - result.StartTime;
            
            return result;
        }
    }
    
    public async Task<List<AuditRecord>> GetAuditTrailAsync(AuditQuery query)
    {
        try
        {
            _logger.LogDebug("Retrieving audit trail for query: {Query}", query);
            
            var auditRecords = await _auditRepository.GetByQueryAsync(query);
            
            // Decrypt sensitive data
            foreach (var record in auditRecords)
            {
                record.Details = await DecryptSensitiveData(record.Details);
            }
            
            _logger.LogDebug("Retrieved {Count} audit records", auditRecords.Count);
            
            return auditRecords;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving audit trail");
            throw;
        }
    }
    
    private async Task<string> EncryptSensitiveData(object details)
    {
        if (details == null) return null;
        
        var json = JsonSerializer.Serialize(details);
        return await _encryptionService.EncryptAsync(json);
    }
    
    private async Task<object> DecryptSensitiveData(string encryptedDetails)
    {
        if (string.IsNullOrEmpty(encryptedDetails)) return null;
        
        var decryptedJson = await _encryptionService.DecryptAsync(encryptedDetails);
        return JsonSerializer.Deserialize<object>(decryptedJson);
    }
}

Conclusion

CargoWise security is a critical aspect of freight forwarding operations that requires continuous attention and improvement. By implementing the security measures and best practices outlined in this guide, you can protect your sensitive data, ensure regulatory compliance, and maintain customer trust.

Key Takeaways:

  1. Implement Multi-Layer Security: Use multiple security controls and defense in depth
  2. Manage API Keys Securely: Implement proper key management, rotation, and monitoring
  3. Use Strong Authentication: Implement MFA and secure authentication methods
  4. Encrypt Data Everywhere: Encrypt data at rest, in transit, and in use
  5. Monitor and Audit: Implement comprehensive logging and monitoring

Next Steps:

  1. Assess Current Security posture and identify gaps
  2. Implement Security Controls based on risk assessment
  3. Train Users on security best practices and procedures
  4. Monitor Continuously for security threats and incidents
  5. Review and Update security measures regularly

For more CargoWise security guidance and implementation support, explore our CargoWise Integration Services or contact our team for personalized consulting.

FAQ

Q: How often should I rotate API keys in CargoWise? A: API keys should be rotated regularly, typically every 90 days for high-privilege keys and every 180 days for standard keys. Implement automatic rotation for critical keys.

Q: What are the best practices for CargoWise password policies? A: Implement strong password policies with minimum length (12+ characters), complexity requirements, password history, and regular expiration. Consider using password managers and passphrases.

Q: How do I implement data encryption in CargoWise? A: Use encryption at rest for database storage, TLS for data in transit, and field-level encryption for sensitive data. Implement proper key management and rotation.

Q: What compliance requirements apply to CargoWise security? A: Common requirements include GDPR, CCPA, SOX, PCI DSS, and industry-specific regulations. Implement appropriate controls based on your jurisdiction and industry.

Q: How do I monitor CargoWise security events? A: Implement comprehensive audit logging, security monitoring, and alerting systems. Monitor for suspicious activities, failed authentication attempts, and data access patterns.

Related posts