network/e2e/deployments/https_external_test.go
2026-01-26 07:53:35 +02:00

174 lines
5.4 KiB
Go

//go:build e2e
package deployments_test
import (
"crypto/tls"
"fmt"
"io"
"net"
"net/http"
"os"
"path/filepath"
"testing"
"time"
"github.com/DeBrosOfficial/network/e2e"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestHTTPS_ExternalAccess tests that deployed apps are accessible via HTTPS
// from the public internet with valid SSL certificates.
//
// This test requires:
// - Orama deployed on a VPS with a real domain
// - DNS properly configured
// - Run with: go test -v -tags e2e -run TestHTTPS ./e2e/deployments/...
func TestHTTPS_ExternalAccess(t *testing.T) {
// Skip if not configured for external testing
externalURL := os.Getenv("ORAMA_EXTERNAL_URL")
if externalURL == "" {
t.Skip("ORAMA_EXTERNAL_URL not set - skipping external HTTPS test")
}
env, err := e2e.LoadTestEnv()
require.NoError(t, err, "Failed to load test environment")
deploymentName := fmt.Sprintf("https-test-%d", time.Now().Unix())
tarballPath := filepath.Join("../../testdata/tarballs/react-vite.tar.gz")
var deploymentID string
// Cleanup after test
defer func() {
if !env.SkipCleanup && deploymentID != "" {
e2e.DeleteDeployment(t, env, deploymentID)
}
}()
t.Run("Deploy static app", func(t *testing.T) {
deploymentID = e2e.CreateTestDeployment(t, env, deploymentName, tarballPath)
require.NotEmpty(t, deploymentID)
t.Logf("Created deployment: %s (ID: %s)", deploymentName, deploymentID)
})
var deploymentDomain string
t.Run("Get deployment domain", func(t *testing.T) {
deployment := e2e.GetDeployment(t, env, deploymentID)
nodeURL := extractNodeURL(t, deployment)
require.NotEmpty(t, nodeURL, "Deployment should have node URL")
deploymentDomain = extractDomain(nodeURL)
t.Logf("Deployment domain: %s", deploymentDomain)
})
t.Run("Wait for DNS propagation", func(t *testing.T) {
// Poll DNS until the domain resolves
deadline := time.Now().Add(2 * time.Minute)
for time.Now().Before(deadline) {
ips, err := net.LookupHost(deploymentDomain)
if err == nil && len(ips) > 0 {
t.Logf("DNS resolved: %s -> %v", deploymentDomain, ips)
return
}
t.Logf("DNS not yet resolved, waiting...")
time.Sleep(5 * time.Second)
}
t.Fatalf("DNS did not resolve within timeout for %s", deploymentDomain)
})
t.Run("Test HTTPS access with valid certificate", func(t *testing.T) {
// Create HTTP client that DOES verify certificates
// (no InsecureSkipVerify - we want to test real SSL)
client := &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
// Use default verification (validates certificate)
InsecureSkipVerify: false,
},
},
}
url := fmt.Sprintf("https://%s/", deploymentDomain)
t.Logf("Testing HTTPS: %s", url)
resp, err := client.Get(url)
require.NoError(t, err, "HTTPS request should succeed with valid certificate")
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should return 200 OK")
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
// Verify it's our React app
assert.Contains(t, string(body), "<div id=\"root\">", "Should serve React app")
t.Logf("HTTPS test passed: %s returned %d", url, resp.StatusCode)
})
t.Run("Verify SSL certificate details", func(t *testing.T) {
conn, err := tls.Dial("tcp", deploymentDomain+":443", nil)
require.NoError(t, err, "TLS dial should succeed")
defer conn.Close()
state := conn.ConnectionState()
require.NotEmpty(t, state.PeerCertificates, "Should have peer certificates")
cert := state.PeerCertificates[0]
t.Logf("Certificate subject: %s", cert.Subject)
t.Logf("Certificate issuer: %s", cert.Issuer)
t.Logf("Certificate valid from: %s to %s", cert.NotBefore, cert.NotAfter)
// Verify certificate is not expired
assert.True(t, time.Now().After(cert.NotBefore), "Certificate should be valid (not before)")
assert.True(t, time.Now().Before(cert.NotAfter), "Certificate should be valid (not expired)")
// Verify domain matches
err = cert.VerifyHostname(deploymentDomain)
assert.NoError(t, err, "Certificate should be valid for domain %s", deploymentDomain)
})
}
// TestHTTPS_DomainFormat verifies deployment URL format
func TestHTTPS_DomainFormat(t *testing.T) {
env, err := e2e.LoadTestEnv()
require.NoError(t, err, "Failed to load test environment")
deploymentName := fmt.Sprintf("domain-test-%d", time.Now().Unix())
tarballPath := filepath.Join("../../testdata/tarballs/react-vite.tar.gz")
var deploymentID string
// Cleanup after test
defer func() {
if !env.SkipCleanup && deploymentID != "" {
e2e.DeleteDeployment(t, env, deploymentID)
}
}()
t.Run("Deploy app and verify domain format", func(t *testing.T) {
deploymentID = e2e.CreateTestDeployment(t, env, deploymentName, tarballPath)
require.NotEmpty(t, deploymentID)
deployment := e2e.GetDeployment(t, env, deploymentID)
t.Logf("Deployment URLs: %+v", deployment["urls"])
// Get deployment URL (handles both array and map formats)
deploymentURL := extractNodeURL(t, deployment)
assert.NotEmpty(t, deploymentURL, "Should have deployment URL")
// URL should be simple format: {name}.{baseDomain} (NOT {name}.node-{shortID}.{baseDomain})
if deploymentURL != "" {
assert.NotContains(t, deploymentURL, ".node-", "URL should NOT contain node identifier (simplified format)")
assert.Contains(t, deploymentURL, deploymentName, "URL should contain deployment name")
t.Logf("Deployment URL: %s", deploymentURL)
}
})
}