sigs.k8s.io/cluster-api-provider-azure@v1.17.0/azure/scope/clients.go (about)

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package scope
    18  
    19  import (
    20  	"context"
    21  	"crypto/sha256"
    22  	"encoding/base64"
    23  	"fmt"
    24  	"os"
    25  	"strings"
    26  
    27  	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
    28  	azureautorest "github.com/Azure/go-autorest/autorest/azure"
    29  	"github.com/Azure/go-autorest/autorest/azure/auth"
    30  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    31  )
    32  
    33  // AzureClients contains all the Azure clients used by the scopes.
    34  type AzureClients struct {
    35  	auth.EnvironmentSettings
    36  
    37  	TokenCredential            azcore.TokenCredential
    38  	ResourceManagerEndpoint    string
    39  	ResourceManagerVMDNSSuffix string
    40  
    41  	authType infrav1.IdentityType
    42  }
    43  
    44  // CloudEnvironment returns the Azure environment the controller runs in.
    45  func (c *AzureClients) CloudEnvironment() string {
    46  	return c.Environment.Name
    47  }
    48  
    49  // TenantID returns the Azure tenant id the controller runs in.
    50  func (c *AzureClients) TenantID() string {
    51  	return c.Values["AZURE_TENANT_ID"]
    52  }
    53  
    54  // ClientID returns the Azure client id from the controller environment.
    55  func (c *AzureClients) ClientID() string {
    56  	return c.Values["AZURE_CLIENT_ID"]
    57  }
    58  
    59  // ClientSecret returns the Azure client secret from the controller environment.
    60  func (c *AzureClients) ClientSecret() string {
    61  	return c.Values["AZURE_CLIENT_SECRET"]
    62  }
    63  
    64  // SubscriptionID returns the Azure subscription id of the cluster,
    65  // either specified or from the environment.
    66  func (c *AzureClients) SubscriptionID() string {
    67  	return c.Values["AZURE_SUBSCRIPTION_ID"]
    68  }
    69  
    70  // Token returns the Azure token credential of the cluster used for SDKv2 services.
    71  func (c *AzureClients) Token() azcore.TokenCredential {
    72  	return c.TokenCredential
    73  }
    74  
    75  // HashKey returns a base64 url encoded sha256 hash for the Auth scope (Azure TenantID + CloudEnv + SubscriptionID +
    76  // ClientID).
    77  func (c *AzureClients) HashKey() string {
    78  	hasher := sha256.New()
    79  	_, _ = hasher.Write([]byte(c.TenantID() + c.CloudEnvironment() + c.SubscriptionID() + c.ClientID() + string(c.authType)))
    80  	return base64.URLEncoding.EncodeToString(hasher.Sum(nil))
    81  }
    82  
    83  func (c *AzureClients) setCredentialsWithProvider(ctx context.Context, subscriptionID, environmentName string, credentialsProvider CredentialsProvider) error {
    84  	if credentialsProvider == nil {
    85  		return fmt.Errorf("credentials provider cannot have an empty value")
    86  	}
    87  
    88  	settings, err := c.getSettingsFromEnvironment(environmentName)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	if subscriptionID == "" {
    94  		subscriptionID = settings.GetSubscriptionID()
    95  		if subscriptionID == "" {
    96  			return fmt.Errorf("error creating azure services. subscriptionID is not set in cluster or AZURE_SUBSCRIPTION_ID env var")
    97  		}
    98  	}
    99  
   100  	c.EnvironmentSettings = settings
   101  	c.ResourceManagerEndpoint = settings.Environment.ResourceManagerEndpoint
   102  	c.ResourceManagerVMDNSSuffix = settings.Environment.ResourceManagerVMDNSSuffix
   103  	c.Values["AZURE_SUBSCRIPTION_ID"] = strings.TrimSuffix(subscriptionID, "\n")
   104  	c.Values["AZURE_TENANT_ID"] = strings.TrimSuffix(credentialsProvider.GetTenantID(), "\n")
   105  	c.Values["AZURE_CLIENT_ID"] = strings.TrimSuffix(credentialsProvider.GetClientID(), "\n")
   106  
   107  	clientSecret, err := credentialsProvider.GetClientSecret(ctx)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	c.Values["AZURE_CLIENT_SECRET"] = strings.TrimSuffix(clientSecret, "\n")
   112  
   113  	c.authType = credentialsProvider.Type()
   114  
   115  	tokenCredential, err := credentialsProvider.GetTokenCredential(ctx, c.ResourceManagerEndpoint, c.Environment.ActiveDirectoryEndpoint, c.Environment.TokenAudience)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	c.TokenCredential = tokenCredential
   120  	return err
   121  }
   122  
   123  func (c *AzureClients) getSettingsFromEnvironment(environmentName string) (s auth.EnvironmentSettings, err error) {
   124  	s = auth.EnvironmentSettings{
   125  		Values: map[string]string{},
   126  	}
   127  	s.Values["AZURE_ENVIRONMENT"] = environmentName
   128  	setValue(s, "AZURE_SUBSCRIPTION_ID")
   129  	setValue(s, "AZURE_TENANT_ID")
   130  	setValue(s, "AZURE_AUXILIARY_TENANT_IDS")
   131  	setValue(s, "AZURE_CLIENT_ID")
   132  	setValue(s, "AZURE_CLIENT_SECRET")
   133  	setValue(s, "AZURE_CERTIFICATE_PATH")
   134  	setValue(s, "AZURE_CERTIFICATE_PASSWORD")
   135  	setValue(s, "AZURE_USERNAME")
   136  	setValue(s, "AZURE_PASSWORD")
   137  	setValue(s, "AZURE_AD_RESOURCE")
   138  	if v := s.Values["AZURE_ENVIRONMENT"]; v == "" {
   139  		s.Environment = azureautorest.PublicCloud
   140  	} else {
   141  		s.Environment, err = azureautorest.EnvironmentFromName(v)
   142  	}
   143  	if s.Values["AZURE_AD_RESOURCE"] == "" {
   144  		s.Values["AZURE_AD_RESOURCE"] = s.Environment.ResourceManagerEndpoint
   145  	}
   146  	return
   147  }
   148  
   149  // setValue adds the specified environment variable value to the Values map if it exists.
   150  func setValue(settings auth.EnvironmentSettings, key string) {
   151  	if v := os.Getenv(key); v != "" {
   152  		settings.Values[key] = v
   153  	}
   154  }