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 }