Skip to content

Commit 63fdf0c

Browse files
authored
CI: test certinfo handlers (#12)
* refactor: add Reader interface for file and password read * ci: add sample keys and certs for testing * ci: add tests for certinfo and common handlers * refactor: methods of structs implementing Reader interface declare only the receiver's type
1 parent 1fda3ab commit 63fdf0c

35 files changed

Lines changed: 1691 additions & 117 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
.direnv
22
dist
33
tests
4-
testdata
4+
internal/requests/testdata
5+
internal/certinfo/testdata/*Cert*
56
manpages
67

78
# ---> Go

.golangci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ linters:
5454
exclude: [""]
5555
arguments: [15]
5656

57+
# https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#cyclomatic
58+
- name: cyclomatic
59+
severity: warning
60+
disabled: false
61+
exclude: [""]
62+
arguments: [15]
63+
5764
exclusions:
5865
generated: lax
5966
presets:

cmd/certinfo.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,19 @@ Examples:
7171

7272
certinfoCfg.SetTLSInsecure(tlsInsecure).SetTLSServerName(tlsServerName)
7373

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

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

8282
if err := certinfoCfg.SetTLSEndpoint(tlsEndpoint); err != nil {
8383
fmt.Printf("Error setting TLS endpoint: %s", err)
8484
}
8585

86-
if err := certinfoCfg.SetPrivateKeyFromFile(keyFileValue); err != nil {
86+
if err := certinfoCfg.SetPrivateKeyFromFile(keyFileValue, fileReader); err != nil {
8787
fmt.Printf("Error importing key from file: %s", err)
8888
}
8989

cmd/requests.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Examples:
9090
fmt.Print(err)
9191
}
9292

93-
if err := requestsCfg.SetCaPoolFromFile(caBundlePath); err != nil {
93+
if err := requestsCfg.SetCaPoolFromFile(caBundlePath, fileReader); err != nil {
9494
fmt.Print(err)
9595
}
9696

cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
_ "github.com/breml/rootcerts"
3636
"github.com/spf13/cobra"
3737
"github.com/spf13/viper"
38+
"github.com/xenos76/https-wrench/internal/certinfo"
3839
)
3940

4041
var (
@@ -43,6 +44,7 @@ var (
4344
caBundlePath string
4445
certBundlePath string
4546
keyFilePath string
47+
fileReader certinfo.InputReader
4648
)
4749

4850
var rootCmd = &cobra.Command{

devenv.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ in {
4040
".gitignore"
4141
".envrc"
4242
"internal/certinfo/common_handlers.go"
43+
"internal/certinfo/testdata"
4344
"completions"
4445
];
4546
hooks = {

internal/certinfo/certinfo.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ import (
55
"crypto/x509"
66
"fmt"
77
"net"
8+
"os"
89
"time"
10+
11+
"golang.org/x/term"
912
)
1013

1114
const (
1215
TLSTimeout = 3 * time.Second
1316
CertExpWarnDays = 40
1417
privateKeyPwEnvVar = "CERTINFO_PKEY_PW"
18+
emptyString = ""
1519
)
1620

1721
type CertinfoConfig struct {
@@ -32,15 +36,34 @@ type CertinfoConfig struct {
3236
TLSInsecure bool
3337
}
3438

39+
type (
40+
Reader interface {
41+
ReadFile(name string) ([]byte, error)
42+
ReadPassword(fd int) ([]byte, error)
43+
}
44+
45+
InputReader struct{}
46+
)
47+
3548
var (
36-
// TODO: remove
37-
// certsBundle []*x509.Certificate
38-
// privKey any
39-
// tlsEndpoint string
4049
TlsServerName string
4150
TlsInsecure bool
51+
inputReader InputReader
4252
)
4353

54+
func (InputReader) ReadFile(name string) ([]byte, error) {
55+
file, err := os.ReadFile(name)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
return file, nil
61+
}
62+
63+
func (InputReader) ReadPassword(fd int) ([]byte, error) {
64+
return term.ReadPassword(fd)
65+
}
66+
4467
func NewCertinfoConfig() (*CertinfoConfig, error) {
4568
defaultCertPool, err := x509.SystemCertPool()
4669
if err != nil {
@@ -54,9 +77,12 @@ func NewCertinfoConfig() (*CertinfoConfig, error) {
5477
return &c, nil
5578
}
5679

57-
func (c *CertinfoConfig) SetCaPoolFromFile(filePath string) error {
58-
if filePath != "" {
59-
caCertsPool, err := GetRootCertsFromFile(filePath)
80+
func (c *CertinfoConfig) SetCaPoolFromFile(filePath string, fileReader Reader) error {
81+
if filePath != emptyString {
82+
caCertsPool, err := GetRootCertsFromFile(
83+
filePath,
84+
fileReader,
85+
)
6086
if err != nil {
6187
return err
6288
}
@@ -68,9 +94,9 @@ func (c *CertinfoConfig) SetCaPoolFromFile(filePath string) error {
6894
return nil
6995
}
7096

71-
func (c *CertinfoConfig) SetCertsFromFile(filePath string) error {
72-
if filePath != "" {
73-
certs, err := GetCertsFromBundle(filePath)
97+
func (c *CertinfoConfig) SetCertsFromFile(filePath string, fileReader Reader) error {
98+
if filePath != emptyString {
99+
certs, err := GetCertsFromBundle(filePath, fileReader)
74100
if err != nil {
75101
return err
76102
}
@@ -82,9 +108,13 @@ func (c *CertinfoConfig) SetCertsFromFile(filePath string) error {
82108
return nil
83109
}
84110

85-
func (c *CertinfoConfig) SetPrivateKeyFromFile(filePath string) error {
86-
if filePath != "" {
87-
keyFromFile, err := GetKeyFromFile(filePath)
111+
func (c *CertinfoConfig) SetPrivateKeyFromFile(filePath string, fileReader Reader) error {
112+
if filePath != emptyString {
113+
keyFromFile, err := GetKeyFromFile(
114+
filePath,
115+
privateKeyPwEnvVar,
116+
fileReader,
117+
)
88118
if err != nil {
89119
return err
90120
}

internal/certinfo/certinfo_handlers.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ func (c *CertinfoConfig) PrintData() {
110110
),
111111
)
112112

113-
rootCerts, err := GetCertsFromBundle(c.CACertsFilePath)
113+
rootCerts, err := GetCertsFromBundle(
114+
c.CACertsFilePath,
115+
inputReader,
116+
)
114117
if err != nil {
115118
fmt.Printf("unable for read Root certificates from %s: %s", c.CACertsFilePath, err)
116119

internal/certinfo/certinfo_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package certinfo
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/alecthomas/assert/v2"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestNewCertinfoConfig(t *testing.T) {
12+
t.Run("NewCertinfoConfig", func(t *testing.T) {
13+
t.Parallel()
14+
15+
cc, err := NewCertinfoConfig()
16+
require.NoError(t, err)
17+
18+
require.NotNil(t, cc.CACertsPool)
19+
})
20+
}
21+
22+
type mockReader struct {
23+
readError error
24+
}
25+
26+
func (mr mockReader) ReadFile(name string) ([]byte, error) {
27+
mr.readError = fmt.Errorf("unable to read file %s", name)
28+
return nil, mr.readError
29+
}
30+
31+
func TestCertinfo_SetCaPoolFromFile(t *testing.T) {
32+
t.Run("FileReadErrors", func(t *testing.T) {
33+
t.Parallel()
34+
35+
cc, err := NewCertinfoConfig()
36+
require.NoError(t, err)
37+
38+
errEmpty := cc.SetCaPoolFromFile(emptyString, inputReader)
39+
require.NoError(t, errEmpty, "error emptyString")
40+
41+
errNoRead := cc.SetCaPoolFromFile(unreadableFile, mockErrReader)
42+
require.Error(t, errNoRead, "error unreadableFile")
43+
assert.Equal(t,
44+
"failed to read CA bundle file: unable to read file testdata/unreadable-file.txt",
45+
errNoRead.Error(),
46+
"check unreadableFile",
47+
)
48+
49+
errNoExist := cc.SetCaPoolFromFile("testdata/not-exist", inputReader)
50+
require.Error(t, errNoExist, "error file not-exist")
51+
assert.Equal(t,
52+
"failed to read CA bundle file: open testdata/not-exist: no such file or directory",
53+
errNoExist.Error(),
54+
"read not-exist file",
55+
)
56+
57+
errWrongCert := cc.SetCaPoolFromFile(RSACaCertKeyFile, inputReader)
58+
require.Error(t, errWrongCert, "error wrong cert")
59+
assert.Equal(t,
60+
"unable to create CertPool from file",
61+
errWrongCert.Error(),
62+
"check wrong cert",
63+
)
64+
65+
// TODO: complete, compare struct data with input
66+
errRSACACert := cc.SetCaPoolFromFile(RSACaCertFile, inputReader)
67+
require.NoError(t, errRSACACert, "error generated RSACaCertFile")
68+
})
69+
}

0 commit comments

Comments
 (0)