Skip to content

Commit

Permalink
feat: Can specify a custom dashboard-index filename #1
Browse files Browse the repository at this point in the history
  • Loading branch information
xntrik committed Sep 22, 2021
1 parent 8b0240d commit eb8d633
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 7 deletions.
24 changes: 17 additions & 7 deletions cmd/hcltm/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type DashboardCommand struct {
flagNoDfd bool
flagDashboardTemplate string
flagThreatmodelTemplate string
flagDashboardFilename string
}

func (c *DashboardCommand) Help() string {
Expand All @@ -56,6 +57,8 @@ Options:
-dashboard-template=<file>
-dashboard-filename=<filename>
-threatmodel-template=<file>
`
Expand All @@ -66,7 +69,8 @@ func (c *DashboardCommand) Run(args []string) int {

flagSet := c.GetFlagset("dashboard")
flagSet.StringVar(&c.flagOutDir, "outdir", "", "Directory to output MD files. Will create directory if it doesn't exist. Must be set")
flagSet.StringVar(&c.flagDashboardTemplate, "dashboard-template", "", "Template file to override the default dashboard.md file")
flagSet.StringVar(&c.flagDashboardTemplate, "dashboard-template", "", "Template file to override the default dashboard index file")
flagSet.StringVar(&c.flagDashboardFilename, "dashboard-filename", "dashboard", "Instead of writing dashboard.md, write to <filename>.md")
flagSet.StringVar(&c.flagThreatmodelTemplate, "threatmodel-template", "", "Template file to override the default threatmodel.md file(s)")
flagSet.BoolVar(&c.flagOverwrite, "overwrite", false, "Overwrite existing files in the outdir. Defaults to false")
flagSet.BoolVar(&c.flagNoDfd, "nodfd", false, "Do not include generated DFD images. Defaults to false")
Expand All @@ -86,13 +90,19 @@ func (c *DashboardCommand) Run(args []string) int {
return 1
}

err := validateFilename(c.flagDashboardFilename)
if err != nil {
fmt.Printf("Error with -dashboard-filename: %s\n", err)
return 1
}

if len(flagSet.Args()) == 0 {
fmt.Printf("Please provide file(s)\n\n")
fmt.Println(c.Help())
return 1
} else {

// Parse the dashboard.md template first before creating folders
// Parse the dashboard-index template first before creating folders

dashboardTemplate := ""

Expand Down Expand Up @@ -170,7 +180,7 @@ func (c *DashboardCommand) Run(args []string) int {
// We use outfiles to generate a list of output files to validate whether
// we're overwriting them or not.
outfiles := []string{
fmt.Sprintf("%s/dashboard.md", c.flagOutDir),
fmt.Sprintf("%s/%s.md", c.flagOutDir, c.flagDashboardFilename),
}

// Find all the .hcl files we're going to parse
Expand Down Expand Up @@ -268,7 +278,7 @@ func (c *DashboardCommand) Run(args []string) int {

fmt.Printf("Successfully wrote to '%s'\n", outfile)

// Now we add it to the dashboard.md tmList
// Now we add it to the dashboard-index tmList

tmListEntry := tmListEntryType{
Name: tm.Name,
Expand Down Expand Up @@ -318,9 +328,9 @@ func (c *DashboardCommand) Run(args []string) int {
return tmList[i].Name < tmList[j].Name
})

// Now we create the dashboard.md file
// Now we create the dashboard-index file

f, err := os.Create(c.flagOutDir + "/dashboard.md")
f, err := os.Create(c.flagOutDir + fmt.Sprintf("/%s.md", c.flagDashboardFilename))
if err != nil {
fmt.Printf("Error creating dashboard file: %s\n", err)
return 1
Expand All @@ -333,7 +343,7 @@ func (c *DashboardCommand) Run(args []string) int {
return 1
}

fmt.Printf("Successfully wrote to '%s/dashboard.md'\n", c.flagOutDir)
fmt.Printf("Successfully wrote to '%s/%s.md'\n", c.flagOutDir, c.flagDashboardFilename)

}

Expand Down
71 changes: 71 additions & 0 deletions cmd/hcltm/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,74 @@ func TestDashboardTmBrokenTemplate(t *testing.T) {
t.Errorf("%s did not contains %s", out, "Error parsing template: template: TMTemplate:3")
}
}

func TestDashboardInvalidDashboardfile(t *testing.T) {
d, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("Error creating tmp dir: %s", err)
}

defer os.RemoveAll(d)

cmd := testDashboardCommand(t)

var code int

out := capturer.CaptureStdout(func() {
code = cmd.Run([]string{
fmt.Sprintf("-outdir=%s", d),
"-overwrite",
"-dashboard-filename=./testdata",
"./testdata/tm1.hcl",
})
})

if code != 1 {
t.Errorf("Code did not equal 1: %d", code)
}

if !strings.Contains(out, "Error with -dashboard-filename") {
t.Errorf("%s did not contains %s", out, "Error with -dashboard-filename")
}

}

func TestDashboardValidDashboardfile(t *testing.T) {
d, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("Error creating tmp dir: %s", err)
}

defer os.RemoveAll(d)

cmd := testDashboardCommand(t)

var code int

out := capturer.CaptureStdout(func() {
code = cmd.Run([]string{
fmt.Sprintf("-outdir=%s", d),
"-overwrite",
"-dashboard-filename=index",
"./testdata/tm1.hcl",
})
})

if code != 0 {
t.Errorf("Code did not equal 0: %d", code)
}

if !strings.Contains(out, fmt.Sprintf("Created the '%s'", d)) {
t.Errorf("%s did not contain %s", out, fmt.Sprintf("Created the '%s'", d))
}

dbfile, err := ioutil.ReadFile(fmt.Sprintf("%s/index.md", d))
if err != nil {
t.Fatalf("Error opening dashboard file: %s", err)
}

if !strings.Contains(string(dbfile), "# HCLTM Dashboard") {
t.Errorf("Expected %s to contain %s", dbfile, "# HCLTM Dashboard")
}

}
11 changes: 11 additions & 0 deletions cmd/hcltm/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ func configFileLocation() (string, error) {
return filepath.Join(homeDir, ".hcltmrc"), nil
}

func validateFilename(filename string) error {
reg := regexp.MustCompile("[^a-zA-Z0-9_-]+")
validFilename := reg.ReplaceAllString(filename, "")

if filename != validFilename {
return fmt.Errorf("Provided filename contains illegal characters")
}

return nil
}

// createOrValidateFolder is used for creating or validating
// an output folder. This is used when a command needs to
// output files into a folder
Expand Down
41 changes: 41 additions & 0 deletions cmd/hcltm/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,44 @@ func TestPrettyBool(t *testing.T) {
})
}
}

func TestValidFilename(t *testing.T) {
cases := []struct {
name string
in string
expectError bool
}{
{
"valid",
"valid",
false,
},
{
"in.valid",
"in.valid",
true,
},
{
"with-slash",
"/no",
true,
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()

err := validateFilename(tc.in)
if tc.expectError && err == nil {
t.Errorf("Expected error... from input '%s'", tc.in)
}

if !tc.expectError && err != nil {
t.Errorf("Did not expect error: %s", err)
}
})
}
}

0 comments on commit eb8d633

Please sign in to comment.