From bbf33c715b537b90b58bb3e5643c006b53c8be8a Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Thu, 12 Oct 2023 15:44:12 -0400 Subject: [PATCH 1/3] Add 'add-debug-admin' command. Fixes #1436 --- ziti/cmd/database/add_debug_admin.go | 129 +++++++++++++++++++++++++++ ziti/cmd/database/cmd.go | 1 + ziti/internal/log/log.go | 55 ------------ 3 files changed, 130 insertions(+), 55 deletions(-) create mode 100644 ziti/cmd/database/add_debug_admin.go diff --git a/ziti/cmd/database/add_debug_admin.go b/ziti/cmd/database/add_debug_admin.go new file mode 100644 index 000000000..6f5b461db --- /dev/null +++ b/ziti/cmd/database/add_debug_admin.go @@ -0,0 +1,129 @@ +/* + Copyright NetFoundry Inc. + + 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 + + https://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 database + +import ( + "github.com/openziti/storage/boltz" + "github.com/openziti/ziti/common/eid" + "github.com/openziti/ziti/controller/change" + "github.com/openziti/ziti/controller/command" + "github.com/openziti/ziti/controller/db" + "github.com/openziti/ziti/controller/model" + "github.com/openziti/ziti/controller/network" + "github.com/openziti/ziti/controller/persistence" + "github.com/spf13/cobra" +) + +func NewAddDebugAdminAction() *cobra.Command { + action := &addDebugAdminAction{} + return &cobra.Command{ + Use: "add-debug-admin ", + Short: "Adds an admin (username: admin, password: admin) to the given database file for debugging purposes", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + action.run(args[0]) + }, + } +} + +type addDebugAdminAction struct { + db boltz.Db + stores *db.Stores + managers *network.Managers +} + +func (action *addDebugAdminAction) GetDb() boltz.Db { + return action.db +} + +func (action *addDebugAdminAction) GetStores() *db.Stores { + return action.stores +} + +func (action *addDebugAdminAction) GetManagers() *network.Managers { + return action.managers +} + +func (action *addDebugAdminAction) noError(err error) { + if err != nil { + panic(err) + } +} + +func (action *addDebugAdminAction) run(dbFile string) { + boltDb, err := db.Open(dbFile) + action.noError(err) + + fabricStores, err := db.InitStores(boltDb) + action.noError(err) + + dispatcher := &command.LocalDispatcher{ + EncodeDecodeCommands: false, + } + controllers := network.NewManagers(nil, dispatcher, boltDb, fabricStores, nil) + + dbProvider := &addDebugAdminAction{ + db: boltDb, + stores: fabricStores, + managers: controllers, + } + + stores, err := persistence.NewBoltStores(dbProvider) + action.noError(err) + + id := "7dbd3fc9-e4c8-489a-ab8f-4bbb3d768f57" + ctx := change.New().SetChangeAuthorType("cli.debug-db").NewMutateContext() + err = dbProvider.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { + tx := ctx.Tx() + identity, _ := stores.Identity.LoadOneById(tx, id) + if identity == nil { + identity = &persistence.Identity{ + BaseExtEntity: boltz.BaseExtEntity{Id: id}, + Name: "DebugAdmin", + IdentityTypeId: "Default", + IsDefaultAdmin: false, + IsAdmin: true, + } + if err = stores.Identity.Create(ctx, identity); err != nil { + return err + } + + authHandler := model.AuthenticatorManager{} + result := authHandler.HashPassword("admin") + authenticator := &persistence.AuthenticatorUpdb{ + Authenticator: persistence.Authenticator{ + BaseExtEntity: boltz.BaseExtEntity{ + Id: eid.New(), + }, + Type: "updb", + IdentityId: id, + }, + Username: "admin", + Password: result.Password, + Salt: result.Salt, + } + authenticator.SubType = authenticator + + if err = stores.Authenticator.Create(ctx, &authenticator.Authenticator); err != nil { + return err + } + } + + return nil + }) + action.noError(err) +} diff --git a/ziti/cmd/database/cmd.go b/ziti/cmd/database/cmd.go index f26bfe68d..79bc89e2a 100644 --- a/ziti/cmd/database/cmd.go +++ b/ziti/cmd/database/cmd.go @@ -25,6 +25,7 @@ func NewCmdDb(out io.Writer, errOut io.Writer) *cobra.Command { cmd.AddCommand(exploreCmd) cmd.AddCommand(NewCompactAction()) cmd.AddCommand(NewDiskUsageAction()) + cmd.AddCommand(NewAddDebugAdminAction()) return cmd } diff --git a/ziti/internal/log/log.go b/ziti/internal/log/log.go index 0d905d629..48182ec06 100644 --- a/ziti/internal/log/log.go +++ b/ziti/internal/log/log.go @@ -61,58 +61,3 @@ func Fatalf(msg string, args ...interface{}) { func Fatal(msg string) { color.Red(msg) } - -func Success(msg string) { - color.Green(msg) -} - -func Successf(msg string, args ...interface{}) { - Success(fmt.Sprintf(msg, args...)) -} - -func Failure(msg string) { - color.Red(msg) -} - -func Failuref(msg string, args ...interface{}) { - Failure(fmt.Sprintf(msg, args...)) -} - -// AskForConfirmation uses Scanln to parse user input. A user must type in "yes" or "no" and -// then press enter. It has fuzzy matching, so "y", "Y", "yes", "YES", and "Yes" all count as -// confirmations. If the input is not recognized, it will ask again. The function does not return -// until it gets a valid response from the user. Typically, you should use fmt to print out a question -// before calling askForConfirmation. E.g. fmt.Println("WARNING: Are you sure? (yes/no)") -func AskForConfirmation(def bool) bool { - var response string - fmt.Scanln(&response) - if len(response) == 0 { - return def - } - okayResponses := []string{"y", "Y", "yes", "Yes", "YES"} - nokayResponses := []string{"n", "N", "no", "No", "NO"} - if containsString(okayResponses, response) { - return true - } else if containsString(nokayResponses, response) { - return false - } else { - Warn("Please type y or n & press enter: ") - return AskForConfirmation(def) - } -} - -// posString returns the first index of element in slice. -// If slice does not contain element, returns -1. -func posString(slice []string, element string) int { - for index, elem := range slice { - if elem == element { - return index - } - } - return -1 -} - -// containsString returns true iff slice contains element -func containsString(slice []string, element string) bool { - return !(posString(slice, element) == -1) -} From 28d0c10ac9f4b4eb4fdf3fa7a3e605a98956c703 Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Thu, 12 Oct 2023 15:48:47 -0400 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4145f82f2..81c14be56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,13 +23,25 @@ Currently only HTTP Connect proxies which don't require authentication are suppo ## Component Updates and Bug Fixes -* github.com/openziti/storage: [v0.2.18 -> v0.2.19](https://github.com/openziti/storage/compare/v0.2.18...v0.2.19) +* github.com/openziti/channel/v2: [v2.0.99 -> v2.0.101](https://github.com/openziti/channel/compare/v2.0.99...v2.0.101) +* github.com/openziti/edge-api: [v0.25.37 -> v0.25.38](https://github.com/openziti/edge-api/compare/v0.25.37...v0.25.38) +* github.com/openziti/foundation/v2: [v2.0.32 -> v2.0.33](https://github.com/openziti/foundation/compare/v2.0.32...v2.0.33) +* github.com/openziti/identity: [v1.0.63 -> v1.0.64](https://github.com/openziti/identity/compare/v1.0.63...v1.0.64) +* github.com/openziti/metrics: [v1.2.35 -> v1.2.36](https://github.com/openziti/metrics/compare/v1.2.35...v1.2.36) +* github.com/openziti/runzmd: [v1.0.32 -> v1.0.33](https://github.com/openziti/runzmd/compare/v1.0.32...v1.0.33) +* github.com/openziti/sdk-golang: [v0.20.116 -> v0.20.122](https://github.com/openziti/sdk-golang/compare/v0.20.116...v0.20.122) + * [Issue #436](https://github.com/openziti/sdk-golang/issues/436) - HTTP calls should respect environment proxy settings + +* github.com/openziti/storage: [v0.2.18 -> v0.2.20](https://github.com/openziti/storage/compare/v0.2.18...v0.2.20) * [Issue #52](https://github.com/openziti/storage/issues/52) - Grammar should expect single valid query followed by EOF +* github.com/openziti/transport/v2: [v2.0.107 -> v2.0.109](https://github.com/openziti/transport/compare/v2.0.107...v2.0.109) * github.com/openziti/ziti: [v0.30.4 -> v0.30.5](https://github.com/openziti/ziti/compare/v0.30.4...v0.30.5) * [Issue #1336](https://github.com/openziti/ziti/issues/1336) - `ziti edge quickstart` did not create the usual edge router/service edge router policy. * [Issue #1397](https://github.com/openziti/ziti/issues/1397) - HTTP Proxy suport for host.v1/host.v2 config types + * [Issue #1423](https://github.com/openziti/ziti/issues/1423) - Controller crashes when edge router reconnects (Client Hello) + * [Issue #1414](https://github.com/openziti/ziti/issues/1414) - Race condition in xgress_edge_tunnel tunneller at start but not seen in pre-compiled binary * [Issue #1406](https://github.com/openziti/ziti/issues/1406) - Entity change event dispatcher isn't shutting down properly when controller shuts down * [Issue #1382](https://github.com/openziti/ziti/issues/1382) - service failure costs are not shrinking over time From 10df7d929bbd48288a0fd811b566b1567fd93930 Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Fri, 13 Oct 2023 11:44:53 -0400 Subject: [PATCH 3/3] Make debug admin username/password user selectable --- ziti/cmd/database/add_debug_admin.go | 73 ++++++++++++++++------------ 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/ziti/cmd/database/add_debug_admin.go b/ziti/cmd/database/add_debug_admin.go index 6f5b461db..09009df2c 100644 --- a/ziti/cmd/database/add_debug_admin.go +++ b/ziti/cmd/database/add_debug_admin.go @@ -17,6 +17,8 @@ package database import ( + "fmt" + "github.com/google/uuid" "github.com/openziti/storage/boltz" "github.com/openziti/ziti/common/eid" "github.com/openziti/ziti/controller/change" @@ -31,11 +33,11 @@ import ( func NewAddDebugAdminAction() *cobra.Command { action := &addDebugAdminAction{} return &cobra.Command{ - Use: "add-debug-admin ", - Short: "Adds an admin (username: admin, password: admin) to the given database file for debugging purposes", - Args: cobra.ExactArgs(1), + Use: "add-debug-admin ", + Short: "Adds an admin user to the given database file for debugging purposes", + Args: cobra.ExactArgs(3), Run: func(cmd *cobra.Command, args []string) { - action.run(args[0]) + action.run(args[0], args[1], args[2]) }, } } @@ -64,7 +66,7 @@ func (action *addDebugAdminAction) noError(err error) { } } -func (action *addDebugAdminAction) run(dbFile string) { +func (action *addDebugAdminAction) run(dbFile, username, password string) { boltDb, err := db.Open(dbFile) action.noError(err) @@ -85,44 +87,51 @@ func (action *addDebugAdminAction) run(dbFile string) { stores, err := persistence.NewBoltStores(dbProvider) action.noError(err) - id := "7dbd3fc9-e4c8-489a-ab8f-4bbb3d768f57" + id := "debug-admin" + name := fmt.Sprintf("debug admin (%v)", uuid.NewString()) ctx := change.New().SetChangeAuthorType("cli.debug-db").NewMutateContext() err = dbProvider.GetDb().Update(ctx, func(ctx boltz.MutateContext) error { tx := ctx.Tx() identity, _ := stores.Identity.LoadOneById(tx, id) - if identity == nil { - identity = &persistence.Identity{ - BaseExtEntity: boltz.BaseExtEntity{Id: id}, - Name: "DebugAdmin", - IdentityTypeId: "Default", - IsDefaultAdmin: false, - IsAdmin: true, - } - if err = stores.Identity.Create(ctx, identity); err != nil { + if identity != nil { + if err = stores.Identity.DeleteById(ctx, id); err != nil { return err } + fmt.Printf("removing existing identity with id '%v'\n", id) + } + + identity = &persistence.Identity{ + BaseExtEntity: boltz.BaseExtEntity{Id: id}, + Name: name, + IdentityTypeId: persistence.DefaultIdentityType, + IsDefaultAdmin: false, + IsAdmin: true, + } + if err = stores.Identity.Create(ctx, identity); err != nil { + return err + } - authHandler := model.AuthenticatorManager{} - result := authHandler.HashPassword("admin") - authenticator := &persistence.AuthenticatorUpdb{ - Authenticator: persistence.Authenticator{ - BaseExtEntity: boltz.BaseExtEntity{ - Id: eid.New(), - }, - Type: "updb", - IdentityId: id, + authHandler := model.AuthenticatorManager{} + result := authHandler.HashPassword(password) + authenticator := &persistence.AuthenticatorUpdb{ + Authenticator: persistence.Authenticator{ + BaseExtEntity: boltz.BaseExtEntity{ + Id: eid.New(), }, - Username: "admin", - Password: result.Password, - Salt: result.Salt, - } - authenticator.SubType = authenticator + Type: "updb", + IdentityId: id, + }, + Username: username, + Password: result.Password, + Salt: result.Salt, + } + authenticator.SubType = authenticator - if err = stores.Authenticator.Create(ctx, &authenticator.Authenticator); err != nil { - return err - } + if err = stores.Authenticator.Create(ctx, &authenticator.Authenticator); err != nil { + return err } + fmt.Printf("added debug admin with username '%v'\n", username) return nil }) action.noError(err)