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
75 changes: 62 additions & 13 deletions cmd/estclient/cacerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"fmt"
"io"
"log"
"os"
"strings"

"github.com/globalsign/pemfile"
)
Expand All @@ -39,6 +41,18 @@ func cacerts(w io.Writer, set *flag.FlagSet) error {
}
}()

// make sure adequate set of filtering flags was passed
numberOfFilterFlagsSet := 0
filterFlags := []bool{cfg.FlagWasPassed(rootsOnlyFlag), cfg.FlagWasPassed(intermediatesOnlyFlag), cfg.FlagWasPassed(rootOutFlag)}
for _, flag := range filterFlags {
if flag {
numberOfFilterFlagsSet++
}
}
if numberOfFilterFlagsSet > 1 {
return fmt.Errorf("only one of -%s, -%s and -%s may be specified", rootsOnlyFlag, intermediatesOnlyFlag, rootOutFlag)
}

client, err := cfg.MakeClient()
if err != nil {
return fmt.Errorf("failed to make EST client: %v", err)
Expand All @@ -52,28 +66,63 @@ func cacerts(w io.Writer, set *flag.FlagSet) error {
return fmt.Errorf("failed to get CA certificates: %v", err)
}

if cfg.FlagWasPassed(rootOutFlag) {
var root *x509.Certificate
// filter certificates if requested
if numberOfFilterFlagsSet == 1 {
var roots, intermediates []*x509.Certificate

for _, cert := range certs {
if bytes.Equal(cert.RawSubject, cert.RawIssuer) && cert.CheckSignatureFrom(cert) == nil {
root = cert
break
roots = append(roots, cert)
if cfg.FlagWasPassed(rootOutFlag) {
break
}
} else {
intermediates = append(intermediates, cert)
}
}
if root == nil {
return errors.New("failed to find a root certificate in CA certificates")

if cfg.FlagWasPassed(rootsOnlyFlag) || cfg.FlagWasPassed(rootOutFlag) {
certs = roots
} else if cfg.FlagWasPassed(intermediatesOnlyFlag) {
certs = intermediates
}
certs = []*x509.Certificate{root}
}

out, closeFunc, err := maybeRedirect(w, cfg.FlagValue(outFlag), 0666)
if err != nil {
return err
if cfg.FlagWasPassed(rootOutFlag) && len(certs) == 0 {
return errors.New("failed to find a root certificate in CA certificates")
}
defer closeFunc()

if err := pemfile.WriteCerts(out, certs); err != nil {
return fmt.Errorf("failed to write CA certificates: %v", err)
if cfg.FlagWasPassed(separateOutFlag) {
var prefix string
if prefix = cfg.FlagValue(outFlag); len(prefix) > 0 {
prefix = strings.TrimSuffix(prefix, ".pem") + "-"
} else {
prefix = "ca-"
}

for i, cert := range certs {
filename := fmt.Sprintf("%s%d.pem", prefix, i+1)

out, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return fmt.Errorf("failed to create output file: %v", err)
}
defer out.Close()

if err := pemfile.WriteCert(out, cert); err != nil {
return fmt.Errorf("failed to write CA certificate: %v", err)
}
}
} else {
out, closeFunc, err := maybeRedirect(w, cfg.FlagValue(outFlag), 0666)
if err != nil {
return err
}
defer closeFunc()

if err := pemfile.WriteCerts(out, certs); err != nil {
return fmt.Errorf("failed to write CA certificates: %v", err)
}
}

return nil
Expand Down
3 changes: 3 additions & 0 deletions cmd/estclient/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ func init() {
insecureFlag,
keyFlag,
outFlag,
separateOutFlag,
passwordFlag,
rootOutFlag,
Comment thread
paulgriffiths marked this conversation as resolved.
rootsOnlyFlag,
intermediatesOnlyFlag,
separatorFlag,
serverFlag,
usernameFlag,
Expand Down
17 changes: 16 additions & 1 deletion cmd/estclient/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ const (
organizationFlag = "org"
organizationalUnitFlag = "ou"
outFlag = "out"
separateOutFlag = "separate"
passwordFlag = "pass"
postalCodeFlag = "postalcode"
provinceFlag = "province"
rootOutFlag = "rootout"
rootsOnlyFlag = "roots"
intermediatesOnlyFlag = "intermediates"
separatorFlag = "separator"
serialNumberFlag = "sn"
serverFlag = "server"
Expand Down Expand Up @@ -204,14 +207,26 @@ var optDefs = map[string]option{
desc: "output file",
defaultValue: "",
},
separateOutFlag: {
desc: fmt.Sprintf("write every CA certificate to a separate file with optional prefix specified by -%s", outFlag),
defaultValue: false,
},
passwordFlag: {
argFmt: stringFmt,
defaultLabel: "none",
desc: "HTTP Basic Auth password",
defaultValue: "",
},
rootOutFlag: {
desc: "output root CA certificate only",
desc: fmt.Sprintf("output the first root CA certificate only; this flag will be deprecated in favor of -%s, which is preferred", rootsOnlyFlag),
defaultValue: false,
},
rootsOnlyFlag: {
desc: "only output root (self-signed) certificates",
defaultValue: false,
},
intermediatesOnlyFlag: {
desc: "only output intermediate certificates",
defaultValue: false,
},
separatorFlag: {
Expand Down