Skip to content

Commit

Permalink
fix(read): error checking prior to file writes (#687)
Browse files Browse the repository at this point in the history
* fix: better error messaging on write oscal

* fix: added checks for bad output models

* fix: added oscal validation to generate
  • Loading branch information
meganwolf0 authored Oct 1, 2024
1 parent 1960a80 commit 1ab0eef
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 5 deletions.
6 changes: 6 additions & 0 deletions src/cmd/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ var generateComponentCmd = &cobra.Command{
var remarks []string
var title = "Component Title"

// Check if output file contains a valid OSCAL model
_, err := oscal.ValidOSCALModelAtPath(opts.OutputFile)
if err != nil {
message.Fatalf(err, "Output file %s is not a valid OSCAL model: %v", opts.OutputFile, err)
}

// check for Catalog Source - this field is required
if componentOpts.CatalogSource == "" {
message.Fatal(fmt.Errorf("no catalog source provided"), "generate component requires a catalog input source")
Expand Down
8 changes: 7 additions & 1 deletion src/cmd/tools/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ var composeCmd = &cobra.Command{
outputFile = GetDefaultOutputFile(composeOpts.InputFile)
}

err := Compose(composeOpts.InputFile, outputFile)
// Check if output file contains a valid OSCAL model
_, err := oscal.ValidOSCALModelAtPath(outputFile)
if err != nil {
message.Fatalf(err, "Output file %s is not a valid OSCAL model: %v", outputFile, err)
}

err = Compose(composeOpts.InputFile, outputFile)
if err != nil {
message.Fatalf(err, "Composition error: %s", err)
}
Expand Down
8 changes: 7 additions & 1 deletion src/cmd/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ var validateCmd = &cobra.Command{
outputFile = getDefaultOutputFile(opts.InputFile)
}

// Check if output file contains a valid OSCAL model
_, err := oscal.ValidOSCALModelAtPath(outputFile)
if err != nil {
message.Fatalf(err, "Output file %s is not a valid OSCAL model: %v", outputFile, err)
}

if SaveResources {
ResourcesDir = filepath.Join(filepath.Dir(outputFile))
}
Expand Down Expand Up @@ -261,7 +267,7 @@ func ValidateOnControlImplementations(controlImplementations *[]oscalTypes_1_1_2
return findings, observations, nil
}

// GetDefaultOutputFile returns the default output file name
// getDefaultOutputFile returns the default output file name and checks if the file already exists
func getDefaultOutputFile(inputFile string) string {
dirPath := filepath.Dir(inputFile)
filename := "assessment-results" + filepath.Ext(inputFile)
Expand Down
27 changes: 24 additions & 3 deletions src/pkg/common/oscal/complete-schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ func WriteOscalModel(filePath string, model *oscalTypes_1_1_2.OscalModels) error
// If the file exists - read the data into the model
existingFileBytes, err := os.ReadFile(filePath)
if err != nil {
return err
return fmt.Errorf("error reading file: %v", err)
}
existingModel, err := NewOscalModel(existingFileBytes)
if err != nil {
return err
return fmt.Errorf("error getting existing model: %v", err)
}

existingModelType, err := GetOscalModel(existingModel)
if err != nil {
return nil
return fmt.Errorf("error getting existing model type: %v", err)
}

if existingModelType != modelType {
Expand Down Expand Up @@ -224,6 +224,27 @@ func GetOscalModel(model *oscalTypes_1_1_2.OscalModels) (modelType string, err e

}

// ValidOSCALModelAtPath takes a path and returns a bool indicating if the model exists/is valid
// bool = T/F that oscal model exists, error = if not nil OSCAL model is invalid
func ValidOSCALModelAtPath(path string) (bool, error) {
_, err := os.Stat(path)
if err != nil {
return false, nil
}

data, err := os.ReadFile(path)
if err != nil {
return true, err
}

_, err = NewOscalModel(data)
if err != nil {
return true, err
}

return true, nil
}

// InjectIntoOSCALModel takes a model target and a map[string]interface{} of values to inject into the model
func InjectIntoOSCALModel(target *oscalTypes_1_1_2.OscalModels, values map[string]interface{}, path string) (*oscalTypes_1_1_2.OscalModels, error) {
// If the target is nil, return an error
Expand Down

0 comments on commit 1ab0eef

Please sign in to comment.