diff --git a/README.md b/README.md index 143f20e..9555e63 100644 --- a/README.md +++ b/README.md @@ -24,29 +24,29 @@ Check the help: ```bash ❯ https-wrench -h -A tool to make HTTPS requests based on a YAML configuration file +HTTPS Wrench, a tool to make HTTPS requests based on a YAML configuration file Usage: https-wrench [flags] https-wrench [command] Available Commands: + certinfo Show info about PEM certificates and keys completion Generate the autocompletion script for the specified shell help Help about any command - requests Make HTTPS requests + requests Make HTTPS requests defined in the YAML configuration file Flags: - --config string config file (default is $HOME/.https-wrench.yaml) - -h, --help help for https-wrench - --show-sample-config Show a sample YAML configuration - --version Display the version + --config string config file (default is $HOME/.https-wrench.yaml) + -h, --help help for https-wrench + --version Display the version Use "https-wrench [command] --help" for more information about a command. ``` Generate a sample config file: ```bash -https-wrench --show-sample-config > sample-wrench.yaml +https-wrench requests --show-sample-config > sample-wrench.yaml ```
@@ -102,7 +102,7 @@ requests: Make the HTTPS requests defined in the YAML file: ```bash -https-wrench --config sample-wrench.yaml requests +https-wrench requests --config sample-wrench.yaml ```
@@ -140,7 +140,7 @@ echo "deb [trusted=yes] https://repo.os76.xyz/apt stable main" | sudo tee /etc/a ``` then: ```bash -apt-get update && apt-get install https-wrench +sudo apt-get update && sudo apt-get install -y https-wrench ``` ### YUM @@ -156,7 +156,7 @@ repo_gpgcheck=0' | sudo tee /etc/yum.repos.d/os76.repo ``` then: ```bash -yum install https-wrench +sudo yum install https-wrench ``` ### Docker image diff --git a/cmd/certinfo.go b/cmd/certinfo.go index 28515c0..c14e345 100644 --- a/cmd/certinfo.go +++ b/cmd/certinfo.go @@ -21,13 +21,16 @@ var ( var certinfoCmd = &cobra.Command{ Use: "certinfo", Short: "Show info about PEM certificates and keys", - Long: `Show info about PEM certificates and keys. -Can fetch certificates from a TLS endpoint, read from a PEM bundle file, and check if a private + Long: ` +HTTPS Wrench certinfo: show info about PEM certificates and keys. + +Certinfo can fetch certificates from a TLS endpoint, read from a PEM bundle file, and check if a private key matches any of the certificates. The certificates can be verified against the system root CAs or a custom CA bundle file. The validation can be skipped. If the private key is password protected, the password can be provided via the CERTINFO_PKEY_PW environment variable or will be prompted on stdin. + Examples: certinfo --tls-endpoint example.com:443 certinfo --cert-bundle ./bundle.pem --key-file ./key.pem @@ -41,6 +44,22 @@ Examples: certinfo --ca-bundle ./ca-bundle.pem --cert-bundle ./bundle.pem --key-file ./key.pem `, Run: func(cmd *cobra.Command, args []string) { + caBundleValue := viper.GetString("ca-bundle") + certBundleValue := viper.GetString("cert-bundle") + keyFileValue := viper.GetString("key-file") + versionRequested := viper.GetBool("version") + + if versionRequested { + fmt.Print(version) + return + } + + // display the help if none of the main flags is set + if len(caBundleValue+certBundleValue+keyFileValue+tlsEndpoint) == 0 { + _ = cmd.Help() + return + } + certinfoCfg, err := certinfo.NewCertinfoConfig() if err != nil { fmt.Printf("Error creating new Certinfo config: %s", err) @@ -49,11 +68,11 @@ Examples: certinfoCfg.SetTLSInsecure(tlsInsecure).SetTLSServerName(tlsServerName) - if err := certinfoCfg.SetCaPoolFromFile(viper.GetString("ca-bundle")); err != nil { + if err := certinfoCfg.SetCaPoolFromFile(caBundleValue); err != nil { fmt.Printf("Error importing CA Certificate bundle from file: %s", err) } - if err := certinfoCfg.SetCertsFromFile(viper.GetString("cert-bundle")); err != nil { + if err := certinfoCfg.SetCertsFromFile(certBundleValue); err != nil { fmt.Printf("Error importing Certificate bundle from file: %s", err) } @@ -61,7 +80,7 @@ Examples: fmt.Printf("Error setting TLS endpoint: %s", err) } - if err := certinfoCfg.SetPrivateKeyFromFile(viper.GetString("key-file")); err != nil { + if err := certinfoCfg.SetPrivateKeyFromFile(keyFileValue); err != nil { fmt.Printf("Error importing key from file: %s", err) } diff --git a/cmd/requests.go b/cmd/requests.go index d7b00ba..010d953 100644 --- a/cmd/requests.go +++ b/cmd/requests.go @@ -7,9 +7,11 @@ package cmd import ( _ "embed" "fmt" + "os" "github.com/gookit/goutil/dump" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/xenos76/https-wrench/internal/requests" ) @@ -21,13 +23,15 @@ var ( var requestsCmd = &cobra.Command{ Use: "requests", - Short: "Make HTTPS requests", - Long: `Make HTTPS requests defined in the YAML configuration file.`, + Short: "Make HTTPS requests defined in the YAML configuration file", + Long: ` +HTTPS Wrench requests: make HTTPS requests defined in the YAML configuration file`, Run: func(cmd *cobra.Command, args []string) { - cfg, err := LoadConfig() - if err != nil { - fmt.Print(err) + versionRequested := viper.GetBool("version") + + if versionRequested { + fmt.Print(version) return } @@ -36,6 +40,24 @@ var requestsCmd = &cobra.Command{ return } + if cfgFile == "" { + _ = cmd.Help() + return + } + + _, err := os.Stat(viper.ConfigFileUsed()) + if err != nil { + fmt.Printf("\nConfig file not found: %s\n", viper.ConfigFileUsed()) + _ = cmd.Help() + return + } + + cfg, err := LoadConfig() + if err != nil { + fmt.Print(err) + return + } + if cfg.Debug { dump.Print(cfg) } diff --git a/cmd/root.go b/cmd/root.go index ea10a2c..4a23f12 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -47,8 +47,9 @@ var ( var rootCmd = &cobra.Command{ Use: "https-wrench", - Short: "A tool to make HTTPS requests based on a YAML configuration file", - Long: "A tool to make HTTPS requests based on a YAML configuration file", + Short: "HTTPS Wrench, a tool to make HTTPS requests based on a YAML configuration file", + Long: ` +HTTPS Wrench, a tool to make HTTPS requests based on a YAML configuration file`, Run: func(cmd *cobra.Command, args []string) { showVersion, _ := cmd.Flags().GetBool("version") @@ -57,9 +58,9 @@ var rootCmd = &cobra.Command{ return } - _, err := os.Stat(viper.ConfigFileUsed()) - if err != nil { - fmt.Printf("Config file not found: %s\n", viper.ConfigFileUsed()) + + if cfgFile == "" { + _ = cmd.Help() } }, } @@ -67,7 +68,7 @@ var rootCmd = &cobra.Command{ func Execute() { err := rootCmd.Execute() if err != nil { - os.Exit(1) + return } } @@ -84,8 +85,8 @@ func init() { } addCaBundleFlag(requestsCmd) - addCertBundleFlag(requestsCmd) - addKeyFileFlag(requestsCmd) + // addCertBundleFlag(requestsCmd) + // addKeyFileFlag(requestsCmd) addCaBundleFlag(certinfoCmd) addCertBundleFlag(certinfoCmd) diff --git a/devenv.lock b/devenv.lock index dce7a0e..c6dfda3 100644 --- a/devenv.lock +++ b/devenv.lock @@ -3,10 +3,10 @@ "devenv": { "locked": { "dir": "src/modules", - "lastModified": 1756732270, + "lastModified": 1763386227, "owner": "cachix", "repo": "devenv", - "rev": "1d5c772e984c5e29935ca3fa6b09f888dae04215", + "rev": "9f855598530d6ee075cc126e4f13812fd008209a", "type": "github" }, "original": { @@ -19,10 +19,10 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1747046372, + "lastModified": 1761588595, "owner": "edolstra", "repo": "flake-compat", - "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "type": "github" }, "original": { @@ -40,10 +40,10 @@ ] }, "locked": { - "lastModified": 1755960406, + "lastModified": 1763319842, "owner": "cachix", "repo": "git-hooks.nix", - "rev": "e891a93b193fcaf2fc8012d890dc7f0befe86ec2", + "rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761", "type": "github" }, "original": { @@ -60,10 +60,10 @@ ] }, "locked": { - "lastModified": 1709087332, + "lastModified": 1762808025, "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "rev": "cb5e3fdca1de58ccbc3ef53de65bd372b48f567c", "type": "github" }, "original": { @@ -74,10 +74,10 @@ }, "nixpkgs": { "locked": { - "lastModified": 1755783167, + "lastModified": 1761313199, "owner": "cachix", "repo": "devenv-nixpkgs", - "rev": "4a880fb247d24fbca57269af672e8f78935b0328", + "rev": "d1c30452ebecfc55185ae6d1c983c09da0c274ff", "type": "github" }, "original": { diff --git a/devenv.nix b/devenv.nix index 1c2fe74..ff14636 100644 --- a/devenv.nix +++ b/devenv.nix @@ -24,6 +24,7 @@ gum goreleaser # golangci-lint + govulncheck curl jq httpie @@ -151,7 +152,10 @@ scripts.update-go-deps.exec = '' gum format "## updating Go dependencies..." go get -u + gum format "## running go mod tidy..." go mod tidy + gum format "## running govulncheck..." + govulncheck ./... ''; scripts.build.exec = '' @@ -203,6 +207,36 @@ curl "https://localhost:9443/get" -k -v ''; + scripts.test-cmd-root-version.exec = '' + gum format "## Command root --version" + ./dist/https-wrench --version | grep -E '[0-9]\.+' + ''; + + scripts.test-cmd-requests-version.exec = '' + gum format "## Command requests --version" + ./dist/https-wrench requests --version | grep -E '[0-9]\.+' + ''; + + scripts.test-cmd-certinfo-version.exec = '' + gum format "## Command certinfo --version" + ./dist/https-wrench certinfo --version | grep -E '[0-9]\.+' + ''; + + scripts.test-cmd-root-help-when-no-flags.exec = '' + gum format "## Command root, help when no flags" + ./dist/https-wrench | grep "help for https-wrench" + ''; + + scripts.test-cmd-requests-help-when-no-flags.exec = '' + gum format "## Command requests, help when no flags" + ./dist/https-wrench requests | grep "help for requests" + ''; + + scripts.test-cmd-certinfo-help-when-no-flags.exec = '' + gum format "## Command certinfo, help when no flags" + ./dist/https-wrench certinfo | grep "help for certinfo" + ''; + scripts.test-requests-sample-config.exec = '' gum format "## test request with sample config" ./dist/https-wrench requests --config ./cmd/embedded/config-example.yaml @@ -566,10 +600,18 @@ enterTest = '' gum format "# Running tests" - update-go-deps + # update-go-deps build run-go-tests + + test-cmd-root-version + test-cmd-requests-version + test-cmd-certinfo-version + test-cmd-root-help-when-no-flags + test-cmd-requests-help-when-no-flags + test-cmd-certinfo-help-when-no-flags + run-requests-tests run-certinfo-priv-key-tests run-certinfo-cert-tests diff --git a/internal/certinfo/certinfo_handlers.go b/internal/certinfo/certinfo_handlers.go index cfd6786..361f82a 100644 --- a/internal/certinfo/certinfo_handlers.go +++ b/internal/certinfo/certinfo_handlers.go @@ -168,7 +168,10 @@ func CertsToTables(certs []*x509.Certificate) { svn := style.CertValueNotice.Render for i := range certs { - header := style.LgSprintf(style.CertKeyP4.Bold(true), "Certificate %d", i) + header := style.LgSprintf( + style.CertKeyP4.Bold(true), + "Certificate %d", + i) cert := certs[i] subject := cert.Subject.String()