Skip to content

Commit

Permalink
add fetch certificate from url
Browse files Browse the repository at this point in the history
  • Loading branch information
chenzhiwei committed Sep 5, 2021
1 parent a748aaa commit f01e247
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 5 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,12 @@ certctl help sign
certctl show cert-filepath.crt
certctl show csr-filepath.csr
```

## Fetch certificate from URL

```
certctl fetch 192.168.122.10:8443
certctl fetch https://pkg.go.dev/io
certctl fetch golang.org
certctl fetch golang.org --file golang.org.crt --noout
```
61 changes: 56 additions & 5 deletions cmd/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package cmd

import (
"errors"
"fmt"
"net/url"
"os"
"strings"
"text/tabwriter"

"github.com/chenzhiwei/certctl/pkg/cert"
"github.com/spf13/cobra"
)

var (
chain bool
noout bool
file string

fetchCmd = &cobra.Command{
Expand All @@ -24,15 +30,60 @@ var (
)

func init() {
fetchCmd.Flags().BoolVar(&chain, "chain", true, "fetch certificate chain")
fetchCmd.Flags().StringVar(&file, "file", "", "save the fetched certificate to a file")
fetchCmd.Flags().BoolVar(&noout, "noout", false, "do not print the certificate info")
fetchCmd.Flags().StringVar(&file, "file", "", "save the certificate to a file")
}

func runFetch(args []string) error {
url := args[0]
if url == "" {
s := args[0]
if s == "" {
return errors.New("something went wrong")
}

if !strings.Contains(s, "://") {
s = "https://" + s
}

u, err := url.Parse(s)
if err != nil {
return err
}

if u.Scheme == "http" {
return errors.New("can't fetch certificate with http")
}

host := u.Host
if !strings.Contains(host, ":") && u.Scheme == "https" {
host = host + ":443"
}

certBytes, err := cert.FetchCert(host)
if err != nil {
return err
}

if file != "" {
if err := os.WriteFile(file, certBytes, 0644); err != nil {
return err
}
}

if !noout {
result, err := cert.GetCertInfo(certBytes)
if err != nil {
return err
}

writer := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', tabwriter.AlignRight)
for _, info := range result {
for k, v := range info {
fmt.Fprintf(writer, "%s\t%s\n", k, v)
}
}

writer.Flush()
}

return nil
}
29 changes: 29 additions & 0 deletions pkg/cert/fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cert

import (
"bytes"
"crypto/tls"
"encoding/pem"
)

func FetchCert(addr string) ([]byte, error) {
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
if err != nil {
return nil, err
}
defer conn.Close()

certs := conn.ConnectionState().PeerCertificates

var buf bytes.Buffer
for _, crt := range certs {
b := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: crt.Raw,
})

buf.Write(b)
}

return buf.Bytes(), nil
}

0 comments on commit f01e247

Please sign in to comment.