From 28f9fedddea06006b39db3caf7f19730a23edd4c Mon Sep 17 00:00:00 2001 From: eddyzags Date: Fri, 24 Mar 2023 14:23:25 +0100 Subject: [PATCH 1/4] cfssljson: add output argument to place files in specific directory + input validation --- cmd/cfssljson/cfssljson.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/cmd/cfssljson/cfssljson.go b/cmd/cfssljson/cfssljson.go index 8d27adac2..71054c3f0 100644 --- a/cmd/cfssljson/cfssljson.go +++ b/cmd/cfssljson/cfssljson.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "os" + "path/filepath" "github.com/cloudflare/cfssl/cli/version" ) @@ -28,6 +29,16 @@ func writeFile(filespec, contents string, perms os.FileMode) { } } +// isDirectory returns true if the given path leads to a directory. +func isDirectory(path string) (bool, error) { + fileInfo, err := os.Stat(path) + if err != nil { + return false, fmt.Errorf("failed to stat the directory (--output=%s): %v", path, err) + } + + return fileInfo.IsDir(), nil +} + // ResponseMessage represents the format of a CFSSL output for an error or message type ResponseMessage struct { Code int `json:"int"` @@ -54,6 +65,7 @@ func main() { inFile := flag.String("f", "-", "JSON input") output := flag.Bool("stdout", false, "output the response instead of saving to a file") printVersion := flag.Bool("version", false, "print version and exit") + outputDirectory := flag.String("output", "./", "place output files in a specific directory. Must be a folder") flag.Parse() if *printVersion { @@ -61,6 +73,15 @@ func main() { return } + if ok, err := isDirectory(*outputDirectory); !ok { + if err != nil { + fmt.Fprintf(os.Stderr, "failed to ensure directory: %v", err) + } else { + fmt.Fprintf(os.Stderr, "output argument is not a folder (path=%s)", *outputDirectory) + } + os.Exit(1) + } + var baseName string if flag.NArg() == 0 { baseName = "cert" @@ -205,7 +226,8 @@ func main() { } fmt.Fprintf(os.Stdout, "%s\n", e.Contents) } else { - writeFile(e.Filename, e.Contents, e.Perms) + p := filepath.Join(*outputDirectory, e.Filename) + writeFile(p, e.Contents, e.Perms) } } } From de15cd2430a57194f46be589d61e27eef655194a Mon Sep 17 00:00:00 2001 From: eddyzags Date: Fri, 24 Mar 2023 14:23:34 +0100 Subject: [PATCH 2/4] cfssljson: add unit test --- cmd/cfssljson/cfssljson_test.go | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cmd/cfssljson/cfssljson_test.go b/cmd/cfssljson/cfssljson_test.go index 749418744..bf77b066d 100644 --- a/cmd/cfssljson/cfssljson_test.go +++ b/cmd/cfssljson/cfssljson_test.go @@ -18,3 +18,38 @@ func TestReadFile(t *testing.T) { t.Fatal("File not read correctly") } } + +func TestIsDirectory(t *testing.T) { + t.Run("OK", func(t *testing.T) { + ok, err := isDirectory("testdata") + if err != nil { + t.Fatal(err) + } + + if ok == false { + t.Fatal("should be a directory") + } + }) + + t.Run("NOK - Not a directory", func(t *testing.T) { + ok, err := isDirectory("cfssljson.go") + if err != nil { + t.Fatal(err) + } + + if ok == true { + t.Fatal("should not be a directory") + } + }) + + t.Run("NOK - File not present", func(t *testing.T) { + ok, err := isDirectory("notpresent") + if err == nil { + t.Fatal(err) + } + + if ok == true { + t.Fatal("should not exist") + } + }) +} From 550a8effc02c25ba27d6dea37feb099569972ab5 Mon Sep 17 00:00:00 2001 From: eddyzags Date: Sat, 25 Mar 2023 12:01:59 +0100 Subject: [PATCH 3/4] cfssljson: improve error msg formatting --- cmd/cfssljson/cfssljson.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cfssljson/cfssljson.go b/cmd/cfssljson/cfssljson.go index 71054c3f0..40e938122 100644 --- a/cmd/cfssljson/cfssljson.go +++ b/cmd/cfssljson/cfssljson.go @@ -33,7 +33,7 @@ func writeFile(filespec, contents string, perms os.FileMode) { func isDirectory(path string) (bool, error) { fileInfo, err := os.Stat(path) if err != nil { - return false, fmt.Errorf("failed to stat the directory (--output=%s): %v", path, err) + return false, fmt.Errorf("failed to stat the directory (--output=%s): %v\n", path, err) } return fileInfo.IsDir(), nil From fb292a11cc1270303e7c0a47d42af4d64b8652e4 Mon Sep 17 00:00:00 2001 From: eddyzags Date: Sat, 25 Mar 2023 12:35:57 +0100 Subject: [PATCH 4/4] README: update doc to explain output argument for cfssljson --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ce044c425..5740fd210 100644 --- a/README.md +++ b/README.md @@ -396,6 +396,9 @@ filenames in the following way: * if __bundle__ is specified, __basename-bundle.pem__ will be produced. * if __ocspResponse__ is specified, __basename-response.der__ will be produced. +If you want to save the files in another directory, you can pass the +folder path using the `-output` argument. + Instead of saving to a file, you can pass `-stdout` to output the encoded contents to standard output.