diff --git a/pkg/repository/udmrepo/kopialib/backend/common.go b/pkg/repository/udmrepo/kopialib/backend/common.go index 2896c068fb..5b0597e2ee 100644 --- a/pkg/repository/udmrepo/kopialib/backend/common.go +++ b/pkg/repository/udmrepo/kopialib/backend/common.go @@ -18,6 +18,8 @@ package backend import ( "context" + "os" + "slices" "time" "github.com/kopia/kopia/repo" @@ -48,16 +50,28 @@ func setupLimits(ctx context.Context, flags map[string]string) throttling.Limits } } +// Helper function to choose between environment variable and default kopia algorithm value +func getKopiaAlgorithm(key, envKey string, flags map[string]string, supportedAlgorithms []string, defaultValue string) string { + algorithm := os.Getenv(envKey) + if len(algorithm) > 0 { + if slices.Contains(supportedAlgorithms, algorithm) { + return algorithm + } + } + + return optionalHaveStringWithDefault(key, flags, defaultValue) +} + // SetupNewRepositoryOptions setups the options when creating a new Kopia repository func SetupNewRepositoryOptions(ctx context.Context, flags map[string]string) repo.NewRepositoryOptions { return repo.NewRepositoryOptions{ BlockFormat: format.ContentFormat{ - Hash: optionalHaveStringWithDefault(udmrepo.StoreOptionGenHashAlgo, flags, hashing.DefaultAlgorithm), - Encryption: optionalHaveStringWithDefault(udmrepo.StoreOptionGenEncryptAlgo, flags, encryption.DefaultAlgorithm), + Hash: getKopiaAlgorithm(udmrepo.StoreOptionGenHashAlgo, "KOPIA_HASHING_ALGORITHM", flags, hashing.SupportedAlgorithms(), hashing.DefaultAlgorithm), + Encryption: getKopiaAlgorithm(udmrepo.StoreOptionGenEncryptAlgo, "KOPIA_ENCRYPTION_ALGORITHM", flags, encryption.SupportedAlgorithms(false), encryption.DefaultAlgorithm), }, ObjectFormat: format.ObjectFormat{ - Splitter: optionalHaveStringWithDefault(udmrepo.StoreOptionGenSplitAlgo, flags, splitter.DefaultAlgorithm), + Splitter: getKopiaAlgorithm(udmrepo.StoreOptionGenSplitAlgo, "KOPIA_SPLITTER_ALGORITHM", flags, splitter.SupportedAlgorithms(), splitter.DefaultAlgorithm), }, RetentionMode: blob.RetentionMode(optionalHaveString(udmrepo.StoreOptionGenRetentionMode, flags)), diff --git a/pkg/repository/udmrepo/kopialib/backend/common_kopia_algorithms_test.go b/pkg/repository/udmrepo/kopialib/backend/common_kopia_algorithms_test.go new file mode 100644 index 0000000000..97419855c5 --- /dev/null +++ b/pkg/repository/udmrepo/kopialib/backend/common_kopia_algorithms_test.go @@ -0,0 +1,144 @@ +/* +Copyright the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package backend + +import ( + "context" + "testing" + + "github.com/kopia/kopia/repo" + "github.com/kopia/kopia/repo/encryption" + "github.com/kopia/kopia/repo/format" + "github.com/kopia/kopia/repo/hashing" + "github.com/kopia/kopia/repo/splitter" + "github.com/stretchr/testify/assert" + + "github.com/vmware-tanzu/velero/pkg/repository/udmrepo" +) + +func TestSetupNewRepoAlgorithms(t *testing.T) { + + testCases := []struct { + name string + envVars map[string]string + flags map[string]string + expected repo.NewRepositoryOptions + }{ + { + name: "with valid non-default hash algo from env", + envVars: map[string]string{ + "KOPIA_HASHING_ALGORITHM": "HMAC-SHA3-224", + }, + flags: map[string]string{}, + expected: repo.NewRepositoryOptions{ + BlockFormat: format.ContentFormat{ + Hash: "HMAC-SHA3-224", + Encryption: encryption.DefaultAlgorithm, + }, + ObjectFormat: format.ObjectFormat{ + Splitter: splitter.DefaultAlgorithm, + }, + }, + }, + { + name: "with valid non-default encryption algo from env", + envVars: map[string]string{ + "KOPIA_HASHING_ALGORITHM": "", + "KOPIA_SPLITTER_ALGORITHM": "", + "KOPIA_ENCRYPTION_ALGORITHM": "CHACHA20-POLY1305-HMAC-SHA256", + }, + flags: map[string]string{}, + expected: repo.NewRepositoryOptions{ + BlockFormat: format.ContentFormat{ + Hash: hashing.DefaultAlgorithm, + Encryption: "CHACHA20-POLY1305-HMAC-SHA256", + }, + ObjectFormat: format.ObjectFormat{ + Splitter: splitter.DefaultAlgorithm, + }, + }, + }, + { + name: "with valid non-default splitter algo from env", + envVars: map[string]string{"KOPIA_SPLITTER_ALGORITHM": "FIXED-512K"}, + flags: map[string]string{}, + expected: repo.NewRepositoryOptions{ + BlockFormat: format.ContentFormat{ + Hash: hashing.DefaultAlgorithm, + Encryption: encryption.DefaultAlgorithm, + }, + ObjectFormat: format.ObjectFormat{ + Splitter: "FIXED-512K", + }, + }, + }, + { + name: "with valid non-default splitter and hashing algo from env, invalid encryption from env", + envVars: map[string]string{"KOPIA_SPLITTER_ALGORITHM": "FIXED-512K", "KOPIA_HASHING_ALGORITHM": "HMAC-SHA3-224", "KOPIA_ENCRYPTION_ALGORITHM": "NON-EXISTING-SHA256"}, + flags: map[string]string{}, + expected: repo.NewRepositoryOptions{ + BlockFormat: format.ContentFormat{ + Hash: "HMAC-SHA3-224", + Encryption: encryption.DefaultAlgorithm, + }, + ObjectFormat: format.ObjectFormat{ + Splitter: "FIXED-512K", + }, + }, + }, + { + name: "with unsupported hash algo in env, fallback to default", + envVars: map[string]string{"KOPIA_HASHING_ALGORITHM": "unsupported-hash"}, + flags: map[string]string{}, + expected: repo.NewRepositoryOptions{ + BlockFormat: format.ContentFormat{ + Hash: hashing.DefaultAlgorithm, + Encryption: encryption.DefaultAlgorithm, + }, + ObjectFormat: format.ObjectFormat{ + Splitter: splitter.DefaultAlgorithm, + }, + }, + }, + { + name: "hash in StoreOptionGenHashAlgo and env, env wins", + envVars: map[string]string{"KOPIA_HASHING_ALGORITHM": "HMAC-SHA3-224"}, + flags: map[string]string{ + udmrepo.StoreOptionGenHashAlgo: "HMAC-SHA3-256", + }, + expected: repo.NewRepositoryOptions{ + BlockFormat: format.ContentFormat{ + Hash: "HMAC-SHA3-224", + Encryption: encryption.DefaultAlgorithm, + }, + ObjectFormat: format.ObjectFormat{ + Splitter: splitter.DefaultAlgorithm, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for key, value := range tc.envVars { + t.Setenv(key, value) + } + ret := SetupNewRepositoryOptions(context.Background(), tc.flags) + assert.Equal(t, tc.expected, ret) + }) + } +}