Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions cmd/certinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ Copyright © 2025 Zeno Belli xeno@os76.xyz
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/xenos76/https-wrench/internal/certinfo"
Expand Down Expand Up @@ -48,14 +45,14 @@ Examples:
https-wrench certinfo --ca-bundle ./ca-bundle.pem --tls-endpoint example.com:443
https-wrench certinfo --ca-bundle ./ca-bundle.pem --cert-bundle ./bundle.pem --key-file ./key.pem
`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, _ []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)
cmd.Print(version)
return
}

Expand All @@ -67,16 +64,16 @@ Examples:

certinfoCfg, err := certinfo.NewCertinfoConfig()
if err != nil {
fmt.Printf("Error creating new Certinfo config: %s", err)
cmd.Printf("Error creating new Certinfo config: %s", err)
return
}

if err = certinfoCfg.SetCaPoolFromFile(caBundleValue, fileReader); err != nil {
fmt.Printf("Error importing CA Certificate bundle from file: %s", err)
cmd.Printf("Error importing CA Certificate bundle from file: %s", err)
}

if err = certinfoCfg.SetCertsFromFile(certBundleValue, fileReader); err != nil {
fmt.Printf("Error importing Certificate bundle from file: %s", err)
cmd.Printf("Error importing Certificate bundle from file: %s", err)
}

certinfoCfg.SetTLSInsecure(tlsInsecure).SetTLSServerName(tlsServerName)
Expand All @@ -85,20 +82,20 @@ Examples:
// before being able to ask details about the certificate we want to a
// webserver using self-signed and valid certificates
if err = certinfoCfg.SetTLSEndpoint(tlsEndpoint); err != nil {
fmt.Printf("Error setting TLS endpoint: %s", err)
cmd.Printf("Error setting TLS endpoint: %s", err)
}

if err = certinfoCfg.SetPrivateKeyFromFile(
keyFileValue,
keyPwEnvVar,
fileReader,
); err != nil {
fmt.Printf("Error importing key from file: %s", err)
cmd.Printf("Error importing key from file: %s", err)
}

// dump.Print(certinfoCfg)
if err = certinfoCfg.PrintData(os.Stdout); err != nil {
fmt.Printf("error printing Certinfo data: %s", err)
if err = certinfoCfg.PrintData(cmd.OutOrStdout()); err != nil {
cmd.Printf("error printing Certinfo data: %s", err)
}
},
}
Expand Down
25 changes: 25 additions & 0 deletions cmd/certinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
)

//nolint:revive
func TestCertinfoCmd(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -88,12 +89,36 @@ func TestCertinfoCmd(t *testing.T) {
"--version Display the version",
},
},
{
name: "version",
args: []string{"certinfo", "--version"},
expectError: false,
expected: []string{version},
},
{
//nolint:revive
name: "invalid files and endpoints",
//nolint:revive
args: []string{"certinfo", "--ca-bundle", "non_existent.pem", "--cert-bundle", "non_existent.pem", "--key-file", "non_existent.pem", "--tls-endpoint", "invalid://"},
expectError: false,
expected: []string{"Error importing CA Certificate bundle", "Error importing Certificate bundle", "Error importing key", "Error setting TLS endpoint"},
},
}

for _, tc := range tests {
tt := tc

t.Run(tt.name, func(t *testing.T) {
t.Cleanup(func() {
require.NoError(t, rootCmd.PersistentFlags().Set("version", "false"))
require.NoError(t, certinfoCmd.Flags().Set("ca-bundle", ""))
require.NoError(t, certinfoCmd.Flags().Set("tls-endpoint", ""))
require.NoError(t, certinfoCmd.Flags().Set("tls-servername", ""))
require.NoError(t, certinfoCmd.Flags().Set("tls-insecure", "false"))
require.NoError(t, certinfoCmd.Flags().Set("cert-bundle", ""))
require.NoError(t, certinfoCmd.Flags().Set("key-file", ""))
})
Comment thread
coderabbitai[bot] marked this conversation as resolved.

reqOut := new(bytes.Buffer)
reqCmd := rootCmd
reqCmd.SetOut(reqOut)
Expand Down
24 changes: 11 additions & 13 deletions cmd/jwtinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ Copyright © 2026 Zeno Belli <xeno@os76.xyz>
package cmd

import (
"fmt"
"io"
"net/http"
"os"

"github.com/MicahParks/keyfunc/v3"
"github.com/spf13/cobra"
Expand All @@ -31,8 +29,8 @@ var (

var jwtinfoCmd = &cobra.Command{
Use: "jwtinfo",
Short: "JwtInfo request and display JWT token data",
Long: `JwtInfo request and display JWT token data
Short: "JwtInfo shows data from a JWT token",
Long: `JwtInfo shows data from a JWT token

Examples:
export REQ_URL="https://sample.provider/oauth/token"
Expand All @@ -51,7 +49,7 @@ Examples:
# Request and validate a JWT token
https-wrench jwtinfo --request-url $REQ_URL --request-values-json $REQ_VALUES --validation-url $VALIDATION_URL
`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, _ []string) {
// TODO: remove global --config option

var err error
Expand All @@ -60,7 +58,7 @@ Examples:
if tokenFile != "" {
tokenData, err = jwtinfo.ReadTokenFromFile(tokenFile)
if err != nil {
fmt.Printf(
cmd.Printf(
"error while reading token value from file: %s",
err,
)
Expand All @@ -78,7 +76,7 @@ Examples:
requestValuesMap,
)
if err != nil {
fmt.Printf(
cmd.Printf(
"error while reading request's values from file: %s",
err,
)
Expand All @@ -92,7 +90,7 @@ Examples:
requestValuesMap,
)
if err != nil {
fmt.Printf(
cmd.Printf(
"error while parsing request's values JSON string: %s",
err,
)
Expand All @@ -107,29 +105,29 @@ Examples:
io.ReadAll,
)
if err != nil {
fmt.Printf("error while requesting token data: %s\n", err)
cmd.Printf("error while requesting token data: %s\n", err)
return
}
}

if tokenData.AccessTokenRaw != "" {
err = tokenData.DecodeBase64()
if err != nil {
fmt.Printf("DecodeBase64 error: %s\n", err)
cmd.Printf("DecodeBase64 error: %s\n", err)
return
}

if jwksURL != "" {
err = tokenData.ParseWithJWKS(jwksURL, keyfuncDefOverride)
if err != nil {
fmt.Printf("error while parsing token data: %s\n", err)
cmd.Printf("error while parsing token data: %s\n", err)
return
}
}

err = jwtinfo.PrintTokenInfo(tokenData, os.Stdout)
err = jwtinfo.PrintTokenInfo(tokenData, cmd.OutOrStdout())
if err != nil {
fmt.Printf("error while printing token data: %s\n", err)
cmd.Printf("error while printing token data: %s\n", err)
return
}
} else {
Expand Down
58 changes: 58 additions & 0 deletions cmd/jwtinfo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cmd

import (
"bytes"
"testing"

"github.com/stretchr/testify/require"
)

func TestJwtinfoCmd(t *testing.T) {
tests := []struct {
name string
args []string
expectError bool
errMsgs []string
expected []string
}{
{
name: "invalid file",
args: []string{"jwtinfo", "--token-file", "non_existent.jwt"},
expectError: false,
expected: []string{"error while reading token value from file"},
},
}

for _, tc := range tests {
tt := tc
t.Run(tt.name, func(t *testing.T) {
t.Cleanup(func() {
rootCmd.Flags().Set("version", "false")
jwtinfoCmd.Flags().Set("token-file", "")
jwtinfoCmd.Flags().Set("clipboard", "false")
})

reqOut := new(bytes.Buffer)
reqCmd := rootCmd
reqCmd.SetOut(reqOut)
reqCmd.SetErr(reqOut)
reqCmd.SetArgs(tt.args)
err := reqCmd.Execute()

if tt.expectError {
require.Error(t, err)

for _, expected := range tt.errMsgs {
require.ErrorContains(t, err, expected)
}
} else {
require.NoError(t, err)
}

got := reqOut.String()
for _, expected := range tt.expected {
require.Contains(t, got, expected)
}
})
}
}
17 changes: 8 additions & 9 deletions cmd/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package cmd

import (
_ "embed"
"fmt"
"os"

"github.com/gookit/goutil/dump"
Expand Down Expand Up @@ -41,7 +40,7 @@ Examples:
https-wrench requests --config https-wrench-sample-config.yaml
`,

Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, _ []string) {
versionRequested := viper.GetBool("version")

if versionRequested {
Expand All @@ -61,14 +60,14 @@ Examples:

_, err := os.Stat(viper.ConfigFileUsed())
if err != nil {
fmt.Printf("\nConfig file not found: %s\n", viper.ConfigFileUsed())
cmd.Printf("\nConfig file not found: %s\n", viper.ConfigFileUsed())
_ = cmd.Help()
return
}

cfg, err := LoadConfig()
if err != nil {
fmt.Print(err)
cmd.Print(err)
return
}

Expand All @@ -78,7 +77,7 @@ Examples:

requestsCfg, err := requests.NewRequestsMetaConfig()
if err != nil {
fmt.Print(err)
cmd.Print(err)
return
}

Expand All @@ -87,16 +86,16 @@ Examples:
SetRequests(cfg.Requests)

if err := requestsCfg.SetCaPoolFromYAML(cfg.CaBundle); err != nil {
fmt.Print(err)
cmd.Print(err)
}

if err := requestsCfg.SetCaPoolFromFile(caBundlePath, fileReader); err != nil {
fmt.Print(err)
cmd.Print(err)
}

responseMap, err := requests.HandleRequests(os.Stdout, requestsCfg)
responseMap, err := requests.HandleRequests(cmd.OutOrStdout(), requestsCfg)
if err != nil {
fmt.Print(err)
cmd.Print(err)
}

if cfg.Debug {
Expand Down
8 changes: 8 additions & 0 deletions cmd/requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
)

//nolint:revive
func TestRequestsCmd(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -111,6 +112,13 @@ func TestRequestsCmd(t *testing.T) {
tt := tc

t.Run(tt.name, func(t *testing.T) {
t.Cleanup(func() {
require.NoError(t, rootCmd.Flags().Set("version", "false"))
require.NoError(t, requestsCmd.Flags().Set("ca-bundle", ""))
require.NoError(t, rootCmd.Flags().Set("config", ""))
require.NoError(t, requestsCmd.Flags().Set("show-sample-config", "false"))
})

reqOut := new(bytes.Buffer)
reqCmd := rootCmd
reqCmd.SetOut(reqOut)
Expand Down
5 changes: 3 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ var rootCmd = &cobra.Command{
Use: "https-wrench",
Short: "HTTPS Wrench, a tool to make Yaml defined HTTPS requests and inspect x.509 certificates and keys",
Long: `
HTTPS Wrench is a tool to make HTTPS requests according to a Yaml configuration file and to inspect x.509 certificates and keys.
HTTPS Wrench is a tool to make HTTPS requests according to a Yaml configuration file
and to inspect x.509 certificates and keys.

https-wrench has two subcommands: requests and certinfo.

Expand All @@ -66,7 +67,7 @@ certinfo can compare public keys extracted from certificates and private keys to
HTTPS Wrench is distributed with an open source license and available at the following address:
https://github.com/xenOs76/https-wrench`,

Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, _ []string) {
showVersion, _ := cmd.Flags().GetBool("version")
if showVersion {
cmd.Println(version)
Expand Down
Loading
Loading