diff --git a/cmd/influxd/upgrade/database.go b/cmd/influxd/upgrade/database.go index be19e63c112..c106e8eb097 100644 --- a/cmd/influxd/upgrade/database.go +++ b/cmd/influxd/upgrade/database.go @@ -13,8 +13,8 @@ import ( ) // upgradeDatabases creates databases, buckets, retention policies and shard info according to 1.x meta and copies data -func upgradeDatabases(ctx context.Context, v1 *influxDBv1, v2 *influxDBv2, v1opts *optionsV1, v2opts *optionsV2, orgID influxdb.ID, log *zap.Logger) (map[string][]string, error) { - db2BucketIds := make(map[string][]string) +func upgradeDatabases(ctx context.Context, v1 *influxDBv1, v2 *influxDBv2, v1opts *optionsV1, v2opts *optionsV2, orgID influxdb.ID, log *zap.Logger) (map[string][]influxdb.ID, error) { + db2BucketIds := make(map[string][]influxdb.ID) targetDataPath := filepath.Join(v2opts.enginePath, "data") targetWalPath := filepath.Join(v2opts.enginePath, "wal") @@ -72,7 +72,7 @@ func upgradeDatabases(ctx context.Context, v1 *influxDBv1, v2 *influxDBv2, v1opt } // db to buckets IDs mapping - db2BucketIds[db.Name] = make([]string, 0, len(db.RetentionPolicies)) + db2BucketIds[db.Name] = make([]influxdb.ID, 0, len(db.RetentionPolicies)) for _, rp := range db.RetentionPolicies { sourcePath := filepath.Join(v1opts.dataDir, db.Name, rp.Name) @@ -95,7 +95,7 @@ func upgradeDatabases(ctx context.Context, v1 *influxDBv1, v2 *influxDBv2, v1opt } - db2BucketIds[db.Name] = append(db2BucketIds[db.Name], bucket.ID.String()) + db2BucketIds[db.Name] = append(db2BucketIds[db.Name], bucket.ID) if options.verbose { log.Info("Creating database with retention policy", zap.String("database", bucket.ID.String())) @@ -176,9 +176,5 @@ func upgradeDatabases(ctx context.Context, v1 *influxDBv1, v2 *influxDBv2, v1opt } } - err = v2.close() - if err != nil { - return nil, fmt.Errorf("error closing v2: %w", err) - } return db2BucketIds, nil } diff --git a/cmd/influxd/upgrade/security.go b/cmd/influxd/upgrade/security.go index 8809c8f1e96..5cd4a5fba1b 100644 --- a/cmd/influxd/upgrade/security.go +++ b/cmd/influxd/upgrade/security.go @@ -1,29 +1,26 @@ package upgrade // Security upgrade implementation. -// Generates script for upgrading 1.x users into tokens in 2.x. +// Creates tokens representing v1 users. import ( + "context" "errors" "fmt" - "os" - "regexp" - "runtime" "sort" - "strings" - "text/template" + platform "github.com/influxdata/influxdb/v2" "github.com/influxdata/influxdb/v2/v1/services/meta" "github.com/influxdata/influxql" "go.uber.org/zap" ) -// generateSecurityScript creates security upgrade script with 1.x users mapped to 2.x tokens. -func generateSecurityScript(v1 *influxDBv1, targetOptions optionsV2, dbBuckets map[string][]string, log *zap.Logger) error { +// upgradeUsers creates tokens representing v1 users. +func upgradeUsers(ctx context.Context, v1 *influxDBv1, v2 *influxDBv2, targetOptions *optionsV2, dbBuckets map[string][]platform.ID, log *zap.Logger) error { // check if there any 1.x users at all v1meta := v1.meta if len(v1meta.Users()) == 0 { - log.Info("There are no users in 1.x, no script will be created.") + log.Info("There are no users in 1.x, nothing to upgrade.") return nil } @@ -36,116 +33,80 @@ func generateSecurityScript(v1 *influxDBv1, targetOptions optionsV2, dbBuckets m return errors.New("upgrade: there were errors/warnings, please fix them and run the command again") } - // create output - var output *os.File - var isFileOutput bool - if targetOptions.securityScriptPath == "" { - output = os.Stdout - } else { - file, err := os.OpenFile(targetOptions.securityScriptPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) - if err != nil { - return err - } - defer file.Close() - output = file - isFileOutput = true - } - - // template data type - type dataObject struct { - AdminUsers []string - IgnoreUsers []string - UpgradeUsers []string - UserArgs map[string][]string - Exe string - TargetAdmin string - TargetOrg string - TargetToken string - IsFileOutput bool - InfluxExe string - } - - // data - data := dataObject{ - UserArgs: make(map[string][]string), - TargetAdmin: targetOptions.userName, - TargetOrg: targetOptions.orgName, - TargetToken: targetOptions.token, - IsFileOutput: isFileOutput, - InfluxExe: targetOptions.influx2CommandPath, - } - - // fill data with users and their permissions + // upgrade users for _, row := range helper.sortUserInfo(v1meta.Users()) { username := row.Name if row.Admin { - data.AdminUsers = append(data.AdminUsers, username) + log.Info("User is admin and will not be upgraded.", zap.String("username", username)) } else if len(row.Privileges) == 0 { - data.IgnoreUsers = append(data.IgnoreUsers, username) + log.Info("User has no privileges and will not be upgraded.", zap.String("username", username)) } else { - data.UpgradeUsers = append(data.UpgradeUsers, username) - dbList := make([]string, 0) + var dbList []string for database := range row.Privileges { dbList = append(dbList, database) } - sort.Strings(dbList) - accessArgs := make([]string, 0) + var permissions []platform.Permission for _, database := range dbList { permission := row.Privileges[database] for _, id := range dbBuckets[database] { switch permission { case influxql.ReadPrivilege: - accessArgs = append(accessArgs, fmt.Sprintf("--read-bucket=%s", id)) + p, err := platform.NewPermissionAtID(id, platform.ReadAction, platform.BucketsResourceType, targetOptions.orgID) + if err != nil { + return err + } + permissions = append(permissions, *p) case influxql.WritePrivilege: - accessArgs = append(accessArgs, fmt.Sprintf("--write-bucket=%s", id)) + p, err := platform.NewPermissionAtID(id, platform.WriteAction, platform.BucketsResourceType, targetOptions.orgID) + if err != nil { + return err + } + permissions = append(permissions, *p) case influxql.AllPrivileges: - accessArgs = append(accessArgs, fmt.Sprintf("--read-bucket=%s", id)) - accessArgs = append(accessArgs, fmt.Sprintf("--write-bucket=%s", id)) + p, err := platform.NewPermissionAtID(id, platform.ReadAction, platform.BucketsResourceType, targetOptions.orgID) + if err != nil { + return err + } + permissions = append(permissions, *p) + p, err = platform.NewPermissionAtID(id, platform.WriteAction, platform.BucketsResourceType, targetOptions.orgID) + if err != nil { + return err + } + permissions = append(permissions, *p) } } } - if len(accessArgs) > 0 { // should always be true - data.UserArgs[username] = accessArgs + if len(permissions) > 0 { + auth := &platform.Authorization{ + Description: username + "'s Token", + Permissions: permissions, + Token: username, + OrgID: targetOptions.orgID, + UserID: targetOptions.userID, + } + err := v2.authSvc.CreateAuthorization(ctx, auth) + if err != nil { + log.Error("Failed to create authorization.", zap.String("user", username), zap.Error(err)) + continue + } + err = v2.authSvc.SetPasswordHash(ctx, auth.ID, row.Hash) + if err != nil { + log.Error("Failed to set user's password.", zap.String("user", username), zap.Error(err)) + continue + } + log.Info("User upgraded.", zap.String("username", username)) + } else { + log.Info("User has no privileges and will not be upgraded.", zap.String("username", username)) } } } - // load template - var tmpl string - if runtime.GOOS == "win" { - tmpl = securityScriptCmdTemplate - } else { - tmpl = securityScriptShTemplate - } - t, err := template.New("script").Funcs(template.FuncMap{ - "shUserVar": func(name string) string { - return helper.shUserVar(name) - }, - "userArgs": func(args []string) string { - return strings.Join(args, " ") - }, - }).Parse(tmpl) - if err != nil { - return err - } - - // generate the script - err = t.Execute(output, data) - if err != nil { - return err - } - - if isFileOutput { - log.Info(fmt.Sprintf("Security upgrade script saved to %s.", targetOptions.securityScriptPath)) - } - return nil } // securityScriptHelper is a helper used by `generate-security-script` command. type securityScriptHelper struct { - shReg *regexp.Regexp - log *zap.Logger + log *zap.Logger } // newSecurityScriptHelper returns new security script helper instance for `generate-security-script` command. @@ -153,11 +114,10 @@ func newSecurityScriptHelper(log *zap.Logger) *securityScriptHelper { helper := &securityScriptHelper{ log: log, } - helper.shReg = regexp.MustCompile("[^a-zA-Z0-9]+") return helper } -func (h *securityScriptHelper) checkDbBuckets(meta *meta.Client, databases map[string][]string) bool { +func (h *securityScriptHelper) checkDbBuckets(meta *meta.Client, databases map[string][]platform.ID) bool { ok := true for _, row := range meta.Users() { for database := range row.Privileges { @@ -181,96 +141,3 @@ func (h *securityScriptHelper) sortUserInfo(info []meta.UserInfo) []meta.UserInf }) return info } - -func (h *securityScriptHelper) shUserVar(name string) string { - return "UPGRADE_USER_" + h.shReg.ReplaceAllString(name, "_") -} - -// script templates - -var securityScriptShTemplate = `#!/bin/sh - -{{- range $u := $.UpgradeUsers}} -{{shUserVar $u}}=yes # user {{$u}} -{{- end}} - -{{- range $u := $.AdminUsers}} -# user {{$u}} is 1.x admin and will not be upgraded automatically -{{- end}} -{{- range $u := $.IgnoreUsers}} -# user {{$u}} has no privileges and will be skipped -{{- end}} - -# -# SCRIPT VARS -# - -INFLUX={{$.InfluxExe}} -INFLUX_TOKEN={{$.TargetToken}} - -{{- if $.IsFileOutput}} -LOG="${0%.*}.$(date +%Y%m%d-%H%M%S).log" -{{end}} - -# -# USERS UPGRADES -# - -{{range $u := $.UpgradeUsers}} -if [ "${{shUserVar $u}}" = "yes" ]; then - echo Creating authorization token for user {{$u}}... - env INFLUX_TOKEN=$INFLUX_TOKEN $INFLUX auth create --user={{$.TargetAdmin}} --org={{$.TargetOrg}} --description="{{$u}}" {{index $.UserArgs $u | userArgs}} -fi {{- if $.IsFileOutput}} 2>&1 | tee -a $LOG{{- end}} - -{{- end}} - -{{- if $.IsFileOutput}} -echo -echo Output saved to $LOG -{{- end}} -` - -var securityScriptCmdTemplate = `@ECHO OFF - -{{- range $u := $.UpgradeUsers}} -REM user {{$u}} -set {{shUserVar $u}}=yes -{{- end}} - -{{- range $u := $.AdminUsers}} -REM user {{$u}} is 1.x admin and will not be upgraded automatically -{{- end}} -{{- range $u := $.IgnoreUsers}} -REM user {{$u}} has no privileges will be skipped -{{- end}} - -REM -REM SCRIPT VARS -REM - -set INFLUX="{{$.InfluxExe}}.exe" -set INFLUX_TOKEN={{$.TargetToken}} - -{{- if $.IsFileOutput}} -set PATH=%PATH%;C:\WINDOWS\system32\wbem -for /f %%x in ('wmic os get localdatetime ^| findstr /b [0-9]') do @set X=%%x && set LOG=%~dpn0.%X:~0,8%-%X:~8,6%.log -{{end}} - -REM -REM INDIVIDUAL USERS UPGRADES -REM - -{{range $u := $.UpgradeUsers}} -IF /I "%{{shUserVar $u}}%" == "yes" ( - echo Creating authorization token for user {{$u}}... - %INFLUX% auth create --user={{$.TargetAdmin}} --org={{$.TargetOrg}} --description="{{$u}}" {{index $.UserArgs $u | userArgs}} -) {{- if $.IsFileOutput}} >> %LOG% 2>&1 {{- end}} - -{{- end}} - -{{- if $.IsFileOutput}} -type %LOG% -echo. -echo Output saved to %LOG% -{{- end}} -` diff --git a/cmd/influxd/upgrade/security_test.go b/cmd/influxd/upgrade/security_test.go index 2d8b4b06609..9c93ab37cb9 100644 --- a/cmd/influxd/upgrade/security_test.go +++ b/cmd/influxd/upgrade/security_test.go @@ -1,33 +1,43 @@ package upgrade import ( - "bufio" + "context" "errors" - "io/ioutil" - "os" - "path/filepath" "reflect" - "runtime" - "strings" + "sort" "testing" "unsafe" "github.com/google/go-cmp/cmp" + "github.com/influxdata/influxdb/v2" + "github.com/influxdata/influxdb/v2/inmem" + "github.com/influxdata/influxdb/v2/kv" + "github.com/influxdata/influxdb/v2/kv/migration" + "github.com/influxdata/influxdb/v2/kv/migration/all" + "github.com/influxdata/influxdb/v2/tenant" + authv1 "github.com/influxdata/influxdb/v2/v1/authorization" "github.com/influxdata/influxdb/v2/v1/services/meta" "github.com/influxdata/influxql" "github.com/stretchr/testify/require" + "go.uber.org/zap" "go.uber.org/zap/zaptest" + "golang.org/x/crypto/bcrypt" ) -func TestGenerateScript(t *testing.T) { +func TestUpgradeSecurity(t *testing.T) { type testCase struct { name string users []meta.UserInfo - db2ids map[string][]string - skipExe bool - want string + db2ids map[string][]influxdb.ID wantErr error + want []*influxdb.Authorization + } + + hash := func(password string) string { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + require.NoError(t, err) + return string(hash) } var testCases = []testCase{ @@ -37,14 +47,17 @@ func TestGenerateScript(t *testing.T) { { // not upgraded because admin Name: "superman", Admin: true, + Hash: hash("superman@123"), }, { // not upgraded because no privileges Name: "loser", Admin: false, + Hash: hash("loser@123"), }, { Name: "weatherman", Admin: false, + Hash: hash("weatherman@123"), Privileges: map[string]influxql.Privilege{ "water": influxql.AllPrivileges, "air": influxql.AllPrivileges, @@ -53,6 +66,7 @@ func TestGenerateScript(t *testing.T) { { Name: "hitgirl", Admin: false, + Hash: hash("hitgirl@123"), Privileges: map[string]influxql.Privilege{ "hits": influxql.WritePrivilege, }, @@ -60,6 +74,7 @@ func TestGenerateScript(t *testing.T) { { Name: "boss@hits.org", // special name Admin: false, + Hash: hash("boss@123"), Privileges: map[string]influxql.Privilege{ "hits": influxql.AllPrivileges, }, @@ -67,18 +82,40 @@ func TestGenerateScript(t *testing.T) { { Name: "viewer", Admin: false, + Hash: hash("viewer@123"), Privileges: map[string]influxql.Privilege{ "water": influxql.ReadPrivilege, "air": influxql.ReadPrivilege, }, }, }, - db2ids: map[string][]string{ - "water": {"33f9d67bc9cbc5b7", "33f9d67bc9cbc5b8", "33f9d67bc9cbc5b9"}, - "air": {"43f9d67bc9cbc5b7", "43f9d67bc9cbc5b8", "43f9d67bc9cbc5b9"}, - "hits": {"53f9d67bc9cbc5b7"}, + db2ids: map[string][]influxdb.ID{ + "water": {0x33f9d67bc9cbc5b7, 0x33f9d67bc9cbc5b8, 0x33f9d67bc9cbc5b9}, + "air": {0x43f9d67bc9cbc5b7, 0x43f9d67bc9cbc5b8, 0x43f9d67bc9cbc5b9}, + "hits": {0x53f9d67bc9cbc5b7}, + }, + want: []*influxdb.Authorization{ + { + Token: "boss@hits.org", + Status: "active", + Description: "boss@hits.org's Token", + }, + { + Token: "hitgirl", + Status: "active", + Description: "hitgirl's Token", + }, + { + Token: "viewer", + Status: "active", + Description: "viewer's Token", + }, + { + Token: "weatherman", + Status: "active", + Description: "weatherman's Token", + }, }, - want: testScriptShOrdinary, }, { name: "missing buckets", @@ -86,6 +123,7 @@ func TestGenerateScript(t *testing.T) { { Name: "weatherman", Admin: false, + Hash: hash("weatherman@123"), Privileges: map[string]influxql.Privilege{ "water": influxql.AllPrivileges, "air": influxql.AllPrivileges, @@ -98,22 +136,15 @@ func TestGenerateScript(t *testing.T) { { name: "no users", users: []meta.UserInfo{}, - want: "", }, } - var shSuffix, mockInfluxCode string - if runtime.GOOS == "win" { - shSuffix = ".cmd" - mockInfluxCode = testMockInfluxWin - } else { - shSuffix = ".sh" - mockInfluxCode = testMockInfluxUnix - } - for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { // better do not run in parallel + ctx := context.Background() + log := zaptest.NewLogger(t) + // mock v1 meta v1 := &influxDBv1{ meta: &meta.Client{}, @@ -121,42 +152,90 @@ func TestGenerateScript(t *testing.T) { data := &meta.Data{ Users: tc.users, } - // inject users into mock v1 meta client f := reflect.ValueOf(v1.meta).Elem().Field(4) f = reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem() f.Set(reflect.ValueOf(data)) - // script output file - tmpfile, err := ioutil.TempFile(t.TempDir(), "upgrade-security-*"+shSuffix) + // mock v2 meta + kvStore := inmem.NewKVStore() + migrator, err := migration.NewMigrator(zap.NewNop(), kvStore, all.Migrations[:]...) + require.NoError(t, err) + err = migrator.Up(ctx) require.NoError(t, err) - require.NoError(t, tmpfile.Close()) + authStore, err := authv1.NewStore(kvStore) + require.NoError(t, err) + tenantStore := tenant.NewStore(kvStore) + tenantSvc := tenant.NewService(tenantStore) + v2 := &influxDBv2{ + authSvc: authv1.NewService(authStore, tenantSvc), + onboardSvc: tenant.NewOnboardService(tenantSvc, kv.NewService(zap.NewNop(), kvStore, kv.ServiceConfig{})), + } - // mock influx command path - testExePath, err := os.Executable() + // onboard admin + oReq := &influxdb.OnboardingRequest{ + User: "admin", + Password: "12345", + Org: "testers", + Bucket: "def", + RetentionPeriod: influxdb.InfiniteRetention, + } + oResp, err := setupAdmin(ctx, v2, oReq) require.NoError(t, err) - mockInfluxExePath := filepath.Join(filepath.Dir(testExePath), "influx") - // options passed on cmdline + // target options targetOptions := optionsV2{ - userName: "admin", - orgName: "demo", - token: "ABC007==", - securityScriptPath: tmpfile.Name(), - influx2CommandPath: mockInfluxExePath, + userName: oReq.User, + orgName: oReq.Org, + token: oResp.Auth.Token, + orgID: oResp.Auth.OrgID, + userID: oResp.Auth.UserID, } - // create mock v2.x influx executable - if !tc.skipExe { - file, err := os.OpenFile(mockInfluxExePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) - require.NoError(t, err) - _, err = file.WriteString(mockInfluxCode) - require.NoError(t, err) - file.Close() - defer os.Remove(mockInfluxExePath) + // fill in expected permissions now that we know IDs + for _, want := range tc.want { + for _, user := range tc.users { + if want.Token == user.Name { // v1 username is v2 token + var permissions []influxdb.Permission + for db, privilege := range user.Privileges { + ids, ok := tc.db2ids[db] + require.True(t, ok) + for _, id := range ids { + id := id + resource := influxdb.Resource{ + Type: influxdb.BucketsResourceType, + OrgID: &targetOptions.orgID, + ID: &id, + } + switch privilege { + case influxql.ReadPrivilege: + permissions = append(permissions, influxdb.Permission{ + Action: influxdb.ReadAction, + Resource: resource, + }) + case influxql.WritePrivilege: + permissions = append(permissions, influxdb.Permission{ + Action: influxdb.WriteAction, + Resource: resource, + }) + case influxql.AllPrivileges: + permissions = append(permissions, influxdb.Permission{ + Action: influxdb.ReadAction, + Resource: resource, + }) + permissions = append(permissions, influxdb.Permission{ + Action: influxdb.WriteAction, + Resource: resource, + }) + } + } + } + want.Permissions = permissions + } + } } // command execution - err = generateSecurityScript(v1, targetOptions, tc.db2ids, zaptest.NewLogger(t)) + err = upgradeUsers(ctx, v1, v2, &targetOptions, tc.db2ids, log) if err != nil { if tc.wantErr != nil { if diff := cmp.Diff(tc.wantErr.Error(), err.Error()); diff != "" { @@ -168,98 +247,35 @@ func TestGenerateScript(t *testing.T) { } else if tc.wantErr != nil { t.Fatalf("should have failed with %v", tc.wantErr) } - - // validate result by comparing arrays of non-empty lines of wanted vs actual output - parse := func(content string) []string { - var lines []string - scanner := bufio.NewScanner(strings.NewReader(content)) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if line != "" { - lines = append(lines, line) - } + for _, want := range tc.want { + actual, err := v2.authSvc.FindAuthorizationByToken(ctx, want.Token) + require.NoError(t, err) + if diff := cmp.Diff(targetOptions.orgID, actual.OrgID); diff != "" { + t.Fatal(diff) } - return lines - } - bs, err := ioutil.ReadFile(tmpfile.Name()) - if err != nil { - t.Fatal(err) - } - if strings.Contains(tc.want, "?") { - // Generated security script contains path to `influx` executable - // and this must be updated with test executable build path in the wanted result. - exePath, err := os.Executable() - if err != nil { - t.Fatal(err) + if diff := cmp.Diff(targetOptions.userID, actual.UserID); diff != "" { + t.Fatal(diff) + } + if diff := cmp.Diff(want.Token, actual.Token); diff != "" { + t.Fatal(diff) + } + if diff := cmp.Diff(want.Description, actual.Description); diff != "" { + t.Fatal(diff) + } + if diff := cmp.Diff(want.Status, actual.Status); diff != "" { + t.Fatal(diff) + } + sort.Slice(want.Permissions, func(i, j int) bool { + return *(want.Permissions[i].Resource.ID) < *(want.Permissions[j].Resource.ID) + }) + sort.Slice(actual.Permissions, func(i, j int) bool { + return *(actual.Permissions[i].Resource.ID) < *(actual.Permissions[j].Resource.ID) + }) + if diff := cmp.Diff(want.Permissions, actual.Permissions); diff != "" { + t.Logf("permissions mismatch for user %s", want.Token) + t.Fatal(diff) } - tc.want = strings.Replace(tc.want, "?", filepath.Dir(exePath), -1) - } - expected := parse(tc.want) - actual := parse(string(bs)) - if diff := cmp.Diff(expected, actual); diff != "" { - t.Fatal(diff) } }) } } - -var testScriptShOrdinary = `#!/bin/sh - -UPGRADE_USER_boss_hits_org=yes # user boss@hits.org -UPGRADE_USER_hitgirl=yes # user hitgirl -UPGRADE_USER_viewer=yes # user viewer -UPGRADE_USER_weatherman=yes # user weatherman - -# user superman is 1.x admin and will not be upgraded automatically -# user loser has no privileges and will be skipped - -# -# SCRIPT VARS -# - -INFLUX=?/influx -INFLUX_TOKEN=ABC007== -LOG="${0%.*}.$(date +%Y%m%d-%H%M%S).log" - -# -# USERS UPGRADES -# - -if [ "$UPGRADE_USER_boss_hits_org" = "yes" ]; then - echo Creating authorization token for user boss@hits.org... - env INFLUX_TOKEN=$INFLUX_TOKEN $INFLUX auth create --user=admin --org=demo --description="boss@hits.org" --read-bucket=53f9d67bc9cbc5b7 --write-bucket=53f9d67bc9cbc5b7 -fi 2>&1 | tee -a $LOG - -if [ "$UPGRADE_USER_hitgirl" = "yes" ]; then - echo Creating authorization token for user hitgirl... - env INFLUX_TOKEN=$INFLUX_TOKEN $INFLUX auth create --user=admin --org=demo --description="hitgirl" --write-bucket=53f9d67bc9cbc5b7 -fi 2>&1 | tee -a $LOG - -if [ "$UPGRADE_USER_viewer" = "yes" ]; then - echo Creating authorization token for user viewer... - env INFLUX_TOKEN=$INFLUX_TOKEN $INFLUX auth create --user=admin --org=demo --description="viewer" --read-bucket=43f9d67bc9cbc5b7 --read-bucket=43f9d67bc9cbc5b8 --read-bucket=43f9d67bc9cbc5b9 --read-bucket=33f9d67bc9cbc5b7 --read-bucket=33f9d67bc9cbc5b8 --read-bucket=33f9d67bc9cbc5b9 -fi 2>&1 | tee -a $LOG - -if [ "$UPGRADE_USER_weatherman" = "yes" ]; then - echo Creating authorization token for user weatherman... - env INFLUX_TOKEN=$INFLUX_TOKEN $INFLUX auth create --user=admin --org=demo --description="weatherman" --read-bucket=43f9d67bc9cbc5b7 --write-bucket=43f9d67bc9cbc5b7 --read-bucket=43f9d67bc9cbc5b8 --write-bucket=43f9d67bc9cbc5b8 --read-bucket=43f9d67bc9cbc5b9 --write-bucket=43f9d67bc9cbc5b9 --read-bucket=33f9d67bc9cbc5b7 --write-bucket=33f9d67bc9cbc5b7 --read-bucket=33f9d67bc9cbc5b8 --write-bucket=33f9d67bc9cbc5b8 --read-bucket=33f9d67bc9cbc5b9 --write-bucket=33f9d67bc9cbc5b9 -fi 2>&1 | tee -a $LOG - -echo -echo Output saved to $LOG -` - -var testMockInfluxUnix = `#!/bin/sh -if [ "$1" = "version" ]; then - echo Influx CLI 2.0.0 -else - exit 1 -fi -` -var testMockInfluxWin = `@echo off -IF /I "%1" == "version" ( - echo "Influx CLI 2.0.0" -) else ( - exit 1 -) -` diff --git a/cmd/influxd/upgrade/upgrade.go b/cmd/influxd/upgrade/upgrade.go index a9564ce98fa..c82d9020473 100644 --- a/cmd/influxd/upgrade/upgrade.go +++ b/cmd/influxd/upgrade/upgrade.go @@ -23,6 +23,7 @@ import ( "github.com/influxdata/influxdb/v2/kv/migration/all" "github.com/influxdata/influxdb/v2/storage" "github.com/influxdata/influxdb/v2/tenant" + authv1 "github.com/influxdata/influxdb/v2/v1/authorization" "github.com/influxdata/influxdb/v2/v1/services/meta" "github.com/influxdata/influxdb/v2/v1/services/meta/filestore" "github.com/spf13/cobra" @@ -69,6 +70,8 @@ type optionsV2 struct { password string orgName string bucket string + orgID influxdb.ID + userID influxdb.ID token string retention string influx2CommandPath string @@ -254,6 +257,7 @@ type influxDBv2 struct { dbrpSvc influxdb.DBRPMappingServiceV2 bucketSvc influxdb.BucketService onboardSvc influxdb.OnboardingService + authSvc *authv1.Service kvService *kv.Service meta *meta.Client } @@ -343,7 +347,7 @@ func runUpgradeE(*cobra.Command, []string) error { defer func() { if err := v2.close(); err != nil { - log.Error("Failed to close 2.0 services", zap.Error(err)) + log.Error("Failed to close 2.0 services.", zap.Error(err)) } }() @@ -365,6 +369,8 @@ func runUpgradeE(*cobra.Command, []string) error { return err } + options.target.orgID = or.Org.ID + options.target.userID = or.User.ID options.target.token = or.Auth.Token db2BucketIds, err := upgradeDatabases(ctx, v1, v2, &options.source, &options.target, or.Org.ID, log) @@ -381,7 +387,7 @@ func runUpgradeE(*cobra.Command, []string) error { return err } - if err = generateSecurityScript(v1, options.target, db2BucketIds, log); err != nil { + if err = upgradeUsers(ctx, v1, v2, &options.target, db2BucketIds, log); err != nil { return err } @@ -468,6 +474,13 @@ func newInfluxDBv2(ctx context.Context, opts *optionsV2, log *zap.Logger) (svc * // on-boarding service (influx setup) svc.onboardSvc = tenant.NewOnboardService(svc.ts, authSvc) + // v1 auth service + authStore, err := authv1.NewStore(svc.kvStore) + if err != nil { + return nil, err + } + svc.authSvc = authv1.NewService(authStore, svc.ts) + return svc, nil }