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
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ module github.com/stolostron/submariner-addon
go 1.25.0

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1
github.com/aws/aws-sdk-go-v2/config v1.32.10
github.com/coreos/go-semver v0.3.1
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/gophercloud/gophercloud/v2 v2.11.1
github.com/gophercloud/utils/v2 v2.0.0-20260107124036-1d7954eb9711
github.com/onsi/ginkgo/v2 v2.28.1
github.com/onsi/gomega v1.39.1
github.com/openshift/api v0.0.0-20260317165824-54a3998d81eb
github.com/openshift/controller-runtime-common v0.0.0-20260318085703-1812aed6dbd2
github.com/openshift/library-go v0.0.0-20260318142011-72bf34f474bc
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.10.2
Expand All @@ -30,12 +33,12 @@ require (
k8s.io/code-generator v0.35.3
k8s.io/component-base v0.35.3
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2
open-cluster-management.io/addon-framework v1.2.0
open-cluster-management.io/api v1.2.0
sigs.k8s.io/controller-runtime v0.23.0
sigs.k8s.io/controller-runtime v0.23.3
sigs.k8s.io/mcs-api v0.3.0
sigs.k8s.io/structured-merge-diff/v6 v6.3.1
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482
)

require (
Expand All @@ -44,7 +47,6 @@ require (
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v8 v8.0.0 // indirect
Expand All @@ -56,7 +58,6 @@ require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.41.2 // indirect
github.com/aws/aws-sdk-go-v2/config v1.32.10 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 // indirect
Expand Down Expand Up @@ -175,6 +176,7 @@ require (
golang.org/x/text v0.35.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.42.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260316180232-0b37fe3546d5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 // indirect
google.golang.org/grpc v1.79.3 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ github.com/openshift/api v0.0.0-20260317165824-54a3998d81eb h1:iwBR3mzmyE3EMFx7R
github.com/openshift/api v0.0.0-20260317165824-54a3998d81eb/go.mod h1:pyVjK0nZ4sRs4fuQVQ4rubsJdahI1PB94LnQ8sGdvxo=
github.com/openshift/client-go v0.0.0-20260317180604-743f664b82d1 h1:Hr/R38eg5ZJXfbiaHumjJIN1buDZwhsm4ys4npVCXH0=
github.com/openshift/client-go v0.0.0-20260317180604-743f664b82d1/go.mod h1:Za51LlH76ALiQ/aKGBYJXmyJNkA//IDJ+I///30CA2M=
github.com/openshift/controller-runtime-common v0.0.0-20260318085703-1812aed6dbd2 h1:GrZlVichOCE/lz8fg1+eNrAtkM0VSlqa9buuzN0vnb0=
github.com/openshift/controller-runtime-common v0.0.0-20260318085703-1812aed6dbd2/go.mod h1:XGabTMnNbz0M5Oa7IbscZp/jmcc7aHobvOCUWwkzKvM=
github.com/openshift/library-go v0.0.0-20260318142011-72bf34f474bc h1:a+rVRzEdFIwgDQLTbhiG3MEVuBXjLb/6HJRikTob+nY=
github.com/openshift/library-go v0.0.0-20260318142011-72bf34f474bc/go.mod h1:3bi4pLpYRdVd1aEhsHfRTJkwxwPLfRZ+ZePn3RmJd2k=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
Expand Down Expand Up @@ -538,6 +540,8 @@ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZ
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
open-cluster-management.io/addon-framework v1.2.0 h1:/HsZmavrIrRzvH/htZxEhasrIxNOYW9YYUeOEPEefeQ=
open-cluster-management.io/addon-framework v1.2.0/go.mod h1:dIcbnfLXMbXvO4T32ZY8dmok0OSA0UsrDGR27LLv69Q=
open-cluster-management.io/api v1.2.0 h1:+yeQgJiErrur5S4s205UM37EcZ2XbC9pFSm0xgV5/hU=
Expand All @@ -548,6 +552,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUo
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/controller-runtime v0.23.0 h1:Ubi7klJWiwEWqDY+odSVZiFA0aDSevOCXpa38yCSYu8=
sigs.k8s.io/controller-runtime v0.23.0/go.mod h1:DBOIr9NsprUqCZ1ZhsuJ0wAnQSIxY/C6VjZbmLgw0j0=
sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80=
sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kube-storage-version-migrator v0.0.6-0.20230721195810-5c8923c5ff96 h1:PFWFSkpArPNJxFX4ZKWAk9NSeRoZaXschn+ULa4xVek=
Expand All @@ -558,5 +564,7 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 h1:JrhdFMqOd/+3ByqlP2I45kTOZmTRLBUm5pvRjeheg7E=
sigs.k8s.io/structured-merge-diff/v6 v6.3.1/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
73 changes: 44 additions & 29 deletions pkg/cloud/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"fmt"
"strings"

"github.com/aws/aws-sdk-go-v2/config"
"github.com/pkg/errors"
"github.com/stolostron/submariner-addon/pkg/cloud/provider"
"github.com/stolostron/submariner-addon/pkg/cloud/reporter"
"github.com/stolostron/submariner-addon/pkg/cloud/tls"
"github.com/stolostron/submariner-addon/pkg/constants"
submreporter "github.com/submariner-io/admiral/pkg/reporter"
cpapi "github.com/submariner-io/cloud-prepare/pkg/api"
Expand Down Expand Up @@ -66,39 +68,21 @@ func NewProvider(ctx context.Context, info *provider.Info) (*awsProvider, error)
info.CredentialsSecret.Name)
}

awsClient, err := cpclient.New(ctx, info.Region, cpclient.WithCredentials(string(accessKeyID), string(secretAccessKey)))
rep := reporter.NewEventRecorderWrapper("AWSCloudProvider", info.EventRecorder)

httpClient, err := tls.GetConfiguredHTTPClient(ctx, info.DynamicClient, rep, false)
if err != nil {
return nil, errors.Wrap(err, "error creating AWS client")
return nil, errors.Wrap(err, "unable to create HTTP client")
}

var cloudOptions []cpaws.CloudOption

if info.SubmarinerConfigAnnotations != nil {
annotations := info.SubmarinerConfigAnnotations

if vpcID, exists := annotations["submariner.io/vpc-id"]; exists {
cloudOptions = append(cloudOptions, cpaws.WithVPCName(vpcID))
}

if subnetIDList, exists := annotations["submariner.io/subnet-id-list"]; exists {
subnetIDs := strings.Split(subnetIDList, ",")
for i := range subnetIDs {
subnetIDs[i] = strings.TrimSpace(subnetIDs[i])
}

cloudOptions = append(cloudOptions, cpaws.WithPublicSubnetList(subnetIDs))
}

if controlPlaneSGID, exists := annotations["submariner.io/control-plane-sg-id"]; exists {
cloudOptions = append(cloudOptions, cpaws.WithControlPlaneSecurityGroup(controlPlaneSGID))
}

if workerSGID, exists := annotations["submariner.io/worker-sg-id"]; exists {
cloudOptions = append(cloudOptions, cpaws.WithWorkerSecurityGroup(workerSGID))
}
awsClient, err := cpclient.New(ctx, info.Region,
cpclient.WithCredentials(string(accessKeyID), string(secretAccessKey)),
config.WithHTTPClient(httpClient))
if err != nil {
return nil, errors.Wrap(err, "error creating AWS client")
}

cloudPrepare := cpaws.NewCloud(awsClient, info.InfraID, info.Region, cloudOptions...)
cloudPrepare := cpaws.NewCloud(awsClient, info.InfraID, info.Region, getCloudOptions(info)...)

machineSetDeployer := ocp.NewK8sMachinesetDeployer(info.RestMapper, info.DynamicClient)

Expand All @@ -108,7 +92,7 @@ func NewProvider(ctx context.Context, info *provider.Info) (*awsProvider, error)
}

return &awsProvider{
reporter: reporter.NewEventRecorderWrapper("AWSCloudProvider", info.EventRecorder),
reporter: rep,
nattPort: int64(info.IPSecNATTPort),
nattDiscoveryPort: int64(info.NATTDiscoveryPort),
cniType: info.NetworkType,
Expand Down Expand Up @@ -163,3 +147,34 @@ func (a *awsProvider) CleanUpSubmarinerClusterEnv(ctx context.Context) error {

return nil
}

func getCloudOptions(info *provider.Info) []cpaws.CloudOption {
var cloudOptions []cpaws.CloudOption

if info.SubmarinerConfigAnnotations != nil {
annotations := info.SubmarinerConfigAnnotations

if vpcID, exists := annotations["submariner.io/vpc-id"]; exists {
cloudOptions = append(cloudOptions, cpaws.WithVPCName(vpcID))
}

if subnetIDList, exists := annotations["submariner.io/subnet-id-list"]; exists {
subnetIDs := strings.Split(subnetIDList, ",")
for i := range subnetIDs {
subnetIDs[i] = strings.TrimSpace(subnetIDs[i])
}

cloudOptions = append(cloudOptions, cpaws.WithPublicSubnetList(subnetIDs))
}

if controlPlaneSGID, exists := annotations["submariner.io/control-plane-sg-id"]; exists {
cloudOptions = append(cloudOptions, cpaws.WithControlPlaneSecurityGroup(controlPlaneSGID))
}

if workerSGID, exists := annotations["submariner.io/worker-sg-id"]; exists {
cloudOptions = append(cloudOptions, cpaws.WithWorkerSecurityGroup(workerSGID))
}
}

return cloudOptions
}
29 changes: 26 additions & 3 deletions pkg/cloud/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import (
"os"
"strings"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/pkg/errors"
"github.com/stolostron/submariner-addon/pkg/cloud/provider"
"github.com/stolostron/submariner-addon/pkg/cloud/reporter"
"github.com/stolostron/submariner-addon/pkg/cloud/tls"
"github.com/stolostron/submariner-addon/pkg/constants"
submreporter "github.com/submariner-io/admiral/pkg/reporter"
"github.com/submariner-io/cloud-prepare/pkg/api"
Expand Down Expand Up @@ -37,7 +40,7 @@ type azureProvider struct {
airGapped bool
}

func NewProvider(info *provider.Info) (*azureProvider, error) {
func NewProvider(ctx context.Context, info *provider.Info) (*azureProvider, error) {
if info.InfraID == "" {
return nil, errors.New("cluster infraID is empty")
}
Expand All @@ -56,7 +59,22 @@ func NewProvider(info *provider.Info) (*azureProvider, error) {
return nil, errors.Wrap(err, "unable to initialize from auth file")
}

credentials, err := azidentity.NewEnvironmentCredential(nil)
rep := reporter.NewEventRecorderWrapper("AzureCloudProvider", info.EventRecorder)

// Create HTTP client with TLS configuration BEFORE creating credentials
// This ensures the credential's token acquisition uses the cluster TLS profile
httpClient, err := tls.GetConfiguredHTTPClient(ctx, info.DynamicClient, rep, false)
if err != nil {
return nil, errors.Wrap(err, "unable to create HTTP client")
}

// Create credentials with the TLS-configured HTTP client
// This ensures token requests respect the cluster TLS profile
credentials, err := azidentity.NewEnvironmentCredential(&azidentity.EnvironmentCredentialOptions{
ClientOptions: policy.ClientOptions{
Transport: httpClient,
},
})
if err != nil {
return nil, errors.Wrap(err, "unable to create the Azure credentials")
}
Expand All @@ -72,6 +90,11 @@ func NewProvider(info *provider.Info) (*azureProvider, error) {
BaseGroupName: info.InfraID + "-rg",
TokenCredential: credentials,
K8sClient: k8sClient,
ClientOptions: &arm.ClientOptions{
ClientOptions: policy.ClientOptions{
Transport: httpClient,
},
},
}

gwDeployer := azure.NewOcpGatewayDeployer(&cloudInfo, msDeployer, instanceType)
Expand All @@ -84,7 +107,7 @@ func NewProvider(info *provider.Info) (*azureProvider, error) {
cniType: info.NetworkType,
cloudPrepare: cloudPrepare,
gwDeployer: gwDeployer,
reporter: reporter.NewEventRecorderWrapper("AzureCloudProvider", info.EventRecorder),
reporter: rep,
nattDiscoveryPort: int64(info.NATTDiscoveryPort),
gateways: info.Gateways,
airGapped: info.SubmarinerConfigSpec.AirGappedDeployment,
Expand Down
2 changes: 1 addition & 1 deletion pkg/cloud/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func init() {
})

RegisterProvider("Azure", func(info *provider.Info) (Provider, error) {
return azure.NewProvider(info)
return azure.NewProvider(context.TODO(), info)
})
}

Expand Down
35 changes: 30 additions & 5 deletions pkg/cloud/gcp/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package gcp
import (
"context"
"fmt"
"net/http"
"strings"

"github.com/pkg/errors"
"github.com/stolostron/submariner-addon/pkg/cloud/provider"
"github.com/stolostron/submariner-addon/pkg/cloud/reporter"
"github.com/stolostron/submariner-addon/pkg/cloud/tls"
"github.com/stolostron/submariner-addon/pkg/constants"
submreporter "github.com/submariner-io/admiral/pkg/reporter"
"github.com/submariner-io/cloud-prepare/pkg/api"
Expand All @@ -16,10 +18,12 @@ import (
"github.com/submariner-io/cloud-prepare/pkg/k8s"
"github.com/submariner-io/cloud-prepare/pkg/ocp"
"github.com/submariner-io/submariner/pkg/cni"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/dns/v1"
"google.golang.org/api/option"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/dynamic"
"k8s.io/klog/v2"
)

Expand Down Expand Up @@ -53,7 +57,9 @@ func NewProvider(ctx context.Context, info *provider.Info) (*gcpProvider, error)
return nil, errors.New("the count of gateways is less than 1")
}

projectID, gcpClient, err := newClient(ctx, info.CredentialsSecret)
rep := reporter.NewEventRecorderWrapper("GCPCloudProvider", info.EventRecorder)

projectID, gcpClient, err := newClient(ctx, info.DynamicClient, rep, info.CredentialsSecret)
if err != nil {
klog.Errorf("Unable to retrieve the gcpclient :%v", err)
return nil, err
Expand Down Expand Up @@ -92,7 +98,7 @@ func NewProvider(ctx context.Context, info *provider.Info) (*gcpProvider, error)
cniType: info.NetworkType,
cloudPrepare: cloudPrepare,
gwDeployer: gwDeployer,
reporter: reporter.NewEventRecorderWrapper("GCPCloudProvider", info.EventRecorder),
reporter: rep,
nattDiscoveryPort: int64(info.NATTDiscoveryPort),
gateways: info.Gateways,
}, nil
Expand Down Expand Up @@ -149,22 +155,41 @@ func (g *gcpProvider) CleanUpSubmarinerClusterEnv(ctx context.Context) error {
return nil
}

func newClient(ctx context.Context, credentialsSecret *corev1.Secret) (string, gcpclient.Interface, error) {
func newClient(ctx context.Context, dynamicClient dynamic.Interface, rep submreporter.Interface, credentialsSecret *corev1.Secret,
) (string, gcpclient.Interface, error) {
authJSON, ok := credentialsSecret.Data[gcpCredentialsName]
if !ok {
return "", nil, fmt.Errorf("the gcp credentials %s is not in secret %s/%s", gcpCredentialsName,
credentialsSecret.Namespace, credentialsSecret.Name)
}

// Create HTTP client with TLS configuration BEFORE setting up credentials
// This ensures the OAuth2 token acquisition also uses the cluster TLS profile
baseHTTPClient, err := tls.GetConfiguredHTTPClient(ctx, dynamicClient, rep, false)
if err != nil {
return "", nil, errors.Wrap(err, "unable to create HTTP client")
}

// since we're using a single creds var, we should specify all the required scopes when initializing
// Use CredentialsFromJSONWithType to explicitly validate that we're loading a service account credential
creds, err := google.CredentialsFromJSONWithType(ctx, authJSON, google.ServiceAccount, dns.CloudPlatformScope)
if err != nil {
return "", nil, errors.Wrap(err, "error retrieving credentials")
}

// Create a GCP client with the credentials.
computeClient, err := gcpclient.NewClient(ctx, creds.ProjectID, []option.ClientOption{option.WithCredentials(creds)})
// Wrap the TLS-configured transport with OAuth2 transport to apply service account authentication
// while preserving the cluster TLS profile settings
httpClient := &http.Client{
Transport: &oauth2.Transport{
Base: baseHTTPClient.Transport,
Source: creds.TokenSource,
},
}

// Create a GCP client with the custom HTTP client (which includes both TLS config and auth)
computeClient, err := gcpclient.NewClient(ctx, creds.ProjectID, []option.ClientOption{
option.WithHTTPClient(httpClient),
})
if err != nil {
return "", nil, errors.Wrap(err, "error creating GCP client")
}
Expand Down
Loading
Loading