diff --git a/.gitignore b/.gitignore index 6553b562a..dc1950f61 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ db/ *.dll *.so *.dylib +/ziti/cmd/ziti/ziti # Test binary, built with `go test -c` *.test diff --git a/ziti/cmd/ziti/cmd/config_templates/edge.router.yml b/ziti/cmd/ziti/cmd/config_templates/edge.router.yml new file mode 100644 index 000000000..9646a3857 --- /dev/null +++ b/ziti/cmd/ziti/cmd/config_templates/edge.router.yml @@ -0,0 +1,88 @@ +# Config Format Version +# +# Whenever a breaking change is made to the semantics of this configuration file, the configuration version +# expected by the router will be incremented. When the controller tries to load a configuration file with +# an incompatible version, it will abort with a message prompting the operator to seek out the breaking changes +# documentation. +# +v: 3 + +identity: + cert: "{{ .ZitiPKI }}/{{ .ZitiCtrlIntermediateName }}/certs/{{ .EdgeRouterName }}-client.cert" + server_cert: "{{ .ZitiPKI }}/{{ .ZitiCtrlIntermediateName }}/certs/{{ .EdgeRouterName }}-server.cert" + key: "{{ .ZitiPKI }}/{{ .ZitiCtrlIntermediateName }}/keys/{{ .EdgeRouterName }}-server.key" + ca: "{{ .ZitiPKI }}/{{ .ZitiCtrlIntermediateName }}/certs/{{ .EdgeRouterName }}-cas.cert" + +ctrl: + endpoint: tls:{{ .ZitiCtrlHostname }}:{{ .ZitiFabCtrlPort }} + +link: + listeners: + - binding: transport + bind: tls:0.0.0.0:10080 + advertise: tls:{{ .ZitiEdgeRouterHostname }}:10080 + options: + outQueueSize: 16 + dialers: + - binding: transport + +listeners: + - binding: tunnel + options: + mode: host #tproxy|tun|host + - binding: edge + address: {{if .WssEnabled}}ws{{else}}tls{{end}}:0.0.0.0:{{if .WssEnabled}}3023{{else}}{{ .ZitiEdgeRouterPort }}{{end}} + options: + advertise: {{ .ZitiEdgeRouterHostname }}:{{if .WssEnabled}}3023{{else}}{{ .ZitiEdgeRouterPort }}{{end}} + connectTimeoutMs: 5000 + getSessionTimeout: 60s + +edge: + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + sans: + dns: + - {{ .ZitiEdgeRouterHostname }} + - localhost + ip: + - "127.0.0.1" + + {{if .WssEnabled }} +transport: + ws: + writeTimeout: 10 + readTimeout: 5 + idleTimeout: 5 + pongTimeout: 60 + pingInterval: 54 + handshakeTimeout: 10 + readBufferSize: 4096 + writeBufferSize: 4096 + enableCompression: true + server_cert: { { .ZitiPKI } }/{{ .ZitiCtrlIntermediateName }}/certs/{{ .EdgeRouterName }}-router-server.cert + key: { { .ZitiPKI } }/{{ .ZitiCtrlIntermediateName }}/keys/{{ .EdgeRouterName }}-router-server.key + {{else}} +#transport: +# ws: +# writeTimeout: 10 +# readTimeout: 5 +# idleTimeout: 5 +# pongTimeout: 60 +# pingInterval: 54 +# handshakeTimeout: 10 +# readBufferSize: 4096 +# writeBufferSize: 4096 +# enableCompression: true +# server_cert: {{ .ZitiPKI }}/{{ .ZitiCtrlIntermediateName }}/certs/{{ .EdgeRouterName }}-router-server.cert +# key: {{ .ZitiPKI }}/{{ .ZitiCtrlIntermediateName }}/keys/{{ .EdgeRouterName }}-router-server.key + {{end}} +forwarder: + latencyProbeInterval: 1000 + xgressDialQueueLength: 1000 + xgressDialWorkerCount: 128 + linkDialQueueLength: 1000 + linkDialWorkerCount: 10 \ No newline at end of file diff --git a/ziti/cmd/ziti/cmd/create_config.go b/ziti/cmd/ziti/cmd/create_config.go index e6ff710df..4d2389125 100644 --- a/ziti/cmd/ziti/cmd/create_config.go +++ b/ziti/cmd/ziti/cmd/create_config.go @@ -20,12 +20,14 @@ import ( "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "io" + "os" ) const ( - optionVerbose = "Zerbose" + optionVerbose = "verbose" defaultVerbose = false verboseDescription = "Enable verbose logging. Logging will be sent to stdout if the config output is sent to a file. If output is sent to stdout, logging will be sent to stderr" optionOutput = "output" @@ -37,13 +39,35 @@ const ( type CreateConfigOptions struct { common.CommonOptions - Output string - DatabaseFile string + Output string + DatabaseFile string +} + +type ConfigTemplateValues struct { ZitiPKI string - Verbose bool ZitiCtrlIntermediateName string ZitiCtrlHostname string ZitiFabCtrlPort string + + // Controller specific + CtrlListener string + MgmtListener string + ZitiHome string + Hostname string + ZitiFabMgmtPort string + ZitiEdgeCtrlAPI string + ZitiSigningIntermediateName string + ZitiEdgeCtrlPort string + ZitiCtrlRawname string + ZitiEdgeCtrlIntermediateName string + ZitiEdgeCtrlHostname string + + // Router specific + EdgeRouterName string + ZitiEdgeRouterHostname string + ZitiEdgeRouterPort string + ZitiEdgeWSSRouterName string + WssEnabled bool } // NewCmdCreateConfig creates a command object for the "config" command @@ -57,15 +81,104 @@ func NewCmdCreateConfig(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cob }, } - cmd.AddCommand(NewCmdCreateConfigController(f, out, errOut)) - //cmd.AddCommand(NewCmdCreateEnvironment(f, out, errOut)) - //cmd.AddCommand(NewCmdCreateConfigRouter(options.Factory, options.Out, options.Err)) + // Get env variable data global to all config files + templateData := &ConfigTemplateValues{} + templateData.populateEnvVars() + + cmd.AddCommand(NewCmdCreateConfigController(templateData)) + cmd.AddCommand(NewCmdCreateEnvironment(f, out, errOut)) + cmd.AddCommand(NewCmdCreateConfigRouter(templateData)) return cmd } // Add flags that are global to all "create config" commands func (options *CreateConfigOptions) addCreateFlags(cmd *cobra.Command) { - cmd.PersistentFlags().BoolVarP(&options.Verbose, "verbose", "v", false, "verbose logging") - cmd.PersistentFlags().StringVarP(&options.Output, "output", "q", defaultOutput, outputDescription) + cmd.PersistentFlags().BoolVarP(&options.Verbose, optionVerbose, "v", defaultVerbose, verboseDescription) + cmd.PersistentFlags().StringVarP(&options.Output, optionOutput, "o", defaultOutput, outputDescription) +} + +func (data *ConfigTemplateValues) populateEnvVars() { + + // Get and add hostname to the params + hostname, err := os.Hostname() + handleVariableError(err, "hostname") + + // Get and add ziti home to the params + zitiHome, err := cmdhelper.GetZitiHome() + handleVariableError(err, cmdhelper.ZitiHomeVarName) + + // Get Ziti Controller Rawname + zitiCtrlRawname, err := cmdhelper.GetZitiCtrlRawname() + handleVariableError(err, cmdhelper.ZitiCtrlRawnameVarName) + + // Get Ziti Fabric Management Port + zitiFabMgmtPort, err := cmdhelper.GetZitiFabMgmtPort() + handleVariableError(err, cmdhelper.ZitiFabMgmtPortVarName) + + // Get Ziti Edge Controller API + zitiEdgeCtrlAPI, err := cmdhelper.GetZitiEdgeControllerAPI() + handleVariableError(err, cmdhelper.ZitiEdgeCtrlAPIVarName) + + // Get Ziti Signing Intermediate Name + zitiSigningIntermediateName, err := cmdhelper.GetZitiSigningIntermediateName() + handleVariableError(err, cmdhelper.ZitiSigningIntermediateNameVarName) + + // Get Ziti Edge Controller Port + zitiEdgeCtrlPort, err := cmdhelper.GetZitiEdgeCtrlPort() + handleVariableError(err, cmdhelper.ZitiEdgeCtrlPortVarName) + + // Get Ziti Edge Intermediate Name + zitiEdgeIntermediateName, err := cmdhelper.GetZitiEdgeCtrlIntermediateName() + handleVariableError(err, cmdhelper.ZitiEdgeCtrlPortVarName) + + // Get Ziti Edge Controller Hostname + zitiEdgeCtrlHostname, err := cmdhelper.GetZitiEdgeCtrlHostname() + handleVariableError(err, cmdhelper.ZitiEdgeCtrlHostnameVarName) + + // Get Ziti Controller Intermediate Name + zitiCtrlIntName, err := cmdhelper.GetZitiCtrlIntermediateName() + handleVariableError(err, cmdhelper.ZitiCtrlIntermediateNameVarName) + + // Get Ziti Controller Hostname + zitiCtrlHostname, err := cmdhelper.GetZitiCtrlHostname() + handleVariableError(err, cmdhelper.ZitiCtrlHostnameVarName) + + // Get Ziti fabric ctrl port + zitiFabCtrlPort, err := cmdhelper.GetZitiFabCtrlPort() + handleVariableError(err, cmdhelper.ZitiFabCtrlPortVarName) + + // Get Ziti PKI path + zitiPKI, err := cmdhelper.GetZitiPKI() + handleVariableError(err, cmdhelper.ZitiPKIVarName) + + // Get Ziti Edge Router Hostname + zitiEdgeRouterHostName, err := cmdhelper.GetZitiEdgeRouterHostname() + handleVariableError(err, cmdhelper.ZitiEdgeRouterHostnameVarName) + + // Get Ziti Edge Router Port + zitiEdgeRouterPort, err := cmdhelper.GetZitiEdgeRouterPort() + handleVariableError(err, cmdhelper.ZitiEdgeRouterPortVarName) + + data.ZitiPKI = zitiPKI + data.ZitiCtrlIntermediateName = zitiCtrlIntName + data.ZitiCtrlHostname = zitiCtrlHostname + data.ZitiFabCtrlPort = zitiFabCtrlPort + data.ZitiHome = zitiHome + data.Hostname = hostname + data.ZitiFabMgmtPort = zitiFabMgmtPort + data.ZitiEdgeCtrlAPI = zitiEdgeCtrlAPI + data.ZitiSigningIntermediateName = zitiSigningIntermediateName + data.ZitiEdgeCtrlPort = zitiEdgeCtrlPort + data.ZitiCtrlRawname = zitiCtrlRawname + data.ZitiEdgeCtrlIntermediateName = zitiEdgeIntermediateName + data.ZitiEdgeCtrlHostname = zitiEdgeCtrlHostname + data.ZitiEdgeRouterHostname = zitiEdgeRouterHostName + data.ZitiEdgeRouterPort = zitiEdgeRouterPort +} + +func handleVariableError(err error, varName string) { + if err != nil { + logrus.Errorf("Unable to get %s", varName) + } } diff --git a/ziti/cmd/ziti/cmd/create_config_controller.go b/ziti/cmd/ziti/cmd/create_config_controller.go index 1fceb8c3b..b979859e2 100644 --- a/ziti/cmd/ziti/cmd/create_config_controller.go +++ b/ziti/cmd/ziti/cmd/create_config_controller.go @@ -18,14 +18,11 @@ package cmd import ( _ "embed" - "fmt" - cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "io" "os" "strings" "text/template" @@ -64,23 +61,33 @@ var controllerConfigTemplate string type CreateConfigControllerOptions struct { CreateConfigOptions - ZitiHome string - Hostname string - CtrlListener string - MgmtListener string - ZitiFabMgmtPort string - ZitiEdgeCtrlAPI string - ZitiSigningIntermediateName string - ZitiEdgeCtrlPort string - ZitiCtrlRawname string - ZitiEdgeCtrlIntermediateName string - ZitiEdgeCtrlHostname string - Zerbose bool + CtrlListener string + MgmtListener string } +//type ControllerConfigValues struct { +// *ConfigValues +// +// CtrlListener string +// MgmtListener string +// ZitiHome string +// Hostname string +// ZitiFabMgmtPort string +// ZitiEdgeCtrlAPI string +// ZitiSigningIntermediateName string +// ZitiEdgeCtrlPort string +// ZitiCtrlRawname string +// ZitiEdgeCtrlIntermediateNameVarName string +// ZitiEdgeCtrlHostname string +//} + // NewCmdCreateConfigController creates a command object for the "create" command -func NewCmdCreateConfigController(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := &CreateConfigControllerOptions{} +func NewCmdCreateConfigController(data *ConfigTemplateValues) *cobra.Command { + controllerOptions := &CreateConfigControllerOptions{} + + // controllerOptions := &CreateConfigControllerOptions{ + // CreateConfigOptions: configOptions, + // } cmd := &cobra.Command{ Use: "controller", @@ -89,12 +96,27 @@ func NewCmdCreateConfigController(f cmdutil.Factory, out io.Writer, errOut io.Wr Long: createConfigControllerLong, Example: createConfigControllerExample, PreRun: func(cmd *cobra.Command, args []string) { - // TODO: Might not use this + // Setup logging + var logOut *os.File + if controllerOptions.Verbose { + logrus.SetLevel(logrus.DebugLevel) + // Only print log to stdout if not printing config to stdout + if strings.ToLower(controllerOptions.Output) != "stdout" { + logOut = os.Stdout + } else { + logOut = os.Stderr + } + logrus.SetOutput(logOut) + } + + // Update controller specific values with configOptions passed in + // data.CtrlListener = controllerOptions.CtrlListener + // data.MgmtListener = controllerOptions.MgmtListener }, Run: func(cmd *cobra.Command, args []string) { - options.Cmd = cmd - options.Args = args - err := run(options) + controllerOptions.Cmd = cmd + controllerOptions.Args = args + err := controllerOptions.run(data) cmdhelper.CheckErr(err) }, PostRun: func(cmd *cobra.Command, args []string) { @@ -102,43 +124,27 @@ func NewCmdCreateConfigController(f cmdutil.Factory, out io.Writer, errOut io.Wr logrus.SetOutput(os.Stdout) }, } - options.addCreateFlags(cmd) - options.addFlags(cmd) + controllerOptions.addCreateFlags(cmd) + controllerOptions.addFlags(cmd) return cmd } func (options *CreateConfigControllerOptions) addFlags(cmd *cobra.Command) { - cmd.PersistentFlags().BoolVarP(&options.Zerbose, "zerbose", "z", false, "zerbose logging") - cmd.Flags().StringVar(&options.CtrlListener, optionCtrlListener, "tls:0.0.0.0:6262", "address of the config controller listener") cmd.Flags().StringVar(&options.DatabaseFile, optionsDatabaseFile, "ctrl.db", "location of the database file") cmd.Flags().StringVar(&options.MgmtListener, optionMgmtListener, "tls:127.0.0.1:10000", "address of the config management listener") } // run implements the command -func run(options *CreateConfigControllerOptions) error { - outputFile := options.Output - fmt.Printf("###run() output is: `%s`\n", outputFile) - - // Setup logging - var logOut *os.File - if options.Zerbose { - logrus.SetLevel(logrus.DebugLevel) - // Only print log to stdout if not printing config to stdout - if strings.ToLower(options.Output) != "stdout" { - logOut = os.Stdout - } else { - logOut = os.Stderr - } - logrus.SetOutput(logOut) - } +func (options *CreateConfigControllerOptions) run(data *ConfigTemplateValues) error { tmpl, err := template.New("controller-config").Parse(controllerConfigTemplate) if err != nil { return err } + // TODO: Do we want to create the path if it doesn't exist? //baseDir := filepath.Dir(options.Output) //if baseDir != "." { // if err := os.MkdirAll(baseDir, 0700); err != nil { @@ -146,11 +152,9 @@ func run(options *CreateConfigControllerOptions) error { // } //} - populateEnvVars(options) - var f *os.File if strings.ToLower(options.Output) != "stdout" { - f, err = os.Create(outputFile) + f, err = os.Create(options.Output) logrus.Debugf("Created output file: %s", options.Output) if err != nil { return errors.Wrapf(err, "unable to create config file: %s", options.Output) @@ -160,12 +164,7 @@ func run(options *CreateConfigControllerOptions) error { } defer func() { _ = f.Close() }() - //// If using stdout for config, send logs to stderr - //if strings.ToLower(options.Output) == "stdout" { - // logrus.SetOutput(os.Stderr) - //} - - if err := tmpl.Execute(f, options); err != nil { + if err := tmpl.Execute(f, data); err != nil { return errors.Wrap(err, "unable to execute template") } @@ -173,78 +172,3 @@ func run(options *CreateConfigControllerOptions) error { return nil } - -func populateEnvVars(options *CreateConfigControllerOptions) { - - // Get and add hostname to the params - hostname, err := os.Hostname() - handleVariableError(err, "hostname") - - // Get and add ziti home to the params - zitiHome, err := cmdhelper.GetZitiHome() - handleVariableError(err, cmdhelper.ZitiHomeVarName) - - // Get Ziti Controller Rawname - zitiCtrlRawname, err := cmdhelper.GetZitiCtrlRawname() - handleVariableError(err, cmdhelper.ZitiCtrlRawnameVarName) - - // Get Ziti fabric ctrl port - zitiFabCtrlPort, err := cmdhelper.GetZitiFabCtrlPort() - handleVariableError(err, cmdhelper.ZitiFabCtrlPortVarName) - - // Get Ziti PKI path - zitiPKI, err := cmdhelper.GetZitiPKI() - handleVariableError(err, cmdhelper.ZitiPKIVarName) - - // Get Ziti Controller Intermediate Name - zitiCtrlIntName, err := cmdhelper.GetZitiCtrlIntermediateName() - handleVariableError(err, cmdhelper.ZitiCtrlIntermediateNameVarName) - - // Get Ziti Controller Hostname - zitiCtrlHostname, err := cmdhelper.GetZitiCtrlHostname() - handleVariableError(err, cmdhelper.ZitiCtrlHostnameVarName) - - // Get Ziti Fabric Management Port - zitiFabMgmtPort, err := cmdhelper.GetZitiFabMgmtPort() - handleVariableError(err, cmdhelper.ZitiFabMgmtPortVarName) - - // Get Ziti Edge Controller API - zitiEdgeCtrlAPI, err := cmdhelper.GetZitiEdgeControllerAPI() - handleVariableError(err, cmdhelper.ZitiEdgeCtrlAPIVarName) - - // Get Ziti Signing Intermediate Name - zitiSigningIntermediateName, err := cmdhelper.GetZitiSigningIntermediateName() - handleVariableError(err, cmdhelper.ZitiSigningIntermediateNameVarName) - - // Get Ziti Edge Controller Port - zitiEdgeCtrlPort, err := cmdhelper.GetZitiEdgeCtrlPort() - handleVariableError(err, cmdhelper.ZitiEdgeCtrlPortVarName) - - // Get Ziti Edge Intermediate Name - zitiEdgeIntermediateName, err := cmdhelper.GetZitiEdgeCtrlIntermediateName() - handleVariableError(err, cmdhelper.ZitiEdgeCtrlPortVarName) - - // Get Ziti Edge Controller Hostname - zitiEdgeCtrlHostname, err := cmdhelper.GetZitiEdgeCtrlHostname() - handleVariableError(err, cmdhelper.ZitiEdgeCtrlHostnameVarName) - - options.ZitiHome = zitiHome - options.Hostname = hostname - options.ZitiPKI = zitiPKI - options.ZitiFabCtrlPort = zitiFabCtrlPort - options.ZitiCtrlIntermediateName = zitiCtrlIntName - options.ZitiCtrlHostname = zitiCtrlHostname - options.ZitiFabMgmtPort = zitiFabMgmtPort - options.ZitiEdgeCtrlAPI = zitiEdgeCtrlAPI - options.ZitiSigningIntermediateName = zitiSigningIntermediateName - options.ZitiEdgeCtrlPort = zitiEdgeCtrlPort - options.ZitiCtrlRawname = zitiCtrlRawname - options.ZitiEdgeCtrlIntermediateName = zitiEdgeIntermediateName - options.ZitiEdgeCtrlHostname = zitiEdgeCtrlHostname -} - -func handleVariableError(err error, varName string) { - if err != nil { - logrus.Errorf("Unable to get %s", varName) - } -} diff --git a/ziti/cmd/ziti/cmd/create_config_router.go b/ziti/cmd/ziti/cmd/create_config_router.go index 33e33f18f..bd87f3bb1 100644 --- a/ziti/cmd/ziti/cmd/create_config_router.go +++ b/ziti/cmd/ziti/cmd/create_config_router.go @@ -17,18 +17,19 @@ package cmd import ( - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" - cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory" + _ "embed" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "io" + "os" + "strings" ) const ( optionRouterName = "routerName" ) -// CreateConfigRouterOptions the options for the create spring command +// CreateConfigRouterOptions the options for the router command type CreateConfigRouterOptions struct { CreateConfigOptions @@ -36,34 +37,41 @@ type CreateConfigRouterOptions struct { } // NewCmdCreateConfigRouter creates a command object for the "router" command -func NewCmdCreateConfigRouter(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := &CreateConfigRouterOptions{ - CreateConfigOptions: CreateConfigOptions{ - CommonOptions: common.CommonOptions{ - Factory: f, - Out: out, - Err: errOut, - }, - }, - } +func NewCmdCreateConfigRouter(data *ConfigTemplateValues) *cobra.Command { + options := &CreateConfigRouterOptions{} cmd := &cobra.Command{ Use: "router", - Short: "Creates a config file for specified Router type", + Short: "Creates a config file for specified Router name", Aliases: []string{"rtr"}, + PreRun: func(cmd *cobra.Command, args []string) { + // Setup logging + var logOut *os.File + if options.Verbose { + logrus.SetLevel(logrus.DebugLevel) + // Only print log to stdout if not printing config to stdout + if strings.ToLower(options.Output) != "stdout" { + logOut = os.Stdout + } else { + logOut = os.Stderr + } + logrus.SetOutput(logOut) + } + }, Run: func(cmd *cobra.Command, args []string) { cmdhelper.CheckErr(cmd.Help()) }, } - cmd.AddCommand(NewCmdCreateConfigRouterEdge(common.NewOptionsProvider(out, errOut))) + cmd.AddCommand(NewCmdCreateConfigRouterEdge(data)) + options.addCreateFlags(cmd) options.addFlags(cmd) return cmd } func (options *CreateConfigRouterOptions) addFlags(cmd *cobra.Command) { - cmd.PersistentFlags().StringVar(&options.RouterName, optionRouterName, "", "name of the router") + cmd.PersistentFlags().StringVarP(&options.RouterName, optionRouterName, "n", "", "name of the router") err := cmd.MarkPersistentFlagRequired(optionRouterName) if err != nil { return diff --git a/ziti/cmd/ziti/cmd/create_config_router_edge.go b/ziti/cmd/ziti/cmd/create_config_router_edge.go index 86b081c96..c49f00659 100644 --- a/ziti/cmd/ziti/cmd/create_config_router_edge.go +++ b/ziti/cmd/ziti/cmd/create_config_router_edge.go @@ -17,11 +17,21 @@ package cmd import ( - "fmt" - "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" + _ "embed" cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" "github.com/openziti/ziti/ziti/cmd/ziti/cmd/templates" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "os" + "strings" + "text/template" +) + +const ( + optionWSS = "wss" + defaultWSS = false + wssDescription = "Create an edge router config with wss enabled" ) var ( @@ -31,24 +41,23 @@ var ( createConfigRouterEdgeExample = templates.Examples(` # Create the edge router config for a router named my_router - ziti create config router edge --name my_router + ziti create config router edge --routerName my_router `) ) -// CreateConfigRouterEdgeOptions the options for the create spring command +// CreateConfigRouterEdgeOptions the options for the edge command type CreateConfigRouterEdgeOptions struct { CreateConfigRouterOptions + + WssEnabled bool } +//go:embed config_templates/edge.router.yml +var routerConfigEdgeTemplate string + // NewCmdCreateConfigRouterEdge creates a command object for the "edge" command -func NewCmdCreateConfigRouterEdge(p common.OptionsProvider) *cobra.Command { - options := &CreateConfigRouterEdgeOptions{ - CreateConfigRouterOptions: CreateConfigRouterOptions{ - CreateConfigOptions: CreateConfigOptions{ - CommonOptions: p(), - }, - }, - } +func NewCmdCreateConfigRouterEdge(data *ConfigTemplateValues) *cobra.Command { + options := &CreateConfigRouterEdgeOptions{} cmd := &cobra.Command{ Use: "edge", @@ -56,27 +65,79 @@ func NewCmdCreateConfigRouterEdge(p common.OptionsProvider) *cobra.Command { Aliases: []string{"edge"}, Long: createConfigRouterEdgeLong, Example: createConfigRouterEdgeExample, + PreRun: func(cmd *cobra.Command, args []string) { + // Setup logging + var logOut *os.File + if options.Verbose { + logrus.SetLevel(logrus.DebugLevel) + // Only print log to stdout if not printing config to stdout + if strings.ToLower(options.Output) != "stdout" { + logOut = os.Stdout + } else { + logOut = os.Stderr + } + logrus.SetOutput(logOut) + } + + // Update edge router specific values with options passed in + data.EdgeRouterName = options.RouterName + data.WssEnabled = options.WssEnabled + }, Run: func(cmd *cobra.Command, args []string) { options.Cmd = cmd options.Args = args - err := options.Run() + err := options.run(data) cmdhelper.CheckErr(err) }, } + options.addCreateFlags(cmd) options.addFlags(cmd) return cmd } func (options *CreateConfigRouterEdgeOptions) addFlags(cmd *cobra.Command) { - // TODO: implement + cmd.Flags().BoolVar(&options.WssEnabled, optionWSS, defaultWSS, wssDescription) + cmd.PersistentFlags().StringVarP(&options.RouterName, optionRouterName, "n", "", "name of the router") + err := cmd.MarkPersistentFlagRequired(optionRouterName) + if err != nil { + return + } } -// Run implements the command -func (options *CreateConfigRouterEdgeOptions) Run() error { +// run implements the command +func (options *CreateConfigRouterEdgeOptions) run(data *ConfigTemplateValues) error { + tmpl, err := template.New("router-config").Parse(routerConfigEdgeTemplate) + if err != nil { + return err + } - return fmt.Errorf("UNIMPLEMENTED: '%s'", "create config router edge") + // TODO: Do we want to create the path if it doesn't exist? + //baseDir := filepath.Dir(options.Output) + //if baseDir != "." { + // if err := os.MkdirAll(baseDir, 0700); err != nil { + // return errors.Wrapf(err, "unable to create directory to house config file: %v", options.Output) + // } + //} - // return nil + var f *os.File + if strings.ToLower(options.Output) != "stdout" { + f, err = os.Create(options.Output) + logrus.Debugf("Created output file: %s", options.Output) + if err != nil { + return errors.Wrapf(err, "unable to create config file: %s", options.Output) + } + } else { + f = os.Stdout + } + defer func() { _ = f.Close() }() + + if err := tmpl.Execute(f, data); err != nil { + return errors.Wrap(err, "unable to execute template") + } + + logrus.Debugf("Edge Router configuration generated successfully and written to: %s", options.Output) + + return nil } diff --git a/ziti/cmd/ziti/cmd/helpers/env_helpers.go b/ziti/cmd/ziti/cmd/helpers/env_helpers.go new file mode 100644 index 000000000..8014303de --- /dev/null +++ b/ziti/cmd/ziti/cmd/helpers/env_helpers.go @@ -0,0 +1,269 @@ +/* + 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 helpers + +import ( + "github.com/pkg/errors" + "os" +) + +const ( + ZitiHomeVarName = "ZITI_HOME" + + ZitiPKIVarName = "ZITI_PKI" + + ZitiFabCtrlPortVarName = "ZITI_FAB_CTRL_PORT" + + ZitiCtrlHostnameVarName = "ZITI_CONTROLLER_HOSTNAME" + + ZitiCtrlRawnameVarName = "ZITI_CONTROLLER_RAWNAME" + + ZitiNetworkVarName = "ZITI_NETWORK" + + ZitiDomainSuffixVarName = "ZITI_DOMAIN_SUFFIX" + + ZitiCtrlIntermediateNameVarName = "ZITI_CONTROLLER_INTERMEDIATE_NAME" + + ZitiEdgeCtrlAPIVarName = "ZITI_EDGE_CONTROLLER_API" + + ZitiEdgeCtrlHostnameVarName = "ZITI_EDGE_CONTROLLER_HOSTNAME" + + ZitiEdgeCtrlPortVarName = "ZITI_EDGE_CONTROLLER_PORT" + + ZitiSigningIntermediateNameVarName = "ZITI_SIGNING_INTERMEDIATE_NAME" + + ZitiSigningCertNameVarName = "ZITI_SIGNING_CERT_NAME" + + ZitiFabMgmtPortVarName = "ZITI_FAB_MGMT_PORT" + + ZitiEdgeCtrlIntermediateNameVarName = "ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME" + + ZitiEdgeRouterHostnameVarName = "ZITI_EDGE_ROUTER_HOSTNAME" + + ZitiEdgeRouterPortVarName = "ZITI_EDGE_ROUTER_PORT" +) + +func HomeDir() string { + if h := os.Getenv("HOME"); h != "" { + return h + } + h := os.Getenv("USERPROFILE") // windows + if h == "" { + h = "." + } + return h +} + +func GetZitiHome() (string, error) { + + // Get path from env variable + retVal := os.Getenv(ZitiHomeVarName) + if retVal != "" { + return retVal, nil + } + + // If not set, create a default path + hostname, err := os.Hostname() + if err != nil { + return "", err + } + + homePath := HomeDir() + + pathSep := string(os.PathSeparator) + err = os.Setenv(ZitiHomeVarName, homePath+pathSep+".ziti"+pathSep+"quickstart"+pathSep+hostname) + if err != nil { + return "", err + } + + retVal = os.Getenv(ZitiHomeVarName) + + return retVal, nil +} + +func GetZitiPKI() (string, error) { + zitiHome, err := GetZitiHome() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiHomeVarName) + if err != nil { + return "", err + } + } + return getOrSetEnvVar(ZitiPKIVarName, zitiHome+string(os.PathSeparator)+"pki") +} + +func GetZitiCtrlIntermediateName() (string, error) { + zitiCtrlHostname, err := GetZitiCtrlHostname() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiCtrlHostnameVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiCtrlIntermediateNameVarName, zitiCtrlHostname+"-intermediate") +} + +func GetZitiEdgeCtrlHostname() (string, error) { + zitiNetwork, err := GetZitiNetwork() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiEdgeCtrlHostnameVarName, zitiNetwork) +} + +func GetZitiEdgeCtrlPort() (string, error) { + return getOrSetEnvVar(ZitiEdgeCtrlPortVarName, "1280") +} + +func GetZitiEdgeControllerAPI() (string, error) { + zitiEdgeCtrlHostname, err := GetZitiEdgeCtrlHostname() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiCtrlHostnameVarName) + if err != nil { + return "", err + } + } + + zitiEdgeCtrlPort, err := GetZitiEdgeCtrlPort() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiEdgeCtrlPortVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiEdgeCtrlAPIVarName, zitiEdgeCtrlHostname+":"+zitiEdgeCtrlPort) +} + +func GetZitiSigningCertName() (string, error) { + zitiNetwork, err := GetZitiNetwork() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiSigningCertNameVarName, zitiNetwork+"-signing") +} + +func GetZitiSigningIntermediateName() (string, error) { + zitiSigningCertName, err := GetZitiSigningCertName() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiSigningCertNameVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiSigningIntermediateNameVarName, zitiSigningCertName+"-intermediate") +} + +func GetZitiFabCtrlPort() (string, error) { + return getOrSetEnvVar(ZitiFabCtrlPortVarName, "6262") +} + +func GetZitiCtrlHostname() (string, error) { + zitiNetwork, err := GetZitiNetwork() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiCtrlHostnameVarName, zitiNetwork) +} + +func GetZitiCtrlRawname() (string, error) { + zitiNetwork, err := GetZitiNetwork() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) + if err != nil { + return "", err + } + } + + defaultZitiCtrlRawName := zitiNetwork + "-controller" + return getOrSetEnvVar(ZitiCtrlRawnameVarName, defaultZitiCtrlRawName) +} + +func GetZitiNetwork() (string, error) { + hostName, err := os.Hostname() + if err != nil { + err := errors.Wrap(err, "Unable to get hostname") + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiNetworkVarName, hostName) +} + +func GetZitiFabMgmtPort() (string, error) { + return getOrSetEnvVar(ZitiFabMgmtPortVarName, "10000") +} + +func GetZitiEdgeCtrlIntermediateName() (string, error) { + zitiEdgeCtrlHostname, err := GetZitiEdgeCtrlHostname() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiEdgeCtrlHostnameVarName) + if err != nil { + return "", err + } + } + + return getOrSetEnvVar(ZitiEdgeCtrlIntermediateNameVarName, zitiEdgeCtrlHostname+"-intermediate") +} + +func GetZitiEdgeRouterHostname() (string, error) { + zitiNetwork, err := GetZitiNetwork() + if err != nil { + err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) + if err != nil { + return "", err + } + } + return getOrSetEnvVar(ZitiEdgeRouterHostnameVarName, zitiNetwork) +} + +func GetZitiEdgeRouterPort() (string, error) { + return getOrSetEnvVar(ZitiEdgeRouterPortVarName, "3022") +} + +func getOrSetEnvVar(envVarName string, defaultValue string) (string, error) { + + // Get path from env variable + retVal := os.Getenv(envVarName) + if retVal != "" { + return retVal, nil + } + + err := os.Setenv(envVarName, defaultValue) + if err != nil { + return "", err + } + + retVal = os.Getenv(envVarName) + + return retVal, nil +} diff --git a/ziti/cmd/ziti/cmd/helpers/helpers.go b/ziti/cmd/ziti/cmd/helpers/helpers.go index 8ab584600..ba18cd5b7 100644 --- a/ziti/cmd/ziti/cmd/helpers/helpers.go +++ b/ziti/cmd/ziti/cmd/helpers/helpers.go @@ -18,7 +18,6 @@ package helpers import ( "fmt" - "github.com/pkg/errors" "net/url" "os" "strings" @@ -31,36 +30,6 @@ const ( DefaultErrorExitCode = 1 DefaultWritePermissions = 0760 - - ZitiHomeVarName = "ZITI_HOME" - - ZitiPKIVarName = "ZITI_PKI" - - ZitiFabCtrlPortVarName = "ZITI_FAB_CTRL_PORT" - - ZitiCtrlHostnameVarName = "ZITI_CONTROLLER_HOSTNAME" - - ZitiCtrlRawnameVarName = "ZITI_CONTROLLER_RAWNAME" - - ZitiNetworkVarName = "ZITI_NETWORK" - - ZitiDomainSuffixVarName = "ZITI_DOMAIN_SUFFIX" - - ZitiCtrlIntermediateNameVarName = "ZITI_CONTROLLER_INTERMEDIATE_NAME" - - ZitiEdgeCtrlAPIVarName = "ZITI_EDGE_CONTROLLER_API" - - ZitiEdgeCtrlHostnameVarName = "ZITI_EDGE_CONTROLLER_HOSTNAME" - - ZitiEdgeCtrlPortVarName = "ZITI_EDGE_CONTROLLER_PORT" - - ZitiSigningIntermediateNameVarName = "ZITI_SIGNING_INTERMEDIATE_NAME" - - ZitiSigningCertNameVarName = "ZITI_SIGNING_CERT_NAME" - - ZitiFabMgmtPortVarName = "ZITI_FAB_MGMT_PORT" - - ZitiEdgeCtrlIntermediateName = "ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME" ) type debugError interface { @@ -227,202 +196,6 @@ func UsageError(cmd *cobra.Command, format string, args ...interface{}) error { return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath()) } -func HomeDir() string { - if h := os.Getenv("HOME"); h != "" { - return h - } - h := os.Getenv("USERPROFILE") // windows - if h == "" { - h = "." - } - return h -} - -func GetZitiHome() (string, error) { - - // Get path from env variable - retVal := os.Getenv(ZitiHomeVarName) - if retVal != "" { - return retVal, nil - } - - // If not set, create a default path - hostname, err := os.Hostname() - if err != nil { - return "", err - } - - homePath := HomeDir() - - pathSep := string(os.PathSeparator) - err = os.Setenv(ZitiHomeVarName, homePath+pathSep+".ziti"+pathSep+"quickstart"+pathSep+hostname) - if err != nil { - return "", err - } - - retVal = os.Getenv(ZitiHomeVarName) - - return retVal, nil -} - -func GetZitiPKI() (string, error) { - zitiHome, err := GetZitiHome() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiHomeVarName) - if err != nil { - return "", err - } - } - return getOrSetEnvVar(ZitiPKIVarName, zitiHome+string(os.PathSeparator)+"pki") -} - -func GetZitiCtrlIntermediateName() (string, error) { - zitiCtrlHostname, err := GetZitiCtrlHostname() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiCtrlHostnameVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiCtrlIntermediateNameVarName, zitiCtrlHostname+"-intermediate") -} - -func GetZitiEdgeCtrlHostname() (string, error) { - zitiNetwork, err := GetZitiNetwork() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiEdgeCtrlHostnameVarName, zitiNetwork) -} - -func GetZitiEdgeCtrlPort() (string, error) { - return getOrSetEnvVar(ZitiEdgeCtrlPortVarName, "1280") -} - -func GetZitiEdgeControllerAPI() (string, error) { - zitiEdgeCtrlHostname, err := GetZitiEdgeCtrlHostname() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiCtrlHostnameVarName) - if err != nil { - return "", err - } - } - - zitiEdgeCtrlPort, err := GetZitiEdgeCtrlPort() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiEdgeCtrlPortVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiEdgeCtrlAPIVarName, zitiEdgeCtrlHostname+":"+zitiEdgeCtrlPort) -} - -func GetZitiSigningCertName() (string, error) { - zitiNetwork, err := GetZitiNetwork() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiSigningCertNameVarName, zitiNetwork+"-signing") -} - -func GetZitiSigningIntermediateName() (string, error) { - zitiSigningCertName, err := GetZitiSigningCertName() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiSigningCertNameVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiSigningIntermediateNameVarName, zitiSigningCertName+"-intermediate") -} - -func GetZitiFabCtrlPort() (string, error) { - return getOrSetEnvVar(ZitiFabCtrlPortVarName, "6262") -} - -func GetZitiCtrlHostname() (string, error) { - zitiNetwork, err := GetZitiNetwork() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiCtrlHostnameVarName, zitiNetwork) -} - -func GetZitiCtrlRawname() (string, error) { - zitiNetwork, err := GetZitiNetwork() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiNetworkVarName) - if err != nil { - return "", err - } - } - - defaultZitiCtrlRawName := zitiNetwork + "-controller" - return getOrSetEnvVar(ZitiCtrlRawnameVarName, defaultZitiCtrlRawName) -} - -func GetZitiNetwork() (string, error) { - hostName, err := os.Hostname() - if err != nil { - err := errors.Wrap(err, "Unable to get hostname") - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiNetworkVarName, hostName) -} - -func GetZitiFabMgmtPort() (string, error) { - return getOrSetEnvVar(ZitiFabMgmtPortVarName, "10000") -} - -func getOrSetEnvVar(envVarName string, defaultValue string) (string, error) { - - // Get path from env variable - retVal := os.Getenv(envVarName) - if retVal != "" { - return retVal, nil - } - - err := os.Setenv(envVarName, defaultValue) - if err != nil { - return "", err - } - - retVal = os.Getenv(envVarName) - - return retVal, nil -} - -func GetZitiEdgeCtrlIntermediateName() (string, error) { - zitiEdgeCtrlHostname, err := GetZitiEdgeCtrlHostname() - if err != nil { - err := errors.Wrap(err, "Unable to get "+ZitiEdgeCtrlHostnameVarName) - if err != nil { - return "", err - } - } - - return getOrSetEnvVar(ZitiEdgeCtrlIntermediateName, zitiEdgeCtrlHostname+"-intermediate") -} - func JFrogAPIKey() string { if h := os.Getenv("JFROG_API_KEY"); h != "" { return h