Skip to content

Security & Validation #202

@jmgilman

Description

@jmgilman

Security & Validation

Overview

Implement comprehensive security measures and input validation to ensure the Certificate API Service is protected against common vulnerabilities and only processes valid, authorized requests.

Objective

Create robust security controls including input validation, CSR validation, TLS configuration, and secret management integration to maintain the security and integrity of the certificate issuance system.

Canonical Scope

  • This document is the canonical source for:
    • Error response schema and error codes used across the API
    • All input validation rules (domains, IPs, profiles, validity)
    • CSR parsing, signature checks, and key-strength validation
    • Outbound TLS requirements and certificate pinning for AWS calls
  • Server-side TLS termination is provided by Envoy Gateway. The API server SHOULD NOT implement in-process TLS except for local development scenarios. See 06 Monitoring & Observability for operational concerns.

Tasks

Input Validation Framework

  • Implement input validation in internal/api/validation/validators.go
  • Create custom Gin validators for certificate requests
  • Implement domain name validation:
    func ValidateDomainName(domain string) error {
      // RFC-compliant domain name validation
      // Check for valid characters, length, format
      // Reject invalid TLDs or reserved domains
    }
  • Implement IP address validation for SANs:
    func ValidateIPAddress(ip string) error {
      // Validate IPv4 and IPv6 addresses
      // Check for private IP ranges if restricted
      // Validate format and range
    }
  • Validate certificate profile against allowed values:
    func ValidateProfile(profile string) error {
      allowedProfiles := []string{"client", "server", "machine"}
      // Ensure profile is in allowed list
    }
  • Enforce validity period (max 7 days):
    func ValidateValidityPeriod(days int) error {
      if days < 1 || days > 7 {
        return errors.New("validity period must be between 1 and 7 days")
      }
      return nil
    }
  • Implement wildcard certificate validation rules
  • Create validators for all API request fields

CSR Validation

  • Implement CSR validation in internal/ca/validation.go
  • Parse and validate CSR format using crypto/x509:
    func ValidateCSR(csrPEM []byte) (*x509.CertificateRequest, error) {
      block, _ := pem.Decode(csrPEM)
      if block == nil || block.Type != "CERTIFICATE REQUEST" {
        return nil, errors.New("invalid CSR format")
      }
    
      csr, err := x509.ParseCertificateRequest(block.Bytes)
      if err != nil {
        return nil, err
      }
    
      // Verify CSR signature
      if err := csr.CheckSignature(); err != nil {
        return nil, errors.New("invalid CSR signature")
      }
    
      return csr, nil
    }
  • Validate key strength:
    • RSA: minimum 2048 bits
    • ECDSA: P-256 minimum
  • Validate subject fields:
    • Common Name format
    • Organization fields (if required)
    • Country codes (if present)
  • Extract and validate SAN entries from CSR
  • Ensure CSR subject matches requested certificate parameters

TLS for External Calls

  • Note: API server TLS is handled by Envoy Gateway
  • Configure TLS for outbound AWS PCA API calls only:
    func ConfigureAWSClientTLS() *tls.Config {
      // Configure TLS 1.2 minimum for AWS API calls
      return &tls.Config{
        MinVersion: tls.VersionTLS12,
      }
    }

Secret Management

  • Note: Secrets are provided via Kubernetes ExternalSecret (managed by external-secrets-operator)
  • Secrets are loaded through the configuration system which reads environment variables
  • Expected secrets from ExternalSecret injected as environment variables:
    • Database credentials (handled by config system as per issue feat: adds cuetools package #1)
    • Any API keys (if needed)
    • Service account credentials (if needed)
  • Use IAM roles for AWS service access (via IRSA - IAM Roles for Service Accounts)
  • Ensure secrets are never logged:
    func (c *Config) String() string {
      // Redact sensitive fields when printing config
      redacted := *c
      redacted.Database.Password = "[REDACTED]"
      return fmt.Sprintf("%+v", redacted)
    }
  • Validate all required secrets are present during config validation on startup

Certificate Pinning

  • Implement certificate pinning for AWS PCA API calls
  • Configure trusted CA certificates for AWS APIs:
    func ConfigureAWSCertificatePinning() *tls.Config {
      // Load AWS root certificates
      // Configure pinning in TLS config
      // Return configured TLS transport
    }
  • Validate AWS API certificates against pinned certificates
  • Handle certificate rotation gracefully

Input Sanitization

  • Sanitize all input parameters before processing
  • Prevent SQL injection through GORM parameterized queries:
    // Always use parameterized queries
    db.Where("serial_number = ?", serial).First(&cert)
    // Never concatenate user input into queries
  • Sanitize log output to prevent log injection:
    func SanitizeForLogging(input string) string {
      // Remove newlines and control characters
      // Escape special characters
      // Truncate if too long
    }
  • Validate JSON structure before parsing
  • Implement request size limits

Error Response Security

  • Ensure error messages don't leak sensitive information
  • Implement consistent error response format:
    type ErrorResponse struct {
      Error   string                 `json:"error"`
      Message string                 `json:"message"`
      Details map[string]interface{} `json:"details,omitempty"`
    }
  • Map internal errors to safe external messages
  • Log detailed errors internally, return generic errors to clients
  • Implement the common error codes as specified:
    • invalid_token - JWT token invalid or expired
    • insufficient_permissions - RBAC authorization failed
    • invalid_csr - CSR format or signature invalid
    • domain_not_authorized - Requested domain not permitted
    • certificate_not_found - Certificate serial not found
    • renewal_too_early - Certificate not yet eligible for renewal

Security Audit

  • Implement security event logging:
    • Failed authentication attempts
    • Authorization failures
    • Invalid CSR submissions
    • Rate limit violations
    • TLS handshake failures
  • Create security metrics for monitoring

Acceptance Criteria

  • All input validation working correctly
  • CSR validation rejecting invalid requests
  • TLS 1.2 minimum enforced for AWS API calls
  • Secrets read from environment variables (provided by ExternalSecret)
  • No SQL injection vulnerabilities
  • No log injection vulnerabilities
  • Security headers properly set
  • Error messages don't leak sensitive data
  • Certificate pinning implemented for AWS APIs

Technical Considerations

  • Use crypto/x509 for certificate operations
  • Use AWS SDK v2 for Secrets Manager
  • Implement defense in depth (multiple layers of security)
  • Follow OWASP best practices
  • Use constant-time comparisons for security-sensitive operations
  • Validate input at multiple levels (API, business logic, database)
  • Consider security testing tools integration

Dependencies

Testing Requirements

  • Unit tests for all validators
  • Unit tests for CSR validation
  • Unit tests for sanitization functions
  • Security testing:
    • SQL injection attempts
    • Log injection attempts
    • Invalid input handling
  • Test missing environment variables handling
  • Test rate limiting
  • Penetration testing (if applicable)
  • OWASP top 10 vulnerability scanning

Definition of Done

  • Code reviewed and approved
  • All tests passing
  • Security review completed
  • No vulnerable dependencies
  • Secrets properly managed
  • Input validation comprehensive
  • Security documentation updated

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions