github.com/thiagoyeds/go-cloud@v0.26.0/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  	"strings"
    23  	"testing"
    24  
    25  	"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault"
    26  	"github.com/Azure/go-autorest/autorest"
    27  	"github.com/Azure/go-autorest/autorest/azure"
    28  	"gocloud.dev/internal/testing/setup"
    29  	"gocloud.dev/secrets"
    30  	"gocloud.dev/secrets/driver"
    31  	"gocloud.dev/secrets/drivertest"
    32  )
    33  
    34  // Prerequisites for --record mode
    35  //
    36  // 1. Sign-in to your Azure Subscription at http://portal.azure.com.
    37  //
    38  // 2. Create a KeyVault, see
    39  // https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal.
    40  //
    41  // 3. Choose an authentication model. This test uses Service Principal, see
    42  // https://docs.microsoft.com/en-us/rest/api/azure/index#register-your-client-application-with-azure-ad.
    43  // For documentation on acceptable auth models, see
    44  // https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis.
    45  //
    46  // 4. Set your environment variables depending on the auth model selection.
    47  // Modify helper initEnv() as needed.
    48  // For Service Principal, please set the following, see
    49  // https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization.
    50  //
    51  // - AZURE_TENANT_ID: Go to "Azure Active Directory", then "Properties". The
    52  //     "Directory ID" property is your AZURE_TENANT_ID.
    53  // - AZURE_CLIENT_ID: Go to "Azure Active Directory", then "App Registrations",
    54  //     then "View all applications". The "Application ID" column shows your
    55  //     AZURE_CLIENT_ID.
    56  // - AZURE_CLIENT_SECRET: Click on the application from the previous step,
    57  //     then "Settings" and then "Keys". Create a key and use it as your
    58  //     AZURE_CLIENT_SECRET. Make sure to save the value as it's hidden after
    59  //     the initial creation.
    60  // - AZURE_ENVIRONMENT: (optional).
    61  // - AZURE_AD_RESOURCE: (optional).
    62  //
    63  // 5. Create/Import a Key. This can be done in the Azure Portal under "Key vaults".
    64  //
    65  // 6. Update constants below to match your Azure KeyVault settings.
    66  
    67  const (
    68  	keyID1 = "https://go-cdk.vault.azure.net/keys/test1"
    69  	keyID2 = "https://go-cdk.vault.azure.net/keys/test2"
    70  )
    71  
    72  type harness struct {
    73  	client *keyvault.BaseClient
    74  	close  func()
    75  }
    76  
    77  func (h *harness) MakeDriver(ctx context.Context) (driver.Keeper, driver.Keeper, error) {
    78  	keeper1, err := openKeeper(h.client, keyID1, nil)
    79  	if err != nil {
    80  		return nil, nil, err
    81  	}
    82  	keeper2, err := openKeeper(h.client, keyID2, nil)
    83  	if err != nil {
    84  		return nil, nil, err
    85  	}
    86  	return keeper1, keeper2, nil
    87  }
    88  
    89  func (h *harness) Close() {
    90  	h.close()
    91  }
    92  
    93  func newHarness(ctx context.Context, t *testing.T) (drivertest.Harness, error) {
    94  	// Use initEnv to setup your environment variables.
    95  	var client *keyvault.BaseClient
    96  	if *setup.Record {
    97  		initEnv()
    98  		var err error
    99  		client, err = Dial()
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  	} else {
   104  		// Use a null authorizer for replay mode.
   105  		c := keyvault.NewWithoutDefaults()
   106  		client = &c
   107  		client.Authorizer = &autorest.NullAuthorizer{}
   108  	}
   109  	sender, done := setup.NewAzureKeyVaultTestClient(ctx, t)
   110  	client.Sender = sender
   111  	return &harness{
   112  		client: client,
   113  		close:  done,
   114  	}, nil
   115  }
   116  
   117  func initEnv() {
   118  	env, err := azure.EnvironmentFromName("AZUREPUBLICCLOUD")
   119  	if err != nil {
   120  		log.Fatalln(err)
   121  	}
   122  
   123  	// For Client Credentials authorization, set AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
   124  	// For Client Certificate and Azure Managed Service Identity, see doc below for help
   125  	// https://github.com/Azure/azure-sdk-for-go
   126  
   127  	if os.Getenv("AZURE_TENANT_ID") == "" ||
   128  		os.Getenv("AZURE_CLIENT_ID") == "" ||
   129  		os.Getenv("AZURE_CLIENT_SECRET") == "" {
   130  		log.Fatal("Missing environment for recording tests, set AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET")
   131  	}
   132  
   133  	os.Setenv("AZURE_ENVIRONMENT", env.Name)
   134  
   135  	vaultEndpoint := strings.TrimSuffix(env.KeyVaultEndpoint, "/")
   136  	os.Setenv("AZURE_AD_RESOURCE", vaultEndpoint)
   137  }
   138  
   139  func TestConformance(t *testing.T) {
   140  	drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{}})
   141  }
   142  
   143  type verifyAs struct{}
   144  
   145  func (v verifyAs) Name() string {
   146  	return "verify As function"
   147  }
   148  
   149  func (v verifyAs) ErrorCheck(k *secrets.Keeper, err error) error {
   150  	var e autorest.DetailedError
   151  	if !k.ErrorAs(err, &e) {
   152  		return errors.New("Keeper.ErrorAs failed")
   153  	}
   154  	return nil
   155  }
   156  
   157  // Key Vault-specific tests.
   158  
   159  func TestNoConnectionError(t *testing.T) {
   160  	client := keyvault.NewWithoutDefaults()
   161  	k, err := OpenKeeper(&client, keyID1, nil)
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	defer k.Close()
   166  	if _, err := k.Encrypt(context.Background(), []byte("secrets")); err == nil {
   167  		t.Error("Encrypt: got nil, want no connection error")
   168  	}
   169  }
   170  
   171  // This test no longer works on MacOS, as OpenKeeper always fails with "MSI not available".
   172  /*
   173  func TestOpenKeeper(t *testing.T) {
   174  	tests := []struct {
   175  		URL     string
   176  		WantErr bool
   177  	}{
   178  		// OK.
   179  		{"azurekeyvault://mykeyvault.vault.azure.net/keys/mykey/myversion", false},
   180  		// No version -> OK.
   181  		{"azurekeyvault://mykeyvault.vault.azure.net/keys/mykey", false},
   182  		// Setting algorithm query param -> OK.
   183  		{"azurekeyvault://mykeyvault.vault.azure.net/keys/mykey/myversion?algorithm=RSA-OAEP", false},
   184  		// Invalid query parameter.
   185  		{"azurekeyvault://mykeyvault.vault.azure.net/keys/mykey/myversion?param=value", true},
   186  		// Missing key vault name.
   187  		{"azurekeyvault:///vault.azure.net/keys/mykey/myversion", true},
   188  		// Missing "keys".
   189  		{"azurekeyvault://mykeyvault.vault.azure.net/mykey/myversion", true},
   190  	}
   191  
   192  	ctx := context.Background()
   193  	for _, test := range tests {
   194  		keeper, err := secrets.OpenKeeper(ctx, test.URL)
   195  		if (err != nil) != test.WantErr {
   196  			t.Errorf("%s: got error %v, want error %v", test.URL, err, test.WantErr)
   197  		}
   198  		if err == nil {
   199  			if err = keeper.Close(); err != nil {
   200  				t.Errorf("%s: got error during close: %v", test.URL, err)
   201  			}
   202  		}
   203  	}
   204  }
   205  */
   206  
   207  func TestKeyIDRE(t *testing.T) {
   208  	client := keyvault.NewWithoutDefaults()
   209  
   210  	testCases := []struct {
   211  		// input
   212  		keyID string
   213  
   214  		// output
   215  		keyVaultURI string
   216  		keyName     string
   217  		keyVersion  string
   218  	}{
   219  		{
   220  			keyID:       keyID1,
   221  			keyVaultURI: "https://go-cdk.vault.azure.net/",
   222  			keyName:     "test1",
   223  		},
   224  		{
   225  			keyID:       keyID2,
   226  			keyVaultURI: "https://go-cdk.vault.azure.net/",
   227  			keyName:     "test2",
   228  		},
   229  		{
   230  			keyID:       "https://mykeyvault.vault.azure.net/keys/mykey/myversion",
   231  			keyVaultURI: "https://mykeyvault.vault.azure.net/",
   232  			keyName:     "mykey",
   233  			keyVersion:  "myversion",
   234  		},
   235  		{
   236  			keyID:       "https://mykeyvault.vault.usgovcloudapi.net/keys/mykey/myversion",
   237  			keyVaultURI: "https://mykeyvault.vault.usgovcloudapi.net/",
   238  			keyName:     "mykey",
   239  			keyVersion:  "myversion",
   240  		},
   241  		{
   242  			keyID:       "https://mykeyvault.vault.region01.external.com/keys/mykey/myversion",
   243  			keyVaultURI: "https://mykeyvault.vault.region01.external.com/",
   244  			keyName:     "mykey",
   245  			keyVersion:  "myversion",
   246  		},
   247  	}
   248  
   249  	for _, testCase := range testCases {
   250  		t.Run(testCase.keyID, func(t *testing.T) {
   251  			k, err := openKeeper(&client, testCase.keyID, nil)
   252  			if err != nil {
   253  				t.Fatal(err)
   254  			}
   255  			defer k.Close()
   256  
   257  			if k.keyVaultURI != testCase.keyVaultURI {
   258  				t.Errorf("got key vault URI %s, want key vault URI %s", k.keyVaultURI, testCase.keyVaultURI)
   259  			}
   260  
   261  			if k.keyName != testCase.keyName {
   262  				t.Errorf("got key name %s, want key name %s", k.keyName, testCase.keyName)
   263  			}
   264  
   265  			if k.keyVersion != testCase.keyVersion {
   266  				t.Errorf("got key version %s, want key version %s", k.keyVersion, testCase.keyVersion)
   267  			}
   268  		})
   269  	}
   270  }