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) -}