diff --git a/README.md b/README.md index 0defe08..e8ce4ef 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,9 @@ This repo defines a command line interface used by the enterprise, solution, or ### Synopsis -**kabanero** is a command line interface for managing the stacks in a Kabanero -environment, as well as to on-board the people that will use -the environment to build applications. +The Kabenero CLI is a command line interface for managing the stacks in a Kabanero environment to create governed applications for businesses. -Before using the cli please configure the github authorization for the cli service. Steps can be found in the following documentation: https://kabanero.io/docs/ref/general/configuration/github-authorization.html +Before using the CLI please configure the github authorization for the CLI service. Steps can be found in the following documentation: https://kabanero.io/docs/ref/general/configuration/github-authorization.html Complete documentation is available at https://kabanero.io @@ -28,6 +26,7 @@ Complete documentation is available at https://kabanero.io ### SEE ALSO * [kabanero deactivate](#kabanero-deactivate) - Remove the specified stack from the list of available application types, without deleting it from the Kabanero instance. +* [kabanero describe](#kabanero-describe) - Get more information about the specified stack * [kabanero list](#kabanero-list) - List all the stacks in the kabanero instance, and their status * [kabanero login](#kabanero-login) - Will authenticate you to a Kabanero instance * [kabanero logout](#kabanero-logout) - Disconnect from Kabanero instance @@ -35,7 +34,7 @@ Complete documentation is available at https://kabanero.io * [kabanero sync](#kabanero-sync) - sync the stack list * [kabanero version](#kabanero-version) - Show Kabanero CLI version -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 ## kabanero login Will authenticate you to a Kabanero instance @@ -50,7 +49,8 @@ Will authenticate you to a Kabanero instance ``` -kabanero login kabanero-url -u Github userid /n PASSWORDPROMPT:GitHub Password|PAT [flags] +kabanero login kabanero-cli-url -u Github userid + At the password prompt, enter your GitHub Password/PAT [flags] ``` ### Examples @@ -67,8 +67,11 @@ kabanero login kabanero-url -u Github userid /n PASSWORDPROMPT:GitHub Password|P ### Options ``` - -h, --help help for login - -u, --username string github username + --certificate-authority string Path to a cert file for the certificate authority + -h, --help help for login + --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + -p, --password string github password/PAT. If no password is provided, prompt will appear + -u, --username string github username ``` ### Options inherited from parent commands @@ -81,7 +84,7 @@ kabanero login kabanero-url -u Github userid /n PASSWORDPROMPT:GitHub Password|P * [kabanero](#kabanero) - This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero stacks that are used by developers to create governed applications for their business. -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 ## kabanero logout Disconnect from Kabanero instance @@ -112,7 +115,7 @@ kabanero logout [flags] * [kabanero](#kabanero) - This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero stacks that are used by developers to create governed applications for their business. -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 ## kabanero list List all the stacks in the kabanero instance, and their status @@ -142,7 +145,7 @@ kabanero list [flags] * [kabanero](#kabanero) - This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero stacks that are used by developers to create governed applications for their business. -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 ## kabanero sync sync the stack list @@ -174,7 +177,7 @@ kabanero sync [flags] * [kabanero](#kabanero) - This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero stacks that are used by developers to create governed applications for their business. -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 ## kabanero onboard Command to onboard a developer to the Kabanero infrastructure @@ -205,7 +208,7 @@ kabanero onboard github-id [flags] * [kabanero](#kabanero) - This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero stacks that are used by developers to create governed applications for their business. -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 ## kabanero deactivate Remove the specified stack from the list of available application types, without deleting it from the Kabanero instance. @@ -237,4 +240,4 @@ kabanero deactivate stack-name version [flags] * [kabanero](#kabanero) - This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero stacks that are used by developers to create governed applications for their business. -###### Auto generated by spf13/cobra on 21-Feb-2020 +###### Auto generated by spf13/cobra on 6-May-2020 diff --git a/cmd/login.go b/cmd/login.go index 6245136..3b3c51a 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -16,13 +16,16 @@ limitations under the License. package cmd import ( + "bufio" "encoding/json" "fmt" "net/http" + "os" "strconv" "strings" "syscall" "time" + "unicode" "github.com/kabanero-io/kabanero-command-line/pkg/security" "github.com/spf13/cobra" @@ -31,6 +34,11 @@ import ( "golang.org/x/crypto/ssh/terminal" ) +var ( + InsecureTLS bool + clientCert string +) + type JWTResponse struct { JWT string Message string @@ -70,6 +78,60 @@ func is06Compatible() bool { return true } +func HandleTLSFLag(insecureTLS bool) { + cliConfig.Set("insecureTLS", insecureTLS) + err := cliConfig.WriteConfig() + if err != nil { + messageAndExit("There was a problem writing to the cli config") + } + + if clientCert != "" { + cliConfig.Set(CertKey, clientCert) + err = cliConfig.WriteConfig() + if err != nil { + messageAndExit("There was a problem writing to the cli config") + } + return + } + + if !insecureTLS && clientCert == "" { + + fmt.Print("Are you sure you want to continue with an insecure connection to " + cliConfig.GetString(KabURLKey) + " (y/n): ") + + reader := bufio.NewReader(os.Stdin) + char, _, err := reader.ReadRune() + if err != nil { + fmt.Println(err) + //TODO handle incorrect characters or full yes + } + fmt.Println() + switch unicode.ToLower(char) { + case 'y': + cliConfig.Set("insecureTLS", true) + err = cliConfig.WriteConfig() + if err != nil { + messageAndExit("There was a problem writing to the cli config") + } + case 'n': + cliConfig.Set("insecureTLS", false) + err = cliConfig.WriteConfig() + if err != nil { + messageAndExit("There was a problem writing to the cli config") + } + + if cliConfig.GetString(CertKey) == "" { + messageAndExit("To continue with a secure connection, provide path to certificate with --certificate-authority at login. See login -h for help.") + } + + default: + messageAndExit("Please enter y or n") + + } + + } + +} + // loginCmd represents the login command var loginCmd = &cobra.Command{ Use: "login kabanero-cli-url -u Github userid \n At the password prompt, enter your GitHub Password/PAT", @@ -118,6 +180,9 @@ var loginCmd = &cobra.Command{ messageAndExit("No Kabanero instance url specified") } } + + HandleTLSFLag(InsecureTLS) + kabLoginURL = getRESTEndpoint("login") requestBody, _ := json.Marshal(map[string]string{"gituser": username, "gitpat": password}) @@ -179,9 +244,13 @@ var loginCmd = &cobra.Command{ func init() { rootCmd.AddCommand(loginCmd) + loginCmd.Flags().StringP("username", "u", "", "github username") + _ = loginCmd.MarkFlagRequired("username") loginCmd.Flags().StringP("password", "p", "", "github password/PAT. If no password is provided, prompt will appear") + loginCmd.Flags().BoolVar(&InsecureTLS, "insecure-skip-tls-verify", false, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure") + loginCmd.Flags().StringVar(&clientCert, "certificate-authority", "", "Path to a cert file for the certificate authority") // Cobra supports Persistent Flags which will work for this command // and all subcommands, e.g.: diff --git a/cmd/root.go b/cmd/root.go index 8872251..0b5e9d7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -27,6 +27,7 @@ var ( verboseHTTP bool klogInitialized = false KabURLKey = "KABURL" + CertKey = "CertLocation" ) func homeDir() string { diff --git a/cmd/sync.go b/cmd/sync.go index d6950a6..12d5439 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -18,8 +18,10 @@ package cmd import ( "bytes" "crypto/tls" + "crypto/x509" "encoding/json" "fmt" + "io/ioutil" "net/http" "net/http/httputil" "os" @@ -49,13 +51,6 @@ func getRESTEndpoint(appendValue string) string { } func sendHTTPRequest(method string, url string, jsonBody []byte) (*http.Response, error) { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - client := &http.Client{ - Timeout: time.Second * 30, - Transport: tr, - } var resp *http.Response var requestBody *bytes.Buffer @@ -74,6 +69,28 @@ func sendHTTPRequest(method string, url string, jsonBody []byte) (*http.Response 539: "CLI has not been configured", } + rootCAPool, _ := x509.SystemCertPool() + if rootCAPool == nil { + rootCAPool = x509.NewCertPool() + } + if !cliConfig.GetBool("insecureTLS") { + cert, err := ioutil.ReadFile(cliConfig.GetString(CertKey)) + if err != nil { + messageAndExit(fmt.Sprintf("Problem with the certificate for %s, provided at %s", cliConfig.GetString(KabURLKey), cliConfig.GetString(CertKey))) + } + rootCAPool.AppendCertsFromPEM(cert) + } + + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: rootCAPool, + InsecureSkipVerify: cliConfig.GetBool("insecureTLS")}, + } + client := &http.Client{ + Timeout: time.Second * 30, + Transport: tr, + } + if jsonBody != nil { requestBody = bytes.NewBuffer(jsonBody) req, err = http.NewRequest(method, url, requestBody) @@ -107,8 +124,8 @@ func sendHTTPRequest(method string, url string, jsonBody []byte) (*http.Response resp, err = client.Do(req) if err != nil { - msg := "No response from url: " + cliConfig.GetString(KabURLKey) - messageandDebugExit(msg, msg+" "+err.Error()) + msg := "Could not connect to url: " + cliConfig.GetString(KabURLKey) + "\nError: " + err.Error() + messageAndExit(msg) } if verboseHTTP { responseDump, err := httputil.DumpResponse(resp, true) diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go index be8c51b..bed9ebb 100644 --- a/vendor/github.com/hashicorp/hcl/decoder.go +++ b/vendor/github.com/hashicorp/hcl/decoder.go @@ -505,7 +505,7 @@ func expandObject(node ast.Node, result reflect.Value) ast.Node { // we need to un-flatten the ast enough to decode newNode := &ast.ObjectItem{ Keys: []*ast.ObjectKey{ - { + &ast.ObjectKey{ Token: keyToken, }, }, diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go index 943bad0..09498e7 100644 --- a/vendor/github.com/spf13/afero/memmap.go +++ b/vendor/github.com/spf13/afero/memmap.go @@ -269,7 +269,7 @@ func (m *MemMapFs) RemoveAll(path string) error { m.mu.RLock() defer m.mu.RUnlock() - for p := range m.getData() { + for p, _ := range m.getData() { if strings.HasPrefix(p, path) { m.mu.RUnlock() m.mu.Lock() diff --git a/vendor/github.com/spf13/viper/go.mod b/vendor/github.com/spf13/viper/go.mod index 439d2d8..86e801c 100644 --- a/vendor/github.com/spf13/viper/go.mod +++ b/vendor/github.com/spf13/viper/go.mod @@ -22,5 +22,3 @@ require ( golang.org/x/text v0.3.0 // indirect gopkg.in/yaml.v2 v2.2.2 ) - -go 1.13 diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index 9a3eddb..7173c6e 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -1702,7 +1702,7 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac func (v *Viper) mergeFlatMap(shadow map[string]bool, m map[string]interface{}) map[string]bool { // scan keys outer: - for k := range m { + for k, _ := range m { path := strings.Split(k, v.keyDelim) // scan intermediate paths var parentKey string diff --git a/vendor/golang.org/x/text/unicode/cldr/cldr.go b/vendor/golang.org/x/text/unicode/cldr/cldr.go index f4d49a0..f39b2e3 100644 --- a/vendor/golang.org/x/text/unicode/cldr/cldr.go +++ b/vendor/golang.org/x/text/unicode/cldr/cldr.go @@ -117,7 +117,7 @@ func (cldr *CLDR) Supplemental() *SupplementalData { func (cldr *CLDR) Locales() []string { loc := []string{"root"} hasRoot := false - for l := range cldr.locale { + for l, _ := range cldr.locale { if l == "root" { hasRoot = true continue diff --git a/vendor/golang.org/x/text/unicode/cldr/resolve.go b/vendor/golang.org/x/text/unicode/cldr/resolve.go index abbc9ac..31cc7be 100644 --- a/vendor/golang.org/x/text/unicode/cldr/resolve.go +++ b/vendor/golang.org/x/text/unicode/cldr/resolve.go @@ -289,7 +289,7 @@ var distinguishing = map[string][]string{ "mzone": nil, "from": nil, "to": nil, - "type": { + "type": []string{ "abbreviationFallback", "default", "mapping", @@ -527,7 +527,7 @@ func (cldr *CLDR) inheritSlice(enc, v, parent reflect.Value) (res reflect.Value, } } keys := make([]string, 0, len(index)) - for k := range index { + for k, _ := range index { keys = append(keys, k) } sort.Strings(keys) diff --git a/vendor/golang.org/x/text/unicode/cldr/slice.go b/vendor/golang.org/x/text/unicode/cldr/slice.go index ea5f31a..388c983 100644 --- a/vendor/golang.org/x/text/unicode/cldr/slice.go +++ b/vendor/golang.org/x/text/unicode/cldr/slice.go @@ -83,7 +83,7 @@ func (s Slice) Group(fn func(e Elem) string) []Slice { m[key] = append(m[key], vi) } keys := []string{} - for k := range m { + for k, _ := range m { keys = append(keys, k) } sort.Strings(keys) diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go index 3bd76af..30a3aa9 100644 --- a/vendor/golang.org/x/text/unicode/norm/maketables.go +++ b/vendor/golang.org/x/text/unicode/norm/maketables.go @@ -242,7 +242,7 @@ func compactCCC() { m[c.ccc] = 0 } cccs := []int{} - for v := range m { + for v, _ := range m { cccs = append(cccs, int(v)) } sort.Ints(cccs) diff --git a/vendor/gopkg.in/yaml.v2/readerc.go b/vendor/gopkg.in/yaml.v2/readerc.go index b0c436c..7c1f5fa 100644 --- a/vendor/gopkg.in/yaml.v2/readerc.go +++ b/vendor/gopkg.in/yaml.v2/readerc.go @@ -95,7 +95,7 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { // [Go] This function was changed to guarantee the requested length size at EOF. // The fact we need to do this is pretty awful, but the description above implies - // for that to be the case, and there are tests + // for that to be the case, and there are tests // If the EOF flag is set and the raw buffer is empty, do nothing. if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { diff --git a/vendor/gopkg.in/yaml.v2/resolve.go b/vendor/gopkg.in/yaml.v2/resolve.go index bf830ee..6c151db 100644 --- a/vendor/gopkg.in/yaml.v2/resolve.go +++ b/vendor/gopkg.in/yaml.v2/resolve.go @@ -180,7 +180,7 @@ func resolve(tag string, in string) (rtag string, out interface{}) { return yaml_INT_TAG, uintv } } else if strings.HasPrefix(plain, "-0b") { - intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) + intv, err := strconv.ParseInt("-" + plain[3:], 2, 64) if err == nil { if true || intv == int64(int(intv)) { return yaml_INT_TAG, int(intv) diff --git a/vendor/gopkg.in/yaml.v2/sorter.go b/vendor/gopkg.in/yaml.v2/sorter.go index 2edd734..4c45e66 100644 --- a/vendor/gopkg.in/yaml.v2/sorter.go +++ b/vendor/gopkg.in/yaml.v2/sorter.go @@ -52,7 +52,7 @@ func (l keyList) Less(i, j int) bool { var ai, bi int var an, bn int64 if ar[i] == '0' || br[i] == '0' { - for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { + for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { if ar[j] != '0' { an = 1 bn = 1