Skip to content

Commit 13b489f

Browse files
Merge pull request #57 from WarpBuilds/fix/transparent-cache
2 parents 6dd5739 + d9d45ae commit 13b489f

File tree

8 files changed

+112
-53
lines changed

8 files changed

+112
-53
lines changed

.github/workflows/release-testing.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Branch Build and Upload to R2
33
on:
44
push:
55
branches:
6-
- ah-docker-layer-caching
6+
- fix/transparent-cache
77

88
env:
99
AWS_ACCESS_KEY_ID: ${{ secrets.WB_PACKAGES_DEV_R2_ACCESS_KEY_ID }}

pkg/app/app.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"os"
88
"os/signal"
9+
"path/filepath"
910
"strings"
1011
"syscall"
1112
"time"
@@ -90,10 +91,11 @@ type ProxySettings struct {
9091
}
9192

9293
type TransparentCacheSettings struct {
93-
DerpPort int `json:"derp_port"`
94-
OginyPort int `json:"oginy_port"`
95-
AsurPort int `json:"asur_port"`
96-
LoggingEnabled bool `json:"logging_enabled"`
94+
DerpPort int `json:"derp_port"`
95+
OginyPort int `json:"oginy_port"`
96+
AsurPort int `json:"asur_port"`
97+
LoggingEnabled bool `json:"logging_enabled"`
98+
CertDir string `json:"cert_dir"`
9799
}
98100

99101
func (t *TransparentCacheSettings) ApplyDefaults() {
@@ -106,6 +108,14 @@ func (t *TransparentCacheSettings) ApplyDefaults() {
106108
if t.AsurPort == 0 {
107109
t.AsurPort = 59993
108110
}
111+
if t.CertDir == "" {
112+
// Default to ~/runner/certs, with fallback to /home/runner/certs
113+
homeBase := os.Getenv("HOME")
114+
if homeBase == "" {
115+
homeBase = "/home/runner"
116+
}
117+
t.CertDir = filepath.Join(homeBase, "certs")
118+
}
109119
}
110120

111121
type RunnerSettings struct {
@@ -258,6 +268,7 @@ func NewApp(ctx context.Context, opts *ApplicationOptions) error {
258268
settings.TransparentCache.AsurPort,
259269
settings.Proxy.CacheBackendHost,
260270
settings.Agent.RunnerVerificationToken,
271+
settings.TransparentCache.CertDir,
261272
settings.TransparentCache.LoggingEnabled,
262273
); err != nil {
263274
log.Logger().Errorf("failed to start transparent cache: %v", err)

pkg/manager/manager_github.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ func (m *ghManager) StartRunner(ctx context.Context, opts *StartRunnerOptions) (
147147
})
148148
if err != nil {
149149
log.Logger().Errorf("error running post-end hook %s: %v", hook.HookID(), err)
150-
return nil, err
151150
}
152151
}
153152

pkg/manager/manager_github_cri.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ func (m *ghcriManager) StartRunner(ctx context.Context, opts *StartRunnerOptions
141141
})
142142
if err != nil {
143143
log.Logger().Errorf("error running post-end hook %s: %v", hook.HookID(), err)
144-
return nil, err
145144
}
146145
}
147146

pkg/manager/manager_windows_github_cri.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ func (m *ghWindowsCriManager) StartRunner(ctx context.Context, opts *StartRunner
149149
})
150150
if err != nil {
151151
log.Logger().Errorf("error running post-end hook %s: %v", hook.HookID(), err)
152-
return nil, err
153152
}
154153
}
155154

pkg/transparent-cache/oginy/oginy.go

