diff --git a/CHANGELOG.md b/CHANGELOG.md index dbf1e73ec..ca9d78d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,36 @@ * `ziti edge quickstart`](https://github.com/openziti/ziti/issues/1298). You can now download the `ziti` CLI and have a functioning network with just one command. The network it creates is ephemeral and is intended to be torn down when the process exits. - It is intended for quick evaluation and testing of an overlay network. - + It is intended for quick evaluation and testing of an overlay network. It supports the + following flags: + + ``` + --ctrl-address string Sets the advertised address for the control plane and API + --ctrl-port int16 Sets the port to use for the control plane and API + -h, --help help for quickstart + --home string Sets the directory the environment should be installed into. defaults to a temporary directory + -p, --password string Password to use for authenticating to the Ziti Edge Controller. default: admin + --persistent Prevents the environment from being destroyed when shutting down. default: false + --router-address string Sets the advertised address for the integrated router + --router-port int16 Sets the port to use for the integrated router + --skip-pki-gen Specifies the PKI does not need to be created. default: false + -u, --username string Username to use when creating the Ziti Edge Controller. default: admin + ``` + + Example Usage: + ``` + build/ziti edge quickstart \ + --ctrl-address potato \ + --ctrl-port 12345 \ + --router-address avacado \ + --router-port 23456 \ + --home /tmp/my-pet-ziti \ + --persistent \ + --skip-pki-gen \ + --username someOtherUsername \ + --password someOtherPassword + ``` + * Bugfixes ## Component Updates and Bug Fixes diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index 5a4e68963..b016284ca 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -34,44 +34,99 @@ import ( "net/http" "os" "os/signal" + "strconv" "syscall" "time" ) +type QuickstartOpts struct { + Username string + Password string + Persistent bool + AlreadyInitialized bool + Home string + ControllerAddress string + ControllerPort int16 + RouterAddress string + RouterPort int16 + out io.Writer + errOut io.Writer +} + // NewQuickStartCmd creates a command object for the "create" command func NewQuickStartCmd(out io.Writer, errOut io.Writer, context context.Context) *cobra.Command { + options := &QuickstartOpts{} cmd := &cobra.Command{ Use: "quickstart", Short: "runs a Controller and Router in quickstart mode", Long: "runs a Controller and Router in quickstart mode. A totally ephemeral network only valid while running.", Run: func(cmd *cobra.Command, args []string) { - run(out, errOut, context) + options.out = out + options.errOut = errOut + options.run(context) }, } + cmd.Flags().StringVarP(&options.Username, "username", "u", "", "Username to use when creating the Ziti Edge Controller. default: admin") + cmd.Flags().StringVarP(&options.Password, "password", "p", "", "Password to use for authenticating to the Ziti Edge Controller. default: admin") + cmd.Flags().BoolVar(&options.Persistent, "persistent", false, "Prevents the environment from being destroyed when shutting down. default: false") + cmd.Flags().BoolVar(&options.AlreadyInitialized, "already-initialized", false, "Specifies the PKI does not need to be created and the db does not need to be initialized. default: false") + cmd.Flags().StringVar(&options.Home, "home", "", "Sets the directory the environment should be installed into. defaults to a temporary directory") + + cmd.Flags().StringVar(&options.ControllerAddress, "ctrl-address", "", "Sets the advertised address for the control plane and API") + cmd.Flags().Int16Var(&options.ControllerPort, "ctrl-port", 0, "Sets the port to use for the control plane and API") + cmd.Flags().StringVar(&options.RouterAddress, "router-address", "", "Sets the advertised address for the integrated router") + cmd.Flags().Int16Var(&options.RouterPort, "router-port", 0, "Sets the port to use for the integrated router") return cmd } -func removeTempDir(tmpDir string) { - fmt.Println("Removing temp directory at: " + tmpDir) - _ = os.RemoveAll(tmpDir) +func (o *QuickstartOpts) cleanupHome() { + if o.Persistent { + fmt.Println("Persistent flag set. Environment left intact at: " + o.Home) + } else { + fmt.Println("Removing temp directory at: " + o.Home) + _ = os.RemoveAll(o.Home) + } } -func run(out io.Writer, errOut io.Writer, ctx context.Context) { - tmpDir, _ := os.MkdirTemp("", "quickstart") +func (o *QuickstartOpts) run(ctx context.Context) { + //set env vars + if o.Home == "" { + tmpDir, _ := os.MkdirTemp("", "quickstart") + o.Home = tmpDir + } + if o.ControllerAddress != "" { + _ = os.Setenv(constants.CtrlAdvertisedAddressVarName, o.ControllerAddress) + _ = os.Setenv(constants.CtrlEdgeAdvertisedAddressVarName, o.ControllerAddress) + } + if o.ControllerPort > 0 { + _ = os.Setenv(constants.CtrlAdvertisedPortVarName, strconv.Itoa(int(o.ControllerPort))) + } + if o.RouterAddress != "" { + _ = os.Setenv(constants.ZitiEdgeRouterAdvertisedAddressVarName, o.RouterAddress) + } + if o.RouterPort > 0 { + _ = os.Setenv(constants.ZitiEdgeRouterPortVarName, strconv.Itoa(int(o.RouterPort))) + } + if o.Username == "" { + o.Username = "admin" + } + if o.Password == "" { + o.Password = "admin" + } - defer removeTempDir(tmpDir) + defer o.cleanupHome() - ctrlYaml := tmpDir + "/ctrl.yaml" + ctrlYaml := o.Home + "/ctrl.yaml" //ZITI_HOME=/tmp ziti create config controller | grep -v "#" | sed -E 's/^ *$//g' | sed '/^$/d' - _ = os.Setenv("ZITI_HOME", tmpDir) - _ = os.Setenv("ZITI_PKI_CTRL_CA", tmpDir+"/pki/root-ca/certs/root-ca.cert") - _ = os.Setenv("ZITI_PKI_CTRL_KEY", tmpDir+"/pki/intermediate-ca/keys/server.key") - _ = os.Setenv("ZITI_PKI_CTRL_CERT", tmpDir+"/pki/intermediate-ca/certs/client.cert") - _ = os.Setenv("ZITI_PKI_SIGNER_CERT", tmpDir+"/pki/intermediate-ca/certs/intermediate-ca.cert") - _ = os.Setenv("ZITI_PKI_SIGNER_KEY", tmpDir+"/pki/intermediate-ca/keys/intermediate-ca.key") - _ = os.Setenv("ZITI_PKI_CTRL_SERVER_CERT", tmpDir+"/pki/intermediate-ca/certs/server.chain.pem") + _ = os.Setenv("ZITI_HOME", o.Home) + _ = os.Setenv("ZITI_PKI_CTRL_CA", o.Home+"/pki/root-ca/certs/root-ca.cert") + _ = os.Setenv("ZITI_PKI_CTRL_KEY", o.Home+"/pki/intermediate-ca/keys/server.key") + _ = os.Setenv("ZITI_PKI_CTRL_CERT", o.Home+"/pki/intermediate-ca/certs/client.cert") + _ = os.Setenv("ZITI_PKI_SIGNER_CERT", o.Home+"/pki/intermediate-ca/certs/intermediate-ca.cert") + _ = os.Setenv("ZITI_PKI_SIGNER_KEY", o.Home+"/pki/intermediate-ca/keys/intermediate-ca.key") + _ = os.Setenv("ZITI_PKI_CTRL_SERVER_CERT", o.Home+"/pki/intermediate-ca/certs/server.chain.pem") routerName := "quickstart-router" routerNameFromEnv := os.Getenv(constants.ZitiEdgeRouterNameVarName) @@ -79,11 +134,11 @@ func run(out io.Writer, errOut io.Writer, ctx context.Context) { routerName = routerNameFromEnv } - dbDir := tmpDir + "/db" + dbDir := o.Home + "/db" _, _ = fmt.Fprintf(os.Stdout, "creating the tmp dir [%v] for the database.\n\n", dbDir) _ = os.MkdirAll(dbDir, 0o777) - createMinimalPki(out, errOut, tmpDir+"/pki") + o.createMinimalPki() ctrl := create.NewCmdCreateConfigController() ctrl.SetArgs([]string{ @@ -91,15 +146,17 @@ func run(out io.Writer, errOut io.Writer, ctx context.Context) { }) _ = ctrl.Execute() - initCmd := edgeSubCmd.NewEdgeInitializeCmd(version.GetCmdBuildInfo()) - initCmd.SetArgs([]string{ - fmt.Sprintf("--username=%s", "admin"), - fmt.Sprintf("--password=%s", "admin"), - ctrlYaml, - }) - initErr := initCmd.Execute() - if initErr != nil { - logrus.Fatal(initErr) + if !o.AlreadyInitialized { + initCmd := edgeSubCmd.NewEdgeInitializeCmd(version.GetCmdBuildInfo()) + initCmd.SetArgs([]string{ + fmt.Sprintf("--username=%s", o.Username), + fmt.Sprintf("--password=%s", o.Password), + ctrlYaml, + }) + initErr := initCmd.Execute() + if initErr != nil { + logrus.Fatal(initErr) + } } go func() { @@ -129,63 +186,64 @@ func run(out io.Writer, errOut io.Writer, ctx context.Context) { logrus.Info("Controller online. Continuing...") case <-time.After(timeout): fmt.Println("timed out waiting for controller") - removeTempDir(tmpDir) + o.cleanupHome() return } - //ziti edge login https://localhost:1280 -u admin -p admin -y - loginCmd := NewLoginCmd(out, errOut) - loginCmd.SetArgs([]string{ - ctrlUrl, - fmt.Sprintf("--username=%s", "admin"), - fmt.Sprintf("--password=%s", "admin"), - "-y", - }) - loginErr := loginCmd.Execute() - if loginErr != nil { - logrus.Fatal(loginErr) - } + erYaml := o.Home + "/" + routerName + ".yaml" + if !o.AlreadyInitialized { + loginCmd := NewLoginCmd(o.out, o.errOut) + loginCmd.SetArgs([]string{ + ctrlUrl, + fmt.Sprintf("--username=%s", o.Username), + fmt.Sprintf("--password=%s", o.Password), + "-y", + }) + loginErr := loginCmd.Execute() + if loginErr != nil { + logrus.Fatal(loginErr) + } - //./ziti edge create edge-router ${ZITI_HOSTNAME}-edge-router -o ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.jwt -t -a public - createErCmd := NewCreateEdgeRouterCmd(out, errOut) - erJwt := tmpDir + "/" + routerName + ".jwt" - createErCmd.SetArgs([]string{ - routerName, - fmt.Sprintf("--jwt-output-file=%s", erJwt), - "--tunneler-enabled", - fmt.Sprintf("--role-attributes=%s", "public"), - }) - createErErr := createErCmd.Execute() - if createErErr != nil { - logrus.Fatal(createErErr) - } + //./ziti edge create edge-router ${ZITI_HOSTNAME}-edge-router -o ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.jwt -t -a public + createErCmd := NewCreateEdgeRouterCmd(o.out, o.errOut) + erJwt := o.Home + "/" + routerName + ".jwt" + createErCmd.SetArgs([]string{ + routerName, + fmt.Sprintf("--jwt-output-file=%s", erJwt), + "--tunneler-enabled", + fmt.Sprintf("--role-attributes=%s", "public"), + }) + createErErr := createErCmd.Execute() + if createErErr != nil { + logrus.Fatal(createErErr) + } - //./ziti create config router edge --routerName ${ZITI_HOSTNAME}-edge-router >${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.yaml - opts := &create.CreateConfigRouterOptions{} + //./ziti create config router edge --routerName ${ZITI_HOSTNAME}-edge-router >${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.yaml + opts := &create.CreateConfigRouterOptions{} - data := &create.ConfigTemplateValues{} - data.PopulateConfigValues() - create.SetZitiRouterIdentity(&data.Router, routerName) - erCfg := create.NewCmdCreateConfigRouterEdge(opts, data) - erYaml := tmpDir + "/" + routerName + ".yaml" - erCfg.SetArgs([]string{ - fmt.Sprintf("--routerName=%s", routerName), - fmt.Sprintf("--output=%s", erYaml), - }) - erCfgErr := erCfg.Execute() - if erCfgErr != nil { - logrus.Fatal(erCfgErr) - } + data := &create.ConfigTemplateValues{} + data.PopulateConfigValues() + create.SetZitiRouterIdentity(&data.Router, routerName) + erCfg := create.NewCmdCreateConfigRouterEdge(opts, data) + erCfg.SetArgs([]string{ + fmt.Sprintf("--routerName=%s", routerName), + fmt.Sprintf("--output=%s", erYaml), + }) + erCfgErr := erCfg.Execute() + if erCfgErr != nil { + logrus.Fatal(erCfgErr) + } - //./ziti router enroll ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.yaml --jwt ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.jwt - erEnroll := router.NewEnrollGwCmd() - erEnroll.SetArgs([]string{ - erYaml, - fmt.Sprintf("--jwt=%s", erJwt), - }) - erEnrollErr := erEnroll.Execute() - if erEnrollErr != nil { - logrus.Fatal(erEnrollErr) + //./ziti router enroll ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.yaml --jwt ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.jwt + erEnroll := router.NewEnrollGwCmd() + erEnroll.SetArgs([]string{ + erYaml, + fmt.Sprintf("--jwt=%s", erJwt), + }) + erEnrollErr := erEnroll.Execute() + if erEnrollErr != nil { + logrus.Fatal(erEnrollErr) + } } go func() { @@ -209,64 +267,67 @@ func run(out io.Writer, errOut io.Writer, ctx context.Context) { case <-ctx.Done(): fmt.Println("Cancellation request received") } - removeTempDir(tmpDir) + o.cleanupHome() } -func createMinimalPki(out io.Writer, errOut io.Writer, where string) { - fmt.Println("emitting a minimal PKI") +func (o *QuickstartOpts) createMinimalPki() { + if !o.AlreadyInitialized { + where := o.Home + "/pki" + fmt.Println("emitting a minimal PKI") - //ziti pki create ca --pki-root="$pkiDir" --ca-file="root-ca" --ca-name="root-ca" - ca := pki.NewCmdPKICreateCA(out, errOut) - ca.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-file=%s", "root-ca"), - fmt.Sprintf("--ca-name=%s", "root-ca"), - }) - pkiErr := ca.Execute() - if pkiErr != nil { - logrus.Fatal(pkiErr) - } + //ziti pki create ca --pki-root="$pkiDir" --ca-file="root-ca" --ca-name="root-ca" + ca := pki.NewCmdPKICreateCA(o.out, o.errOut) + ca.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", "root-ca"), + fmt.Sprintf("--ca-name=%s", "root-ca"), + }) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } - //ziti pki create intermediate --pki-root "$pkiDir" --ca-name "root-ca" --intermediate-name "intermediate-ca" --intermediate-file "intermediate-ca" --max-path-len "1" - intermediate := pki.NewCmdPKICreateIntermediate(out, errOut) - intermediate.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-name=%s", "root-ca"), - fmt.Sprintf("--intermediate-name=%s", "intermediate-ca"), - fmt.Sprintf("--intermediate-file=%s", "intermediate-ca"), - "--max-path-len=1", - }) - intErr := intermediate.Execute() - if intErr != nil { - logrus.Fatal(intErr) - } + //ziti pki create intermediate --pki-root "$pkiDir" --ca-name "root-ca" --intermediate-name "intermediate-ca" --intermediate-file "intermediate-ca" --max-path-len "1" + intermediate := pki.NewCmdPKICreateIntermediate(o.out, o.errOut) + intermediate.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", "root-ca"), + fmt.Sprintf("--intermediate-name=%s", "intermediate-ca"), + fmt.Sprintf("--intermediate-file=%s", "intermediate-ca"), + "--max-path-len=1", + }) + intErr := intermediate.Execute() + if intErr != nil { + logrus.Fatal(intErr) + } - //ziti pki create server --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --server-name "server" --server-file "server" --dns "localhost,${ZITI_HOSTNAME}" - svr := pki.NewCmdPKICreateServer(out, errOut) - svr.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-name=%s", "intermediate-ca"), - fmt.Sprintf("--server-name=%s", "server"), - fmt.Sprintf("--server-file=%s", "server"), - fmt.Sprintf("--dns=%s,%s", "localhost", helpers.GetCtrlAdvertisedAddress()), - }) - svrErr := svr.Execute() - if svrErr != nil { - logrus.Fatal(svrErr) - } + //ziti pki create server --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --server-name "server" --server-file "server" --dns "localhost,${ZITI_HOSTNAME}" + svr := pki.NewCmdPKICreateServer(o.out, o.errOut) + svr.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", "intermediate-ca"), + fmt.Sprintf("--server-name=%s", "server"), + fmt.Sprintf("--server-file=%s", "server"), + fmt.Sprintf("--dns=%s,%s", "localhost", helpers.GetCtrlAdvertisedAddress()), + }) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } - //ziti pki create client --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --client-name "client" --client-file "client" --key-file "server" - client := pki.NewCmdPKICreateClient(out, errOut) - client.SetArgs([]string{ - fmt.Sprintf("--pki-root=%s", where), - fmt.Sprintf("--ca-name=%s", "intermediate-ca"), - fmt.Sprintf("--client-name=%s", "client"), - fmt.Sprintf("--client-file=%s", "client"), - fmt.Sprintf("--key-file=%s", "server"), - }) - clientErr := client.Execute() - if clientErr != nil { - logrus.Fatal(clientErr) + //ziti pki create client --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --client-name "client" --client-file "client" --key-file "server" + client := pki.NewCmdPKICreateClient(o.out, o.errOut) + client.SetArgs([]string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", "intermediate-ca"), + fmt.Sprintf("--client-name=%s", "client"), + fmt.Sprintf("--client-file=%s", "client"), + fmt.Sprintf("--key-file=%s", "server"), + }) + clientErr := client.Execute() + if clientErr != nil { + logrus.Fatal(clientErr) + } } }