Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion pkg/runner/chunk_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package runner
import (
"context"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding"
"encoding/hex"
"fmt"
Expand Down Expand Up @@ -57,6 +59,32 @@ type ChunkRunner struct {
signal chan struct{}
}

// newHTTPClientWithSystemCerts creates an HTTP client configured with the system's trusted certificate chain
func newHTTPClientWithSystemCerts() *http.Client {
// Load the system's trusted certificate pool
certPool, err := x509.SystemCertPool()
if err != nil {
klog.Warningf("Failed to load system certificate pool, using default: %v", err)
return http.DefaultClient
}

// Clone the default transport to preserve performance optimizations
transport := http.DefaultTransport.(*http.Transport).Clone()

// Create TLS configuration with system certificates
tlsConfig := &tls.Config{
RootCAs: certPool,
}

// Update the TLS configuration
transport.TLSClientConfig = tlsConfig

// Return a new HTTP client with the custom transport
return &http.Client{
Transport: transport,
}
}

// NewChunkRunner creates a new Runner instance
func NewChunkRunner(
handlerName string,
Expand All @@ -67,7 +95,7 @@ func NewChunkRunner(
handlerName: handlerName,
client: clientset,
chunkInformer: sharedInformerFactory.Task().V1alpha1().Chunks(),
httpClient: http.DefaultClient,
httpClient: newHTTPClientWithSystemCerts(),
signal: make(chan struct{}, 1),
}

Expand Down
126 changes: 126 additions & 0 deletions pkg/runner/chunk_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
Copyright 2025 The OpenCIDN Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package runner

import (
"crypto/x509"
"net/http"
"testing"

"github.com/OpenCIDN/cidn/pkg/clientset/versioned/fake"
"github.com/OpenCIDN/cidn/pkg/informers/externalversions"
)

func TestNewHTTPClientWithSystemCerts(t *testing.T) {
client := newHTTPClientWithSystemCerts()

if client == nil {
t.Fatal("Expected non-nil HTTP client")
}

if client.Transport == nil {
t.Fatal("Expected non-nil transport")
}

transport, ok := client.Transport.(*http.Transport)
if !ok {
t.Fatal("Expected transport to be *http.Transport")
}

if transport.TLSClientConfig == nil {
t.Fatal("Expected non-nil TLS client config")
}

if transport.TLSClientConfig.RootCAs == nil {
t.Fatal("Expected non-nil RootCAs (system certificate pool)")
}
}

func TestNewChunkRunnerUsesSystemCerts(t *testing.T) {
clientset := fake.NewSimpleClientset()
sharedInformerFactory := externalversions.NewSharedInformerFactory(clientset, 0)

runner := NewChunkRunner("test-handler", clientset, sharedInformerFactory)

if runner == nil {
t.Fatal("Expected non-nil ChunkRunner")
}

if runner.httpClient == nil {
t.Fatal("Expected non-nil HTTP client")
}

transport, ok := runner.httpClient.Transport.(*http.Transport)
if !ok {
t.Fatal("Expected transport to be *http.Transport")
}

if transport.TLSClientConfig == nil {
t.Fatal("Expected non-nil TLS client config")
}

if transport.TLSClientConfig.RootCAs == nil {
t.Fatal("Expected non-nil RootCAs (system certificate pool)")
}
}

func TestHTTPClientWithSystemCertsMatchesSystemPool(t *testing.T) {
// Get the system certificate pool for comparison
systemPool, err := x509.SystemCertPool()
if err != nil {
t.Skipf("Skipping test: cannot load system cert pool: %v", err)
}

client := newHTTPClientWithSystemCerts()
transport := client.Transport.(*http.Transport)
tlsConfig := transport.TLSClientConfig

// Verify that the RootCAs is set (we can't directly compare cert pools,
// but we can verify it's not nil and appears to be configured)
if tlsConfig.RootCAs == nil {
t.Fatal("Expected RootCAs to be configured with system certificates")
}

// Verify it's not an empty pool by checking subjects
// The system pool should have at least some certificates
if len(systemPool.Subjects()) == 0 {
t.Skip("Skipping test: system cert pool appears to be empty")
}
}

func TestHTTPClientTLSConfiguration(t *testing.T) {
client := newHTTPClientWithSystemCerts()
transport, ok := client.Transport.(*http.Transport)
if !ok {
t.Fatal("Expected transport to be *http.Transport")
}

tlsConfig := transport.TLSClientConfig
if tlsConfig == nil {
t.Fatal("Expected non-nil TLS config")
}

// Verify TLS configuration properties
if tlsConfig.RootCAs == nil {
t.Error("Expected RootCAs to be set")
}

// Verify that InsecureSkipVerify is false (default)
if tlsConfig.InsecureSkipVerify {
t.Error("Expected InsecureSkipVerify to be false by default")
}
}