@@ -7,22 +7,32 @@ import (
77 "fmt"
88 "net/http"
99 "os"
10- "path/filepath"
11- "strings"
1210 "sync"
1311 "time"
1412
1513 "github.com/Azure/azure-sdk-for-go/sdk/azcore"
1614 "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
1715 "github.com/Azure/go-autorest/autorest/azure"
1816 "github.com/pkg/errors"
17+ corev1 "k8s.io/api/core/v1"
18+ apierrors "k8s.io/apimachinery/pkg/api/errors"
1919 "k8s.io/client-go/rest"
2020 azurepkg "sigs.k8s.io/cluster-api-provider-azure/azure"
2121 "sigs.k8s.io/cluster-api-provider-azure/util/tele"
22+ "sigs.k8s.io/controller-runtime/pkg/client"
2223)
2324
2425const (
25- AzureEnvironentFolderEnvName = "AZURE_ENVIRONMENT_FOLDER"
26+ // Deprecated: Use ConfigMaps instead
27+ AzureEnvironentFolderEnvName = "AZURE_ENVIRONMENT_FOLDER_CAPZ"
28+
29+ // ConfigMap names for Azure secret cloud configuration
30+ AzureEnvConfigMapName = "azure-capz-env-config"
31+ AzureCertConfigMapName = "azure-capz-cert-config"
32+
33+ // ConfigMap keys
34+ AzureEnvConfigKey = "azure-capz-env.json"
35+ AzureCertConfigKey = "azure-ca.crt"
2636)
2737
2838var (
@@ -37,69 +47,110 @@ var (
3747)
3848
3949func init () {
40-
4150 _ , log , done := tele .StartSpanWithLogger (context .Background (), "scope.AzureScope.init" )
42- log .Info ("AzureSecretCloud initializing" )
4351 defer done ()
44- path := os .Getenv (AzureEnvironentFolderEnvName )
45- log .Info ("Path is" , path )
46- if path == "" {
47- // If no environment folder is set, treat as Public/Gov cloud (no custom cert)
48- return
52+
53+ log .Info ("Azure secret cloud init completed - ConfigMap initialization will be performed during controller setup" )
54+
55+ // Check for deprecated environment variable
56+ if path := os .Getenv (AzureEnvironentFolderEnvName ); path != "" {
57+ log .Info ("DEPRECATED: AZURE_ENVIRONMENT_FOLDER_CAPZ is deprecated, use ConfigMaps instead" )
58+ fmt .Printf ("CAPZ: WARNING - AZURE_ENVIRONMENT_FOLDER_CAPZ is deprecated. Please use ConfigMaps instead.\n " )
4959 }
50- files , err := os .ReadDir (path )
51- if err != nil {
52- log .Error (err , "error reading folder" , "path" , path )
53- return
54- }
55-
56- var certData []byte
57- for _ , file := range files {
58- if ! file .IsDir () {
59- filePath := filepath .Join (path , file .Name ())
60- fileExt := filepath .Ext (file .Name ())
61-
62- // Load Azure environment JSON files
63- if strings .EqualFold (fileExt , ".json" ) {
64- // Read and log the file contents for debugging
65- if jsonData , err := os .ReadFile (filePath ); err == nil {
66- //fmt.Printf("CAPZ: Loading Azure environment JSON file: %s\n", file.Name())
67- fmt .Printf ("CAPZ: JSON file contents: %s\n " , string (jsonData ))
68- }
69-
70- if env , err := azure .EnvironmentFromFile (filePath ); err == nil {
71- azure .SetEnvironment (env .Name , env )
72- log .Info ("loaded Azure environment from file" , "EnvName" , env .Name )
73- log .Info ("loaded Azure environment from file" , "filename" , file .Name ())
74- } else {
75- fmt .Printf ("CAPZ: Failed to load Azure environment from file %s: %v\n " , file .Name (), err )
76- log .Error (err , "failed to load Azure environment from file" , "filename" , file .Name ())
77- }
78- }
79-
80- // Load certificate files
81- if strings .EqualFold (fileExt , ".crt" ) || strings .EqualFold (fileExt , ".pem" ) {
82- if data , err := os .ReadFile (filePath ); err == nil && len (data ) > 0 {
83- certData = data
84- fmt .Printf ("CAPZ: Successfully loaded certificate from file: %s (%d bytes)\n " , file .Name (), len (data ))
85- log .Info ("loaded certificate from file" , "filename" , file .Name ())
86- } else {
87- log .Error (err , "failed to load certificate from file" , "filename" , file .Name ())
88- }
89- }
60+ }
61+
62+ // InitializeAzureConfigForCluster initializes Azure environment and certificates from ConfigMaps
63+ // in the specified cluster namespace
64+ func InitializeAzureConfigForCluster (ctx context.Context , kubeClient client.Client , namespace , azureEnvironment string ) error {
65+ _ , log , done := tele .StartSpanWithLogger (ctx , "scope.InitializeAzureConfigForCluster" )
66+ defer done ()
67+
68+ log .Info ("Initializing Azure config for cluster" , "namespace" , namespace , "azureEnvironment" , azureEnvironment )
69+
70+ // Try to read environment ConfigMap from cluster namespace
71+ envConfigMap := & corev1.ConfigMap {}
72+ envKey := client.ObjectKey {Namespace : namespace , Name : AzureEnvConfigMapName }
73+
74+ if err := kubeClient .Get (ctx , envKey , envConfigMap ); err != nil {
75+ if apierrors .IsNotFound (err ) {
76+ log .Info ("Azure environment ConfigMap not found in cluster namespace, using default configuration" , "namespace" , namespace )
77+ return nil // No custom config, use defaults
9078 }
79+ return errors .Wrap (err , "failed to read Azure environment ConfigMap from cluster namespace" )
80+ }
81+
82+ // ConfigMap found, process environment JSON
83+ envJSON , hasEnvJSON := envConfigMap .Data [AzureEnvConfigKey ]
84+ if ! hasEnvJSON || envJSON == "" {
85+ return errors .New ("Azure environment ConfigMap found but JSON data is missing" )
86+ }
87+
88+ log .Info ("Processing Azure environment JSON from cluster ConfigMap" )
89+ if err := processAzureEnvironmentJSON (envJSON ); err != nil {
90+ return errors .Wrap (err , "failed to process Azure environment JSON" )
9191 }
9292
93- // Initialize global transport with certificate data if found
94- if len (certData ) > 0 {
95- if err := initializeGlobalTransportWithCertData (certData ); err != nil {
96- log .Error (err , "failed to initialize global transport with certificate" )
93+ // Try to read certificate ConfigMap from cluster namespace
94+ certConfigMap := & corev1.ConfigMap {}
95+ certKey := client.ObjectKey {Namespace : namespace , Name : AzureCertConfigMapName }
96+
97+ if err := kubeClient .Get (ctx , certKey , certConfigMap ); err != nil {
98+ if apierrors .IsNotFound (err ) {
99+ return errors .New ("Azure environment ConfigMap found but certificate ConfigMap is missing - custom Azure environments require certificates" )
97100 }
98- } else {
99- // If environment folder is set but no certificates found, log error
100- log .Error (errors .New ("no certificate files found in environment folder" ), "expected certificate files (.crt or .pem) but none found" , "path" , path )
101+ return errors .Wrap (err , "failed to read Azure certificate ConfigMap from cluster namespace" )
101102 }
102- // If no certificate found in environment folder, treat as Public/Gov cloud (no custom cert)
103+
104+ // Certificate ConfigMap found, process certificate data
105+ certPEM , hasCertPEM := certConfigMap .Data [AzureCertConfigKey ]
106+ if ! hasCertPEM || certPEM == "" {
107+ return errors .New ("Azure certificate ConfigMap found but certificate data is missing" )
108+ }
109+
110+ certData := []byte (certPEM )
111+ log .Info ("Successfully loaded certificate from cluster ConfigMap" , "bytes" , len (certData ))
112+
113+ // Initialize global transport with certificate data
114+ if err := initializeGlobalTransportWithCertData (certData ); err != nil {
115+ return errors .Wrap (err , "failed to initialize global transport with certificate" )
116+ }
117+
118+ log .Info ("Azure config initialization completed successfully for cluster" , "namespace" , namespace )
119+ return nil
120+ }
121+
122+ // processAzureEnvironmentJSON processes the Azure environment JSON configuration
123+ func processAzureEnvironmentJSON (envJSON string ) error {
124+ // Create a temporary file for azure.EnvironmentFromFile to read
125+ tmpFile , err := os .CreateTemp ("" , "azure-env-*.json" )
126+ if err != nil {
127+ return errors .Wrap (err , "failed to create temporary file for Azure environment" )
128+ }
129+ defer os .Remove (tmpFile .Name ())
130+ defer tmpFile .Close ()
131+
132+ // Write JSON content to temporary file
133+ if _ , err := tmpFile .WriteString (envJSON ); err != nil {
134+ return errors .Wrap (err , "failed to write Azure environment JSON to temporary file" )
135+ }
136+
137+ // Parse Azure environment from file
138+ env , err := azure .EnvironmentFromFile (tmpFile .Name ())
139+ if err != nil {
140+ return errors .Wrap (err , "failed to parse Azure environment JSON" )
141+ }
142+
143+ azure .SetEnvironment (env .Name , env )
144+ fmt .Printf ("CAPZ: Loaded Azure environment: %s\n " , env .Name )
145+ return nil
146+ }
147+
148+ // initializeDefaultTransport initializes the default transport for public clouds
149+ func initializeDefaultTransport () error {
150+ globalTransportMutex .Lock ()
151+ defer globalTransportMutex .Unlock ()
152+
153+ return updateGlobalTransportLocked (nil )
103154}
104155
105156// initializeGlobalTransportWithCertData initializes the global transport with provided certificate data
0 commit comments