github.com/opentofu/opentofu@v1.7.1/internal/backend/remote-state/azure/client_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package azure
     7  
     8  import (
     9  	"context"
    10  	"os"
    11  	"testing"
    12  
    13  	"github.com/opentofu/opentofu/internal/backend"
    14  	"github.com/opentofu/opentofu/internal/encryption"
    15  	"github.com/opentofu/opentofu/internal/legacy/helper/acctest"
    16  	"github.com/opentofu/opentofu/internal/states/remote"
    17  	"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
    18  )
    19  
    20  func TestRemoteClient_impl(t *testing.T) {
    21  	var _ remote.Client = new(RemoteClient)
    22  	var _ remote.ClientLocker = new(RemoteClient)
    23  }
    24  
    25  func TestRemoteClientAccessKeyBasic(t *testing.T) {
    26  	testAccAzureBackend(t)
    27  	rs := acctest.RandString(4)
    28  	res := testResourceNames(rs, "testState")
    29  	armClient := buildTestClient(t, res)
    30  
    31  	ctx := context.TODO()
    32  	err := armClient.buildTestResources(ctx, &res)
    33  	defer armClient.destroyTestResources(ctx, res)
    34  	if err != nil {
    35  		t.Fatalf("Error creating Test Resources: %q", err)
    36  	}
    37  
    38  	b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
    39  		"storage_account_name": res.storageAccountName,
    40  		"container_name":       res.storageContainerName,
    41  		"key":                  res.storageKeyName,
    42  		"access_key":           res.storageAccountAccessKey,
    43  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
    44  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
    45  	})).(*Backend)
    46  
    47  	state, err := b.StateMgr(backend.DefaultStateName)
    48  	if err != nil {
    49  		t.Fatal(err)
    50  	}
    51  
    52  	remote.TestClient(t, state.(*remote.State).Client)
    53  }
    54  
    55  func TestRemoteClientManagedServiceIdentityBasic(t *testing.T) {
    56  	testAccAzureBackendRunningInAzure(t)
    57  	rs := acctest.RandString(4)
    58  	res := testResourceNames(rs, "testState")
    59  	armClient := buildTestClient(t, res)
    60  
    61  	ctx := context.TODO()
    62  	err := armClient.buildTestResources(ctx, &res)
    63  	defer armClient.destroyTestResources(ctx, res)
    64  	if err != nil {
    65  		t.Fatalf("Error creating Test Resources: %q", err)
    66  	}
    67  
    68  	b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
    69  		"storage_account_name": res.storageAccountName,
    70  		"container_name":       res.storageContainerName,
    71  		"key":                  res.storageKeyName,
    72  		"resource_group_name":  res.resourceGroup,
    73  		"use_msi":              true,
    74  		"subscription_id":      os.Getenv("ARM_SUBSCRIPTION_ID"),
    75  		"tenant_id":            os.Getenv("ARM_TENANT_ID"),
    76  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
    77  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
    78  	})).(*Backend)
    79  
    80  	state, err := b.StateMgr(backend.DefaultStateName)
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  
    85  	remote.TestClient(t, state.(*remote.State).Client)
    86  }
    87  
    88  func TestRemoteClientSasTokenBasic(t *testing.T) {
    89  	testAccAzureBackend(t)
    90  	rs := acctest.RandString(4)
    91  	res := testResourceNames(rs, "testState")
    92  	armClient := buildTestClient(t, res)
    93  
    94  	ctx := context.TODO()
    95  	err := armClient.buildTestResources(ctx, &res)
    96  	defer armClient.destroyTestResources(ctx, res)
    97  	if err != nil {
    98  		t.Fatalf("Error creating Test Resources: %q", err)
    99  	}
   100  
   101  	sasToken, err := buildSasToken(res.storageAccountName, res.storageAccountAccessKey)
   102  	if err != nil {
   103  		t.Fatalf("Error building SAS Token: %+v", err)
   104  	}
   105  
   106  	b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
   107  		"storage_account_name": res.storageAccountName,
   108  		"container_name":       res.storageContainerName,
   109  		"key":                  res.storageKeyName,
   110  		"sas_token":            *sasToken,
   111  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
   112  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
   113  	})).(*Backend)
   114  
   115  	state, err := b.StateMgr(backend.DefaultStateName)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	remote.TestClient(t, state.(*remote.State).Client)
   121  }
   122  
   123  func TestRemoteClientServicePrincipalBasic(t *testing.T) {
   124  	testAccAzureBackend(t)
   125  	rs := acctest.RandString(4)
   126  	res := testResourceNames(rs, "testState")
   127  	armClient := buildTestClient(t, res)
   128  
   129  	ctx := context.TODO()
   130  	err := armClient.buildTestResources(ctx, &res)
   131  	defer armClient.destroyTestResources(ctx, res)
   132  	if err != nil {
   133  		t.Fatalf("Error creating Test Resources: %q", err)
   134  	}
   135  
   136  	b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
   137  		"storage_account_name": res.storageAccountName,
   138  		"container_name":       res.storageContainerName,
   139  		"key":                  res.storageKeyName,
   140  		"resource_group_name":  res.resourceGroup,
   141  		"subscription_id":      os.Getenv("ARM_SUBSCRIPTION_ID"),
   142  		"tenant_id":            os.Getenv("ARM_TENANT_ID"),
   143  		"client_id":            os.Getenv("ARM_CLIENT_ID"),
   144  		"client_secret":        os.Getenv("ARM_CLIENT_SECRET"),
   145  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
   146  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
   147  	})).(*Backend)
   148  
   149  	state, err := b.StateMgr(backend.DefaultStateName)
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  
   154  	remote.TestClient(t, state.(*remote.State).Client)
   155  }
   156  
   157  func TestRemoteClientAccessKeyLocks(t *testing.T) {
   158  	testAccAzureBackend(t)
   159  	rs := acctest.RandString(4)
   160  	res := testResourceNames(rs, "testState")
   161  	armClient := buildTestClient(t, res)
   162  
   163  	ctx := context.TODO()
   164  	err := armClient.buildTestResources(ctx, &res)
   165  	defer armClient.destroyTestResources(ctx, res)
   166  	if err != nil {
   167  		t.Fatalf("Error creating Test Resources: %q", err)
   168  	}
   169  
   170  	b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
   171  		"storage_account_name": res.storageAccountName,
   172  		"container_name":       res.storageContainerName,
   173  		"key":                  res.storageKeyName,
   174  		"access_key":           res.storageAccountAccessKey,
   175  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
   176  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
   177  	})).(*Backend)
   178  
   179  	b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
   180  		"storage_account_name": res.storageAccountName,
   181  		"container_name":       res.storageContainerName,
   182  		"key":                  res.storageKeyName,
   183  		"access_key":           res.storageAccountAccessKey,
   184  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
   185  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
   186  	})).(*Backend)
   187  
   188  	s1, err := b1.StateMgr(backend.DefaultStateName)
   189  	if err != nil {
   190  		t.Fatal(err)
   191  	}
   192  
   193  	s2, err := b2.StateMgr(backend.DefaultStateName)
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	remote.TestRemoteLocks(t, s1.(*remote.State).Client, s2.(*remote.State).Client)
   199  }
   200  
   201  func TestRemoteClientServicePrincipalLocks(t *testing.T) {
   202  	testAccAzureBackend(t)
   203  	rs := acctest.RandString(4)
   204  	res := testResourceNames(rs, "testState")
   205  	armClient := buildTestClient(t, res)
   206  
   207  	ctx := context.TODO()
   208  	err := armClient.buildTestResources(ctx, &res)
   209  	defer armClient.destroyTestResources(ctx, res)
   210  	if err != nil {
   211  		t.Fatalf("Error creating Test Resources: %q", err)
   212  	}
   213  
   214  	b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
   215  		"storage_account_name": res.storageAccountName,
   216  		"container_name":       res.storageContainerName,
   217  		"key":                  res.storageKeyName,
   218  		"resource_group_name":  res.resourceGroup,
   219  		"subscription_id":      os.Getenv("ARM_SUBSCRIPTION_ID"),
   220  		"tenant_id":            os.Getenv("ARM_TENANT_ID"),
   221  		"client_id":            os.Getenv("ARM_CLIENT_ID"),
   222  		"client_secret":        os.Getenv("ARM_CLIENT_SECRET"),
   223  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
   224  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
   225  	})).(*Backend)
   226  
   227  	b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
   228  		"storage_account_name": res.storageAccountName,
   229  		"container_name":       res.storageContainerName,
   230  		"key":                  res.storageKeyName,
   231  		"resource_group_name":  res.resourceGroup,
   232  		"subscription_id":      os.Getenv("ARM_SUBSCRIPTION_ID"),
   233  		"tenant_id":            os.Getenv("ARM_TENANT_ID"),
   234  		"client_id":            os.Getenv("ARM_CLIENT_ID"),
   235  		"client_secret":        os.Getenv("ARM_CLIENT_SECRET"),
   236  		"environment":          os.Getenv("ARM_ENVIRONMENT"),
   237  		"endpoint":             os.Getenv("ARM_ENDPOINT"),
   238  	})).(*Backend)
   239  
   240  	s1, err := b1.StateMgr(backend.DefaultStateName)
   241  	if err != nil {
   242  		t.Fatal(err)
   243  	}
   244  
   245  	s2, err := b2.StateMgr(backend.DefaultStateName)
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  
   250  	remote.TestRemoteLocks(t, s1.(*remote.State).Client, s2.(*remote.State).Client)
   251  }
   252  
   253  func TestPutMaintainsMetaData(t *testing.T) {
   254  	testAccAzureBackend(t)
   255  	rs := acctest.RandString(4)
   256  	res := testResourceNames(rs, "testState")
   257  	armClient := buildTestClient(t, res)
   258  
   259  	ctx := context.TODO()
   260  	err := armClient.buildTestResources(ctx, &res)
   261  	defer armClient.destroyTestResources(ctx, res)
   262  	if err != nil {
   263  		t.Fatalf("Error creating Test Resources: %q", err)
   264  	}
   265  
   266  	headerName := "acceptancetest"
   267  	expectedValue := "f3b56bad-33ad-4b93-a600-7a66e9cbd1eb"
   268  
   269  	client, err := armClient.getBlobClient(ctx)
   270  	if err != nil {
   271  		t.Fatalf("Error building Blob Client: %+v", err)
   272  	}
   273  
   274  	_, err = client.PutBlockBlob(ctx, res.storageAccountName, res.storageContainerName, res.storageKeyName, blobs.PutBlockBlobInput{})
   275  	if err != nil {
   276  		t.Fatalf("Error Creating Block Blob: %+v", err)
   277  	}
   278  
   279  	blobReference, err := client.GetProperties(ctx, res.storageAccountName, res.storageContainerName, res.storageKeyName, blobs.GetPropertiesInput{})
   280  	if err != nil {
   281  		t.Fatalf("Error loading MetaData: %+v", err)
   282  	}
   283  
   284  	blobReference.MetaData[headerName] = expectedValue
   285  	opts := blobs.SetMetaDataInput{
   286  		MetaData: blobReference.MetaData,
   287  	}
   288  	_, err = client.SetMetaData(ctx, res.storageAccountName, res.storageContainerName, res.storageKeyName, opts)
   289  	if err != nil {
   290  		t.Fatalf("Error setting MetaData: %+v", err)
   291  	}
   292  
   293  	// update the metadata using the Backend
   294  	remoteClient := RemoteClient{
   295  		keyName:       res.storageKeyName,
   296  		containerName: res.storageContainerName,
   297  		accountName:   res.storageAccountName,
   298  
   299  		giovanniBlobClient: *client,
   300  	}
   301  
   302  	bytes := []byte(acctest.RandString(20))
   303  	err = remoteClient.Put(bytes)
   304  	if err != nil {
   305  		t.Fatalf("Error putting data: %+v", err)
   306  	}
   307  
   308  	// Verify it still exists
   309  	blobReference, err = client.GetProperties(ctx, res.storageAccountName, res.storageContainerName, res.storageKeyName, blobs.GetPropertiesInput{})
   310  	if err != nil {
   311  		t.Fatalf("Error loading MetaData: %+v", err)
   312  	}
   313  
   314  	if blobReference.MetaData[headerName] != expectedValue {
   315  		t.Fatalf("%q was not set to %q in the MetaData: %+v", headerName, expectedValue, blobReference.MetaData)
   316  	}
   317  }