## Description Instead of initializing static AWS credentials, we rely on the credential provider chain in [Kopia](https://github.com/kopia/kopia/pull/2213) to discover and initialize credentials. This currently supports the following in this order: - Static credentials - Environment variables (what Corso used to implement) - IAM Going forward, this will also allow us to support shared credentials (cred file) once that is added to the credential provider chain. ## Type of change Please check the type of change your PR introduces: - [x] 🌻 Feature - [ ] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Test - [ ] 🐹 Trivial/Minor ## Issue(s) - #384 ## Test Plan <!-- How will this be tested prior to merging.--> - [x] 💪 Manual (see test output below) - [ ] ⚡ Unit test - [x] 💚 E2E
296 lines
7.7 KiB
Go
296 lines
7.7 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
|
|
"github.com/spf13/viper"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/alcionai/corso/internal/tester"
|
|
"github.com/alcionai/corso/pkg/account"
|
|
"github.com/alcionai/corso/pkg/credentials"
|
|
"github.com/alcionai/corso/pkg/storage"
|
|
)
|
|
|
|
const (
|
|
configFileTemplate = `
|
|
` + BucketNameKey + ` = '%s'
|
|
` + EndpointKey + ` = 's3.amazonaws.com'
|
|
` + PrefixKey + ` = 'test-prefix'
|
|
` + StorageProviderTypeKey + ` = 'S3'
|
|
` + AccountProviderTypeKey + ` = 'M365'
|
|
` + TenantIDKey + ` = '%s'
|
|
`
|
|
)
|
|
|
|
type ConfigSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func TestConfigSuite(t *testing.T) {
|
|
suite.Run(t, new(ConfigSuite))
|
|
}
|
|
|
|
func (suite *ConfigSuite) TestReadRepoConfigBasic() {
|
|
var (
|
|
t = suite.T()
|
|
vpr = viper.New()
|
|
)
|
|
|
|
const (
|
|
b = "read-repo-config-basic-bucket"
|
|
tID = "6f34ac30-8196-469b-bf8f-d83deadbbbba"
|
|
)
|
|
|
|
// Generate test config file
|
|
testConfigData := fmt.Sprintf(configFileTemplate, b, tID)
|
|
testConfigFilePath := path.Join(t.TempDir(), "corso.toml")
|
|
err := ioutil.WriteFile(testConfigFilePath, []byte(testConfigData), 0o700)
|
|
require.NoError(t, err)
|
|
|
|
// Configure viper to read test config file
|
|
vpr.SetConfigFile(testConfigFilePath)
|
|
|
|
// Read and validate config
|
|
require.NoError(t, vpr.ReadInConfig(), "reading repo config")
|
|
|
|
s3Cfg, err := s3ConfigsFromViper(vpr)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, b, s3Cfg.Bucket)
|
|
|
|
m365, err := m365ConfigsFromViper(vpr)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tID, m365.TenantID)
|
|
}
|
|
|
|
func (suite *ConfigSuite) TestWriteReadConfig() {
|
|
var (
|
|
t = suite.T()
|
|
vpr = viper.New()
|
|
)
|
|
|
|
const (
|
|
bkt = "write-read-config-bucket"
|
|
tid = "3c0748d2-470e-444c-9064-1268e52609d5"
|
|
)
|
|
|
|
// Configure viper to read test config file
|
|
testConfigFilePath := path.Join(t.TempDir(), "corso.toml")
|
|
require.NoError(t, initWithViper(vpr, testConfigFilePath), "initializing repo config")
|
|
|
|
s3Cfg := storage.S3Config{Bucket: bkt}
|
|
m365 := account.M365Config{TenantID: tid}
|
|
|
|
require.NoError(t, writeRepoConfigWithViper(vpr, s3Cfg, m365), "writing repo config")
|
|
require.NoError(t, vpr.ReadInConfig(), "reading repo config")
|
|
|
|
readS3Cfg, err := s3ConfigsFromViper(vpr)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, readS3Cfg.Bucket, s3Cfg.Bucket)
|
|
|
|
readM365, err := m365ConfigsFromViper(vpr)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, readM365.TenantID, m365.TenantID)
|
|
}
|
|
|
|
func (suite *ConfigSuite) TestMustMatchConfig() {
|
|
var (
|
|
t = suite.T()
|
|
vpr = viper.New()
|
|
)
|
|
|
|
const (
|
|
bkt = "must-match-config-bucket"
|
|
tid = "dfb12063-7598-458b-85ab-42352c5c25e2"
|
|
)
|
|
|
|
// Configure viper to read test config file
|
|
testConfigFilePath := path.Join(t.TempDir(), "corso.toml")
|
|
require.NoError(t, initWithViper(vpr, testConfigFilePath), "initializing repo config")
|
|
|
|
s3Cfg := storage.S3Config{Bucket: bkt}
|
|
m365 := account.M365Config{TenantID: tid}
|
|
|
|
require.NoError(t, writeRepoConfigWithViper(vpr, s3Cfg, m365), "writing repo config")
|
|
require.NoError(t, vpr.ReadInConfig(), "reading repo config")
|
|
|
|
table := []struct {
|
|
name string
|
|
input map[string]string
|
|
errCheck assert.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
name: "full match",
|
|
input: map[string]string{
|
|
storage.Bucket: bkt,
|
|
account.TenantID: tid,
|
|
},
|
|
errCheck: assert.NoError,
|
|
},
|
|
{
|
|
name: "empty values",
|
|
input: map[string]string{
|
|
storage.Bucket: "",
|
|
account.TenantID: "",
|
|
},
|
|
errCheck: assert.NoError,
|
|
},
|
|
{
|
|
name: "no overrides",
|
|
input: map[string]string{},
|
|
errCheck: assert.NoError,
|
|
},
|
|
{
|
|
name: "nil map",
|
|
input: nil,
|
|
errCheck: assert.NoError,
|
|
},
|
|
{
|
|
name: "no recognized keys",
|
|
input: map[string]string{
|
|
"fnords": "smurfs",
|
|
"nonsense": "",
|
|
},
|
|
errCheck: assert.NoError,
|
|
},
|
|
{
|
|
name: "mismatch",
|
|
input: map[string]string{
|
|
storage.Bucket: tid,
|
|
account.TenantID: bkt,
|
|
},
|
|
errCheck: assert.Error,
|
|
},
|
|
}
|
|
for _, test := range table {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
test.errCheck(t, mustMatchConfig(vpr, test.input))
|
|
})
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// integration tests
|
|
// ------------------------------------------------------------
|
|
|
|
type ConfigIntegrationSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func TestConfigIntegrationSuite(t *testing.T) {
|
|
if err := tester.RunOnAny(
|
|
tester.CorsoCITests,
|
|
tester.CorsoCLIConfigTests,
|
|
); err != nil {
|
|
t.Skip(err)
|
|
}
|
|
|
|
suite.Run(t, new(ConfigIntegrationSuite))
|
|
}
|
|
|
|
func (suite *ConfigIntegrationSuite) SetupSuite() {
|
|
_, err := tester.GetRequiredEnvSls(
|
|
tester.AWSStorageCredEnvs,
|
|
tester.M365AcctCredEnvs)
|
|
require.NoError(suite.T(), err)
|
|
}
|
|
|
|
func (suite *ConfigIntegrationSuite) TestGetStorageAndAccount() {
|
|
t := suite.T()
|
|
vpr := viper.New()
|
|
|
|
const (
|
|
bkt = "get-storage-and-account-bucket"
|
|
end = "https://get-storage-and-account.com"
|
|
pfx = "get-storage-and-account-prefix"
|
|
tid = "3a2faa4e-a882-445c-9d27-f552ef189381"
|
|
)
|
|
|
|
// Configure viper to read test config file
|
|
testConfigFilePath := path.Join(t.TempDir(), "corso.toml")
|
|
require.NoError(t, initWithViper(vpr, testConfigFilePath), "initializing repo config")
|
|
|
|
s3Cfg := storage.S3Config{
|
|
Bucket: bkt,
|
|
Endpoint: end,
|
|
Prefix: pfx,
|
|
}
|
|
m365 := account.M365Config{TenantID: tid}
|
|
|
|
require.NoError(t, writeRepoConfigWithViper(vpr, s3Cfg, m365), "writing repo config")
|
|
require.NoError(t, vpr.ReadInConfig(), "reading repo config")
|
|
|
|
st, ac, err := getStorageAndAccountWithViper(vpr, true, nil)
|
|
require.NoError(t, err, "getting storage and account from config")
|
|
|
|
readS3Cfg, err := st.S3Config()
|
|
require.NoError(t, err, "reading s3 config from storage")
|
|
assert.Equal(t, readS3Cfg.Bucket, s3Cfg.Bucket)
|
|
assert.Equal(t, readS3Cfg.Endpoint, s3Cfg.Endpoint)
|
|
assert.Equal(t, readS3Cfg.Prefix, s3Cfg.Prefix)
|
|
|
|
common, err := st.CommonConfig()
|
|
require.NoError(t, err, "reading common config from storage")
|
|
assert.Equal(t, common.CorsoPassword, os.Getenv(credentials.CorsoPassword))
|
|
|
|
readM365, err := ac.M365Config()
|
|
require.NoError(t, err, "reading m365 config from account")
|
|
assert.Equal(t, readM365.TenantID, m365.TenantID)
|
|
assert.Equal(t, readM365.ClientID, os.Getenv(credentials.ClientID))
|
|
assert.Equal(t, readM365.ClientSecret, os.Getenv(credentials.ClientSecret))
|
|
}
|
|
|
|
func (suite *ConfigIntegrationSuite) TestGetStorageAndAccount_noFileOnlyOverrides() {
|
|
t := suite.T()
|
|
vpr := viper.New()
|
|
|
|
const (
|
|
bkt = "get-storage-and-account-no-file-bucket"
|
|
end = "https://get-storage-and-account.com/no-file"
|
|
pfx = "get-storage-and-account-no-file-prefix"
|
|
tid = "88f8522b-18e4-4d0f-b514-2d7b34d4c5a1"
|
|
)
|
|
|
|
// Configure viper to read test config file
|
|
s3Cfg := storage.S3Config{
|
|
Bucket: bkt,
|
|
Endpoint: end,
|
|
Prefix: pfx,
|
|
}
|
|
m365 := account.M365Config{TenantID: tid}
|
|
|
|
overrides := map[string]string{
|
|
account.TenantID: tid,
|
|
AccountProviderTypeKey: account.ProviderM365.String(),
|
|
storage.Bucket: bkt,
|
|
storage.Endpoint: end,
|
|
storage.Prefix: pfx,
|
|
StorageProviderTypeKey: storage.ProviderS3.String(),
|
|
}
|
|
|
|
st, ac, err := getStorageAndAccountWithViper(vpr, false, overrides)
|
|
require.NoError(t, err, "getting storage and account from config")
|
|
|
|
readS3Cfg, err := st.S3Config()
|
|
require.NoError(t, err, "reading s3 config from storage")
|
|
assert.Equal(t, readS3Cfg.Bucket, s3Cfg.Bucket)
|
|
assert.Equal(t, readS3Cfg.Endpoint, s3Cfg.Endpoint)
|
|
assert.Equal(t, readS3Cfg.Prefix, s3Cfg.Prefix)
|
|
|
|
common, err := st.CommonConfig()
|
|
require.NoError(t, err, "reading common config from storage")
|
|
assert.Equal(t, common.CorsoPassword, os.Getenv(credentials.CorsoPassword))
|
|
|
|
readM365, err := ac.M365Config()
|
|
require.NoError(t, err, "reading m365 config from account")
|
|
assert.Equal(t, readM365.TenantID, m365.TenantID)
|
|
assert.Equal(t, readM365.ClientID, os.Getenv(credentials.ClientID))
|
|
assert.Equal(t, readM365.ClientSecret, os.Getenv(credentials.ClientSecret))
|
|
}
|