From e48c687f153ed6f4c6189dcb515256c42091dc5e Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:00:44 -0500 Subject: [PATCH 01/20] add quickstart support for ha --- .../create/config_templates/controller.yml | 4 +- ziti/cmd/create/config_templates/router.yml | 3 + ziti/cmd/create/create_config.go | 5 +- ziti/cmd/create/create_config_router.go | 1 + ziti/cmd/create/create_config_router_edge.go | 1 + ziti/cmd/edge/quickstart.go | 607 ++++++++++++++---- ziti/cmd/pki/common_test.go | 178 +++++ ziti/cmd/pki/pki_create_ca.go | 5 + ziti/cmd/pki/pki_create_ca_test.go | 105 +++ ziti/cmd/pki/pki_create_client.go | 14 +- ziti/cmd/pki/pki_create_client_test.go | 124 ++++ ziti/cmd/pki/pki_create_intermediate_test.go | 35 + ziti/cmd/pki/pki_create_server.go | 42 +- ziti/cmd/pki/pki_create_server_test.go | 124 ++++ ziti/cmd/verify/ops_verify_traffic.go | 47 +- 15 files changed, 1135 insertions(+), 160 deletions(-) create mode 100644 ziti/cmd/pki/common_test.go create mode 100644 ziti/cmd/pki/pki_create_ca_test.go create mode 100644 ziti/cmd/pki/pki_create_client_test.go create mode 100644 ziti/cmd/pki/pki_create_intermediate_test.go create mode 100644 ziti/cmd/pki/pki_create_server_test.go diff --git a/ziti/cmd/create/config_templates/controller.yml b/ziti/cmd/create/config_templates/controller.yml index 41035a93e..80fdd3a56 100644 --- a/ziti/cmd/create/config_templates/controller.yml +++ b/ziti/cmd/create/config_templates/controller.yml @@ -10,7 +10,7 @@ v: 3 {{ if .Controller.Ctrl.MinClusterSize }} raft: - dataDir: "{{ .ZitiHome }}/raft" + dataDir: "{{ .ZitiHome }}/raft{{ .InstanceId }}" minClusterSize: {{ .Controller.Ctrl.MinClusterSize }} {{ else }} db: "{{ .Controller.Database.DatabaseFile }}" @@ -233,6 +233,8 @@ web: options: { } - binding: fabric options: { } + - binding: edge-oidc + options: { } {{ if not .Controller.Web.BindPoints.Console.Enabled }}#{{- end }}- binding: zac {{ if not .Controller.Web.BindPoints.Console.Enabled }}#{{- end }} options: {{ if not .Controller.Web.BindPoints.Console.Enabled }}#{{- end }} location: {{ .Controller.Web.BindPoints.Console.Location }} diff --git a/ziti/cmd/create/config_templates/router.yml b/ziti/cmd/create/config_templates/router.yml index a137f9a41..5e5cb22b4 100644 --- a/ziti/cmd/create/config_templates/router.yml +++ b/ziti/cmd/create/config_templates/router.yml @@ -16,6 +16,9 @@ identity: {{ if not .Router.AltCertsEnabled }}#{{ end }} - server_cert: "{{ .Router.AltServerCert }}" {{ if not .Router.AltCertsEnabled }}#{{ end }} server_key: "{{ .Router.AltServerKey }}" +ha: + enabled: {{ .Router.IsHA }} + ctrl: endpoint: tls:{{ .Controller.Ctrl.AdvertisedAddress }}:{{ .Controller.Ctrl.AdvertisedPort }} diff --git a/ziti/cmd/create/create_config.go b/ziti/cmd/create/create_config.go index b3867ea7c..950dbd7fa 100644 --- a/ziti/cmd/create/create_config.go +++ b/ziti/cmd/create/create_config.go @@ -112,8 +112,8 @@ type BindPointsValues struct { } type ConsoleValues struct { - Enabled bool - Location string + Enabled bool + Location string } type IdentityValues struct { @@ -165,6 +165,7 @@ type RouterTemplateValues struct { Wss WSSRouterTemplateValues Forwarder RouterForwarderTemplateValues Listener RouterListenerTemplateValues + IsHA bool } type EdgeRouterTemplateValues struct { diff --git a/ziti/cmd/create/create_config_router.go b/ziti/cmd/create/create_config_router.go index 2537dbf4e..202443b6c 100644 --- a/ziti/cmd/create/create_config_router.go +++ b/ziti/cmd/create/create_config_router.go @@ -38,6 +38,7 @@ type CreateConfigRouterOptions struct { IsPrivate bool TunnelerMode string LanInterface string + IsHA bool } type NewCreateConfigRouterCmd struct { diff --git a/ziti/cmd/create/create_config_router_edge.go b/ziti/cmd/create/create_config_router_edge.go index e9e255667..53f5fcf53 100644 --- a/ziti/cmd/create/create_config_router_edge.go +++ b/ziti/cmd/create/create_config_router_edge.go @@ -78,6 +78,7 @@ func NewCmdCreateConfigRouterEdge(routerOptions *CreateConfigRouterOptions, data data.Router.Edge.LanInterface = routerOptions.LanInterface data.Router.Edge.Resolver = cmdhelper.GetZitiEdgeRouterResolver() data.Router.Edge.DnsSvcIpRange = cmdhelper.GetZitiEdgeRouterDnsSvcIpRange() + data.Router.IsHA = routerOptions.IsHA }, Run: func(cmd *cobra.Command, args []string) { routerOptions.Cmd = cmd diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index d0ed9b16a..3a3bccc69 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -20,25 +20,37 @@ import ( "context" "crypto/tls" "fmt" - "github.com/openziti/ziti/common/version" - edgeSubCmd "github.com/openziti/ziti/controller/subcmd" - "github.com/openziti/ziti/ziti/cmd/create" - "github.com/openziti/ziti/ziti/cmd/helpers" - "github.com/openziti/ziti/ziti/cmd/pki" - "github.com/openziti/ziti/ziti/constants" - controller2 "github.com/openziti/ziti/ziti/controller" - "github.com/openziti/ziti/ziti/router" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" "io" + "net" "net/http" + "net/url" "os" "os/signal" "os/user" + "path" + "regexp" "strconv" "strings" "syscall" "time" + + "github.com/google/uuid" + "github.com/michaelquigley/pfxlog" + "github.com/openziti/ziti/common/version" + "github.com/openziti/ziti/controller/rest_client/raft" + edgeSubCmd "github.com/openziti/ziti/controller/subcmd" + "github.com/openziti/ziti/ziti/cmd/agentcli" + "github.com/openziti/ziti/ziti/cmd/api" + "github.com/openziti/ziti/ziti/cmd/common" + "github.com/openziti/ziti/ziti/cmd/create" + "github.com/openziti/ziti/ziti/cmd/helpers" + "github.com/openziti/ziti/ziti/cmd/pki" + "github.com/openziti/ziti/ziti/constants" + ctrlcmd "github.com/openziti/ziti/ziti/controller" + "github.com/openziti/ziti/ziti/router" + "github.com/openziti/ziti/ziti/util" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" ) type QuickstartOpts struct { @@ -53,16 +65,46 @@ type QuickstartOpts struct { out io.Writer errOut io.Writer cleanOnExit bool + TrustDomain string + isHA bool + InstanceID string + MemberPID int + joinCommand bool + verbose bool + nonVoter bool + routerless bool + ha bool } -// NewQuickStartCmd creates a command object for the "create" command -func NewQuickStartCmd(out io.Writer, errOut io.Writer, context context.Context) *cobra.Command { +func addCommonQuickstartFlags(cmd *cobra.Command, options *QuickstartOpts) { currentCtrlAddy := helpers.GetCtrlEdgeAdvertisedAddress() currentCtrlPort := helpers.GetCtrlEdgeAdvertisedPort() currentRouterAddy := helpers.GetRouterAdvertisedAddress() currentRouterPort := helpers.GetZitiEdgeRouterPort() - defautlCtrlPort, _ := strconv.ParseInt(constants.DefaultCtrlEdgeAdvertisedPort, 10, 16) - defautlRouterPort, _ := strconv.ParseInt(constants.DefaultZitiEdgeRouterPort, 10, 16) + defaultCtrlPort, _ := strconv.ParseInt(constants.DefaultCtrlEdgeAdvertisedPort, 10, 16) + defaultRouterPort, _ := strconv.ParseInt(constants.DefaultZitiEdgeRouterPort, 10, 16) + + cmd.Flags().StringVarP(&options.Username, "username", "u", "", "admin username, default: admin") + cmd.Flags().StringVarP(&options.Password, "password", "p", "", "admin password, default: admin") + + cmd.Flags().StringVar(&options.Home, "home", "", "permanent directory") + + cmd.Flags().StringVar(&options.ControllerAddress, "ctrl-address", "", "sets the advertised address for the control plane and API. current: "+currentCtrlAddy) + cmd.Flags().Int16Var(&options.ControllerPort, "ctrl-port", int16(defaultCtrlPort), "sets the port to use for the control plane and API. current: "+currentCtrlPort) + cmd.Flags().StringVar(&options.RouterAddress, "router-address", "", "sets the advertised address for the integrated router. current: "+currentRouterAddy) + cmd.Flags().Int16Var(&options.RouterPort, "router-port", int16(defaultRouterPort), "sets the port to use for the integrated router. current: "+currentRouterPort) + cmd.Flags().BoolVar(&options.routerless, "no-router", false, "specifies the quickstart should not start a router") + + cmd.Flags().BoolVar(&options.verbose, "verbose", false, "Show additional output.") +} + +func addQuickstartHaFlags(cmd *cobra.Command, options *QuickstartOpts) { + cmd.Flags().StringVar(&options.TrustDomain, "trust-domain", "", "the specified trust domain to be used in SPIFFE ids.") + cmd.Flags().StringVar(&options.InstanceID, "instance-id", "", "specifies a unique instance id for use in ha mode.") +} + +// 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", @@ -74,15 +116,47 @@ func NewQuickStartCmd(out io.Writer, errOut io.Writer, context context.Context) options.run(context) }, } - cmd.Flags().StringVarP(&options.Username, "username", "u", "", "Admin username, default: admin") - cmd.Flags().StringVarP(&options.Password, "password", "p", "", "Admin password, default: admin") - - cmd.Flags().StringVar(&options.Home, "home", "", "permanent directory") + addCommonQuickstartFlags(cmd, options) + cmd.AddCommand(NewQuickStartJoinClusterCmd(out, errOut, context)) + cmd.AddCommand(NewQuickStartHaCmd(out, errOut, context)) + return cmd +} - cmd.Flags().StringVar(&options.ControllerAddress, "ctrl-address", "", "Sets the advertised address for the control plane and API. current: "+currentCtrlAddy) - cmd.Flags().Int16Var(&options.ControllerPort, "ctrl-port", int16(defautlCtrlPort), "Sets the port to use for the control plane and API. current: "+currentCtrlPort) - cmd.Flags().StringVar(&options.RouterAddress, "router-address", "", "Sets the advertised address for the integrated router. current: "+currentRouterAddy) - cmd.Flags().Int16Var(&options.RouterPort, "router-port", int16(defautlRouterPort), "Sets the port to use for the integrated router. current: "+currentRouterPort) +func NewQuickStartHaCmd(out io.Writer, errOut io.Writer, context context.Context) *cobra.Command { + options := &QuickstartOpts{} + cmd := &cobra.Command{ + Use: "ha", + Short: "runs a Controller and Router in quickstart HA mode and creates the first cluster member", + Long: "runs a Controller and Router in quickstart HA mode and creates the first cluster member with a temporary directory; suitable for testing and development", + Run: func(cmd *cobra.Command, args []string) { + options.out = out + options.errOut = errOut + options.isHA = true + options.run(context) + }, + } + addCommonQuickstartFlags(cmd, options) + addQuickstartHaFlags(cmd, options) + cmd.Hidden = true + return cmd +} +func NewQuickStartJoinClusterCmd(out io.Writer, errOut io.Writer, context context.Context) *cobra.Command { + options := &QuickstartOpts{} + cmd := &cobra.Command{ + Use: "join", + Short: "runs a Controller and Router in quickstart mode and joins an existing cluster", + Long: "runs a Controller and Router in quickstart mode and joins an existing cluster with a temporary directory; suitable for testing and development", + Run: func(cmd *cobra.Command, args []string) { + options.out = out + options.errOut = errOut + options.join(context) + }, + } + addCommonQuickstartFlags(cmd, options) + addQuickstartHaFlags(cmd, options) + cmd.Flags().IntVarP(&options.MemberPID, "member-pid", "m", 0, "the pid of a cluster member. required") + cmd.Flags().BoolVar(&options.nonVoter, "non-voting", true, "used with ha mode. specifies the member is a non-voting member") + cmd.Hidden = true return cmd } @@ -95,7 +169,27 @@ func (o *QuickstartOpts) cleanupHome() { } } +func (o *QuickstartOpts) join(ctx context.Context) { + if strings.TrimSpace(o.InstanceID) == "" { + logrus.Fatalf("the instance-id is required when joining a cluster") + } + if strings.TrimSpace(o.Home) == "" { + logrus.Fatalf("the home directory must be specified when joining an existing cluster. the root-ca is used to create the server's pki") + } + + if o.MemberPID == 0 { + logrus.Fatalf("--member-pid is required") + } + o.isHA = true + o.joinCommand = true + o.run(ctx) +} + func (o *QuickstartOpts) run(ctx context.Context) { + if o.verbose { + pfxlog.GlobalInit(logrus.DebugLevel, pfxlog.DefaultOptions().Color()) + } + //set env vars if o.Home == "" { tmpDir, _ := os.MkdirTemp("", "quickstart") @@ -137,52 +231,73 @@ func (o *QuickstartOpts) run(ctx context.Context) { o.Password = "admin" } - ctrlYaml := o.Home + "/ctrl.yaml" + if o.InstanceID == "" { + o.InstanceID = uuid.New().String() + } + + ctrlYaml := path.Join(o.instHome(), "ctrl.yaml") + routerName := "router-" + o.InstanceID //ZITI_HOME=/tmp ziti create config controller | grep -v "#" | sed -E 's/^ *$//g' | sed '/^$/d' _ = 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.chain.pem") - _ = 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" + pkiLoc := path.Join(o.Home, "pki") + rootLoc := path.Join(pkiLoc, "root-ca") + pkiIntermediateName := o.scopedName("intermediate-ca") + pkiServerName := o.scopedNameOff("server") + pkiClientName := o.scopedNameOff("client") + intermediateLoc := path.Join(pkiLoc, pkiIntermediateName) + _ = os.Setenv("ZITI_PKI_CTRL_CA", path.Join(rootLoc, "certs", "root-ca.cert")) + _ = os.Setenv("ZITI_PKI_CTRL_KEY", path.Join(intermediateLoc, "keys", pkiServerName+".key")) + _ = os.Setenv("ZITI_PKI_CTRL_SERVER_CERT", path.Join(intermediateLoc, "certs", pkiServerName+".chain.pem")) + _ = os.Setenv("ZITI_PKI_CTRL_CERT", path.Join(intermediateLoc, "certs", pkiClientName+".chain.pem")) + _ = os.Setenv("ZITI_PKI_SIGNER_CERT", path.Join(intermediateLoc, "certs", pkiIntermediateName+".cert")) + _ = os.Setenv("ZITI_PKI_SIGNER_KEY", path.Join(intermediateLoc, "keys", pkiIntermediateName+".key")) + routerNameFromEnv := os.Getenv(constants.ZitiEdgeRouterNameVarName) if routerNameFromEnv != "" { routerName = routerNameFromEnv } - dbDir := o.Home + "/db" + dbDir := path.Join(o.instHome(), "db") if _, err := os.Stat(dbDir); !os.IsNotExist(err) { o.AlreadyInitialized = true } else { - _ = os.MkdirAll(dbDir, 0o777) + _ = os.MkdirAll(dbDir, 0o700) logrus.Debugf("made directory '%s'", dbDir) o.createMinimalPki() + _ = os.Setenv("ZITI_HOME", o.instHome()) ctrl := create.NewCmdCreateConfigController() - ctrl.SetArgs([]string{ + args := []string{ fmt.Sprintf("--output=%s", ctrlYaml), - }) - _ = ctrl.Execute() + } + if o.isHA { + args = append(args, fmt.Sprintf("--minCluster=%d", 1)) + } + ctrl.SetArgs(args) + err = ctrl.Execute() + if err != nil { + logrus.Fatal(err) + } - 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) + if !o.isHA { + 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) + } } } + fmt.Println("Starting controller...") go func() { - runCtrl := controller2.NewRunCmd() + runCtrl := ctrlcmd.NewRunCmd() runCtrl.SetArgs([]string{ ctrlYaml, }) @@ -191,15 +306,13 @@ func (o *QuickstartOpts) run(ctx context.Context) { logrus.Fatal(runCtrlErr) } }() - - fmt.Println("Controller running... Configuring and starting Router...") + fmt.Println("Controller running...") ctrlAddy := helpers.GetCtrlEdgeAdvertisedAddress() ctrlPort := helpers.GetCtrlEdgeAdvertisedPort() ctrlUrl := fmt.Sprintf("https://%s:%s", ctrlAddy, ctrlPort) c := make(chan struct{}) - defer close(c) timeout, _ := time.ParseDuration("30s") go waitForController(ctrlUrl, c) select { @@ -212,7 +325,121 @@ func (o *QuickstartOpts) run(ctx context.Context) { return } - erYaml := o.Home + "/" + routerName + ".yaml" + if o.isHA { + p := common.NewOptionsProvider(o.out, o.errOut) + if !o.joinCommand { + fmt.Println("waiting three seconds for controller to become ready...") + time.Sleep(3 * time.Second) + agentInitCmd := agentcli.NewAgentCtrlInit(p) + pid := os.Getpid() + args := []string{ + o.Username, + o.Password, + o.Username, + fmt.Sprintf("--pid=%d", pid), + } + agentInitCmd.SetArgs(args) + + agentInitErr := agentInitCmd.Execute() + if agentInitErr != nil { + logrus.Fatal(agentInitErr) + } + } else { + agentJoinCmd := agentcli.NewAgentClusterAdd(p) + + args := []string{ + fmt.Sprintf("tls:%s:%s", helpers.GetCtrlAdvertisedAddress(), helpers.GetCtrlAdvertisedPort()), + fmt.Sprintf("--pid=%d", o.MemberPID), + fmt.Sprintf("--voter=%t", !o.nonVoter), + } + agentJoinCmd.SetArgs(args) + + fmt.Println("waiting three seconds for controller to become ready...") + time.Sleep(3 * time.Second) + + addChan := make(chan struct{}) + addTimeout := time.Second * 30 + go func() { + o.waitForLeader() + agentJoinErr := agentJoinCmd.Execute() + if agentJoinErr != nil { + logrus.Fatal(agentJoinErr) + } + close(addChan) + }() + + select { + case <-addChan: + //completed normally + logrus.Info("Add command successful. continuing...") + case <-time.After(addTimeout): + fmt.Println("timed out adding to cluster") + o.cleanupHome() + return + } + } + } + + erConfigFile := path.Join(o.instHome(), routerName+".yaml") + o.configureRouter(routerName, erConfigFile, ctrlUrl) + o.runRouter(erConfigFile) + + ch := make(chan os.Signal, 1) + signal.Notify(ch, os.Interrupt, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM) + + if !o.routerless { + r := make(chan struct{}) + timeout, _ = time.ParseDuration("30s") + go waitForRouter(o.RouterAddress, o.RouterPort, r) + select { + case <-r: + //completed normally + case <-time.After(timeout): + fmt.Println("timed out waiting for router:", ctrlUrl) + o.cleanupHome() + return + } + } + + if o.isHA { + go func() { + time.Sleep(3 * time.Second) // output this after a bit... + nextInstId := incrementStringSuffix(o.InstanceID) + fmt.Println() + fmt.Println("=======================================================================================") + fmt.Println("controller and router started.") + fmt.Println(" controller located at : " + helpers.GetCtrlAdvertisedAddress() + ":" + strconv.Itoa(int(o.ControllerPort))) + fmt.Println(" router located at : " + helpers.GetRouterAdvertisedAddress() + ":" + strconv.Itoa(int(o.RouterPort))) + fmt.Println(" config dir located at : " + o.Home) + fmt.Println(" configured trust domain: " + o.TrustDomain) + fmt.Printf(" instance pid : %d\n", os.Getpid()) + fmt.Println("=======================================================================================") + fmt.Println("Quickly add another member to this cluster using: ") + fmt.Printf(" ziti edge quickstart join \\\n") + fmt.Printf(" --ctrl-port %d \\\n", o.ControllerPort+1) + fmt.Printf(" --router-port %d \\\n", o.RouterPort+1) + fmt.Printf(" --home \"%s\" \\\n", o.Home) + fmt.Printf(" --member-pid %d\\ \n", os.Getpid()) + fmt.Printf(" --instance-id \"%s\"\n", nextInstId) + fmt.Println("=======================================================================================") + fmt.Println() + }() + } + + select { + case <-ch: + fmt.Println("Signal to shutdown received") + case <-ctx.Done(): + fmt.Println("Cancellation request received") + } + o.cleanupHome() +} + +func (o *QuickstartOpts) configureRouter(routerName string, configFile string, ctrlUrl string) { + if o.routerless { + return + } + if !o.AlreadyInitialized { loginCmd := NewLoginCmd(o.out, o.errOut) loginCmd.SetArgs([]string{ @@ -221,47 +448,33 @@ func (o *QuickstartOpts) run(ctx context.Context) { fmt.Sprintf("--password=%s", o.Password), "-y", }) + if o.joinCommand { + o.waitForLeader() + } loginErr := loginCmd.Execute() if loginErr != nil { logrus.Fatal(loginErr) } - // Allow all identities to use any edge router with the "public" attribute - // ziti edge create edge-router-policy all-endpoints-public-routers --edge-router-roles "#public" --identity-roles "#all" - erpCmd := NewCreateEdgeRouterPolicyCmd(o.out, o.errOut) - erpCmd.SetArgs([]string{ - "all-endpoints-public-routers", - fmt.Sprintf("--edge-router-roles=%s", "#public"), - fmt.Sprintf("--identity-roles=%s", "#all"), - }) - erpCmdErr := erpCmd.Execute() - if erpCmdErr != nil { - logrus.Fatal(erpCmdErr) - } + o.configureOverlay() - // # Allow all edge-routers to access all services - // ziti edge create service-edge-router-policy all-routers-all-services --edge-router-roles "#all" --service-roles "#all" - serpCmd := NewCreateServiceEdgeRouterPolicyCmd(o.out, o.errOut) - serpCmd.SetArgs([]string{ - "all-routers-all-services", - fmt.Sprintf("--edge-router-roles=%s", "#all"), - fmt.Sprintf("--service-roles=%s", "#all"), - }) - serpCmdErr := serpCmd.Execute() - if serpCmdErr != nil { - logrus.Fatal(serpCmdErr) - } + time.Sleep(1 * time.Second) + + var erJwt string // 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" + erJwt = path.Join(o.Home, routerName+".jwt") createErCmd.SetArgs([]string{ routerName, fmt.Sprintf("--jwt-output-file=%s", erJwt), "--tunneler-enabled", fmt.Sprintf("--role-attributes=%s", "public"), }) + + o.waitForLeader() //wait for a leader before doing anything createErErr := createErCmd.Execute() + if createErErr != nil { logrus.Fatal(createErErr) } @@ -271,12 +484,15 @@ func (o *QuickstartOpts) run(ctx context.Context) { data := &create.ConfigTemplateValues{} data.PopulateConfigValues() + opts.IsHA = o.isHA create.SetZitiRouterIdentity(&data.Router, routerName) erCfg := create.NewCmdCreateConfigRouterEdge(opts, data) erCfg.SetArgs([]string{ fmt.Sprintf("--routerName=%s", routerName), - fmt.Sprintf("--output=%s", erYaml), + fmt.Sprintf("--output=%s", configFile), }) + + o.waitForLeader() erCfgErr := erCfg.Execute() if erCfgErr != nil { logrus.Fatal(erCfgErr) @@ -285,62 +501,81 @@ func (o *QuickstartOpts) run(ctx context.Context) { // 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, + configFile, fmt.Sprintf("--jwt=%s", erJwt), }) + + o.waitForLeader() //needed? erEnrollErr := erEnroll.Execute() if erEnrollErr != nil { logrus.Fatal(erEnrollErr) } } +} +func (o *QuickstartOpts) runRouter(configFile string) { + if o.routerless { + return + } go func() { // ziti router run ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.yaml &> ${ZITI_HOME}/${ZITI_HOSTNAME}-edge-router.log & erRunCmd := router.NewRunCmd() erRunCmd.SetArgs([]string{ - erYaml, + configFile, }) + + o.waitForLeader() //needed? erRunCmdErr := erRunCmd.Execute() if erRunCmdErr != nil { logrus.Fatal(erRunCmdErr) } }() - - ch := make(chan os.Signal, 1) - signal.Notify(ch, os.Interrupt, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM) - - select { - case <-ch: - fmt.Println("Signal to shutdown received") - case <-ctx.Done(): - fmt.Println("Cancellation request received") - } - o.cleanupHome() } func (o *QuickstartOpts) createMinimalPki() { - where := o.Home + "/pki" + where := path.Join(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(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) + intermediateId := fmt.Sprintf("spiffe://%s/intermediate/%s", o.TrustDomain, o.InstanceID) + sid := fmt.Sprintf("spiffe://%s/controller/%s", o.TrustDomain, o.InstanceID) + + //ziti pki create ca --pki-root="$pkiDir" --ca-file="root-ca" --ca-name="root-ca" --spiffe-id="whatever" + if o.joinCommand { + // indicates we are joining a cluster. don't emit a root-ca, expect it'll be there or error + } else { + rootCaPath := path.Join(where, "root-ca", "certs", "root-ca.cert") + rootCa, statErr := os.Stat(rootCaPath) //pki/root-ca/certs/root-ca.cert + if statErr != nil { + logrus.Warnf("cold not check for root-ca? %v", statErr) + } + if rootCa == nil { + ca := pki.NewCmdPKICreateCA(o.out, o.errOut) + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", "root-ca"), + fmt.Sprintf("--ca-name=%s", "root-ca"), + fmt.Sprintf("--trust-domain=%s", o.TrustDomain), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } + + } else { + logrus.Infof("%s exists and will be reused", rootCaPath) + } } - //ziti pki create intermediate --pki-root "$pkiDir" --ca-name "root-ca" --intermediate-name "intermediate-ca" --intermediate-file "intermediate-ca" --max-path-len "1" + //ziti pki create intermediate --pki-root "$pkiDir" --ca-name "root-ca" --intermediate-name "intermediate-ca" --intermediate-file "intermediate-ca" --max-path-len "1" --spiffe-id="whatever" 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"), + fmt.Sprintf("--intermediate-name=%s", o.scopedName("intermediate-ca")), + fmt.Sprintf("--intermediate-file=%s", o.scopedName("intermediate-ca")), + fmt.Sprintf("--spiffe-id=%s", intermediateId), "--max-path-len=1", }) intErr := intermediate.Execute() @@ -348,34 +583,38 @@ func (o *QuickstartOpts) createMinimalPki() { 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}" + //ziti pki create server --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --server-name "server" --server-file "server" --dns "localhost,${ZITI_HOSTNAME}" --spiffe-id="whatever" svr := pki.NewCmdPKICreateServer(o.out, o.errOut) var ips = "127.0.0.1,::1" - ip_override := os.Getenv("ZITI_CTRL_EDGE_IP_OVERRIDE") - if ip_override != "" { - ips = ips + "," + ip_override + ipOverride := os.Getenv("ZITI_CTRL_EDGE_IP_OVERRIDE") + if ipOverride != "" { + ips = ips + "," + ipOverride } - svr.SetArgs([]string{ + args := []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("--ca-name=%s", o.scopedName("intermediate-ca")), + fmt.Sprintf("--server-name=%s", o.InstanceID), + fmt.Sprintf("--server-file=%s", o.scopedNameOff("server")), fmt.Sprintf("--dns=%s,%s", "localhost", helpers.GetCtrlAdvertisedAddress()), fmt.Sprintf("--ip=%s", ips), - }) + fmt.Sprintf("--spiffe-id=%s", sid), + } + + svr.SetArgs(args) 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" + //ziti pki create client --pki-root="${ZITI_HOME}/pki" --ca-name "intermediate-ca" --client-name "client" --client-file "client" --key-file "server" --spiffe-id="whatever" 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"), + fmt.Sprintf("--ca-name=%s", o.scopedName("intermediate-ca")), + fmt.Sprintf("--client-name=%s", o.InstanceID), + fmt.Sprintf("--client-file=%s", o.scopedNameOff("client")), + fmt.Sprintf("--key-file=%s", o.scopedNameOff("server")), + fmt.Sprintf("--spiffe-id=%s", sid), }) clientErr := client.Execute() if clientErr != nil { @@ -396,3 +635,137 @@ func waitForController(ctrlUrl string, done chan struct{}) { } done <- struct{}{} } + +func waitForRouter(address string, port int16, done chan struct{}) { + for { + addr := fmt.Sprintf("%s:%d", address, port) + conn, err := net.DialTimeout("tcp", addr, 2*time.Second) + if err == nil { + _ = conn.Close() + fmt.Printf("Router is available on %s:%d\n", address, port) + close(done) + return + } + time.Sleep(25 * time.Millisecond) + } +} + +func (o *QuickstartOpts) scopedNameOff(name string) string { + return name +} +func (o *QuickstartOpts) scopedName(name string) string { + if o.InstanceID != "" { + return name + "-" + o.InstanceID + } else { + return name + } +} + +func (o *QuickstartOpts) instHome() string { + return path.Join(o.Home, o.InstanceID) +} + +var configuredTrustDomain = fmt.Sprintf("spiffe://%s", uuid.New().String()) + +func (o *QuickstartOpts) trustDomaina() string { + if strings.TrimSpace(o.TrustDomain) != "" { + spiffeId, err := url.Parse(o.TrustDomain) + if spiffeId == nil || err != nil { + logrus.Fatal("spiffe id is invalid: " + o.TrustDomain) + return "" // placate the foolish warning checker that doesn't realize Fatal is 'fatal' + } + if spiffeId.Scheme != "" && spiffeId.Scheme != "spiffe" { + logrus.Fatal("spiffe id scheme is invalid: " + spiffeId.Scheme) + } + configuredTrustDomain = fmt.Sprintf("spiffe://%s", spiffeId.Hostname()) + configuredTrustDomain = strings.TrimSuffix(configuredTrustDomain, "/") + } else { + logrus.Fatal("trust domain is invalid: " + o.TrustDomain) + } + + return configuredTrustDomain +} + +func (o *QuickstartOpts) configureOverlay() { + if o.joinCommand { + return + } + + // Allow all identities to use any edge router with the "public" attribute + // ziti edge create edge-router-policy all-endpoints-public-routers --edge-router-roles "#public" --identity-roles "#all" + erpCmd := NewCreateEdgeRouterPolicyCmd(o.out, o.errOut) + erpCmd.SetArgs([]string{ + "all-endpoints-public-routers", + fmt.Sprintf("--edge-router-roles=%s", "#public"), + fmt.Sprintf("--identity-roles=%s", "#all"), + }) + erpCmdErr := erpCmd.Execute() + if erpCmdErr != nil { + logrus.Fatal(erpCmdErr) + } + + // # Allow all edge-routers to access all services + // ziti edge create service-edge-router-policy all-routers-all-services --edge-router-roles "#all" --service-roles "#all" + serpCmd := NewCreateServiceEdgeRouterPolicyCmd(o.out, o.errOut) + serpCmd.SetArgs([]string{ + "all-routers-all-services", + fmt.Sprintf("--edge-router-roles=%s", "#all"), + fmt.Sprintf("--service-roles=%s", "#all"), + }) + o.waitForLeader() + serpCmdErr := serpCmd.Execute() + if serpCmdErr != nil { + logrus.Fatal(serpCmdErr) + } +} + +type raftListMembersAction struct { + api.Options +} + +func (o *QuickstartOpts) waitForLeader() bool { + for { + p := common.NewOptionsProvider(o.out, o.errOut) + action := &raftListMembersAction{ + Options: api.Options{CommonOptions: p()}, + } + + client, err := util.NewFabricManagementClient(action) + if err != nil { + return false + } + members, err := client.Raft.RaftListMembers(&raft.RaftListMembersParams{ + Context: context.Background(), + }) + + if err != nil { + return false + } + for _, m := range members.Payload.Data { + if m.Leader != nil && *m.Leader { + time.Sleep(500 * time.Millisecond) // this just gives time for the leader to 'settle' -- shouldn't be necessary + return true + } + } + time.Sleep(50 * time.Millisecond) + } +} + +func incrementStringSuffix(input string) string { + // Regular expression to capture the numeric suffix + re := regexp.MustCompile(`(\d+)$`) + match := re.FindStringSubmatch(input) + + if len(match) == 0 { + return uuid.New().String() + } + + numStr := match[1] + numLength := len(numStr) + num, _ := strconv.Atoi(numStr) + num++ + + incremented := fmt.Sprintf("%0*d", numLength, num) + + return strings.TrimSuffix(input, numStr) + incremented +} diff --git a/ziti/cmd/pki/common_test.go b/ziti/cmd/pki/common_test.go new file mode 100644 index 000000000..c3a81a378 --- /dev/null +++ b/ziti/cmd/pki/common_test.go @@ -0,0 +1,178 @@ +package pki + +import ( + "bytes" + "fmt" + "github.com/openziti/ziti/ziti/pki/pki" + "github.com/openziti/ziti/ziti/pki/store" + "github.com/sirupsen/logrus" + "net" + "net/url" + "os" + "testing" +) + +var where = "/tmp/pki-test" +var trustDomain = "pki-test-domain" +var testPki *pki.ZitiPKI + +var rootCaWithSpiffeIdName = "root-ca-with-spiffe-id" +var rootCaWithoutSpiffeIdName = "root-ca-without-spiffe-id" +var intCaNameWithSpiffeIdName = "intermediate-ca-with-spiffe-id" +var intCaNameWithoutSpiffeIdName = "intermediate-ca-without-spiffe-id" + +func streams() (*bytes.Buffer, *bytes.Buffer) { + return new(bytes.Buffer), new(bytes.Buffer) +} + +type URLSlice []*url.URL + +func (u URLSlice) Paths() []string { + paths := make([]string, len(u)) + for i, uri := range u { + paths[i] = uri.Path + } + return paths +} +func (u URLSlice) Hosts() []string { + hosts := make([]string, len(u)) + for i, uri := range u { + hosts[i] = uri.Host + } + return hosts +} + +func urisAsStrings(uris []*url.URL) []string { + urisAsStrings := make([]string, len(uris)) + for i, uri := range uris { + urisAsStrings[i] = uri.String() + } + return urisAsStrings +} + +func ipsAsStrings(ips []net.IP) []string { + ipsAsStrings := make([]string, len(ips)) + for i, ip := range ips { + ipsAsStrings[i] = ip.String() + } + return ipsAsStrings +} + +func TestMain(m *testing.M) { + var code int + if setup() { + // Run tests + code = m.Run() + } + teardown() + + // Exit with the code from the test run + os.Exit(code) +} + +func setup() bool { + where, _ = os.MkdirTemp("", "pki-test") + testPki = &pki.ZitiPKI{Store: &store.Local{}} + local := testPki.Store.(*store.Local) + local.Root = where + if !createTestCaWithSpiffeId() { + return false + } + if !createTestCaWithoutSpiffeId() { + return false + } + if !createTestIntermediateWithSpiffeId() { + return false + } + if !createTestIntermediateWithoutSpiffeId() { + return false + } + + return true +} + +func createTestCaWithSpiffeId() bool { + out, errOut := streams() + ca := NewCmdPKICreateCA(out, errOut) + + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", rootCaWithSpiffeIdName), + fmt.Sprintf("--ca-name=%s", rootCaWithSpiffeIdName), + fmt.Sprintf("--trust-domain=%s", "spiffe://"+rootCaWithSpiffeIdName), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Error(pkiErr) + return false + } + return true +} +func createTestCaWithoutSpiffeId() bool { + out, errOut := streams() + ca := NewCmdPKICreateCA(out, errOut) + + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", rootCaWithoutSpiffeIdName), + fmt.Sprintf("--ca-name=%s", rootCaWithoutSpiffeIdName), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Error(pkiErr) + return false + } + return true +} +func createTestIntermediateWithSpiffeId() bool { + out, errOut := streams() + intermediateCmd := NewCmdPKICreateIntermediate(out, errOut) + intermediateArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", rootCaWithSpiffeIdName), + fmt.Sprintf("--intermediate-name=%s", intCaNameWithSpiffeIdName), + fmt.Sprintf("--intermediate-file=%s", intCaNameWithSpiffeIdName), + "--max-path-len=1", + } + + intermediateCmd.SetArgs(intermediateArgs) + pkiErr := intermediateCmd.Execute() + if pkiErr != nil { + logrus.Error(pkiErr) + return false + } + return true +} +func createTestIntermediateWithoutSpiffeId() bool { + out, errOut := streams() + intermediateCmd := NewCmdPKICreateIntermediate(out, errOut) + intermediateArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", rootCaWithoutSpiffeIdName), + fmt.Sprintf("--intermediate-name=%s", intCaNameWithoutSpiffeIdName), + fmt.Sprintf("--intermediate-file=%s", intCaNameWithoutSpiffeIdName), + "--max-path-len=1", + } + + intermediateCmd.SetArgs(intermediateArgs) + pkiErr := intermediateCmd.Execute() + if pkiErr != nil { + logrus.Error(pkiErr) + return false + } + return true +} + +func teardown() { + fmt.Printf("removing temp directory: %s\n", where) + _ = os.RemoveAll(where) +} + +func addSpiffeArg(id string, args []string) []string { + args = append(args, "--spiffe-id="+id) + return args +} diff --git a/ziti/cmd/pki/pki_create_ca.go b/ziti/cmd/pki/pki_create_ca.go index 4b92e4295..56dcb93b4 100644 --- a/ziti/cmd/pki/pki_create_ca.go +++ b/ziti/cmd/pki/pki_create_ca.go @@ -114,6 +114,11 @@ func (o *PKICreateCAOptions) Run() error { if err != nil { return errors.Wrapf(err, "unable to parse spiffe id [%v]", o.Flags.SpiffeID) } + + if len(spiffeId.Path) > 0 && strings.TrimSpace(spiffeId.Path) != "/" { + log.Warnf("trust-domain [%v] includes path information and will be ignored", spiffeId.String()) + spiffeId.Path = "" + } template.URIs = append(template.URIs, spiffeId) } diff --git a/ziti/cmd/pki/pki_create_ca_test.go b/ziti/cmd/pki/pki_create_ca_test.go new file mode 100644 index 000000000..9a29fe012 --- /dev/null +++ b/ziti/cmd/pki/pki_create_ca_test.go @@ -0,0 +1,105 @@ +package pki + +import ( + "fmt" + "github.com/google/uuid" + "github.com/sirupsen/logrus" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTrustDomain(t *testing.T) { + out, errOut := streams() + ca := NewCmdPKICreateCA(out, errOut) + name := uuid.New().String() + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", name), + fmt.Sprintf("--ca-name=%s", name), + fmt.Sprintf("--trust-domain=%s", "spiffe://"+trustDomain), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } + + bundle, e := testPki.GetCA(name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), "spiffe://"+trustDomain) +} + +func TestNoTrustDomain(t *testing.T) { + out, errOut := streams() + ca := NewCmdPKICreateCA(out, errOut) + name := uuid.New().String() + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", name), + fmt.Sprintf("--ca-name=%s", name), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } + + bundle, e := testPki.GetCA(name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Empty(t, bundle.Cert.URIs) +} + +func TestTrustDomainSpiffeAppended(t *testing.T) { + out, errOut := streams() + ca := NewCmdPKICreateCA(out, errOut) + name := uuid.New().String() + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", name), + fmt.Sprintf("--ca-name=%s", name), + fmt.Sprintf("--trust-domain=%s", trustDomain), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } + + bundle, e := testPki.GetCA(name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), "spiffe://"+trustDomain) +} + +func TestTrustDomainWithPath(t *testing.T) { + out, errOut := streams() + ca := NewCmdPKICreateCA(out, errOut) + name := uuid.New().String() + rootCaArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-file=%s", name), + fmt.Sprintf("--ca-name=%s", name), + fmt.Sprintf("--trust-domain=%s", "spiffe://"+trustDomain+"/path"), + } + + ca.SetArgs(rootCaArgs) + pkiErr := ca.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } + + bundle, e := testPki.GetCA(name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), "spiffe://"+trustDomain) +} diff --git a/ziti/cmd/pki/pki_create_client.go b/ziti/cmd/pki/pki_create_client.go index 0f70dd67a..86457fe6c 100644 --- a/ziti/cmd/pki/pki_create_client.go +++ b/ziti/cmd/pki/pki_create_client.go @@ -78,7 +78,7 @@ func (o *PKICreateClientOptions) addPKICreateClientFlags(cmd *cobra.Command) { cmd.Flags().IntVarP(&o.Flags.CAMaxPath, "max-path-len", "", -1, "Intermediate maximum path length") cmd.Flags().IntVarP(&o.Flags.CAPrivateKeySize, "private-key-size", "", 4096, "Size of the RSA private key, ignored if -curve is set") cmd.Flags().StringVarP(&o.Flags.EcCurve, "curve", "", "", "If set an EC private key is generated and -private-key-size is ignored, options: P224, P256, P384, P521") - cmd.Flags().StringVar(&o.Flags.SpiffeID, "spiffe-id", "", "Optionally provide the path portion of a SPIFFE id. The trust domain will be taken from the signing certificate.") + cmd.Flags().StringVar(&o.Flags.SpiffeID, "spiffe-id", "", "The SPIFFE id to use. If not a complete SPIFFE id, this is treated as the SPIFFE id path and the trust domain will be taken from the signing certificate.") cmd.Flags().BoolVar(&o.Flags.AllowOverwrite, "allow-overwrite", false, "Allow overwrite existing certs") } @@ -132,7 +132,7 @@ func (o *PKICreateClientOptions) Run() error { for _, uri := range signer.Cert.URIs { if uri.Scheme == "spiffe" { if trustDomain != nil { - return errors.New("signing cert contained multiple spiffe ids, which is not allowed") + return errors.New("signing cert contained multiple spiffe ids") } trustDomain = uri } @@ -142,9 +142,13 @@ func (o *PKICreateClientOptions) Run() error { return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") } - spiffId := *trustDomain - spiffId.Path = o.Flags.SpiffeID - template.URIs = append(template.URIs, &spiffId) + spiffeId := *trustDomain + sid, serr := url.Parse(o.Flags.SpiffeID) + if serr != nil { + return serr + } + spiffeId.Path = sid.Path + template.URIs = append(template.URIs, &spiffeId) } privateKeyOptions, err := o.ObtainPrivateKeyOptions() diff --git a/ziti/cmd/pki/pki_create_client_test.go b/ziti/cmd/pki/pki_create_client_test.go new file mode 100644 index 000000000..8f5cad345 --- /dev/null +++ b/ziti/cmd/pki/pki_create_client_test.go @@ -0,0 +1,124 @@ +package pki + +import ( + "fmt" + "github.com/google/uuid" + "github.com/sirupsen/logrus" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestClientCertNoSpiffeIdFromIntermediate(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateClient(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithoutSpiffeIdName), + fmt.Sprintf("--client-name=%s", name), + fmt.Sprintf("--client-file=%s", name), + fmt.Sprintf("--dns=%s", "localhost,dns.entry"), + fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), + } + + svr.SetArgs(args) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, bundle.Cert.DNSNames, "dns.entry") + assert.Contains(t, bundle.Cert.DNSNames, "localhost") + ips := ipsAsStrings(bundle.Cert.IPAddresses) + assert.Contains(t, ips, "127.0.0.1") + assert.Contains(t, ips, "::1") + assert.Nil(t, bundle.Cert.URIs) +} + +func TestClientCertSpiffeIdFromIntermediate(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateClient(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithSpiffeIdName), + fmt.Sprintf("--client-name=%s", name), + fmt.Sprintf("--client-file=%s", name), + fmt.Sprintf("--dns=%s", "localhost,dns.entry"), + fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), + } + + svr.SetArgs(addSpiffeArg("/some/path", args)) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + urls := URLSlice(bundle.Cert.URIs) + + assert.Contains(t, bundle.Cert.DNSNames, "dns.entry") + assert.Contains(t, bundle.Cert.DNSNames, "localhost") + ips := ipsAsStrings(bundle.Cert.IPAddresses) + assert.Contains(t, ips, "127.0.0.1") + assert.Contains(t, ips, "::1") + assert.Contains(t, urls.Hosts(), rootCaWithSpiffeIdName) + assert.Contains(t, urls.Paths(), "/some/path") +} + +func TestClientCertNoSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateClient(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithoutSpiffeIdName), + fmt.Sprintf("--client-name=%s", name), + fmt.Sprintf("--client-file=%s", name), + } + + sid := "spiffe://not-from-ca/the-path" + svr.SetArgs(addSpiffeArg(sid, args)) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), sid) +} + +func TestClientCertSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateClient(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithSpiffeIdName), + fmt.Sprintf("--client-name=%s", name), + fmt.Sprintf("--client-file=%s", name), + } + + sid := "spiffe://from-ca/the-path" + svr.SetArgs(addSpiffeArg(sid, args)) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), sid) +} diff --git a/ziti/cmd/pki/pki_create_intermediate_test.go b/ziti/cmd/pki/pki_create_intermediate_test.go new file mode 100644 index 000000000..37fb07ca1 --- /dev/null +++ b/ziti/cmd/pki/pki_create_intermediate_test.go @@ -0,0 +1,35 @@ +package pki + +import ( + "fmt" + "github.com/google/uuid" + "github.com/sirupsen/logrus" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSpiffedSetFromCa(t *testing.T) { + out, errOut := streams() + intermediateCmd := NewCmdPKICreateIntermediate(out, errOut) + name := uuid.New().String() + intermediateArgs := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", rootCaWithSpiffeIdName), + fmt.Sprintf("--intermediate-name=%s", name), + fmt.Sprintf("--intermediate-file=%s", name), + "--max-path-len=1", + } + + intermediateCmd.SetArgs(intermediateArgs) + pkiErr := intermediateCmd.Execute() + if pkiErr != nil { + logrus.Fatal(pkiErr) + } + + bundle, e := testPki.GetCA(name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), "spiffe://"+rootCaWithSpiffeIdName) +} diff --git a/ziti/cmd/pki/pki_create_server.go b/ziti/cmd/pki/pki_create_server.go index 9530da676..014d15f1c 100644 --- a/ziti/cmd/pki/pki_create_server.go +++ b/ziti/cmd/pki/pki_create_server.go @@ -29,6 +29,7 @@ import ( "github.com/spf13/cobra" "io" "net/url" + "strings" ) // PKICreateServerOptions the options for the create spring command @@ -79,7 +80,7 @@ func (o *PKICreateServerOptions) addPKICreateServerFlags(cmd *cobra.Command) { cmd.Flags().IntVarP(&o.Flags.CAMaxPath, "max-path-len", "", -1, "Intermediate maximum path length") cmd.Flags().IntVarP(&o.Flags.CAPrivateKeySize, "private-key-size", "", 4096, "Size of the RSA private key, ignored if -curve is set") cmd.Flags().StringVarP(&o.Flags.EcCurve, "curve", "", "", "If set an EC private key is generated and -private-key-size is ignored, options: P224, P256, P384, P521") - cmd.Flags().StringVar(&o.Flags.SpiffeID, "spiffe-id", "", "Optionally provide the path portion of a SPIFFE id. The trust domain will be taken from the signing certificate.") + cmd.Flags().StringVar(&o.Flags.SpiffeID, "spiffe-id", "", "The SPIFFE id to use. If not a complete SPIFFE id, this is treated as the SPIFFE id path and the trust domain will be taken from the signing certificate.") cmd.Flags().BoolVar(&o.Flags.AllowOverwrite, "allow-overwrite", false, "Allow overwrite existing certs") } @@ -135,23 +136,36 @@ func (o *PKICreateServerOptions) Run() error { } if o.Flags.SpiffeID != "" { - var trustDomain *url.URL - for _, uri := range signer.Cert.URIs { - if uri.Scheme == "spiffe" { - if trustDomain != nil { - return errors.New("signing cert contained multiple spiffe ids, which is not allowed") + if !strings.HasPrefix(o.Flags.SpiffeID, "spiffe://") { + var trustDomain *url.URL + for _, uri := range signer.Cert.URIs { + if uri.Scheme == "spiffe" { + if trustDomain != nil { + return errors.New("signing cert contained multiple spiffe ids") + } + trustDomain = uri } - trustDomain = uri } - } - if trustDomain == nil { - return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") - } + if trustDomain == nil { + return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") + } - spiffId := *trustDomain - spiffId.Path = o.Flags.SpiffeID - template.URIs = append(template.URIs, &spiffId) + spiffeId := *trustDomain + sid, serr := url.Parse(o.Flags.SpiffeID) + if serr != nil { + return serr + } + spiffeId.Path = sid.Path + template.URIs = append(template.URIs, &spiffeId) + } else { + // just use whatever spiffe id was provided + sid, serr := url.Parse(o.Flags.SpiffeID) + if serr != nil { + return serr + } + template.URIs = append(template.URIs, sid) + } } privateKeyOptions, err := o.ObtainPrivateKeyOptions() diff --git a/ziti/cmd/pki/pki_create_server_test.go b/ziti/cmd/pki/pki_create_server_test.go new file mode 100644 index 000000000..4ab5d110e --- /dev/null +++ b/ziti/cmd/pki/pki_create_server_test.go @@ -0,0 +1,124 @@ +package pki + +import ( + "fmt" + "github.com/google/uuid" + "github.com/sirupsen/logrus" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestServerCertNoSpiffeIdFromIntermediate(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateServer(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithoutSpiffeIdName), + fmt.Sprintf("--server-name=%s", name), + fmt.Sprintf("--server-file=%s", name), + fmt.Sprintf("--dns=%s", "localhost,dns.entry"), + fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), + } + + svr.SetArgs(args) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, bundle.Cert.DNSNames, "dns.entry") + assert.Contains(t, bundle.Cert.DNSNames, "localhost") + ips := ipsAsStrings(bundle.Cert.IPAddresses) + assert.Contains(t, ips, "127.0.0.1") + assert.Contains(t, ips, "::1") + assert.Nil(t, bundle.Cert.URIs) +} + +func TestServerCertSpiffeIdFromIntermediate(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateServer(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithSpiffeIdName), + fmt.Sprintf("--server-name=%s", name), + fmt.Sprintf("--server-file=%s", name), + fmt.Sprintf("--dns=%s", "localhost,dns.entry"), + fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), + } + + svr.SetArgs(addSpiffeArg("/some/path", args)) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + urls := URLSlice(bundle.Cert.URIs) + + assert.Contains(t, bundle.Cert.DNSNames, "dns.entry") + assert.Contains(t, bundle.Cert.DNSNames, "localhost") + ips := ipsAsStrings(bundle.Cert.IPAddresses) + assert.Contains(t, ips, "127.0.0.1") + assert.Contains(t, ips, "::1") + assert.Contains(t, urls.Hosts(), rootCaWithSpiffeIdName) + assert.Contains(t, urls.Paths(), "/some/path") +} + +func TestServerCertNoSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateServer(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithoutSpiffeIdName), + fmt.Sprintf("--server-name=%s", name), + fmt.Sprintf("--server-file=%s", name), + } + + sid := "spiffe://not-from-ca/the-path" + svr.SetArgs(addSpiffeArg(sid, args)) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), sid) +} + +func TestServerCertSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { + out, errOut := streams() + svr := NewCmdPKICreateServer(out, errOut) + name := uuid.New().String() + args := []string{ + fmt.Sprintf("--pki-root=%s", where), + fmt.Sprintf("--ca-name=%s", intCaNameWithSpiffeIdName), + fmt.Sprintf("--server-name=%s", name), + fmt.Sprintf("--server-file=%s", name), + } + + sid := "spiffe://from-ca/the-path" + svr.SetArgs(addSpiffeArg(sid, args)) + svrErr := svr.Execute() + if svrErr != nil { + logrus.Fatal(svrErr) + } + + bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) + assert.NotNil(t, bundle) + assert.Nil(t, e) + + assert.Contains(t, urisAsStrings(bundle.Cert.URIs), sid) +} diff --git a/ziti/cmd/verify/ops_verify_traffic.go b/ziti/cmd/verify/ops_verify_traffic.go index f1602cee2..b22fd4f4d 100644 --- a/ziti/cmd/verify/ops_verify_traffic.go +++ b/ziti/cmd/verify/ops_verify_traffic.go @@ -1,17 +1,17 @@ /* - Copyright NetFoundry Inc. +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 +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 +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. +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 verify @@ -41,7 +41,6 @@ import ( "github.com/openziti/ziti/internal/rest/mgmt" ) - type traffic struct { loginOpts edge.LoginOptions prefix string @@ -56,6 +55,7 @@ type traffic struct { clientIdName string bindSPName string dialSPName string + haEnabled bool } func NewVerifyTraffic(out io.Writer, errOut io.Writer) *cobra.Command { @@ -72,7 +72,7 @@ func NewVerifyTraffic(out io.Writer, errOut io.Writer) *cobra.Command { pfxlog.GlobalInit(logLvl, pfxlog.DefaultOptions().Color()) configureLogFormat(logLvl) - + timePrefix := time.Now().Format("2006-01-02-1504") if t.prefix == "" { if t.mode != "both" { @@ -131,7 +131,9 @@ func NewVerifyTraffic(out io.Writer, errOut io.Writer) *cobra.Command { cmd.Flags().StringVarP(&t.mode, "mode", "m", "", "[optional, default 'both'] The mode to perform: server, client, both.") cmd.Flags().BoolVar(&t.cleanup, "cleanup", false, "Whether to perform cleanup.") cmd.Flags().BoolVar(&t.allowMultipleServers, "allow-multiple-servers", false, "Whether to allows the same server multiple times.") - + cmd.Flags().BoolVar(&t.haEnabled, "ha", false, "Enable high availability mode.") + _ = cmd.Flags().MarkHidden("ha") + edge.AddLoginFlags(cmd, &t.loginOpts) t.loginOpts.Out = out t.loginOpts.Err = errOut @@ -139,11 +141,13 @@ func NewVerifyTraffic(out io.Writer, errOut io.Writer) *cobra.Command { return cmd } -func startServer(ctx context.Context, serviceName string, zitiCfg *ziti.Config) error { +func (t *traffic) startServer(ctx context.Context, serviceName string, zitiCfg *ziti.Config) error { + zitiCfg.EnableHa = t.haEnabled c, err := ziti.NewContext(zitiCfg) if err != nil { log.Fatal(err) } + listener, err := c.Listen(serviceName) if err != nil { log.Fatal(err) @@ -200,8 +204,9 @@ func handleConnection(conn net.Conn) { log.Debugf("responding with : %s", strings.TrimSpace(resp)) } -func startClient(client *rest_management_api_client.ZitiEdgeManagement, serviceName string, zitiCfg *ziti.Config) error { +func (t *traffic) startClient(client *rest_management_api_client.ZitiEdgeManagement, serviceName string, zitiCfg *ziti.Config) error { waitForTerminator(client, serviceName, 10*time.Second) + zitiCfg.EnableHa = t.haEnabled c, err := ziti.NewContext(zitiCfg) if err != nil { log.Fatal(err) @@ -279,8 +284,8 @@ func createIdentity(client *rest_management_api_client.ZitiEdgeManagement, name Enrollment: &rest_model.IdentityCreateEnrollment{ Ott: true, }, - IsAdmin: &falseVar, - Name: &name, + IsAdmin: &falseVar, + Name: &name, RoleAttributes: &roleAttributes, Type: &usrType, } @@ -395,7 +400,7 @@ func enrollIdentity(client *rest_management_api_client.ZitiEdgeManagement, id st // Get the identity object params := &identity.DetailIdentityParams{ Context: context.Background(), - ID: id, + ID: id, } params.SetTimeout(5 * time.Second) resp, err := client.Identity.DetailIdentity(params, nil) @@ -513,7 +518,7 @@ func (t *traffic) doServer(ctx context.Context, configureServices bool) { } serverCfg := t.configureServer() defer t.cleanupServer() - if err := startServer(ctx, t.svcName, serverCfg); err != nil { + if err := t.startServer(ctx, t.svcName, serverCfg); err != nil { log.Fatalf("unexpected error: %v", err) } } @@ -521,7 +526,7 @@ func (t *traffic) doServer(ctx context.Context, configureServices bool) { func (t *traffic) doClient(cancel context.CancelFunc) { clientCfg := t.configureClient() defer t.cleanupClient() - if err := startClient(t.client, t.svcName, clientCfg); err != nil { + if err := t.startClient(t.client, t.svcName, clientCfg); err != nil { log.Fatal(err) } @@ -529,4 +534,4 @@ func (t *traffic) doClient(cancel context.CancelFunc) { cancel() //end the server time.Sleep(1 * time.Second) log.Info("client complete") -} \ No newline at end of file +} From f653365e9366ad630c932a0ec528ec96af00dfc1 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:21:40 -0500 Subject: [PATCH 02/20] remove unused stuff --- ziti/cmd/edge/quickstart.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index 3a3bccc69..d4e4c77fe 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -23,7 +23,6 @@ import ( "io" "net" "net/http" - "net/url" "os" "os/signal" "os/user" @@ -73,7 +72,6 @@ type QuickstartOpts struct { verbose bool nonVoter bool routerless bool - ha bool } func addCommonQuickstartFlags(cmd *cobra.Command, options *QuickstartOpts) { @@ -665,27 +663,6 @@ func (o *QuickstartOpts) instHome() string { return path.Join(o.Home, o.InstanceID) } -var configuredTrustDomain = fmt.Sprintf("spiffe://%s", uuid.New().String()) - -func (o *QuickstartOpts) trustDomaina() string { - if strings.TrimSpace(o.TrustDomain) != "" { - spiffeId, err := url.Parse(o.TrustDomain) - if spiffeId == nil || err != nil { - logrus.Fatal("spiffe id is invalid: " + o.TrustDomain) - return "" // placate the foolish warning checker that doesn't realize Fatal is 'fatal' - } - if spiffeId.Scheme != "" && spiffeId.Scheme != "spiffe" { - logrus.Fatal("spiffe id scheme is invalid: " + spiffeId.Scheme) - } - configuredTrustDomain = fmt.Sprintf("spiffe://%s", spiffeId.Hostname()) - configuredTrustDomain = strings.TrimSuffix(configuredTrustDomain, "/") - } else { - logrus.Fatal("trust domain is invalid: " + o.TrustDomain) - } - - return configuredTrustDomain -} - func (o *QuickstartOpts) configureOverlay() { if o.joinCommand { return From c812a3ac8f2c239916304b555670a9eef3712de9 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:54:22 -0500 Subject: [PATCH 03/20] better warning --- ziti/cmd/edge/quickstart.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index d4e4c77fe..cbe07bbf8 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -542,9 +542,11 @@ func (o *QuickstartOpts) createMinimalPki() { // indicates we are joining a cluster. don't emit a root-ca, expect it'll be there or error } else { rootCaPath := path.Join(where, "root-ca", "certs", "root-ca.cert") - rootCa, statErr := os.Stat(rootCaPath) //pki/root-ca/certs/root-ca.cert + rootCa, statErr := os.Stat(rootCaPath) if statErr != nil { - logrus.Warnf("cold not check for root-ca? %v", statErr) + if !os.IsNotExist(statErr) { + logrus.Warnf("could not check for root-ca: %v", statErr) + } } if rootCa == nil { ca := pki.NewCmdPKICreateCA(o.out, o.errOut) From c9163ed50c56eda42dac2d027e0e3390710e380d Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:35:00 -0500 Subject: [PATCH 04/20] more refinements after more testing --- .../create/config_templates/controller.yml | 2 +- ziti/cmd/create/create_config.go | 1 + ziti/cmd/edge/quickstart.go | 35 +++++++++++++------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ziti/cmd/create/config_templates/controller.yml b/ziti/cmd/create/config_templates/controller.yml index 80fdd3a56..e71470788 100644 --- a/ziti/cmd/create/config_templates/controller.yml +++ b/ziti/cmd/create/config_templates/controller.yml @@ -10,7 +10,7 @@ v: 3 {{ if .Controller.Ctrl.MinClusterSize }} raft: - dataDir: "{{ .ZitiHome }}/raft{{ .InstanceId }}" + dataDir: "{{ .ZitiHome }}/raft" minClusterSize: {{ .Controller.Ctrl.MinClusterSize }} {{ else }} db: "{{ .Controller.Database.DatabaseFile }}" diff --git a/ziti/cmd/create/create_config.go b/ziti/cmd/create/create_config.go index 950dbd7fa..4536beca9 100644 --- a/ziti/cmd/create/create_config.go +++ b/ziti/cmd/create/create_config.go @@ -72,6 +72,7 @@ type CtrlValues struct { BindAddress string AltAdvertisedAddress string MinClusterSize int + InstanceId string } type HealthChecksValues struct { diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index cbe07bbf8..b324204b8 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -111,6 +111,8 @@ func NewQuickStartCmd(out io.Writer, errOut io.Writer, context context.Context) Run: func(cmd *cobra.Command, args []string) { options.out = out options.errOut = errOut + options.TrustDomain = "quickstart" + options.InstanceID = "quickstart" options.run(context) }, } @@ -138,6 +140,7 @@ func NewQuickStartHaCmd(out io.Writer, errOut io.Writer, context context.Context cmd.Hidden = true return cmd } + func NewQuickStartJoinClusterCmd(out io.Writer, errOut io.Writer, context context.Context) *cobra.Command { options := &QuickstartOpts{} cmd := &cobra.Command{ @@ -153,7 +156,7 @@ func NewQuickStartJoinClusterCmd(out io.Writer, errOut io.Writer, context contex addCommonQuickstartFlags(cmd, options) addQuickstartHaFlags(cmd, options) cmd.Flags().IntVarP(&options.MemberPID, "member-pid", "m", 0, "the pid of a cluster member. required") - cmd.Flags().BoolVar(&options.nonVoter, "non-voting", true, "used with ha mode. specifies the member is a non-voting member") + cmd.Flags().BoolVar(&options.nonVoter, "non-voting", false, "used with ha mode. specifies the member is a non-voting member") cmd.Hidden = true return cmd } @@ -404,24 +407,23 @@ func (o *QuickstartOpts) run(ctx context.Context) { time.Sleep(3 * time.Second) // output this after a bit... nextInstId := incrementStringSuffix(o.InstanceID) fmt.Println() - fmt.Println("=======================================================================================") - fmt.Println("controller and router started.") - fmt.Println(" controller located at : " + helpers.GetCtrlAdvertisedAddress() + ":" + strconv.Itoa(int(o.ControllerPort))) - fmt.Println(" router located at : " + helpers.GetRouterAdvertisedAddress() + ":" + strconv.Itoa(int(o.RouterPort))) - fmt.Println(" config dir located at : " + o.Home) - fmt.Println(" configured trust domain: " + o.TrustDomain) - fmt.Printf(" instance pid : %d\n", os.Getpid()) + o.printDetails() fmt.Println("=======================================================================================") fmt.Println("Quickly add another member to this cluster using: ") fmt.Printf(" ziti edge quickstart join \\\n") fmt.Printf(" --ctrl-port %d \\\n", o.ControllerPort+1) fmt.Printf(" --router-port %d \\\n", o.RouterPort+1) fmt.Printf(" --home \"%s\" \\\n", o.Home) + fmt.Printf(" --trust-domain=\"%s\" \\\n", o.TrustDomain) fmt.Printf(" --member-pid %d\\ \n", os.Getpid()) fmt.Printf(" --instance-id \"%s\"\n", nextInstId) fmt.Println("=======================================================================================") fmt.Println() }() + } else { + fmt.Println() + o.printDetails() + fmt.Println("=======================================================================================") } select { @@ -433,6 +435,16 @@ func (o *QuickstartOpts) run(ctx context.Context) { o.cleanupHome() } +func (o *QuickstartOpts) printDetails() { + fmt.Println("=======================================================================================") + fmt.Println("controller and router started.") + fmt.Println(" controller located at : " + helpers.GetCtrlAdvertisedAddress() + ":" + strconv.Itoa(int(o.ControllerPort))) + fmt.Println(" router located at : " + helpers.GetRouterAdvertisedAddress() + ":" + strconv.Itoa(int(o.RouterPort))) + fmt.Println(" config dir located at : " + o.Home) + fmt.Println(" configured trust domain: " + o.TrustDomain) + fmt.Printf(" instance pid : %d\n", os.Getpid()) +} + func (o *QuickstartOpts) configureRouter(routerName string, configFile string, ctrlUrl string) { if o.routerless { return @@ -534,7 +546,6 @@ func (o *QuickstartOpts) createMinimalPki() { where := path.Join(o.Home, "pki") fmt.Println("emitting a minimal PKI") - intermediateId := fmt.Sprintf("spiffe://%s/intermediate/%s", o.TrustDomain, o.InstanceID) sid := fmt.Sprintf("spiffe://%s/controller/%s", o.TrustDomain, o.InstanceID) //ziti pki create ca --pki-root="$pkiDir" --ca-file="root-ca" --ca-name="root-ca" --spiffe-id="whatever" @@ -575,7 +586,6 @@ func (o *QuickstartOpts) createMinimalPki() { fmt.Sprintf("--ca-name=%s", "root-ca"), fmt.Sprintf("--intermediate-name=%s", o.scopedName("intermediate-ca")), fmt.Sprintf("--intermediate-file=%s", o.scopedName("intermediate-ca")), - fmt.Sprintf("--spiffe-id=%s", intermediateId), "--max-path-len=1", }) intErr := intermediate.Execute() @@ -662,7 +672,10 @@ func (o *QuickstartOpts) scopedName(name string) string { } func (o *QuickstartOpts) instHome() string { - return path.Join(o.Home, o.InstanceID) + if o.isHA { + return path.Join(o.Home, o.InstanceID) + } + return o.Home } func (o *QuickstartOpts) configureOverlay() { From 7d15ad228d7e348bef8b5f42249f28c14e0d8894 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:56:04 -0500 Subject: [PATCH 05/20] fix tests --- ziti/cmd/pki/pki_create_client.go | 42 +++++++++++++++----------- ziti/cmd/pki/pki_create_client_test.go | 15 --------- ziti/cmd/pki/pki_create_server.go | 18 +++++------ 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/ziti/cmd/pki/pki_create_client.go b/ziti/cmd/pki/pki_create_client.go index 86457fe6c..67d76a25a 100644 --- a/ziti/cmd/pki/pki_create_client.go +++ b/ziti/cmd/pki/pki_create_client.go @@ -29,6 +29,7 @@ import ( "github.com/spf13/cobra" "io" "net/url" + "strings" ) // PKICreateClientOptions the options for the create spring command @@ -128,27 +129,34 @@ func (o *PKICreateClientOptions) Run() error { } if o.Flags.SpiffeID != "" { - var trustDomain *url.URL - for _, uri := range signer.Cert.URIs { - if uri.Scheme == "spiffe" { - if trustDomain != nil { - return errors.New("signing cert contained multiple spiffe ids") + if !strings.HasPrefix(o.Flags.SpiffeID, "spiffe://") { + var trustDomain *url.URL + for _, uri := range signer.Cert.URIs { + if uri.Scheme == "spiffe" { + if trustDomain != nil { + return errors.New("signing cert contained multiple spiffe ids") + } + trustDomain = uri } - trustDomain = uri } - } - - if trustDomain == nil { - return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") - } - spiffeId := *trustDomain - sid, serr := url.Parse(o.Flags.SpiffeID) - if serr != nil { - return serr + if trustDomain != nil { + spiffeId := *trustDomain + sid, serr := url.Parse(o.Flags.SpiffeID) + if serr != nil { + return serr + } + spiffeId.Path = sid.Path + template.URIs = append(template.URIs, &spiffeId) + } + } else { + // just use whatever spiffe id was provided + sid, serr := url.Parse(o.Flags.SpiffeID) + if serr != nil { + return serr + } + template.URIs = append(template.URIs, sid) } - spiffeId.Path = sid.Path - template.URIs = append(template.URIs, &spiffeId) } privateKeyOptions, err := o.ObtainPrivateKeyOptions() diff --git a/ziti/cmd/pki/pki_create_client_test.go b/ziti/cmd/pki/pki_create_client_test.go index 8f5cad345..bf107e274 100644 --- a/ziti/cmd/pki/pki_create_client_test.go +++ b/ziti/cmd/pki/pki_create_client_test.go @@ -18,8 +18,6 @@ func TestClientCertNoSpiffeIdFromIntermediate(t *testing.T) { fmt.Sprintf("--ca-name=%s", intCaNameWithoutSpiffeIdName), fmt.Sprintf("--client-name=%s", name), fmt.Sprintf("--client-file=%s", name), - fmt.Sprintf("--dns=%s", "localhost,dns.entry"), - fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), } svr.SetArgs(args) @@ -32,11 +30,6 @@ func TestClientCertNoSpiffeIdFromIntermediate(t *testing.T) { assert.NotNil(t, bundle) assert.Nil(t, e) - assert.Contains(t, bundle.Cert.DNSNames, "dns.entry") - assert.Contains(t, bundle.Cert.DNSNames, "localhost") - ips := ipsAsStrings(bundle.Cert.IPAddresses) - assert.Contains(t, ips, "127.0.0.1") - assert.Contains(t, ips, "::1") assert.Nil(t, bundle.Cert.URIs) } @@ -49,8 +42,6 @@ func TestClientCertSpiffeIdFromIntermediate(t *testing.T) { fmt.Sprintf("--ca-name=%s", intCaNameWithSpiffeIdName), fmt.Sprintf("--client-name=%s", name), fmt.Sprintf("--client-file=%s", name), - fmt.Sprintf("--dns=%s", "localhost,dns.entry"), - fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), } svr.SetArgs(addSpiffeArg("/some/path", args)) @@ -63,12 +54,6 @@ func TestClientCertSpiffeIdFromIntermediate(t *testing.T) { assert.NotNil(t, bundle) assert.Nil(t, e) urls := URLSlice(bundle.Cert.URIs) - - assert.Contains(t, bundle.Cert.DNSNames, "dns.entry") - assert.Contains(t, bundle.Cert.DNSNames, "localhost") - ips := ipsAsStrings(bundle.Cert.IPAddresses) - assert.Contains(t, ips, "127.0.0.1") - assert.Contains(t, ips, "::1") assert.Contains(t, urls.Hosts(), rootCaWithSpiffeIdName) assert.Contains(t, urls.Paths(), "/some/path") } diff --git a/ziti/cmd/pki/pki_create_server.go b/ziti/cmd/pki/pki_create_server.go index 014d15f1c..d8ea38fff 100644 --- a/ziti/cmd/pki/pki_create_server.go +++ b/ziti/cmd/pki/pki_create_server.go @@ -147,17 +147,15 @@ func (o *PKICreateServerOptions) Run() error { } } - if trustDomain == nil { - return errors.New("signing cert doesn't have a spiffe id. unknown trust domain") - } - - spiffeId := *trustDomain - sid, serr := url.Parse(o.Flags.SpiffeID) - if serr != nil { - return serr + if trustDomain != nil { + spiffeId := *trustDomain + sid, serr := url.Parse(o.Flags.SpiffeID) + if serr != nil { + return serr + } + spiffeId.Path = sid.Path + template.URIs = append(template.URIs, &spiffeId) } - spiffeId.Path = sid.Path - template.URIs = append(template.URIs, &spiffeId) } else { // just use whatever spiffe id was provided sid, serr := url.Parse(o.Flags.SpiffeID) From f9870c7febebf3512c951997bc6e8fd733baf672 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:45:27 -0500 Subject: [PATCH 06/20] fix server test --- ziti/cmd/pki/pki_create_server_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ziti/cmd/pki/pki_create_server_test.go b/ziti/cmd/pki/pki_create_server_test.go index 4ab5d110e..013133df0 100644 --- a/ziti/cmd/pki/pki_create_server_test.go +++ b/ziti/cmd/pki/pki_create_server_test.go @@ -82,6 +82,8 @@ func TestServerCertNoSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { fmt.Sprintf("--ca-name=%s", intCaNameWithoutSpiffeIdName), fmt.Sprintf("--server-name=%s", name), fmt.Sprintf("--server-file=%s", name), + fmt.Sprintf("--dns=%s", "localhost,dns.entry"), + fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), } sid := "spiffe://not-from-ca/the-path" @@ -107,6 +109,8 @@ func TestServerCertSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { fmt.Sprintf("--ca-name=%s", intCaNameWithSpiffeIdName), fmt.Sprintf("--server-name=%s", name), fmt.Sprintf("--server-file=%s", name), + fmt.Sprintf("--dns=%s", "localhost,dns.entry"), + fmt.Sprintf("--ip=%s", "127.0.0.1,::1"), } sid := "spiffe://from-ca/the-path" From f2dd8992189bcedd1ee897d1b76d36cfbceccdb4 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:05:47 -0500 Subject: [PATCH 07/20] missed the copyrights --- .../edge/quickstart_automated_test.go.back | 100 ++++++++++++++++++ ziti/cmd/pki/pki_create_ca_test.go | 15 +++ ziti/cmd/pki/pki_create_client_test.go | 15 +++ ziti/cmd/pki/pki_create_intermediate_test.go | 15 +++ ziti/cmd/pki/pki_create_server_test.go | 15 +++ 5 files changed, 160 insertions(+) create mode 100644 ziti/cmd/edge/quickstart_automated_test.go.back diff --git a/ziti/cmd/edge/quickstart_automated_test.go.back b/ziti/cmd/edge/quickstart_automated_test.go.back new file mode 100644 index 000000000..f13477219 --- /dev/null +++ b/ziti/cmd/edge/quickstart_automated_test.go.back @@ -0,0 +1,100 @@ +//go:build quickstart && automated + +package edge + +import ( + "context" + "fmt" + "github.com/openziti/ziti/ziti/cmd/helpers" + log "github.com/sirupsen/logrus" + "os" + "testing" + "time" +) + +func TestEdgeQuickstartAutomated(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + _ = os.Setenv("ZITI_CTRL_EDGE_ADVERTISED_ADDRESS", "localhost") //force localhost + _ = os.Setenv("ZITI_ROUTER_NAME", "quickstart-router") + cmdComplete := make(chan bool) + qs := NewQuickStartCmd(os.Stdout, os.Stderr, ctx) + go func() { + err := qs.Execute() + if err != nil { + log.Fatal(err) + } + cmdComplete <- true + }() + + ctrlAddy := helpers.GetCtrlEdgeAdvertisedAddress() + ctrlPort := helpers.GetCtrlEdgeAdvertisedPort() + ctrlUrl := fmt.Sprintf("https://%s:%s", ctrlAddy, ctrlPort) + + c := make(chan struct{}) + go waitForController(ctrlUrl, c) + timeout, _ := time.ParseDuration("60s") + select { + case <-c: + //completed normally + log.Info("controller online") + case <-time.After(timeout): + cancel() + panic("timed out waiting for controller") + } + + performQuickstartTest(t) + + cancel() //terminate the running ctrl/router + + select { //wait for quickstart to cleanup + case <-cmdComplete: + fmt.Println("Operation completed") + } +} + +func TestEdgeQuickstartHA(t *testing.T) { + ctrl1 := startHAController1() + + ctrl1() +} + +func startHAController1() context.CancelFunc { + ctx, cancel := context.WithCancel(context.Background()) + _ = os.Setenv("ZITI_CTRL_EDGE_ADVERTISED_ADDRESS", "localhost") //force localhost + _ = os.Setenv("ZITI_ROUTER_NAME", "quickstart-router") + cmdComplete := make(chan bool) + qs := NewQuickStartCmd(os.Stdout, os.Stderr, ctx) + args := []string{ + fmt.Sprintf("ha", "--trust-domain", "quickstart-ha-test-trust-domain", "--instance-id", "inst01"), + } + qs.SetArgs(args) + go func() { + err := qs.Execute() + if err != nil { + log.Fatal(err) + } + cmdComplete <- true + }() + + ctrlAddy := helpers.GetCtrlEdgeAdvertisedAddress() + ctrlPort := helpers.GetCtrlEdgeAdvertisedPort() + ctrlUrl := fmt.Sprintf("https://%s:%s", ctrlAddy, ctrlPort) + + c := make(chan struct{}) + go waitForController(ctrlUrl, c) + timeout, _ := time.ParseDuration("60s") + select { + case <-c: + //completed normally + log.Info("controller online") + case <-time.After(timeout): + cancel() + panic("timed out waiting for controller") + } + + return cancel +} + +func joinHaController() { + +} diff --git a/ziti/cmd/pki/pki_create_ca_test.go b/ziti/cmd/pki/pki_create_ca_test.go index 9a29fe012..d6b25fbc3 100644 --- a/ziti/cmd/pki/pki_create_ca_test.go +++ b/ziti/cmd/pki/pki_create_ca_test.go @@ -1,3 +1,18 @@ +/* +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 pki import ( diff --git a/ziti/cmd/pki/pki_create_client_test.go b/ziti/cmd/pki/pki_create_client_test.go index bf107e274..e36ef6e28 100644 --- a/ziti/cmd/pki/pki_create_client_test.go +++ b/ziti/cmd/pki/pki_create_client_test.go @@ -1,3 +1,18 @@ +/* +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 pki import ( diff --git a/ziti/cmd/pki/pki_create_intermediate_test.go b/ziti/cmd/pki/pki_create_intermediate_test.go index 37fb07ca1..87e97aea7 100644 --- a/ziti/cmd/pki/pki_create_intermediate_test.go +++ b/ziti/cmd/pki/pki_create_intermediate_test.go @@ -1,3 +1,18 @@ +/* +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 pki import ( diff --git a/ziti/cmd/pki/pki_create_server_test.go b/ziti/cmd/pki/pki_create_server_test.go index 013133df0..2ed430921 100644 --- a/ziti/cmd/pki/pki_create_server_test.go +++ b/ziti/cmd/pki/pki_create_server_test.go @@ -1,3 +1,18 @@ +/* +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 pki import ( From 77b8a6eca93b0d2c245d34ce15b04d249dd83f7a Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:08:39 -0500 Subject: [PATCH 08/20] remove unused file, sigh --- .../edge/quickstart_automated_test.go.back | 100 ------------------ 1 file changed, 100 deletions(-) delete mode 100644 ziti/cmd/edge/quickstart_automated_test.go.back diff --git a/ziti/cmd/edge/quickstart_automated_test.go.back b/ziti/cmd/edge/quickstart_automated_test.go.back deleted file mode 100644 index f13477219..000000000 --- a/ziti/cmd/edge/quickstart_automated_test.go.back +++ /dev/null @@ -1,100 +0,0 @@ -//go:build quickstart && automated - -package edge - -import ( - "context" - "fmt" - "github.com/openziti/ziti/ziti/cmd/helpers" - log "github.com/sirupsen/logrus" - "os" - "testing" - "time" -) - -func TestEdgeQuickstartAutomated(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - _ = os.Setenv("ZITI_CTRL_EDGE_ADVERTISED_ADDRESS", "localhost") //force localhost - _ = os.Setenv("ZITI_ROUTER_NAME", "quickstart-router") - cmdComplete := make(chan bool) - qs := NewQuickStartCmd(os.Stdout, os.Stderr, ctx) - go func() { - err := qs.Execute() - if err != nil { - log.Fatal(err) - } - cmdComplete <- true - }() - - ctrlAddy := helpers.GetCtrlEdgeAdvertisedAddress() - ctrlPort := helpers.GetCtrlEdgeAdvertisedPort() - ctrlUrl := fmt.Sprintf("https://%s:%s", ctrlAddy, ctrlPort) - - c := make(chan struct{}) - go waitForController(ctrlUrl, c) - timeout, _ := time.ParseDuration("60s") - select { - case <-c: - //completed normally - log.Info("controller online") - case <-time.After(timeout): - cancel() - panic("timed out waiting for controller") - } - - performQuickstartTest(t) - - cancel() //terminate the running ctrl/router - - select { //wait for quickstart to cleanup - case <-cmdComplete: - fmt.Println("Operation completed") - } -} - -func TestEdgeQuickstartHA(t *testing.T) { - ctrl1 := startHAController1() - - ctrl1() -} - -func startHAController1() context.CancelFunc { - ctx, cancel := context.WithCancel(context.Background()) - _ = os.Setenv("ZITI_CTRL_EDGE_ADVERTISED_ADDRESS", "localhost") //force localhost - _ = os.Setenv("ZITI_ROUTER_NAME", "quickstart-router") - cmdComplete := make(chan bool) - qs := NewQuickStartCmd(os.Stdout, os.Stderr, ctx) - args := []string{ - fmt.Sprintf("ha", "--trust-domain", "quickstart-ha-test-trust-domain", "--instance-id", "inst01"), - } - qs.SetArgs(args) - go func() { - err := qs.Execute() - if err != nil { - log.Fatal(err) - } - cmdComplete <- true - }() - - ctrlAddy := helpers.GetCtrlEdgeAdvertisedAddress() - ctrlPort := helpers.GetCtrlEdgeAdvertisedPort() - ctrlUrl := fmt.Sprintf("https://%s:%s", ctrlAddy, ctrlPort) - - c := make(chan struct{}) - go waitForController(ctrlUrl, c) - timeout, _ := time.ParseDuration("60s") - select { - case <-c: - //completed normally - log.Info("controller online") - case <-time.After(timeout): - cancel() - panic("timed out waiting for controller") - } - - return cancel -} - -func joinHaController() { - -} From 3ae78575584179f48ac8ed9e0013237f2729ac9d Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:09:45 -0500 Subject: [PATCH 09/20] missed copyright here too --- ziti/cmd/pki/common_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ziti/cmd/pki/common_test.go b/ziti/cmd/pki/common_test.go index c3a81a378..6c6207e7b 100644 --- a/ziti/cmd/pki/common_test.go +++ b/ziti/cmd/pki/common_test.go @@ -1,3 +1,18 @@ +/* +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 pki import ( From 28c221e189193727f575fa611b065ceed99cd9c3 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:12:21 -0500 Subject: [PATCH 10/20] use t.Fatal --- ziti/cmd/pki/pki_create_ca_test.go | 9 ++++----- ziti/cmd/pki/pki_create_client_test.go | 9 ++++----- ziti/cmd/pki/pki_create_intermediate_test.go | 3 +-- ziti/cmd/pki/pki_create_server_test.go | 9 ++++----- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/ziti/cmd/pki/pki_create_ca_test.go b/ziti/cmd/pki/pki_create_ca_test.go index d6b25fbc3..01cfb4667 100644 --- a/ziti/cmd/pki/pki_create_ca_test.go +++ b/ziti/cmd/pki/pki_create_ca_test.go @@ -18,7 +18,6 @@ package pki import ( "fmt" "github.com/google/uuid" - "github.com/sirupsen/logrus" "testing" "github.com/stretchr/testify/assert" @@ -38,7 +37,7 @@ func TestTrustDomain(t *testing.T) { ca.SetArgs(rootCaArgs) pkiErr := ca.Execute() if pkiErr != nil { - logrus.Fatal(pkiErr) + t.Fatal(pkiErr) } bundle, e := testPki.GetCA(name) @@ -61,7 +60,7 @@ func TestNoTrustDomain(t *testing.T) { ca.SetArgs(rootCaArgs) pkiErr := ca.Execute() if pkiErr != nil { - logrus.Fatal(pkiErr) + t.Fatal(pkiErr) } bundle, e := testPki.GetCA(name) @@ -85,7 +84,7 @@ func TestTrustDomainSpiffeAppended(t *testing.T) { ca.SetArgs(rootCaArgs) pkiErr := ca.Execute() if pkiErr != nil { - logrus.Fatal(pkiErr) + t.Fatal(pkiErr) } bundle, e := testPki.GetCA(name) @@ -109,7 +108,7 @@ func TestTrustDomainWithPath(t *testing.T) { ca.SetArgs(rootCaArgs) pkiErr := ca.Execute() if pkiErr != nil { - logrus.Fatal(pkiErr) + t.Fatal(pkiErr) } bundle, e := testPki.GetCA(name) diff --git a/ziti/cmd/pki/pki_create_client_test.go b/ziti/cmd/pki/pki_create_client_test.go index e36ef6e28..6e73f02da 100644 --- a/ziti/cmd/pki/pki_create_client_test.go +++ b/ziti/cmd/pki/pki_create_client_test.go @@ -18,7 +18,6 @@ package pki import ( "fmt" "github.com/google/uuid" - "github.com/sirupsen/logrus" "testing" "github.com/stretchr/testify/assert" @@ -38,7 +37,7 @@ func TestClientCertNoSpiffeIdFromIntermediate(t *testing.T) { svr.SetArgs(args) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) @@ -62,7 +61,7 @@ func TestClientCertSpiffeIdFromIntermediate(t *testing.T) { svr.SetArgs(addSpiffeArg("/some/path", args)) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) @@ -88,7 +87,7 @@ func TestClientCertNoSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { svr.SetArgs(addSpiffeArg(sid, args)) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) @@ -113,7 +112,7 @@ func TestClientCertSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { svr.SetArgs(addSpiffeArg(sid, args)) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) diff --git a/ziti/cmd/pki/pki_create_intermediate_test.go b/ziti/cmd/pki/pki_create_intermediate_test.go index 87e97aea7..a20a106fd 100644 --- a/ziti/cmd/pki/pki_create_intermediate_test.go +++ b/ziti/cmd/pki/pki_create_intermediate_test.go @@ -18,7 +18,6 @@ package pki import ( "fmt" "github.com/google/uuid" - "github.com/sirupsen/logrus" "testing" "github.com/stretchr/testify/assert" @@ -39,7 +38,7 @@ func TestSpiffedSetFromCa(t *testing.T) { intermediateCmd.SetArgs(intermediateArgs) pkiErr := intermediateCmd.Execute() if pkiErr != nil { - logrus.Fatal(pkiErr) + t.Fatal(pkiErr) } bundle, e := testPki.GetCA(name) diff --git a/ziti/cmd/pki/pki_create_server_test.go b/ziti/cmd/pki/pki_create_server_test.go index 2ed430921..4793b534b 100644 --- a/ziti/cmd/pki/pki_create_server_test.go +++ b/ziti/cmd/pki/pki_create_server_test.go @@ -18,7 +18,6 @@ package pki import ( "fmt" "github.com/google/uuid" - "github.com/sirupsen/logrus" "testing" "github.com/stretchr/testify/assert" @@ -40,7 +39,7 @@ func TestServerCertNoSpiffeIdFromIntermediate(t *testing.T) { svr.SetArgs(args) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) @@ -71,7 +70,7 @@ func TestServerCertSpiffeIdFromIntermediate(t *testing.T) { svr.SetArgs(addSpiffeArg("/some/path", args)) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) @@ -105,7 +104,7 @@ func TestServerCertNoSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { svr.SetArgs(addSpiffeArg(sid, args)) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithoutSpiffeIdName, name) @@ -132,7 +131,7 @@ func TestServerCertSpiffeIdFromIntermediateAddSpiffeId(t *testing.T) { svr.SetArgs(addSpiffeArg(sid, args)) svrErr := svr.Execute() if svrErr != nil { - logrus.Fatal(svrErr) + t.Fatal(svrErr) } bundle, e := testPki.GetBundle(intCaNameWithSpiffeIdName, name) From 8c600e6ed6eb1f58ff484dcdac7f0f8001bc0c42 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:38:59 -0500 Subject: [PATCH 11/20] add a script to test the ha bringup and fix a small trust-domain issue --- quickstart/test/ha-test.sh | 100 ++++++++++++++++++++++++++++++++++++ ziti/cmd/edge/quickstart.go | 4 ++ 2 files changed, 104 insertions(+) create mode 100755 quickstart/test/ha-test.sh diff --git a/quickstart/test/ha-test.sh b/quickstart/test/ha-test.sh new file mode 100755 index 000000000..66a564e8c --- /dev/null +++ b/quickstart/test/ha-test.sh @@ -0,0 +1,100 @@ +cd ~/git/github/openziti/nf/ziti/quickstart/docker/all-in-one + +export GITHUB_WORKSPACE=$(realpath ../../..) +BUILD_DIR=/tmp/build +mkdir -pv ${BUILD_DIR} + +cd ${GITHUB_WORKSPACE} +go build -o "${BUILD_DIR}" "./..." +cd - + +ctrl_port=2001 +router_port=3001 +rm -rf "/tmp/quickstart-ha-test" +ziti_home="/tmp/quickstart-ha-test" + +function _wait_for_controller { + local advertised_host_port="127.0.0.1:${1}" + local timeout=60 + local elapsed=0 + + while [[ "$(curl -w "%{http_code}" -m 1 -s -k -o /dev/null https://${advertised_host_port}/edge/client/v1/version)" != "200" ]]; do + if (( elapsed >= timeout )); then + echo "Timeout waiting for https://${advertised_host_port}" >&2 + exit 1 + fi + echo "waiting for https://${advertised_host_port}" + sleep 3 + (( elapsed += 3 )) + done + echo "CONTROLLER ONLINE AT: https://${advertised_host_port}" +} + +trap 'kill $inst001pid $inst002pid $inst003pid 2>/dev/null' EXIT + +"${BUILD_DIR}/ziti" edge quickstart ha \ + --home "${ziti_home}" \ + --trust-domain="quickstart-ha-test" \ + --instance-id inst001 \ + --ctrl-port "${ctrl_port}" \ + --router-port "${router_port}" \ + & +inst001pid=$! + +_wait_for_controller "${ctrl_port}" +sleep 5 +echo "controller online" + +"${BUILD_DIR}/ziti" edge quickstart join \ + --home "${ziti_home}" \ + --trust-domain="quickstart-ha-test" \ + --ctrl-port 2002 \ + --router-port 3002 \ + --instance-id "inst002" \ + --member-pid "${inst001pid}" & +inst002pid=$! + +"${BUILD_DIR}/ziti" edge quickstart join \ + --home "${ziti_home}" \ + --trust-domain="quickstart-ha-test" \ + --ctrl-port 2003 \ + --router-port 3003 \ + --instance-id "inst003" \ + --member-pid "${inst001pid}" & +inst003pid=$! + +count=0 +timeout=60 # Timeout in seconds +elapsed=0 + +while [[ $count -lt 3 ]]; do + results=$(ziti fabric list links -j | jq -r '.data[].state') + connected_count=$(echo "$results" | grep -c "Connected") + + if [[ $connected_count -eq 3 ]]; then + echo "All three are connected." + break + else + echo "Waiting for three router links before continuing..." + sleep 3 + ((elapsed+=3)) + + if [[ $elapsed -ge $timeout ]]; then + echo "Timeout reached; not all connections are 'Connected'." + exit 1 + fi + fi +done + +sleep 5 + +echo "killing...." +kill $inst001pid $inst002pid $inst003pid 2>/dev/null + +for pid in $inst001pid $inst002pid $inst003pid; do + while kill -0 "$pid" 2>/dev/null; do + echo "Waiting for process $pid to stop..." + sleep 1 + done + echo "Process $pid has stopped." +done \ No newline at end of file diff --git a/ziti/cmd/edge/quickstart.go b/ziti/cmd/edge/quickstart.go index b324204b8..ef611c973 100644 --- a/ziti/cmd/edge/quickstart.go +++ b/ziti/cmd/edge/quickstart.go @@ -132,6 +132,10 @@ func NewQuickStartHaCmd(out io.Writer, errOut io.Writer, context context.Context options.out = out options.errOut = errOut options.isHA = true + if options.TrustDomain == "" { + options.TrustDomain = uuid.New().String() + fmt.Println("Trust domain was not supplied. Using a random trust domain: " + options.TrustDomain) + } options.run(context) }, } From 12f811285e663eaee75db908ccb1ac41f2171dea Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:48:26 -0500 Subject: [PATCH 12/20] update test some --- quickstart/test/ha-test.sh | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/quickstart/test/ha-test.sh b/quickstart/test/ha-test.sh index 66a564e8c..d471c6a1f 100755 --- a/quickstart/test/ha-test.sh +++ b/quickstart/test/ha-test.sh @@ -68,7 +68,7 @@ timeout=60 # Timeout in seconds elapsed=0 while [[ $count -lt 3 ]]; do - results=$(ziti fabric list links -j | jq -r '.data[].state') + results=$("${BUILD_DIR}/ziti" fabric list links -j | jq -r '.data[].state') connected_count=$(echo "$results" | grep -c "Connected") if [[ $connected_count -eq 3 ]]; then @@ -86,7 +86,32 @@ while [[ $count -lt 3 ]]; do fi done -sleep 5 +# three links == things are ready -- tests start below +output=$("${BUILD_DIR}/ziti" agent cluster list --pid $inst001pid) + +echo "" +echo "$output" +echo "" + +# Extract the columns for LEADER and CONNECTED +leaders=$(echo "$output" | awk '/│ inst/ {print $4}') +connected=$(echo "$output" | awk '/│ inst/ {print $6}') + +# Check there is only one leader +leader_count=$(echo "$leaders" | grep -c "true") +if [[ $leader_count -ne 1 ]]; then + echo "Test failed: Expected 1 leader, found $leader_count" + exit 1 +fi + +# Check all are connected +disconnected_count=$(echo "$connected" | grep -c "false") +if [[ $disconnected_count -ne 0 ]]; then + echo "Test failed: Some instances are not connected" + exit 1 +fi + +echo "Test passed: One leader found and all instances are connected" echo "killing...." kill $inst001pid $inst002pid $inst003pid 2>/dev/null From 8e293db82dba069d967d83b77b9952923bd24671 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 06:53:51 -0500 Subject: [PATCH 13/20] ha quickstart test --- .github/workflows/test-quickstart.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/test-quickstart.yml b/.github/workflows/test-quickstart.yml index f2deeaedf..142213fcf 100644 --- a/.github/workflows/test-quickstart.yml +++ b/.github/workflows/test-quickstart.yml @@ -84,3 +84,19 @@ jobs: ls -lAn ${GOCACHE:-${HOME}/.cache/go-build}/ ${GOPATH:-${HOME}/go}/pkg/mod/ docker compose --profile test logs exit 0 + + haQuickstartTest: + name: Test HA Quickstart + runs-on: ubuntu-latest + steps: + - name: Shallow checkout + uses: actions/checkout@v4 + + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version-file: ./go.mod + + - name: Build and run a three quickstart in HA mode + shell: bash + run: ./quickstart/test/ha-test.zsh \ No newline at end of file From 6d67ff7407eaf97c3660a08be9ef03f33af20388 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 06:54:51 -0500 Subject: [PATCH 14/20] zsh->sh --- .github/workflows/test-quickstart.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-quickstart.yml b/.github/workflows/test-quickstart.yml index 142213fcf..bf6c596f6 100644 --- a/.github/workflows/test-quickstart.yml +++ b/.github/workflows/test-quickstart.yml @@ -99,4 +99,4 @@ jobs: - name: Build and run a three quickstart in HA mode shell: bash - run: ./quickstart/test/ha-test.zsh \ No newline at end of file + run: ./quickstart/test/ha-test.sh \ No newline at end of file From 1943470b70d294321ce8569bdc92e28b34ca3f19 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:02:11 -0500 Subject: [PATCH 15/20] test changes --- .github/workflows/test-quickstart.yml | 6 ++++++ quickstart/test/ha-test.sh | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-quickstart.yml b/.github/workflows/test-quickstart.yml index bf6c596f6..5b7363c7c 100644 --- a/.github/workflows/test-quickstart.yml +++ b/.github/workflows/test-quickstart.yml @@ -97,6 +97,12 @@ jobs: with: go-version-file: ./go.mod + - name: Build ziti executable + shell: bash + run: | + mkdir -pv /tmp/build + go build -o /tmp/build ${GITHUB_WORKSPACE}/... + - name: Build and run a three quickstart in HA mode shell: bash run: ./quickstart/test/ha-test.sh \ No newline at end of file diff --git a/quickstart/test/ha-test.sh b/quickstart/test/ha-test.sh index d471c6a1f..4ba790a49 100755 --- a/quickstart/test/ha-test.sh +++ b/quickstart/test/ha-test.sh @@ -1,12 +1,4 @@ -cd ~/git/github/openziti/nf/ziti/quickstart/docker/all-in-one - -export GITHUB_WORKSPACE=$(realpath ../../..) BUILD_DIR=/tmp/build -mkdir -pv ${BUILD_DIR} - -cd ${GITHUB_WORKSPACE} -go build -o "${BUILD_DIR}" "./..." -cd - ctrl_port=2001 router_port=3001 From 5221424f5353a0f96df909434b9ab224c57994e7 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:14:44 -0500 Subject: [PATCH 16/20] test update --- quickstart/test/ha-test.sh | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/quickstart/test/ha-test.sh b/quickstart/test/ha-test.sh index 4ba790a49..f8334608f 100755 --- a/quickstart/test/ha-test.sh +++ b/quickstart/test/ha-test.sh @@ -22,6 +22,19 @@ function _wait_for_controller { echo "CONTROLLER ONLINE AT: https://${advertised_host_port}" } +function _stop_instances { + echo "killing...." + kill "$@" 2>/dev/null + + for pid in "$@"; do + while kill -0 "$pid" 2>/dev/null; do + echo "Waiting for process $pid to stop..." + sleep 1 + done + echo "Process $pid has stopped." + done +} + trap 'kill $inst001pid $inst002pid $inst003pid 2>/dev/null' EXIT "${BUILD_DIR}/ziti" edge quickstart ha \ @@ -86,13 +99,14 @@ echo "$output" echo "" # Extract the columns for LEADER and CONNECTED -leaders=$(echo "$output" | awk '/│ inst/ {print $4}') -connected=$(echo "$output" | awk '/│ inst/ {print $6}') +leaders=$(echo "$output" | grep inst | awk -F '│' '{print $5}') +connected=$(echo "$output" | grep inst | awk -F '/│' '{print $6}') # Check there is only one leader leader_count=$(echo "$leaders" | grep -c "true") if [[ $leader_count -ne 1 ]]; then echo "Test failed: Expected 1 leader, found $leader_count" + _stop_instances $inst001pid $inst002pid $inst003pid exit 1 fi @@ -100,18 +114,10 @@ fi disconnected_count=$(echo "$connected" | grep -c "false") if [[ $disconnected_count -ne 0 ]]; then echo "Test failed: Some instances are not connected" + _stop_instances $inst001pid $inst002pid $inst003pid exit 1 fi echo "Test passed: One leader found and all instances are connected" +_stop_instances $inst001pid $inst002pid $inst003pid -echo "killing...." -kill $inst001pid $inst002pid $inst003pid 2>/dev/null - -for pid in $inst001pid $inst002pid $inst003pid; do - while kill -0 "$pid" 2>/dev/null; do - echo "Waiting for process $pid to stop..." - sleep 1 - done - echo "Process $pid has stopped." -done \ No newline at end of file From 514e57e0d8d4749102a45c4a2e58ea8597497223 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:35:09 -0500 Subject: [PATCH 17/20] add 1s delay for test --- ziti/cmd/edge/quickstart_shared_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ziti/cmd/edge/quickstart_shared_test.go b/ziti/cmd/edge/quickstart_shared_test.go index d2dbecb6a..be750d6f9 100644 --- a/ziti/cmd/edge/quickstart_shared_test.go +++ b/ziti/cmd/edge/quickstart_shared_test.go @@ -492,6 +492,7 @@ func performQuickstartTest(t *testing.T) { // Create a service that "links" the dial and bind configs createService(client, serviceName, []string{bindSvcConfig.ID, dialSvcConfig.ID}) + time.Sleep(1 * time.Second) //wait one extra second for the controller to be ready // Create a service policy to allow the router to host the web test service fmt.Println("finding hostingRouterName: ", hostingRouterName) hostRouterIdent := getIdentityByName(client, hostingRouterName) From 1c676c53b1949520b2dc28b89e9ad8b81fc90613 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:39:59 -0500 Subject: [PATCH 18/20] add quick retry to find identity instead of blanket sleep --- ziti/cmd/edge/quickstart_shared_test.go | 28 ++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/ziti/cmd/edge/quickstart_shared_test.go b/ziti/cmd/edge/quickstart_shared_test.go index be750d6f9..e9ce76dee 100644 --- a/ziti/cmd/edge/quickstart_shared_test.go +++ b/ziti/cmd/edge/quickstart_shared_test.go @@ -148,13 +148,28 @@ func getIdentityByName(client *rest_management_api_client.ZitiEdgeManagement, na Context: context.Background(), } params.SetTimeout(30 * time.Second) - resp, err := client.Identity.ListIdentities(params, nil) - if err != nil { - log.Fatalf("Could not obtain an ID for the identity named %s", name) - fmt.Println(err) - } - return resp.GetPayload().Data[0] + var resp *identity.ListIdentitiesOK + var err error + + timeout := time.After(3 * time.Second) + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-timeout: + log.Errorf("Could not obtain an ID for the identity named %s after retries", name) + return nil // Return nil if you don't want to panic on failure + case <-ticker.C: + resp, err = client.Identity.ListIdentities(params, nil) + if err == nil && len(resp.GetPayload().Data) > 0 { + return resp.GetPayload().Data[0] + } + // Log and retry + fmt.Printf("Retrying to fetch identity %s...\n", name) + } + } } func getServiceByName(client *rest_management_api_client.ZitiEdgeManagement, name string) *rest_model.ServiceDetail { @@ -492,7 +507,6 @@ func performQuickstartTest(t *testing.T) { // Create a service that "links" the dial and bind configs createService(client, serviceName, []string{bindSvcConfig.ID, dialSvcConfig.ID}) - time.Sleep(1 * time.Second) //wait one extra second for the controller to be ready // Create a service policy to allow the router to host the web test service fmt.Println("finding hostingRouterName: ", hostingRouterName) hostRouterIdent := getIdentityByName(client, hostingRouterName) From c683dacef7ba11a2b63b8cffe3bda06a7037891d Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:45:04 -0500 Subject: [PATCH 19/20] simplify timer --- ziti/cmd/edge/quickstart_shared_test.go | 28 ++++++++++--------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/ziti/cmd/edge/quickstart_shared_test.go b/ziti/cmd/edge/quickstart_shared_test.go index e9ce76dee..47470f76b 100644 --- a/ziti/cmd/edge/quickstart_shared_test.go +++ b/ziti/cmd/edge/quickstart_shared_test.go @@ -149,26 +149,20 @@ func getIdentityByName(client *rest_management_api_client.ZitiEdgeManagement, na } params.SetTimeout(30 * time.Second) - var resp *identity.ListIdentitiesOK - var err error - - timeout := time.After(3 * time.Second) - ticker := time.NewTicker(100 * time.Millisecond) - defer ticker.Stop() + timeout := time.Now().Add(3 * time.Second) for { - select { - case <-timeout: - log.Errorf("Could not obtain an ID for the identity named %s after retries", name) - return nil // Return nil if you don't want to panic on failure - case <-ticker.C: - resp, err = client.Identity.ListIdentities(params, nil) - if err == nil && len(resp.GetPayload().Data) > 0 { - return resp.GetPayload().Data[0] - } - // Log and retry - fmt.Printf("Retrying to fetch identity %s...\n", name) + resp, err := client.Identity.ListIdentities(params, nil) + if err == nil && len(resp.GetPayload().Data) > 0 { + return resp.GetPayload().Data[0] + } + + if time.Now().After(timeout) { + log.Fatalf("Could not obtain an ID for the identity named %s after retries", name) + return nil } + + time.Sleep(100 * time.Millisecond) } } From d4da61141b31148dfda582e41af61025d6a2c034 Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Fri, 15 Nov 2024 07:48:54 -0500 Subject: [PATCH 20/20] add the output back --- ziti/cmd/edge/quickstart_shared_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ziti/cmd/edge/quickstart_shared_test.go b/ziti/cmd/edge/quickstart_shared_test.go index 47470f76b..e73c06b8d 100644 --- a/ziti/cmd/edge/quickstart_shared_test.go +++ b/ziti/cmd/edge/quickstart_shared_test.go @@ -161,7 +161,8 @@ func getIdentityByName(client *rest_management_api_client.ZitiEdgeManagement, na log.Fatalf("Could not obtain an ID for the identity named %s after retries", name) return nil } - + + fmt.Printf("Retrying to fetch identity %s...\n", name) time.Sleep(100 * time.Millisecond) } }