github.com/yorinasub17/go-cloud@v0.27.40/secrets/azurekeyvault/akv_test.go (about) 1 // Copyright 2019 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package azurekeyvault 16 17 import ( 18 "context" 19 "errors" 20 "log" 21 "os" 22 "testing" 23 24 "github.com/Azure/azure-sdk-for-go/sdk/azcore" 25 "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" 26 "github.com/Azure/azure-sdk-for-go/sdk/azidentity" 27 "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys" 28 "gocloud.dev/internal/testing/setup" 29 "gocloud.dev/internal/useragent" 30 "gocloud.dev/secrets" 31 "gocloud.dev/secrets/driver" 32 "gocloud.dev/secrets/drivertest" 33 ) 34 35 // Prerequisites for --record mode 36 // 37 // 1. Sign-in to your Azure Subscription at http://portal.azure.com. 38 // 39 // 2. Create a KeyVault, see 40 // https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal. 41 // 42 // 3. Choose an authentication model. This test uses Service Principal, see 43 // https://docs.microsoft.com/en-us/rest/api/azure/index#register-your-client-application-with-azure-ad. 44 // For documentation on acceptable auth models, see 45 // https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis. 46 // 47 // 4. Set your environment variables depending on the auth model selection. 48 // Modify helper initEnv() as needed. 49 // For Service Principal, please set the following, see 50 // https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization. 51 // 52 // - AZURE_TENANT_ID: Go to "Azure Active Directory", then "Properties". The 53 // "Directory ID" property is your AZURE_TENANT_ID. 54 // - AZURE_CLIENT_ID: Go to "Azure Active Directory", then "App Registrations", 55 // then "View all applications". The "Application ID" column shows your 56 // AZURE_CLIENT_ID. 57 // - AZURE_CLIENT_SECRET: Click on the application from the previous step, 58 // then "Settings" and then "Keys". Create a key and use it as your 59 // AZURE_CLIENT_SECRET. Make sure to save the value as it's hidden after 60 // the initial creation. 61 // - AZURE_ENVIRONMENT: (optional). 62 // - AZURE_AD_RESOURCE: (optional). 63 // 64 // 5. Create/Import a Key. This can be done in the Azure Portal under "Key vaults". 65 // 66 // 6. Update constants below to match your Azure KeyVault settings. 67 68 const ( 69 keyID1 = "https://go-cdk.vault.azure.net/keys/test1" 70 keyID2 = "https://go-cdk.vault.azure.net/keys/test2" 71 ) 72 73 type harness struct { 74 clientMaker ClientMakerT 75 close func() 76 } 77 78 func (h *harness) MakeDriver(ctx context.Context) (driver.Keeper, driver.Keeper, error) { 79 keeper1, err := openKeeper(h.clientMaker, keyID1, nil) 80 if err != nil { 81 return nil, nil, err 82 } 83 keeper2, err := openKeeper(h.clientMaker, keyID2, nil) 84 if err != nil { 85 return nil, nil, err 86 } 87 return keeper1, keeper2, nil 88 } 89 90 func (h *harness) Close() { 91 h.close() 92 } 93 94 type dummyToken struct{} 95 96 func (*dummyToken) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) { 97 return azcore.AccessToken{}, nil 98 } 99 100 func newHarness(ctx context.Context, t *testing.T) (drivertest.Harness, error) { 101 httpClient, done := setup.NewAzureKeyVaultTestClient(ctx, t) 102 clientMaker := func(keyVaultURI string) (*azkeys.Client, error) { 103 var creds azcore.TokenCredential 104 var err error 105 if *setup.Record { 106 initEnv() 107 creds, err = azidentity.NewEnvironmentCredential(nil) 108 } else { 109 creds = &dummyToken{} 110 } 111 if err != nil { 112 return nil, err 113 } 114 return azkeys.NewClient(keyVaultURI, creds, &azkeys.ClientOptions{ 115 ClientOptions: policy.ClientOptions{ 116 Transport: httpClient, 117 Telemetry: policy.TelemetryOptions{ 118 ApplicationID: useragent.AzureUserAgentPrefix("secrets"), 119 }, 120 }, 121 }), nil 122 } 123 return &harness{ 124 clientMaker: clientMaker, 125 close: done, 126 }, nil 127 } 128 129 func initEnv() { 130 // For Client Credentials authorization, set AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET 131 // For Client Certificate and Azure Managed Service Identity, see doc below for help 132 // https://github.com/Azure/azure-sdk-for-go 133 if os.Getenv("AZURE_TENANT_ID") == "" || 134 os.Getenv("AZURE_CLIENT_ID") == "" || 135 os.Getenv("AZURE_CLIENT_SECRET") == "" { 136 log.Fatal("Missing environment for recording tests, set AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET") 137 } 138 os.Setenv("AZURE_ENVIRONMENT", "AzurePublicCloud") 139 os.Setenv("AZURE_AD_RESOURCE", "https://vault.azure.net") 140 } 141 142 func TestConformance(t *testing.T) { 143 drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{}}) 144 } 145 146 type verifyAs struct{} 147 148 func (v verifyAs) Name() string { 149 return "verify As function" 150 } 151 152 func (v verifyAs) ErrorCheck(k *secrets.Keeper, err error) error { 153 var e *azcore.ResponseError 154 if !k.ErrorAs(err, &e) { 155 return errors.New("Keeper.ErrorAs failed") 156 } 157 return nil 158 } 159 160 // Key Vault-specific tests. 161 162 func dummyClientMaker(s string) (*azkeys.Client, error) { 163 return &azkeys.Client{}, nil 164 } 165 166 func TestOpenKeeper(t *testing.T) { 167 tests := []struct { 168 URL string 169 WantErr bool 170 }{ 171 // OK. 172 {"azurekeyvaultdummy://mykeyvault.vault.azure.net/keys/mykey/myversion", false}, 173 // No version -> OK. 174 {"azurekeyvaultdummy://mykeyvault.vault.azure.net/keys/mykey", false}, 175 // Setting algorithm query param -> OK. 176 {"azurekeyvaultdummy://mykeyvault.vault.azure.net/keys/mykey/myversion?algorithm=RSA-OAEP", false}, 177 // Invalid query parameter. 178 {"azurekeyvaultdummy://mykeyvault.vault.azure.net/keys/mykey/myversion?param=value", true}, 179 // Missing key vault name. 180 {"azurekeyvaultdummy:///vault.azure.net/keys/mykey/myversion", true}, 181 // Missing "keys". 182 {"azurekeyvaultdummy://mykeyvault.vault.azure.net/mykey/myversion", true}, 183 } 184 185 secrets.DefaultURLMux().RegisterKeeper(Scheme+"dummy", &URLOpener{ClientMaker: dummyClientMaker}) 186 ctx := context.Background() 187 for _, test := range tests { 188 keeper, err := secrets.OpenKeeper(ctx, test.URL) 189 if (err != nil) != test.WantErr { 190 t.Errorf("%s: got error %v, want error %v", test.URL, err, test.WantErr) 191 } 192 if err == nil { 193 if err = keeper.Close(); err != nil { 194 t.Errorf("%s: got error during close: %v", test.URL, err) 195 } 196 } 197 } 198 } 199 200 func TestKeyIDRE(t *testing.T) { 201 testCases := []struct { 202 // input 203 keyID string 204 205 // output 206 keyVaultURI string 207 keyName string 208 keyVersion string 209 }{ 210 { 211 keyID: keyID1, 212 keyVaultURI: "https://go-cdk.vault.azure.net/", 213 keyName: "test1", 214 }, 215 { 216 keyID: keyID2, 217 keyVaultURI: "https://go-cdk.vault.azure.net/", 218 keyName: "test2", 219 }, 220 { 221 keyID: "https://mykeyvault.vault.azure.net/keys/mykey/myversion", 222 keyVaultURI: "https://mykeyvault.vault.azure.net/", 223 keyName: "mykey", 224 keyVersion: "myversion", 225 }, 226 { 227 keyID: "https://mykeyvault.vault.usgovcloudapi.net/keys/mykey/myversion", 228 keyVaultURI: "https://mykeyvault.vault.usgovcloudapi.net/", 229 keyName: "mykey", 230 keyVersion: "myversion", 231 }, 232 { 233 keyID: "https://mykeyvault.vault.region01.external.com/keys/mykey/myversion", 234 keyVaultURI: "https://mykeyvault.vault.region01.external.com/", 235 keyName: "mykey", 236 keyVersion: "myversion", 237 }, 238 } 239 for _, testCase := range testCases { 240 t.Run(testCase.keyID, func(t *testing.T) { 241 k, err := openKeeper(dummyClientMaker, testCase.keyID, nil) 242 if err != nil { 243 t.Fatal(err) 244 } 245 defer k.Close() 246 247 if k.keyVaultURI != testCase.keyVaultURI { 248 t.Errorf("got key vault URI %s, want key vault URI %s", k.keyVaultURI, testCase.keyVaultURI) 249 } 250 251 if k.keyName != testCase.keyName { 252 t.Errorf("got key name %s, want key name %s", k.keyName, testCase.keyName) 253 } 254 255 if k.keyVersion != testCase.keyVersion { 256 t.Errorf("got key version %s, want key version %s", k.keyVersion, testCase.keyVersion) 257 } 258 }) 259 } 260 }