From 211ec55a30a7696a17661f5aaea0f8a5f623ee89 Mon Sep 17 00:00:00 2001 From: Sekiranda Hamza <55385490+Zanda256@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:45:12 +0300 Subject: [PATCH] Skip reading encryption keys on `tofu init ` with `-backend=false` flag set (#2293) Signed-off-by: Sekiranda --- CHANGELOG.md | 1 + internal/command/init.go | 19 +++-- internal/command/init_test.go | 69 +++++++++++++++++++ .../init-encryption-available/main.tf | 33 +++++++++ 4 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 internal/command/testdata/init-encryption-available/main.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 110cb561a5..730c2b3cff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ NEW FEATURES: ENHANCEMENTS: BUG FIXES: +* `tofu init` command does not attempt to read encryption keys when `-backend=false` flag is set. (https://github.com/opentofu/opentofu/pull/2293) ## Previous Releases diff --git a/internal/command/init.go b/internal/command/init.go index e638ad9dea..7dd5b21af4 100644 --- a/internal/command/init.go +++ b/internal/command/init.go @@ -204,12 +204,19 @@ func (c *InitCommand) Run(args []string) int { return 1 } - // Load the encryption configuration - enc, encDiags := c.EncryptionFromModule(rootModEarly) - diags = diags.Append(encDiags) - if encDiags.HasErrors() { - c.showDiagnostics(diags) - return 1 + var enc encryption.Encryption + // If backend flag is explicitly set to false i.e -backend=false, we disable state and plan encryption + if backendFlagSet && !flagBackend { + enc = encryption.Disabled() + } else { + // Load the encryption configuration + var encDiags tfdiags.Diagnostics + enc, encDiags = c.EncryptionFromModule(rootModEarly) + diags = diags.Append(encDiags) + if encDiags.HasErrors() { + c.showDiagnostics(diags) + return 1 + } } var back backend.Backend diff --git a/internal/command/init_test.go b/internal/command/init_test.go index a2679dc676..365368ccc1 100644 --- a/internal/command/init_test.go +++ b/internal/command/init_test.go @@ -3065,6 +3065,75 @@ func TestInit_invalidExtraLabel(t *testing.T) { } } +func TestInit_skipEncryptionBackendFalse(t *testing.T) { + t.Run("init success with encryption present and -backend=false", func(t *testing.T) { + // Create a temporary working directory that is empty + td := t.TempDir() + testCopyDir(t, testFixturePath("init-encryption-available"), td) + defer testChdir(t, td)() + + overrides := metaOverridesForProvider(testProvider()) + ui := new(cli.MockUi) + view, _ := testView(t) + providerSource, closeCallback := newMockProviderSource(t, map[string][]string{ + // mock aws provider + "hashicorp/aws": {"5.0", "5.8"}, + }) + defer closeCallback() + m := Meta{ + testingOverrides: overrides, + Ui: ui, + View: view, + ProviderSource: providerSource, + } + + c := &InitCommand{ + Meta: m, + } + + args := []string{ + "-backend=false", // should disable reading encryption key run init successfully + } + if code := c.Run(args); code != 0 { + t.Fatalf("init should run successfully with -backend=false: \ngot error : %s\n", ui.ErrorWriter.String()) + } + }) + + t.Run("init fails with encryption present -backend=false not set", func(t *testing.T) { + // Create a temporary working directory that is empty + td := t.TempDir() + testCopyDir(t, testFixturePath("init-encryption-available"), td) + defer testChdir(t, td)() + + overrides := metaOverridesForProvider(testProvider()) + ui := new(cli.MockUi) + view, _ := testView(t) + providerSource, closeCallback := newMockProviderSource(t, map[string][]string{ + // mock aws provider + "hashicorp/aws": {"5.0", "5.8"}, + }) + defer closeCallback() + m := Meta{ + testingOverrides: overrides, + Ui: ui, + View: view, + ProviderSource: providerSource, + } + + c := &InitCommand{ + Meta: m, + } + + var args []string + // Check error is generated from trying to read encryption key or fail test + if code := c.Run(args); code == 0 { + t.Fatalf("init should not run successfully\n") + } else if !strings.Contains(ui.ErrorWriter.String(), "key_provider.aws_kms.key failed with error:") { + t.Fatalf("generated error should contain the string \"Error: Unable to fetch encryption key data\"\ninstead got : %s\n", ui.ErrorWriter.String()) + } + }) +} + // newMockProviderSource is a helper to succinctly construct a mock provider // source that contains a set of packages matching the given provider versions // that are available for installation (from temporary local files). diff --git a/internal/command/testdata/init-encryption-available/main.tf b/internal/command/testdata/init-encryption-available/main.tf new file mode 100644 index 0000000000..83489a9d0e --- /dev/null +++ b/internal/command/testdata/init-encryption-available/main.tf @@ -0,0 +1,33 @@ +variable "encryption_kms_key_id" { + type = string + default = "1234abcd-12ab-34cd-56ef-1234567890ab" +} + +terraform { + + required_providers { + aws = { + source = "hashicorp/aws" + version = "5.8" + } + } + + encryption { + key_provider "aws_kms" "key" { + kms_key_id = var.encryption_kms_key_id + region = "eu-central-1" + key_spec = "AES_256" + } + method "aes_gcm" "encrypt-aes" { + keys = key_provider.aws_kms.key + } + state { + enforced = true + method = method.aes_gcm.encrypt-aes + } + plan { + enforced = true + method = method.aes_gcm.encrypt-aes + } + } +} \ No newline at end of file