separate tenantID from m365 creds (#231)

* separate tenantID from m365 creds

Now that account.Account is in place, tenant id needs
to get removed from the credential set (it isn't actually
a secret) and placed in the account configuration instead.
This commit is contained in:
Keepers 2022-06-27 13:54:37 -06:00 committed by GitHub
parent 108065df75
commit 689c5cc1e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 132 additions and 123 deletions

View File

@ -99,14 +99,16 @@ func ReadRepoConfig() (storage.S3Config, account.Account, error) {
s3Config.Prefix = viper.GetString(PrefixKey) s3Config.Prefix = viper.GetString(PrefixKey)
m365Creds := credentials.GetM365() m365Creds := credentials.GetM365()
tenantID := os.Getenv(account.TenantID)
cfgTenantID := viper.GetString(TenantIDKey) cfgTenantID := viper.GetString(TenantIDKey)
if len(cfgTenantID) > 0 { if len(cfgTenantID) > 0 {
m365Creds.TenantID = cfgTenantID tenantID = cfgTenantID
} }
acct, err = account.NewAccount( acct, err = account.NewAccount(
account.ProviderM365, account.ProviderM365,
account.M365Config{ account.M365Config{
M365: m365Creds, M365: m365Creds,
TenantID: tenantID,
}, },
) )

View File

@ -11,9 +11,9 @@ require (
github.com/kopia/kopia v0.10.7 github.com/kopia/kopia v0.10.7
github.com/microsoft/kiota-abstractions-go v0.8.1 github.com/microsoft/kiota-abstractions-go v0.8.1
github.com/microsoft/kiota-authentication-azure-go v0.3.0 github.com/microsoft/kiota-authentication-azure-go v0.3.0
github.com/microsoft/kiota-serialization-json-go v0.5.1 github.com/microsoft/kiota-serialization-json-go v0.5.3
github.com/microsoftgraph/msgraph-sdk-go v0.25.0 github.com/microsoftgraph/msgraph-sdk-go v0.28.0
github.com/microsoftgraph/msgraph-sdk-go-core v0.26.0 github.com/microsoftgraph/msgraph-sdk-go-core v0.26.1
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.4.0 github.com/spf13/cobra v1.4.0
github.com/spf13/viper v1.12.0 github.com/spf13/viper v1.12.0
@ -59,8 +59,8 @@ require (
github.com/klauspost/pgzip v1.2.5 // indirect github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/microsoft/kiota-http-go v0.5.0 // indirect github.com/microsoft/kiota-http-go v0.5.1 // indirect
github.com/microsoft/kiota-serialization-text-go v0.4.0 // indirect github.com/microsoft/kiota-serialization-text-go v0.4.1 // indirect
github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.28 // indirect github.com/minio/minio-go/v7 v7.0.28 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect github.com/minio/sha256-simd v1.0.0 // indirect

View File

@ -68,8 +68,6 @@ github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dg
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cjlapao/common-go v0.0.20 h1:AIZBtuxwJPXFqyxFOlvVDWZgbsuTSquZEUw4KMx8pNg=
github.com/cjlapao/common-go v0.0.20/go.mod h1:EVLEXIxsBHblPMrhJYOvL4yBCcBj7IYDdW88VlfxpPM=
github.com/cjlapao/common-go v0.0.21 h1:z4PDFLQG4pJxHEmM8ecmnjDgTcR0Xr/30WZiNZF2oYM= github.com/cjlapao/common-go v0.0.21 h1:z4PDFLQG4pJxHEmM8ecmnjDgTcR0Xr/30WZiNZF2oYM=
github.com/cjlapao/common-go v0.0.21/go.mod h1:QHUcl8KX3RgNVonFJ1WpW4mlr9NyWOHmzqxaRbwooPo= github.com/cjlapao/common-go v0.0.21/go.mod h1:QHUcl8KX3RgNVonFJ1WpW4mlr9NyWOHmzqxaRbwooPo=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@ -238,22 +236,20 @@ github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamh
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microsoft/kiota-abstractions-go v0.8.0 h1:mtilyDlfM9EUe4blByCmQh/iO7S0176zHd+oxr7rh20=
github.com/microsoft/kiota-abstractions-go v0.8.0/go.mod h1:uWv0yQ4lYJtK9NIK5RAmw/LeIMUbIG0asu36v4yjyjY=
github.com/microsoft/kiota-abstractions-go v0.8.1 h1:ACCwRwddJYOx+SRqfgcR8Wo8PZTd4g+JMa8lY8ABy+4= github.com/microsoft/kiota-abstractions-go v0.8.1 h1:ACCwRwddJYOx+SRqfgcR8Wo8PZTd4g+JMa8lY8ABy+4=
github.com/microsoft/kiota-abstractions-go v0.8.1/go.mod h1:05aCidCKhzer+yfhGeePaMUY3MH+wrAkQztBVEreTtc= github.com/microsoft/kiota-abstractions-go v0.8.1/go.mod h1:05aCidCKhzer+yfhGeePaMUY3MH+wrAkQztBVEreTtc=
github.com/microsoft/kiota-authentication-azure-go v0.3.0 h1:iLyy5qldAjBiYMGMk1r/rJkcmARA8cKboiN7/XbRxv4= github.com/microsoft/kiota-authentication-azure-go v0.3.0 h1:iLyy5qldAjBiYMGMk1r/rJkcmARA8cKboiN7/XbRxv4=
github.com/microsoft/kiota-authentication-azure-go v0.3.0/go.mod h1:qyZWSCug2eG1zrRnCSacyFHGsgQa4aSCWn3EOkY9Z1M= github.com/microsoft/kiota-authentication-azure-go v0.3.0/go.mod h1:qyZWSCug2eG1zrRnCSacyFHGsgQa4aSCWn3EOkY9Z1M=
github.com/microsoft/kiota-http-go v0.5.0 h1:p88Jz3Puk2ycwiLBhO/L7fygje+ACT2qvN2gKHfMSLE= github.com/microsoft/kiota-http-go v0.5.1 h1:8QLZBfvPRvISUO+qWvv6fBrxaBH5n0V/Venq7Fq51cg=
github.com/microsoft/kiota-http-go v0.5.0/go.mod h1:k/IlqH/z8MOj8loDUU2Z2tRbqzea9Zd4zC199K/GfMU= github.com/microsoft/kiota-http-go v0.5.1/go.mod h1:WqEFNw3rMEatymG4Xh3rLSTxaKq80rJdQ/CSSh7m6jI=
github.com/microsoft/kiota-serialization-json-go v0.5.1 h1:JX8JnonbmlRMRWEn9IzPTJFvB91ZlcaFc7NbgJC1PGg= github.com/microsoft/kiota-serialization-json-go v0.5.3 h1:NrRyed65WYhEH5NwZTzplWs+eoECEYtLpAQ5Dhwq1wc=
github.com/microsoft/kiota-serialization-json-go v0.5.1/go.mod h1:AwvSlqR5aZlv95UBUmirv0ccYayg/1x5JSdErLvJKHM= github.com/microsoft/kiota-serialization-json-go v0.5.3/go.mod h1:GI9vrssO1EvqzDtvMKuhjALn40phZOWkeeaMgtCk6xE=
github.com/microsoft/kiota-serialization-text-go v0.4.0 h1:jJd5+yjej/KeJtHSMvNNeoIuXtEhiq5p89oRh0v0bW4= github.com/microsoft/kiota-serialization-text-go v0.4.1 h1:6QPH7+geUPCpaSZkKCQw0Scngx2IF0vKodrvvWWiu2A=
github.com/microsoft/kiota-serialization-text-go v0.4.0/go.mod h1:jysZ8wwuFHcwI6YhJKVINisrTfQ7VBuly7oiVsd+gHg= github.com/microsoft/kiota-serialization-text-go v0.4.1/go.mod h1:DsriFnVBDCc4D84qxG3j8q/1Sxu16JILfhxMZm3kdfw=
github.com/microsoftgraph/msgraph-sdk-go v0.25.0 h1:WOORTAcuY42BFuuRPd0jAJmIdtPBfDeHcTFAfoQjPik= github.com/microsoftgraph/msgraph-sdk-go v0.28.0 h1:BolP/vNW7gsNXivg/qikcdftOicLMgMm3Z/6PpSFDvU=
github.com/microsoftgraph/msgraph-sdk-go v0.25.0/go.mod h1:m5eXsQYiU3oj+iBnluGtoF1Y5ER2YkZ1JIModpFgSJo= github.com/microsoftgraph/msgraph-sdk-go v0.28.0/go.mod h1:MB2iPD8vd8RTRAqlKTZfhLvE8OBiC/vjaOy8+J+nF1k=
github.com/microsoftgraph/msgraph-sdk-go-core v0.26.0 h1:cszmmU1gfVLuwqkmVR8m7cEB9GzVbk1bvxSG+BLv8Ew= github.com/microsoftgraph/msgraph-sdk-go-core v0.26.1 h1:wzEoPk6uyd+SkBur9NpzpPfKseUQYT1yjFkDUueLpfk=
github.com/microsoftgraph/msgraph-sdk-go-core v0.26.0/go.mod h1:foIwVlCGl22BMQohIhfFmOULUNPeN39/SifGjEyEoEs= github.com/microsoftgraph/msgraph-sdk-go-core v0.26.1/go.mod h1:cKWHZ9CfJnSvBJxzXnAXRA+SSy8JeAbS+4kOn3uyOIY=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.28 h1:VMr3K5qGIEt+/KW3poopRh8mzi5RwuCjmrmstK196Fg= github.com/minio/minio-go/v7 v7.0.28 h1:VMr3K5qGIEt+/KW3poopRh8mzi5RwuCjmrmstK196Fg=

View File

@ -19,6 +19,7 @@ import (
msfolder "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders" msfolder "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/alcionai/corso/pkg/account"
"github.com/alcionai/corso/pkg/logger" "github.com/alcionai/corso/pkg/logger"
) )
@ -39,9 +40,13 @@ type GraphConnector struct {
status *support.ConnectorOperationStatus // contains the status of the last run status status *support.ConnectorOperationStatus // contains the status of the last run status
} }
func NewGraphConnector(tenantId, clientId, secret string) (*GraphConnector, error) { func NewGraphConnector(acct account.Account) (*GraphConnector, error) {
m365, err := acct.M365Config()
if err != nil {
return nil, errors.Wrap(err, "retrieving m356 account configuration")
}
// Client Provider: Uses Secret for access to tenant-level data // Client Provider: Uses Secret for access to tenant-level data
cred, err := az.NewClientSecretCredential(tenantId, clientId, secret, nil) cred, err := az.NewClientSecretCredential(m365.TenantID, m365.ClientID, m365.ClientSecret, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -54,7 +59,7 @@ func NewGraphConnector(tenantId, clientId, secret string) (*GraphConnector, erro
return nil, err return nil, err
} }
gc := GraphConnector{ gc := GraphConnector{
tenant: tenantId, tenant: m365.TenantID,
adapter: *adapter, adapter: *adapter,
client: *msgraphsdk.NewGraphServiceClient(adapter), client: *msgraphsdk.NewGraphServiceClient(adapter),
Users: make(map[string]string, 0), Users: make(map[string]string, 0),

View File

@ -11,6 +11,7 @@ import (
"github.com/alcionai/corso/internal/connector/support" "github.com/alcionai/corso/internal/connector/support"
ctesting "github.com/alcionai/corso/internal/testing" ctesting "github.com/alcionai/corso/internal/testing"
"github.com/alcionai/corso/pkg/account"
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/credentials"
) )
@ -19,7 +20,7 @@ type GraphConnectorIntegrationSuite struct {
connector *GraphConnector connector *GraphConnector
} }
func TestGraphConnectorSuite(t *testing.T) { func TestGraphConnectorIntetgrationSuite(t *testing.T) {
if err := ctesting.RunOnAny( if err := ctesting.RunOnAny(
ctesting.CorsoCITests, ctesting.CorsoCITests,
ctesting.CorsoGraphConnectorTests, ctesting.CorsoGraphConnectorTests,
@ -30,13 +31,13 @@ func TestGraphConnectorSuite(t *testing.T) {
} }
func (suite *GraphConnectorIntegrationSuite) SetupSuite() { func (suite *GraphConnectorIntegrationSuite) SetupSuite() {
evs, err := ctesting.GetRequiredEnvVars(credentials.TenantID, credentials.ClientID, credentials.ClientSecret) _, err := ctesting.GetRequiredEnvVars(ctesting.M365AcctCredEnvs...)
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
suite.connector, err = NewGraphConnector( a, err := ctesting.NewM365Account()
evs[credentials.TenantID], require.NoError(suite.T(), err)
evs[credentials.ClientID],
evs[credentials.ClientSecret]) suite.connector, err = NewGraphConnector(a)
suite.NoError(err) suite.NoError(err)
} }
@ -94,21 +95,38 @@ func (suite *GraphConnectorIntegrationSuite) TestGraphConnector_restoreMessages(
func (suite *DiconnectedGraphConnectorSuite) TestBadConnection() { func (suite *DiconnectedGraphConnectorSuite) TestBadConnection() {
table := []struct { table := []struct {
name string name string
params []string acct func(t *testing.T) account.Account
}{ }{
{ {
name: "Invalid Credentials", name: "Invalid Credentials",
params: []string{"Test", "without", "data"}, acct: func(t *testing.T) account.Account {
a, err := account.NewAccount(
account.ProviderM365,
account.M365Config{
M365: credentials.M365{
ClientID: "Test",
ClientSecret: "without",
},
TenantID: "data",
},
)
require.NoError(t, err)
return a
},
}, },
{ {
name: "Empty Credentials", name: "Empty Credentials",
params: []string{"", "", ""}, acct: func(t *testing.T) account.Account {
// intentionally swallowing the error here
a, _ := account.NewAccount(account.ProviderM365)
return a
},
}, },
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
gc, err := NewGraphConnector(test.params[0], test.params[1], test.params[2]) gc, err := NewGraphConnector(test.acct(t))
assert.Nil(t, gc, test.name+" failed") assert.Nil(t, gc, test.name+" failed")
assert.NotNil(t, err, test.name+"failed") assert.NotNil(t, err, test.name+"failed")
}) })

View File

@ -247,7 +247,7 @@ func TestKopiaIntegrationSuite(t *testing.T) {
} }
func (suite *KopiaIntegrationSuite) SetupSuite() { func (suite *KopiaIntegrationSuite) SetupSuite() {
_, err := ctesting.GetRequiredEnvVars(ctesting.AWSCredentialEnvs...) _, err := ctesting.GetRequiredEnvVars(ctesting.AWSStorageCredEnvs...)
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
} }

View File

@ -7,7 +7,7 @@ import (
"github.com/alcionai/corso/internal/connector" "github.com/alcionai/corso/internal/connector"
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/account"
) )
// BackupOperation wraps an operation with backup-specific props. // BackupOperation wraps an operation with backup-specific props.
@ -15,7 +15,7 @@ type BackupOperation struct {
operation operation
Version string Version string
creds credentials.M365 account account.Account
Targets []string // something for targets/filter/source/app&users/etc Targets []string // something for targets/filter/source/app&users/etc
} }
@ -25,13 +25,13 @@ func NewBackupOperation(
ctx context.Context, ctx context.Context,
opts OperationOpts, opts OperationOpts,
kw *kopia.KopiaWrapper, kw *kopia.KopiaWrapper,
creds credentials.M365, acct account.Account,
targets []string, targets []string,
) (BackupOperation, error) { ) (BackupOperation, error) {
op := BackupOperation{ op := BackupOperation{
operation: newOperation(opts, kw), operation: newOperation(opts, kw),
Version: "v0", Version: "v0",
creds: creds, account: acct,
Targets: targets, Targets: targets,
} }
if err := op.validate(); err != nil { if err := op.validate(); err != nil {
@ -42,15 +42,12 @@ func NewBackupOperation(
} }
func (op BackupOperation) validate() error { func (op BackupOperation) validate() error {
if err := op.creds.Validate(); err != nil {
return errors.Wrap(err, "invalid credentials")
}
return op.operation.validate() return op.operation.validate()
} }
// Run begins a synchronous backup operation. // Run begins a synchronous backup operation.
func (op *BackupOperation) Run(ctx context.Context) (*kopia.BackupStats, error) { func (op *BackupOperation) Run(ctx context.Context) (*kopia.BackupStats, error) {
gc, err := connector.NewGraphConnector(op.creds.TenantID, op.creds.ClientID, op.creds.ClientSecret) gc, err := connector.NewGraphConnector(op.account)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "connecting to graph api") return nil, errors.Wrap(err, "connecting to graph api")
} }

View File

@ -11,7 +11,7 @@ import (
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/internal/operations" "github.com/alcionai/corso/internal/operations"
ctesting "github.com/alcionai/corso/internal/testing" ctesting "github.com/alcionai/corso/internal/testing"
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/account"
"github.com/alcionai/corso/pkg/repository" "github.com/alcionai/corso/pkg/repository"
) )
@ -28,27 +28,29 @@ func TestBackupOpIntegrationSuite(t *testing.T) {
func (suite *BackupOpIntegrationSuite) SetupSuite() { func (suite *BackupOpIntegrationSuite) SetupSuite() {
_, err := ctesting.GetRequiredEnvVars( _, err := ctesting.GetRequiredEnvVars(
credentials.TenantID, append(
credentials.ClientID, ctesting.AWSStorageCredEnvs,
credentials.ClientSecret, ctesting.M365AcctCredEnvs...,
)...,
) )
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
} }
func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() { func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() {
kw := &kopia.KopiaWrapper{} kw := &kopia.KopiaWrapper{}
creds := credentials.GetM365() acct, err := ctesting.NewM365Account()
require.NoError(suite.T(), err)
table := []struct { table := []struct {
name string name string
opts operations.OperationOpts opts operations.OperationOpts
kw *kopia.KopiaWrapper kw *kopia.KopiaWrapper
creds credentials.M365 acct account.Account
targets []string targets []string
errCheck assert.ErrorAssertionFunc errCheck assert.ErrorAssertionFunc
}{ }{
{"good", operations.OperationOpts{}, kw, creds, nil, assert.NoError}, {"good", operations.OperationOpts{}, kw, acct, nil, assert.NoError},
{"missing kopia", operations.OperationOpts{}, nil, creds, nil, assert.Error}, {"missing kopia", operations.OperationOpts{}, nil, acct, nil, assert.Error},
{"invalid creds", operations.OperationOpts{}, kw, credentials.M365{}, nil, assert.Error},
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
@ -56,7 +58,7 @@ func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() {
context.Background(), context.Background(),
operations.OperationOpts{}, operations.OperationOpts{},
test.kw, test.kw,
test.creds, test.acct,
nil) nil)
test.errCheck(t, err) test.errCheck(t, err)
}) })

View File

@ -7,7 +7,7 @@ import (
"github.com/alcionai/corso/internal/connector" "github.com/alcionai/corso/internal/connector"
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/account"
) )
// RestoreOperation wraps an operation with restore-specific props. // RestoreOperation wraps an operation with restore-specific props.
@ -16,7 +16,7 @@ type RestoreOperation struct {
Version string Version string
restorePointID string restorePointID string
creds credentials.M365 account account.Account
Targets []string // something for targets/filter/source/app&users/etc Targets []string // something for targets/filter/source/app&users/etc
} }
@ -26,14 +26,14 @@ func NewRestoreOperation(
ctx context.Context, ctx context.Context,
opts OperationOpts, opts OperationOpts,
kw *kopia.KopiaWrapper, kw *kopia.KopiaWrapper,
creds credentials.M365, acct account.Account,
restorePointID string, restorePointID string,
targets []string, targets []string,
) (RestoreOperation, error) { ) (RestoreOperation, error) {
op := RestoreOperation{ op := RestoreOperation{
operation: newOperation(opts, kw), operation: newOperation(opts, kw),
Version: "v0", Version: "v0",
creds: creds, account: acct,
restorePointID: restorePointID, restorePointID: restorePointID,
Targets: targets, Targets: targets,
} }
@ -45,9 +45,6 @@ func NewRestoreOperation(
} }
func (op RestoreOperation) validate() error { func (op RestoreOperation) validate() error {
if err := op.creds.Validate(); err != nil {
return errors.Wrap(err, "invalid credentials")
}
return op.operation.validate() return op.operation.validate()
} }
@ -59,7 +56,7 @@ func (op *RestoreOperation) Run(ctx context.Context) error {
return errors.Wrap(err, "retrieving service data") return errors.Wrap(err, "retrieving service data")
} }
gc, err := connector.NewGraphConnector(op.creds.TenantID, op.creds.ClientID, op.creds.ClientSecret) gc, err := connector.NewGraphConnector(op.account)
if err != nil { if err != nil {
return errors.Wrap(err, "connecting to graph api") return errors.Wrap(err, "connecting to graph api")
} }

View File

@ -11,7 +11,7 @@ import (
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/internal/operations" "github.com/alcionai/corso/internal/operations"
ctesting "github.com/alcionai/corso/internal/testing" ctesting "github.com/alcionai/corso/internal/testing"
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/account"
) )
type RestoreOpIntegrationSuite struct { type RestoreOpIntegrationSuite struct {
@ -26,28 +26,25 @@ func TestRestoreOpIntegrationSuite(t *testing.T) {
} }
func (suite *RestoreOpIntegrationSuite) SetupSuite() { func (suite *RestoreOpIntegrationSuite) SetupSuite() {
_, err := ctesting.GetRequiredEnvVars( _, err := ctesting.GetRequiredEnvVars(ctesting.M365AcctCredEnvs...)
credentials.TenantID,
credentials.ClientID,
credentials.ClientSecret,
)
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
} }
func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() { func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() {
kw := &kopia.KopiaWrapper{} kw := &kopia.KopiaWrapper{}
creds := credentials.GetM365() acct, err := ctesting.NewM365Account()
require.NoError(suite.T(), err)
table := []struct { table := []struct {
name string name string
opts operations.OperationOpts opts operations.OperationOpts
kw *kopia.KopiaWrapper kw *kopia.KopiaWrapper
creds credentials.M365 acct account.Account
targets []string targets []string
errCheck assert.ErrorAssertionFunc errCheck assert.ErrorAssertionFunc
}{ }{
{"good", operations.OperationOpts{}, kw, creds, nil, assert.NoError}, {"good", operations.OperationOpts{}, kw, acct, nil, assert.NoError},
{"missing kopia", operations.OperationOpts{}, nil, creds, nil, assert.Error}, {"missing kopia", operations.OperationOpts{}, nil, acct, nil, assert.Error},
{"invalid creds", operations.OperationOpts{}, kw, credentials.M365{}, nil, assert.Error},
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
@ -55,7 +52,7 @@ func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() {
context.Background(), context.Background(),
operations.OperationOpts{}, operations.OperationOpts{},
test.kw, test.kw,
test.creds, test.acct,
"restore-point-id", "restore-point-id",
nil) nil)
test.errCheck(t, err) test.errCheck(t, err)

View File

@ -3,21 +3,27 @@ package testing
import ( import (
"github.com/alcionai/corso/pkg/account" "github.com/alcionai/corso/pkg/account"
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/credentials"
"github.com/pkg/errors"
) )
var M365AcctCredEnvs = []string{
credentials.ClientID,
credentials.ClientSecret,
}
// NewM365Account returns an account.Account object initialized with environment // NewM365Account returns an account.Account object initialized with environment
// variables used for integration tests that use Graph Connector. // variables used for integration tests that use Graph Connector.
func NewM365Account() (account.Account, error) { func NewM365Account() (account.Account, error) {
// todo (keepers) include account details in test config cfg, err := readTestConfig()
// cfg, err := readTestConfig() if err != nil {
// if err != nil { return account.Account{}, errors.Wrap(err, "configuring m365 account from test file")
// return account.Account{}, errors.Wrap(err, "configuring m365 account from test file") }
// }
return account.NewAccount( return account.NewAccount(
account.ProviderM365, account.ProviderM365,
account.M365Config{ account.M365Config{
M365: credentials.GetM365(), M365: credentials.GetM365(),
TenantID: cfg[testCfgTenantID],
}, },
) )
} }

View File

@ -5,10 +5,9 @@ import (
"path" "path"
"strings" "strings"
"github.com/alcionai/corso/pkg/account"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/alcionai/corso/pkg/credentials"
) )
const ( const (
@ -66,7 +65,7 @@ func readTestConfig() (map[string]string, error) {
fallbackTo(testEnv, testCfgBucket, vpr.GetString(testCfgBucket), "test-corso-repo-init") fallbackTo(testEnv, testCfgBucket, vpr.GetString(testCfgBucket), "test-corso-repo-init")
fallbackTo(testEnv, testCfgEndpoint, vpr.GetString(testCfgEndpoint), "s3.amazonaws.com") fallbackTo(testEnv, testCfgEndpoint, vpr.GetString(testCfgEndpoint), "s3.amazonaws.com")
fallbackTo(testEnv, testCfgPrefix, vpr.GetString(testCfgPrefix)) fallbackTo(testEnv, testCfgPrefix, vpr.GetString(testCfgPrefix))
fallbackTo(testEnv, testCfgTenantID, os.Getenv(credentials.TenantID), vpr.GetString(testCfgTenantID)) fallbackTo(testEnv, testCfgTenantID, os.Getenv(account.TenantID), vpr.GetString(testCfgTenantID))
return testEnv, nil return testEnv, nil
} }

View File

@ -8,7 +8,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
var AWSCredentialEnvs = []string{ var AWSStorageCredEnvs = []string{
credentials.AWSAccessKeyID, credentials.AWSAccessKeyID,
credentials.AWSSecretAccessKey, credentials.AWSSecretAccessKey,
credentials.AWSSessionToken, credentials.AWSSessionToken,

View File

@ -6,10 +6,14 @@ import (
"github.com/alcionai/corso/pkg/credentials" "github.com/alcionai/corso/pkg/credentials"
) )
type M365Config struct { // config exported name consts
credentials.M365 // requires: ClientID, ClientSecret, TenantID const (
TenantID = "TENANT_ID"
)
// (todo) TenantID string type M365Config struct {
credentials.M365 // requires: ClientID, ClientSecret
TenantID string
} }
// config key consts // config key consts
@ -19,11 +23,9 @@ const (
keyM365TenantID = "m365_tenantID" keyM365TenantID = "m365_tenantID"
) )
// config exported name consts // StringConfig transforms a m365Config struct into a plain
const ( // map[string]string. All values in the original struct which
// (todo) TenantID = "TENANT_ID" // serialize into the map are expected to be strings.
)
func (c M365Config) StringConfig() (map[string]string, error) { func (c M365Config) StringConfig() (map[string]string, error) {
cfg := map[string]string{ cfg := map[string]string{
keyM365ClientID: c.ClientID, keyM365ClientID: c.ClientID,
@ -48,7 +50,7 @@ func (c M365Config) validate() error {
check := map[string]string{ check := map[string]string{
credentials.ClientID: c.ClientID, credentials.ClientID: c.ClientID,
credentials.ClientSecret: c.ClientSecret, credentials.ClientSecret: c.ClientSecret,
credentials.TenantID: c.TenantID, TenantID: c.TenantID,
} }
for k, v := range check { for k, v := range check {
if len(v) == 0 { if len(v) == 0 {

View File

@ -23,8 +23,8 @@ var goodM365Config = account.M365Config{
M365: credentials.M365{ M365: credentials.M365{
ClientID: "cid", ClientID: "cid",
ClientSecret: "cs", ClientSecret: "cs",
TenantID: "tid",
}, },
TenantID: "tid",
} }
func (suite *M365CfgSuite) TestM365Config_Config() { func (suite *M365CfgSuite) TestM365Config_Config() {
@ -64,8 +64,8 @@ func makeTestM365Cfg(cid, cs, tid string) account.M365Config {
M365: credentials.M365{ M365: credentials.M365{
ClientID: cid, ClientID: cid,
ClientSecret: cs, ClientSecret: cs,
TenantID: tid,
}, },
TenantID: tid,
} }
} }

View File

@ -10,14 +10,12 @@ import (
const ( const (
ClientID = "CLIENT_ID" ClientID = "CLIENT_ID"
ClientSecret = "CLIENT_SECRET" ClientSecret = "CLIENT_SECRET"
TenantID = "TENANT_ID"
) )
// M365 aggregates m365 credentials from flag and env_var values. // M365 aggregates m365 credentials from flag and env_var values.
type M365 struct { type M365 struct {
ClientID string ClientID string
ClientSecret string ClientSecret string
TenantID string
} }
// M365 is a helper for aggregating m365 secrets and credentials. // M365 is a helper for aggregating m365 secrets and credentials.
@ -27,7 +25,6 @@ func GetM365() M365 {
return M365{ return M365{
ClientID: os.Getenv(ClientID), ClientID: os.Getenv(ClientID),
ClientSecret: os.Getenv(ClientSecret), ClientSecret: os.Getenv(ClientSecret),
TenantID: os.Getenv(TenantID),
} }
} }
@ -35,7 +32,6 @@ func (c M365) Validate() error {
check := map[string]string{ check := map[string]string{
ClientID: c.ClientID, ClientID: c.ClientID,
ClientSecret: c.ClientSecret, ClientSecret: c.ClientSecret,
TenantID: c.TenantID,
} }
for k, v := range check { for k, v := range check {
if len(v) == 0 { if len(v) == 0 {

View File

@ -10,7 +10,6 @@ import (
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/internal/operations" "github.com/alcionai/corso/internal/operations"
"github.com/alcionai/corso/pkg/account" "github.com/alcionai/corso/pkg/account"
"github.com/alcionai/corso/pkg/credentials"
"github.com/alcionai/corso/pkg/storage" "github.com/alcionai/corso/pkg/storage"
) )
@ -93,39 +92,21 @@ func (r *Repository) Close(ctx context.Context) error {
// NewBackup generates a backupOperation runner. // NewBackup generates a backupOperation runner.
func (r Repository) NewBackup(ctx context.Context, targets []string) (operations.BackupOperation, error) { func (r Repository) NewBackup(ctx context.Context, targets []string) (operations.BackupOperation, error) {
m365, err := r.Account.M365Config()
if err != nil {
return operations.BackupOperation{}, errors.Wrap(err, "retrieving m365 account credentials")
}
creds := credentials.M365{
ClientID: m365.ClientID,
ClientSecret: m365.ClientSecret,
TenantID: m365.TenantID,
}
return operations.NewBackupOperation( return operations.NewBackupOperation(
ctx, ctx,
operations.OperationOpts{}, operations.OperationOpts{},
r.dataLayer, r.dataLayer,
creds, r.Account,
targets) targets)
} }
// NewRestore generates a restoreOperation runner. // NewRestore generates a restoreOperation runner.
func (r Repository) NewRestore(ctx context.Context, restorePointID string, targets []string) (operations.RestoreOperation, error) { func (r Repository) NewRestore(ctx context.Context, restorePointID string, targets []string) (operations.RestoreOperation, error) {
m365, err := r.Account.M365Config()
if err != nil {
return operations.RestoreOperation{}, errors.Wrap(err, "retrieving m365 account credentials")
}
creds := credentials.M365{
ClientID: m365.ClientID,
ClientSecret: m365.ClientSecret,
TenantID: m365.TenantID,
}
return operations.NewRestoreOperation( return operations.NewRestoreOperation(
ctx, ctx,
operations.OperationOpts{}, operations.OperationOpts{},
r.dataLayer, r.dataLayer,
creds, r.Account,
restorePointID, restorePointID,
targets) targets)
} }

View File

@ -100,7 +100,12 @@ func TestRepositoryIntegrationSuite(t *testing.T) {
// ensure all required env values are populated // ensure all required env values are populated
func (suite *RepositoryIntegrationSuite) SetupSuite() { func (suite *RepositoryIntegrationSuite) SetupSuite() {
_, err := ctesting.GetRequiredEnvVars(ctesting.AWSCredentialEnvs...) _, err := ctesting.GetRequiredEnvVars(
append(
ctesting.AWSStorageCredEnvs,
ctesting.M365AcctCredEnvs...,
)...,
)
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
} }

View File

@ -15,6 +15,9 @@ const (
keyCommonCorsoPassword = "common_corsoPassword" keyCommonCorsoPassword = "common_corsoPassword"
) )
// StringConfig transforms a commonConfig struct into a plain
// map[string]string. All values in the original struct which
// serialize into the map are expected to be strings.
func (c CommonConfig) StringConfig() (map[string]string, error) { func (c CommonConfig) StringConfig() (map[string]string, error) {
cfg := map[string]string{ cfg := map[string]string{
keyCommonCorsoPassword: c.CorsoPassword, keyCommonCorsoPassword: c.CorsoPassword,

View File

@ -31,6 +31,9 @@ const (
Prefix = "prefix" Prefix = "prefix"
) )
// StringConfig transforms a s3Config struct into a plain
// map[string]string. All values in the original struct which
// serialize into the map are expected to be strings.
func (c S3Config) StringConfig() (map[string]string, error) { func (c S3Config) StringConfig() (map[string]string, error) {
cfg := map[string]string{ cfg := map[string]string{
keyS3AccessKey: c.AccessKey, keyS3AccessKey: c.AccessKey,