github.com/kubernetes-sigs/azuredisk-csi-driver@v0.7.0/test/utils/credentials/credentials.go (about)

     1  /*
     2  Copyright 2020 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 credentials
    18  
    19  import (
    20  	"fmt"
    21  	"html/template"
    22  	"io/ioutil"
    23  	"os"
    24  
    25  	"github.com/pborman/uuid"
    26  	"github.com/pelletier/go-toml"
    27  
    28  	"k8s.io/klog"
    29  )
    30  
    31  const (
    32  	AzurePublicCloud            = "AzurePublicCloud"
    33  	AzureChinaCloud             = "AzureChinaCloud"
    34  	ResourceGroupPrefix         = "azuredisk-csi-driver-test-"
    35  	TempAzureCredentialFilePath = "/tmp/azure.json"
    36  
    37  	azureCredentialFileTemplate = `{
    38      "cloud": "{{.Cloud}}",
    39      "tenantId": "{{.TenantID}}",
    40      "subscriptionId": "{{.SubscriptionID}}",
    41      "aadClientId": "{{.AADClientID}}",
    42      "aadClientSecret": "{{.AADClientSecret}}",
    43      "resourceGroup": "{{.ResourceGroup}}",
    44      "location": "{{.Location}}"
    45  }`
    46  	defaultAzurePublicCloudLocation = "eastus2"
    47  	defaultAzureChinaCloudLocation  = "chinaeast2"
    48  
    49  	// Env vars
    50  	tenantIDEnvVar        = "TENANT_ID"
    51  	subscriptionIDEnvVar  = "SUBSCRIPTION_ID"
    52  	aadClientIDEnvVar     = "AAD_CLIENT_ID"
    53  	aadClientSecretEnvVar = "AAD_CLIENT_SECRET"
    54  	resourceGroupEnvVar   = "RESOURCE_GROUP"
    55  	locationEnvVar        = "LOCATION"
    56  
    57  	tenantIDChinaEnvVar        = "TENANT_ID_CHINA"
    58  	subscriptionIDChinaEnvVar  = "SUBSCRIPTION_ID_CHINA"
    59  	aadClientIDChinaEnvVar     = "AAD_CLIENT_ID_CHINA"
    60  	aadClientSecretChinaEnvVar = "AAD_CLIENT_SECRET_CHINA"
    61  	resourceGroupChinaEnvVar   = "RESOURCE_GROUP_CHINA"
    62  	locationChinaEnvVar        = "LOCATION_CHINA"
    63  )
    64  
    65  // CredentialsConfig is used in Prow to store Azure credentials
    66  // https://github.com/kubernetes/test-infra/blob/master/kubetest/azure.go#L116-L118
    67  type CredentialsConfig struct {
    68  	Creds CredentialsFromProw
    69  }
    70  
    71  // CredentialsFromProw is used in Prow to store Azure credentials
    72  // https://github.com/kubernetes/test-infra/blob/master/kubetest/azure.go#L107-L114
    73  type CredentialsFromProw struct {
    74  	ClientID           string
    75  	ClientSecret       string
    76  	TenantID           string
    77  	SubscriptionID     string
    78  	StorageAccountName string
    79  	StorageAccountKey  string
    80  }
    81  
    82  // Credentials is used in Azure File CSI Driver to store Azure credentials
    83  type Credentials struct {
    84  	Cloud           string
    85  	TenantID        string
    86  	SubscriptionID  string
    87  	AADClientID     string
    88  	AADClientSecret string
    89  	ResourceGroup   string
    90  	Location        string
    91  }
    92  
    93  // CreateAzureCredentialFile creates a temporary Azure credential file for
    94  // Azure Disk CSI driver tests and returns the credentials
    95  func CreateAzureCredentialFile(isAzureChinaCloud bool) (*Credentials, error) {
    96  	// Search credentials through env vars first
    97  	var cloud, tenantID, subscriptionID, aadClientID, aadClientSecret, resourceGroup, location string
    98  	if isAzureChinaCloud {
    99  		cloud = AzureChinaCloud
   100  		tenantID = os.Getenv(tenantIDChinaEnvVar)
   101  		subscriptionID = os.Getenv(subscriptionIDChinaEnvVar)
   102  		aadClientID = os.Getenv(aadClientIDChinaEnvVar)
   103  		aadClientSecret = os.Getenv(aadClientSecretChinaEnvVar)
   104  		resourceGroup = os.Getenv(resourceGroupChinaEnvVar)
   105  		location = os.Getenv(locationChinaEnvVar)
   106  	} else {
   107  		cloud = AzurePublicCloud
   108  		tenantID = os.Getenv(tenantIDEnvVar)
   109  		subscriptionID = os.Getenv(subscriptionIDEnvVar)
   110  		aadClientID = os.Getenv(aadClientIDEnvVar)
   111  		aadClientSecret = os.Getenv(aadClientSecretEnvVar)
   112  		resourceGroup = os.Getenv(resourceGroupEnvVar)
   113  		location = os.Getenv(locationEnvVar)
   114  	}
   115  
   116  	if resourceGroup == "" {
   117  		resourceGroup = ResourceGroupPrefix + uuid.NewUUID().String()
   118  	}
   119  
   120  	if location == "" {
   121  		if isAzureChinaCloud {
   122  			location = defaultAzureChinaCloudLocation
   123  		} else {
   124  			location = defaultAzurePublicCloudLocation
   125  		}
   126  	}
   127  
   128  	// Running test locally
   129  	if tenantID != "" && subscriptionID != "" && aadClientID != "" && aadClientSecret != "" {
   130  		return parseAndExecuteTemplate(cloud, tenantID, subscriptionID, aadClientID, aadClientSecret, resourceGroup, location)
   131  	}
   132  
   133  	// If the tests are being run in Prow, credentials are not supplied through env vars. Instead, it is supplied
   134  	// through env var AZURE_CREDENTIALS. We need to convert it to AZURE_CREDENTIAL_FILE for sanity, integration and E2E tests
   135  	// https://github.com/kubernetes/test-infra/blob/master/config/jobs/kubernetes-sigs/cloud-provider-azure/cloud-provider-azure-config.yaml#L5-L6
   136  	if azureCredentialsPath, ok := os.LookupEnv("AZURE_CREDENTIALS"); ok {
   137  		klog.V(2).Infof("Running in Prow, converting AZURE_CREDENTIALS to AZURE_CREDENTIAL_FILE")
   138  		c, err := getCredentialsFromAzureCredentials(azureCredentialsPath)
   139  		if err != nil {
   140  			return nil, err
   141  		}
   142  		return parseAndExecuteTemplate(cloud, c.TenantID, c.SubscriptionID, c.ClientID, c.ClientSecret, resourceGroup, location)
   143  	}
   144  
   145  	return nil, fmt.Errorf("If you are running tests locally, you will need to set the following env vars: $%s, $%s, $%s, $%s, $%s, $%s",
   146  		tenantIDEnvVar, subscriptionIDEnvVar, aadClientIDEnvVar, aadClientSecretEnvVar, resourceGroupEnvVar, locationEnvVar)
   147  }
   148  
   149  // CreateAzureCredentialFile deletes the temporary Azure credential file
   150  func DeleteAzureCredentialFile() error {
   151  	if err := os.Remove(TempAzureCredentialFilePath); err != nil && !os.IsNotExist(err) {
   152  		return fmt.Errorf("error removing %s %v", TempAzureCredentialFilePath, err)
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  // getCredentialsFromAzureCredentials parses the azure credentials toml (AZURE_CREDENTIALS)
   159  // in Prow and return the credential information usable to Azure File CSI driver
   160  func getCredentialsFromAzureCredentials(azureCredentialsPath string) (*CredentialsFromProw, error) {
   161  	content, err := ioutil.ReadFile(azureCredentialsPath)
   162  	klog.V(2).Infof("Reading credentials file %v", azureCredentialsPath)
   163  	if err != nil {
   164  		return nil, fmt.Errorf("error reading credentials file %v %v", azureCredentialsPath, err)
   165  	}
   166  
   167  	c := CredentialsConfig{}
   168  	if err := toml.Unmarshal(content, &c); err != nil {
   169  		return nil, fmt.Errorf("error parsing credentials file %v %v", azureCredentialsPath, err)
   170  	}
   171  
   172  	return &c.Creds, nil
   173  }
   174  
   175  // parseAndExecuteTemplate replaces credential placeholders in hack/template/azure.json with actual credentials
   176  func parseAndExecuteTemplate(cloud, tenantID, subscriptionID, aadClientID, aadClientSecret, resourceGroup, location string) (*Credentials, error) {
   177  	t := template.New("AzureCredentialFileTemplate")
   178  	t, err := t.Parse(azureCredentialFileTemplate)
   179  	if err != nil {
   180  		return nil, fmt.Errorf("error parsing  azureCredentialFileTemplate %v", err)
   181  	}
   182  
   183  	f, err := os.Create(TempAzureCredentialFilePath)
   184  	if err != nil {
   185  		return nil, fmt.Errorf("error creating %s %v", TempAzureCredentialFilePath, err)
   186  	}
   187  	defer f.Close()
   188  
   189  	c := Credentials{
   190  		cloud,
   191  		tenantID,
   192  		subscriptionID,
   193  		aadClientID,
   194  		aadClientSecret,
   195  		resourceGroup,
   196  		location,
   197  	}
   198  	err = t.Execute(f, c)
   199  	if err != nil {
   200  		return nil, fmt.Errorf("error executing parsed azure credential file template %v", err)
   201  	}
   202  
   203  	return &c, nil
   204  }