Skip to content

Commit

Permalink
Merge pull request #5 from nathanejohnson/feature/csv
Browse files Browse the repository at this point in the history
adding csv option to fetchca
  • Loading branch information
nathanejohnson authored Jun 10, 2023
2 parents 8eb996e + d140d1f commit 011506b
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 20 deletions.
5 changes: 1 addition & 4 deletions cmd/checkintermediatecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ func NewCheckIntermediateCmd() *CheckIntermediateCmd {
return ci
}



func (ci *CheckIntermediateCmd) Run(args []string) int {
err := ci.f.Parse(args)
if err != nil || (len(ci.files) == 0 && len(ci.hostports) == 0) {
Expand All @@ -52,7 +50,7 @@ func (ci *CheckIntermediateCmd) Run(args []string) int {
func (ci *CheckIntermediateCmd) run() error {
if ci.cafile != "" {
var err error
ci.ca, err = loadCABundle(ci.cafile)
_, ci.ca, err = loadCABundle(ci.cafile)
if err != nil {
return err
}
Expand Down Expand Up @@ -116,7 +114,6 @@ func (ci *CheckIntermediateCmd) run() error {
return nil
}


func (ci *CheckIntermediateCmd) Synopsis() string {
return "Check a site or a pem certificate file to see if it is trusted by the global cert store. " +
"This will also provide an option to " +
Expand Down
2 changes: 2 additions & 0 deletions cmd/dumpcacmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func (dc *DumpCACmd) Run(args []string) int {
log.Printf("error writing csv: %s", err)
return 1
}
defer csvWriter.Flush()
}
for _, cert := range certs {
switch dc.csv {
Expand All @@ -54,5 +55,6 @@ func (dc *DumpCACmd) Run(args []string) int {
return 1
}
}

return 0
}
36 changes: 27 additions & 9 deletions cmd/fetchca.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cmd

import (
"crypto/x509"
"encoding/csv"
"fmt"
"io"
"io/ioutil"
Expand All @@ -14,6 +16,7 @@ type FetchCACmd struct {
URL string
outputFile string
verify bool
csv bool
BaseCmd
}

Expand All @@ -24,6 +27,7 @@ func NewFetchCACmd() *FetchCACmd {
fca.f.StringVar(&fca.URL, "url", "https://curl.se/ca/cacert.pem", "url to remote CA bundle "+
"(required) - please do not abuse curl.se")
fca.f.BoolVar(&fca.verify, "verify", true, "verify downloaded certificate bundle")
fca.f.BoolVar(&fca.csv, "csv", false, "output metadata as csv")
return fca
}

Expand Down Expand Up @@ -88,7 +92,8 @@ func (fca *FetchCACmd) run() error {
return fmt.Errorf("non-200 status code received: %d %s", resp.StatusCode, resp.Status)
}
var r io.Reader = resp.Body
if fca.verify {
var certs []*x509.Certificate
if fca.verify || fca.csv {
tf, err := ioutil.TempFile(os.TempDir(), "fetchca-")
if err != nil {
return fmt.Errorf("could not create temporary file: %w", err)
Expand All @@ -103,21 +108,34 @@ func (fca *FetchCACmd) run() error {
}
// close file to flush and allow loadCABundle to read it properly
tf.Close()
pool, err := loadCABundle(tf.Name())

certs, _, err = loadCABundle(tf.Name())
if err != nil {
return fmt.Errorf("failed validation of downloaded bundle: %w", err)
}
log.Printf("verified %d certificates in bundle downloaded from %s", len(pool.Subjects()), fca.URL)
log.Printf("verified %d certificates in bundle downloaded from %s", len(certs), fca.URL)

// reopen the temp file for reading for the copy below.
f, err := os.Open(tf.Name())
if err != nil {
return fmt.Errorf("unable to reopen temp file: %w", err)
if !fca.csv {
f, err := os.Open(tf.Name())
if err != nil {
return fmt.Errorf("unable to reopen temp file: %w", err)
}
defer f.Close()
r = f
}
defer f.Close()
r = f
}
_, err = io.Copy(w, r)
if fca.csv {
cWriter := csv.NewWriter(w)
writeCertCSVHeader(cWriter)
for _, cert := range certs {
writeCertCSV(cWriter, cert)
}
cWriter.Flush()

} else {
_, err = io.Copy(w, r)
}
if err != nil {
return fmt.Errorf("error copying payload: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/mincacmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (mca *MinCACmd) Run(args []string) int {

var ca *x509.CertPool
if mca.cafile != "" {
ca, err = loadCABundle(mca.cafile)
_, ca, err = loadCABundle(mca.cafile)
if err != nil {
log.Println(err)
os.Exit(1)
Expand Down
13 changes: 7 additions & 6 deletions cmd/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io/ioutil"
golog "log"
"net/http"
"os"
"strconv"
"time"
)
Expand All @@ -19,24 +20,24 @@ var (
log *golog.Logger
)

func loadCABundle(loc string) (*x509.CertPool, error) {
fBytes, err := ioutil.ReadFile(loc)
func loadCABundle(loc string) ([]*x509.Certificate, *x509.CertPool, error) {
fBytes, err := os.ReadFile(loc)
if err != nil {
return nil, err
return nil, nil, err
}
certders := decodePemsByType(fBytes, "CERTIFICATE")
if len(certders) == 0 {
return nil, fmt.Errorf("no certificates found in passed bundle %s", loc)
return nil, nil, fmt.Errorf("no certificates found in passed bundle %s", loc)
}
certs, err := x509.ParseCertificates(certders)
if err != nil {
return nil, fmt.Errorf("error parsing certificates for ca bundle: %w", err)
return nil, nil, fmt.Errorf("error parsing certificates for ca bundle: %w", err)
}
pool := x509.NewCertPool()
for _, cert := range certs {
pool.AddCert(cert)
}
return pool, nil
return certs, pool, nil
}

func writeCert(w io.Writer, cert *x509.Certificate) error {
Expand Down

0 comments on commit 011506b

Please sign in to comment.