Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,6 @@ spec:
configMap:
name: {{ include "name" . }}-configmap
defaultMode: 420
- name: custom-certs
secret:
secretName: {{ include "name" . }}-ca
optional: true
{{- if .Values.imageVectorOverwrite }}
- name: imagevector-overwrite
configMap:
Expand Down

This file was deleted.

4 changes: 1 addition & 3 deletions charts/gardener-extension-provider-stackit/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ config:
capacity: 25Gi
provisioner: block-storage.csi.stackit.cloud
volumeBindingMode: WaitForFirstConsumer
stackitAPIEndpoints:
# Must be base64 encoded
caBundle: ""
stackitAPIEndpoints: {}
registryCaches:
# - server: reg.example.com
# cache: reg-cache.example.com
Expand Down
8 changes: 7 additions & 1 deletion pkg/stackit/client/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/stackit"
)

func NewDNSClient(_ context.Context, endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials) (DNSClient, error) {
func NewDNSClient(_ context.Context, endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials, caBundle string) (DNSClient, error) {
options := clientOptions(endpoints, credentials)

if endpoints.DNS != nil {
Expand All @@ -24,6 +24,12 @@ func NewDNSClient(_ context.Context, endpoints stackitv1alpha1.APIEndpoints, cre
if err != nil {
return nil, err
}
if caBundle != "" {
err = InjectCAIntoHTTPClient(apiClient.GetConfig().HTTPClient, caBundle)
if err != nil {
return nil, err
}
}
return &dnsClient{
api: apiClient.DefaultAPI,
projectID: credentials.ProjectID,
Expand Down
54 changes: 51 additions & 3 deletions pkg/stackit/client/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package client

import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"

extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller"
sdkconfig "github.com/stackitcloud/stackit-sdk-go/core/config"
Expand Down Expand Up @@ -33,18 +37,24 @@ type Factory interface {
type factory struct {
StackitRegion string
StackitAPIEndpoints stackitv1alpha1.APIEndpoints
CABundle string
}

func New(region string, cluster *extensionscontroller.Cluster) Factory {
var apiEndpoints stackitv1alpha1.APIEndpoints
var caBundle string

if cloudProfileConfig, err := helper.CloudProfileConfigFromCluster(cluster); err == nil {
apiEndpoints = ptr.Deref(cloudProfileConfig.APIEndpoints, stackitv1alpha1.APIEndpoints{})
if cloudProfileConfig.CABundle != nil {
ptr.Deref(cloudProfileConfig.CABundle, "")
}
}

return &factory{
StackitRegion: region,
StackitAPIEndpoints: apiEndpoints,
CABundle: caBundle,
}
}

Expand All @@ -54,7 +64,7 @@ func (f factory) LoadBalancing(ctx context.Context, c client.Client, secretRef c
return nil, err
}

return NewLoadBalancingClient(ctx, f.StackitRegion, f.StackitAPIEndpoints, credentials)
return NewLoadBalancingClient(ctx, f.StackitRegion, f.StackitAPIEndpoints, credentials, f.CABundle)
}

func (f factory) IaaS(ctx context.Context, c client.Client, secretRef corev1.SecretReference) (IaaSClient, error) {
Expand All @@ -63,7 +73,7 @@ func (f factory) IaaS(ctx context.Context, c client.Client, secretRef corev1.Sec
return nil, err
}

return NewIaaSClient(f.StackitRegion, f.StackitAPIEndpoints, credentials)
return NewIaaSClient(f.StackitRegion, f.StackitAPIEndpoints, credentials, f.CABundle)
}

func (f factory) DNS(ctx context.Context, c client.Client, secretRef corev1.SecretReference) (DNSClient, error) {
Expand All @@ -72,9 +82,47 @@ func (f factory) DNS(ctx context.Context, c client.Client, secretRef corev1.Secr
return nil, err
}

return NewDNSClient(ctx, f.StackitAPIEndpoints, credentials)
return NewDNSClient(ctx, f.StackitAPIEndpoints, credentials, f.CABundle)
}

// InjectCAIntoHTTPClient injects a CABundle into an existing http.Client
func InjectCAIntoHTTPClient(client *http.Client, caBundle string) error {
caCertPool, err := x509.SystemCertPool()
if err != nil {
// we could also fall back here and use an empty pool via x509.NewCertPool()
return err
}
if ok := caCertPool.AppendCertsFromPEM([]byte(caBundle)); !ok {
return fmt.Errorf("failed to append CA bundle to cert pool")
}
var transport *http.Transport
if client.Transport != nil {
var ok bool
transport, ok = client.Transport.(*http.Transport)
if !ok {
return fmt.Errorf("client.Transport is not an *http.Transport")
}
// Clone it to avoid race conditions if the transport is shared
transport = transport.Clone()
} else {
// Explicitly clone the default transport
// The client should already have transport. Should never happen
transport = http.DefaultTransport.(*http.Transport).Clone()
}

// Inject the custom TLS configuration
if transport.TLSClientConfig == nil {
transport.TLSClientConfig = &tls.Config{}
} else {
transport.TLSClientConfig = transport.TLSClientConfig.Clone()
}

transport.TLSClientConfig.RootCAs = caCertPool

// Re-assign the modified transport back to the client
client.Transport = transport
return nil
}
func clientOptions(endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials) []sdkconfig.ConfigurationOption {
result := []sdkconfig.ConfigurationOption{
sdkconfig.WithUserAgent(UserAgent),
Expand Down
56 changes: 56 additions & 0 deletions pkg/stackit/client/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package client

import (
"crypto/tls"
"encoding/pem"
"net/http"
"net/http/httptest"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("InjectCAIntoHTTPClient", func() {
var (
testServer *httptest.Server
httpClient *http.Client
)

BeforeEach(func() {
testServer = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))

httpClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{},
},
}
})

AfterEach(func() {
testServer.Close()
})

Context("when the custom CA is injected into the HTTP client", func() {
It("should successfully connect to the TLS server without certificate errors", func() {
serverCert := testServer.Certificate()

pemBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: serverCert.Raw,
}
serverCertPEM := pem.EncodeToMemory(pemBlock)

err := InjectCAIntoHTTPClient(httpClient, string(serverCertPEM))
Expect(err).NotTo(HaveOccurred(), "InjectCAIntoHTTPClient should not return an error")

resp, err := httpClient.Get(testServer.URL)

Expect(err).NotTo(HaveOccurred(), "The client should trust the server's certificate")
defer resp.Body.Close()

Expect(resp.StatusCode).To(Equal(http.StatusOK))
})
})
})
8 changes: 7 additions & 1 deletion pkg/stackit/client/iaas.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (c iaasClient) GetNetworkByName(ctx context.Context, name string) ([]iaas.N
return filteredNetworks, nil
}

func NewIaaSClient(region string, endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials) (IaaSClient, error) {
func NewIaaSClient(region string, endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials, caBundle string) (IaaSClient, error) {
options := clientOptions(endpoints, credentials)

if endpoints.IaaS != nil {
Expand All @@ -141,6 +141,12 @@ func NewIaaSClient(region string, endpoints stackitv1alpha1.APIEndpoints, creden
if err != nil {
return nil, err
}
if caBundle != "" {
err = InjectCAIntoHTTPClient(apiClient.GetConfig().HTTPClient, caBundle)
if err != nil {
return nil, err
}
}
return &iaasClient{
Client: apiClient.DefaultAPI,
projectID: credentials.ProjectID,
Expand Down
8 changes: 7 additions & 1 deletion pkg/stackit/client/loadbalancing.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type loadBalancingClient struct {
region string
}

func NewLoadBalancingClient(_ context.Context, region string, endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials) (LoadBalancingClient, error) {
func NewLoadBalancingClient(_ context.Context, region string, endpoints stackitv1alpha1.APIEndpoints, credentials *stackit.Credentials, caBundle string) (LoadBalancingClient, error) {
options := clientOptions(endpoints, credentials)

if endpoints.LoadBalancer != nil {
Expand All @@ -37,6 +37,12 @@ func NewLoadBalancingClient(_ context.Context, region string, endpoints stackitv
if err != nil {
return nil, err
}
if caBundle != "" {
err = InjectCAIntoHTTPClient(apiClient.GetConfig().HTTPClient, caBundle)
if err != nil {
return nil, err
}
}
return &loadBalancingClient{
Client: apiClient.DefaultAPI,
projectID: credentials.ProjectID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ var _ = BeforeSuite(func() {
// TODO: Consider creating manual STACKIT NLB to ensure stackit NLB deletion works
DeferCleanup(testutils.WithFeatureGate(feature.MutableGate, feature.EnsureSTACKITLBDeletion, false))

iaasClient, err = stackitclient.NewIaaSClient(*region, endpoints, credentials)
iaasClient, err = stackitclient.NewIaaSClient(*region, endpoints, credentials, "")
Expect(err).NotTo(HaveOccurred())

repoRoot := filepath.Join("..", "..", "..", "..")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ var _ = BeforeSuite(func() {
Expect(*region).NotTo(BeEmpty())
Expect(validateEnvs()).To(Succeed())

iaasClient, err = stackitclient.NewIaaSClient(*region, endpoints, credentials)
iaasClient, err = stackitclient.NewIaaSClient(*region, endpoints, credentials, "")
Expect(err).NotTo(HaveOccurred())

lbClient, err = stackitclient.NewLoadBalancingClient(ctx, *region, endpoints, credentials)
lbClient, err = stackitclient.NewLoadBalancingClient(ctx, *region, endpoints, credentials, "")
Expect(err).NotTo(HaveOccurred())

repoRoot := filepath.Join("..", "..", "..")
Expand Down