2023-03-15 16:00:52 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2017-08-03 17:24:27 +00:00
|
|
|
package azure
|
2016-02-24 12:14:23 +00:00
|
|
|
|
|
|
|
import (
|
2018-07-24 18:24:32 +00:00
|
|
|
"context"
|
2016-02-24 12:14:23 +00:00
|
|
|
"fmt"
|
2020-10-28 22:04:26 +00:00
|
|
|
"net"
|
2016-02-24 12:14:23 +00:00
|
|
|
"os"
|
2018-07-24 18:24:32 +00:00
|
|
|
"strconv"
|
2016-02-24 12:14:23 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
2016-04-26 03:10:32 +00:00
|
|
|
|
2021-07-16 14:33:53 +00:00
|
|
|
"github.com/hashicorp/vault/helper/testhelpers/azurite"
|
|
|
|
|
2020-10-05 21:37:13 +00:00
|
|
|
"github.com/Azure/azure-storage-blob-go/azblob"
|
2018-04-03 00:46:59 +00:00
|
|
|
log "github.com/hashicorp/go-hclog"
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/logging"
|
|
|
|
"github.com/hashicorp/vault/sdk/physical"
|
2016-02-24 12:14:23 +00:00
|
|
|
)
|
|
|
|
|
2021-07-16 14:33:53 +00:00
|
|
|
/// These tests run against an Azurite docker container, unless AZURE_ACCOUNT_NAME is given.
|
2020-10-28 22:04:26 +00:00
|
|
|
/// Authentication options:
|
|
|
|
/// - Use a static access key via AZURE_ACCOUNT_KEY
|
|
|
|
/// - Use managed identities (leave AZURE_ACCOUNT_KEY empty)
|
|
|
|
///
|
|
|
|
/// To run the tests using managed identities, the following pre-requisites have to be met:
|
|
|
|
/// 1. Access to the Azure Instance Metadata Service (IMDS) is required (e.g. run it on a Azure VM)
|
|
|
|
/// 2. A system-assigned oder user-assigned identity attached to the host running the test
|
|
|
|
/// 3. A role assignment for a storage account with "Storage Blob Data Contributor" permissions
|
|
|
|
|
|
|
|
func testFixture(t *testing.T) (*AzureBackend, func()) {
|
2020-10-05 21:37:13 +00:00
|
|
|
t.Helper()
|
2016-02-24 12:14:23 +00:00
|
|
|
|
|
|
|
ts := time.Now().UnixNano()
|
2017-06-16 16:37:57 +00:00
|
|
|
name := fmt.Sprintf("vault-test-%d", ts)
|
2020-10-28 22:04:26 +00:00
|
|
|
_ = os.Setenv("AZURE_BLOB_CONTAINER", name)
|
2016-02-24 12:14:23 +00:00
|
|
|
|
2021-07-16 14:33:53 +00:00
|
|
|
cleanup := func() {}
|
|
|
|
backendConf := map[string]string{
|
2020-10-28 22:04:26 +00:00
|
|
|
"container": name,
|
2021-07-16 14:33:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if os.Getenv("AZURE_ACCOUNT_NAME") == "" {
|
|
|
|
dockerCleanup, conf := azurite.PrepareTestContainer(t, "")
|
|
|
|
cfgaz := conf.(*azurite.Config)
|
|
|
|
backendConf["accountName"] = cfgaz.AccountName
|
|
|
|
backendConf["accountKey"] = cfgaz.AccountKey
|
|
|
|
backendConf["testHost"] = cfgaz.Endpoint
|
|
|
|
cleanup = dockerCleanup
|
|
|
|
} else {
|
|
|
|
accountKey := os.Getenv("AZURE_ACCOUNT_KEY")
|
|
|
|
if accountKey != "" {
|
|
|
|
t.Log("using account key provided to authenticate against storage account")
|
|
|
|
} else {
|
|
|
|
t.Log("using managed identity to authenticate against storage account")
|
|
|
|
if !isIMDSReachable(t) {
|
|
|
|
t.Log("running managed identity test requires access to the Azure IMDS with a valid identity for a storage account attached to it, skipping")
|
|
|
|
t.SkipNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
backend, err := NewAzureBackend(backendConf, logging.NewVaultLogger(log.Debug))
|
2016-02-24 12:14:23 +00:00
|
|
|
if err != nil {
|
2021-07-16 14:33:53 +00:00
|
|
|
defer cleanup()
|
2016-02-24 12:14:23 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2020-10-28 22:04:26 +00:00
|
|
|
azBackend := backend.(*AzureBackend)
|
|
|
|
|
|
|
|
return azBackend, func() {
|
|
|
|
blobService, err := azBackend.container.GetProperties(context.Background(), azblob.LeaseAccessConditions{})
|
2020-10-05 21:37:13 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Logf("failed to retrieve blob container info: %v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if blobService.StatusCode() == 200 {
|
2020-10-28 22:04:26 +00:00
|
|
|
_, err := azBackend.container.Delete(context.Background(), azblob.ContainerAccessConditions{})
|
2020-10-05 21:37:13 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Logf("clean up failed: %v", err)
|
|
|
|
}
|
|
|
|
}
|
2021-07-16 14:33:53 +00:00
|
|
|
cleanup()
|
2020-10-05 21:37:13 +00:00
|
|
|
}
|
2016-02-24 12:14:23 +00:00
|
|
|
}
|
2018-07-24 18:24:32 +00:00
|
|
|
|
2020-10-05 21:37:13 +00:00
|
|
|
func TestAzureBackend(t *testing.T) {
|
|
|
|
backend, cleanup := testFixture(t)
|
|
|
|
defer cleanup()
|
2018-07-24 18:24:32 +00:00
|
|
|
|
2020-10-05 21:37:13 +00:00
|
|
|
physical.ExerciseBackend(t, backend)
|
|
|
|
physical.ExerciseBackend_ListPrefix(t, backend)
|
|
|
|
}
|
2018-07-24 18:24:32 +00:00
|
|
|
|
2020-10-05 21:37:13 +00:00
|
|
|
func TestAzureBackend_ListPaging(t *testing.T) {
|
|
|
|
backend, cleanup := testFixture(t)
|
|
|
|
defer cleanup()
|
2018-07-24 18:24:32 +00:00
|
|
|
|
|
|
|
// by default, azure returns 5000 results in a page, load up more than that
|
|
|
|
for i := 0; i < MaxListResults+100; i++ {
|
|
|
|
if err := backend.Put(context.Background(), &physical.Entry{
|
2021-07-16 14:33:53 +00:00
|
|
|
Key: "foo" + strconv.Itoa(i),
|
2018-07-24 18:24:32 +00:00
|
|
|
Value: []byte(strconv.Itoa(i)),
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
results, err := backend.List(context.Background(), "")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
2020-10-05 21:37:13 +00:00
|
|
|
|
2018-07-24 18:24:32 +00:00
|
|
|
if len(results) != MaxListResults+100 {
|
2021-07-16 14:33:53 +00:00
|
|
|
t.Fatalf("expected %d, got %d, %v", MaxListResults+100, len(results), results)
|
2020-10-28 22:04:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func isIMDSReachable(t *testing.T) bool {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
_, err := net.DialTimeout("tcp", "169.254.169.254:80", time.Second*3)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|