Lines changed: 92 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import (
1818
"net/http/httputil"
1919
"net/url"
2020
"os"
21+
"os/exec"
2122
"path/filepath"
23+
"runtime"
2224
"strings"
2325
"sync"
2426
"time"
@@ -393,10 +395,90 @@ func resolveRealIP(hostname string) (string, error) {
393395
return "", fmt.Errorf("no A record found for %s", hostname)
394396
}
395397

398+
// detectOS detects the OS using runtime.GOOS
399+
// Returns: "ubuntu" (assumes Canonical Ubuntu for Linux), "darwin" (macOS), "windows" (Windows)
400+
func detectOS() string {
401+
switch runtime.GOOS {
402+
case "linux":
403+
return "ubuntu"
404+
case "darwin":
405+
return "darwin"
406+
case "windows":
407+
return "windows"
408+
default:
409+
panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
410+
}
411+
}
412+
413+
// UpdateSystemCATrust adds the local CA to the system's trusted certificate store
414+
// This integrates the CA with the OS-level trust store, making it trusted system-wide
415+
// Fully implemented for Ubuntu (Canonical), shell methods only for macOS and Windows
416+
func UpdateSystemCATrust(caCertPath string) error {
417+
switch detectOS() {
418+
case "ubuntu":
419+
// Fully implemented for Ubuntu (Canonical) - uses update-ca-certificates
420+
return updateUbuntuCATrust(caCertPath)
421+
case "darwin":
422+
// macOS - shell method only (not fully implemented)
423+
return updateDarwinCATrust(caCertPath)
424+
case "windows":
425+
// Windows - shell method only (not fully implemented)
426+
return updateWindowsCATrust(caCertPath)
427+
default:
428+
log.Printf("System CA trust update not implemented for OS: %s", detectOS())
429+
log.Printf("Supported OS: ubuntu (Canonical Ubuntu), darwin (macOS), windows")
430+
return fmt.Errorf("unsupported OS: %s", detectOS())
431+
}
432+
}
433+
434+
func updateUbuntuCATrust(caCertPath string) error {
435+
// Copy CA to system location
436+
systemCALocation := "/usr/local/share/ca-certificates/warpbuild-local-ca.crt"
437+
438+
// Read the CA certificate
439+
caData, err := os.ReadFile(caCertPath)
440+
if err != nil {
441+
return fmt.Errorf("read CA certificate: %v", err)
442+
}
443+
444+
// Write to system location (requires root)
445+
if err := os.WriteFile(systemCALocation, caData, 0644); err != nil {
446+
log.Printf("Warning: Could not write CA to system location %s (need root): %v", systemCALocation, err)
447+
log.Printf("To add CA to system trust store, run as root or manually:")
448+
log.Printf(" sudo cp %s %s", caCertPath, systemCALocation)
449+
log.Printf(" sudo update-ca-certificates")
450+
return fmt.Errorf("write CA to system location: %v", err)
451+
}
452+
453+
// Run update-ca-certificates
454+
cmd := exec.Command("update-ca-certificates")
455+
output, err := cmd.CombinedOutput()
456+
if err != nil {
457+
log.Printf("Warning: update-ca-certificates failed: %v", err)
458+
log.Printf("Output: %s", string(output))
459+
return fmt.Errorf("update-ca-certificates failed: %v", err)
460+
}
461+
462+
log.Printf("Successfully added CA to Ubuntu system trust store")
463+
log.Printf("CA is now trusted system-wide at: %s", systemCALocation)
464+
return nil
465+
}
466+
467+
func updateDarwinCATrust(caCertPath string) error {
468+
return nil
469+
}
470+
471+
func updateWindowsCATrust(caCertPath string) error {
472+
return nil
473+
}
474+
396475
// Start starts the OGINY TLS reverse proxy service
397476
// If port is > 0, it uses that port, otherwise defaults to 443
398477
// If loggingEnabled is true, all proxy traffic will be logged to files
399-
func Start(port int, loggingEnabled bool) error {
478+
// derpPort and asurPort are used to route requests to the correct backend services
479+
// certDir specifies the directory where certificates should be stored
480+
// OS is automatically detected from the system
481+
func Start(port int, derpPort int, asurPort int, certDir string, loggingEnabled bool) error {
400482
// Ignore cfgPath since we're inlining the config
401483
listenAddr := ":443"
402484
if port > 0 {
@@ -437,17 +519,12 @@ func Start(port int, loggingEnabled bool) error {
437519
}
438520
}
439521

440-
// Set up certificate directory
441-
var certDir string
522+
// Determine certDir with priority: OGINY_CERT_DIR env var -> settings file value (defaults already applied)
442523
if dir := os.Getenv("OGINY_CERT_DIR"); dir != "" {
443524
certDir = dir
525+
log.Printf("Using certificate directory from OGINY_CERT_DIR: %s", certDir)
444526
} else {
445-
// Use $HOME env var with fallback to /home
446-
homeBase := os.Getenv("HOME")
447-
if homeBase == "" {
448-
homeBase = "/home"
449-
}
450-
certDir = filepath.Join(homeBase, "runner", "certs")
527+
log.Printf("Using certificate directory from settings: %s", certDir)
451528
}
452529

453530
// Create certificate directory if it doesn't exist
@@ -471,37 +548,10 @@ func Start(port int, loggingEnabled bool) error {
471548
log.Printf("CA certificate generated at %s", caCertPath)
472549
}
473550

474-
// Set environment variables for current process and children
475-
os.Setenv("NODE_OPTIONS", "--use-openssl-ca")
476-
os.Setenv("NODE_EXTRA_CA_CERTS", caCertPath)
477-
os.Setenv("SSL_CERT_FILE", caCertPath)
478-
479-
// If running in GitHub Actions, write to GITHUB_ENV
480-
if githubEnv := os.Getenv("GITHUB_ENV"); githubEnv != "" {
481-
log.Printf("Detected GitHub Actions environment, writing to GITHUB_ENV")
482-
if err := appendToFile(githubEnv, fmt.Sprintf("NODE_OPTIONS=--use-openssl-ca\nNODE_EXTRA_CA_CERTS=%s\n", caCertPath)); err != nil {
483-
log.Printf("Warning: failed to write to GITHUB_ENV: %v", err)
484-
}
485-
// Write SSL_CERT_FILE in a separate call to avoid duplicate-check skipping
486-
if err := appendToFile(githubEnv, fmt.Sprintf("SSL_CERT_FILE=%s\n", caCertPath)); err != nil {
487-
log.Printf("Warning: failed to write SSL_CERT_FILE to GITHUB_ENV: %v", err)
488-
}
489-
}
490-
491-
// Also write to /etc/environment if we have permissions (for system-wide)
492-
if err := appendToFile("/etc/environment", fmt.Sprintf("NODE_OPTIONS=\"--use-openssl-ca\"\nNODE_EXTRA_CA_CERTS=\"%s\"\n", caCertPath)); err != nil {
493-
// This is expected to fail if not running as root
494-
log.Printf("Note: Could not write to /etc/environment (need root): %v", err)
495-
log.Printf("To set system-wide, run as root or manually add to /etc/environment:")
496-
log.Printf(" NODE_OPTIONS=\"--use-openssl-ca\"")
497-
log.Printf(" NODE_EXTRA_CA_CERTS=\"%s\"", caCertPath)
498-
log.Printf(" SSL_CERT_FILE=\"%s\"", caCertPath)
499-
} else {
500-
log.Printf("Successfully updated /etc/environment")
501-
// Write SSL_CERT_FILE in a separate call to avoid duplicate-check skipping
502-
if err := appendToFile("/etc/environment", fmt.Sprintf("SSL_CERT_FILE=\"%s\"\n", caCertPath)); err != nil {
503-
log.Printf("Warning: failed to append SSL_CERT_FILE to /etc/environment: %v", err)
504-
}
551+
// Update system CA trust store (OS-specific)
552+
// This integrates the CA with the OS-level trust store, making it trusted system-wide
553+
if err := UpdateSystemCATrust(caCertPath); err != nil {
554+
log.Printf("Warning: Failed to update system CA trust store: %v", err)
505555
}
506556

507557
// Generate certificates for each domain
@@ -515,13 +565,13 @@ func Start(port int, loggingEnabled bool) error {
515565
serverName: "warpbuild.blob.core.windows.net",
516566
certFile: filepath.Join(certDir, "warpbuild.crt"),
517567
keyFile: filepath.Join(certDir, "warpbuild.key"),
518-
targetURL: "http://127.0.0.1:50053",
568+
targetURL: fmt.Sprintf("http://127.0.0.1:%d", asurPort),
519569
},
520570
{
521571
serverName: resultsReceiverHost,
522572
certFile: filepath.Join(certDir, "results-receiver.crt"),
523573
keyFile: filepath.Join(certDir, "results-receiver.key"),
524-
targetURL: "http://127.0.0.1:50052",
574+
targetURL: fmt.Sprintf("http://127.0.0.1:%d", derpPort),
525575
},
526576
}
527577

pkg/transparent-cache/transparent-cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func setupNftables(hostMappings map[string]string, oginyPort int) error {
209209
return nil
210210
}
211211

212-
func Start(derpPort, oginyPort, asurPort int, cacheBackendHost, warpBuildRunnerVerificationToken string, loggingEnabled bool) error {
212+
func Start(derpPort, oginyPort, asurPort int, cacheBackendHost, warpBuildRunnerVerificationToken string, certDir string, loggingEnabled bool) error {
213213
log.Println("========================================")
214214
log.Println("Starting Transparent Cache Services")
215215
log.Println("========================================")
@@ -248,7 +248,7 @@ func Start(derpPort, oginyPort, asurPort int, cacheBackendHost, warpBuildRunnerV
248248
go func() {
249249
defer wg.Done()
250250
log.Printf("Starting OGINY TLS Reverse Proxy on port %d...", oginyPort)
251-
if err := oginy.Start(oginyPort, loggingEnabled); err != nil {
251+
if err := oginy.Start(oginyPort, derpPort, asurPort, certDir, loggingEnabled); err != nil {
252252
errChan <- fmt.Errorf("OGINY service error: %v", err)
253253
}
254254
}()

test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ func main() {
6565

6666
// Start the transparent cache services in a goroutine
6767
go func() {
68-
err := transparentcache.Start(*derpPort, *oginyPort, *asurPort, *backendURL, *authToken, *debug)
68+
// Use empty string for certDir to use default behavior
69+
err := transparentcache.Start(*derpPort, *oginyPort, *asurPort, *backendURL, *authToken, "/home/runner/certs", *debug)
6970
errChan <- err
7071
}()
7172

0 commit comments

Comments
 (0)