Skip to content

🔒 SECURITY: Add TLS/HTTPS Support to REST API #326

@sfloess

Description

@sfloess

Problem Statement

The REST API server uses JDK's built-in HttpServer, which has no native TLS support, meaning all API traffic (including authentication credentials, application data, and management commands) is transmitted in plaintext.

Current Behavior

Location: jplatform-rest-api module

  • Uses com.sun.net.httpserver.HttpServer (JDK 21)
  • No TLS/HTTPS capability
  • API key authentication transmitted unencrypted
  • All application management commands in plaintext

Security Risks:

  • Credential interception: API keys sniffed on network
  • Man-in-the-middle attacks: Traffic modified in transit
  • Data exposure: Application configs, logs, metrics visible
  • Replay attacks: Captured requests can be replayed
  • Failed compliance: PCI-DSS, HIPAA, SOC 2 require encryption in transit

Expected Behavior

All API traffic should be encrypted via TLS 1.2+:

  • HTTPS endpoints (not HTTP)
  • Certificate-based server authentication
  • Strong cipher suites (no weak TLS 1.0/1.1)
  • Configurable keystores for certificates

Proposed Solutions

Option 1: Migrate to Netty HTTP Server (Recommended)

Pros:

  • Native TLS support
  • Better performance (async I/O)
  • Production-grade HTTP server
  • Stub module already exists: jplatform-rest-api-netty

Implementation:

// Complete jplatform-rest-api-netty module
ServerBootstrap bootstrap = new ServerBootstrap()
    .group(bossGroup, workerGroup)
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializer<SocketChannel>() {
        protected void initChannel(SocketChannel ch) {
            SslContext sslContext = SslContextBuilder
                .forServer(certChainFile, keyFile)
                .build();
            ch.pipeline().addLast(sslContext.newHandler(ch.alloc()));
            ch.pipeline().addLast(new HttpServerCodec());
            // ... add handlers
        }
    });

Option 2: Undertow Web Server

Pros:

  • Excellent TLS support
  • Lightweight, embeddable
  • Used by WildFly/JBoss

Implementation:

Undertow server = Undertow.builder()
    .addHttpsListener(8443, "0.0.0.0", 
        loadKeyStore(), loadTrustStore())
    .setHandler(apiHandler)
    .build();

Option 3: Reverse Proxy (Workaround)

Pros:

  • No code changes
  • Offload TLS to nginx/Traefik

Cons:

  • Requires separate infrastructure
  • Added deployment complexity
  • Not suitable for all environments

Documentation approach:
Create TLS_DEPLOYMENT.md with nginx configuration:

server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/certs/platform.crt;
    ssl_certificate_key /etc/ssl/private/platform.key;
    
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Recommended Approach

Phase 1 (Short-term): Document reverse proxy setup in TLS_DEPLOYMENT.md

Phase 2 (Medium-term): Complete jplatform-rest-api-netty module with TLS

Configuration Design

Add TLS settings to ApiServerConfig:

public static class Builder {
    private boolean enableTls = false;
    private String keystorePath;
    private String keystorePassword;
    private String keyAlias;
    private String[] enabledProtocols = {"TLSv1.2", "TLSv1.3"};
    private String[] enabledCiphers = {/* modern ciphers only */};
    
    public Builder enableTls(boolean enable) {
        this.enableTls = enable;
        return this;
    }
    
    public Builder keystorePath(String path) {
        this.keystorePath = path;
        return this;
    }
}

Acceptance Criteria

Phase 1 (Documentation):

  • TLS_DEPLOYMENT.md created with reverse proxy examples
  • nginx configuration tested
  • Traefik configuration provided
  • Certificate generation guide included
  • Let's Encrypt integration documented

Phase 2 (Netty Implementation):

  • jplatform-rest-api-netty module completed
  • TLS configuration in ApiServerConfig
  • Keystore loading and validation
  • Self-signed certificate generation for testing
  • Unit tests for TLS handshake
  • Integration tests with curl/HTTP client
  • Documentation updated

Verification Steps

Phase 1:

  1. Deploy with nginx reverse proxy
  2. Test HTTPS endpoint: curl https://localhost:443/api/applications
  3. Verify certificate validation works
  4. Check TLS version: openssl s_client -connect localhost:443 -tls1_2

Phase 2:

  1. Generate test keystore: keytool -genkeypair ...
  2. Configure Netty server with keystore
  3. Start server: mvn exec:java -pl jplatform-launcher
  4. Test: curl -k https://localhost:8443/api/applications
  5. Verify TLS 1.2+: nmap --script ssl-enum-ciphers -p 8443 localhost

References


Priority: HIGH | Production Readiness Review Score: 8.3/10

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions