func ParseComponent(componentData []byte, fileName string) (base.Component, error) { b := base.Base{} err := yaml.Unmarshal(componentData, &b) if err != nil { // If we have a human friendly BaseComponentParseError, return it. switch err.(type) { case base.BaseComponentParseError: return nil, err } // Otherwise, just return a generic error about the schema. return nil, fmt.Errorf("Unable to parse component %s. Error: %s", fileName, err.Error()) } var component base.Component switch { case ComponentV2_0_0.EQ(b.SchemaVersion): c := new(v2.Component) err = yaml.Unmarshal(componentData, c) component = c case ComponentV3_0_0.EQ(b.SchemaVersion): c := new(v3.Component) err = yaml.Unmarshal(componentData, c) component = c default: return nil, config.ErrUnknownSchemaVersion } if err != nil { return nil, fmt.Errorf("Unable to parse component. Please check component.yaml schema for version %s", b.SchemaVersion.String()) } // Copy version from base because some versions of the component can not expect to parse directly into it's own struct // e.g. version 2.0.0 with 2.0 float component.SetVersion(b.SchemaVersion) return component, nil }
// getNarrativeSection will just print the narrative section text. No need to print the section header since it was specified. func getNarrativeSection(text string, justification models.Verification, component base.Component, specifiedSections *set.Set) string { // Add the component name. text = fmt.Sprintf("%s%s\n", text, component.GetName()) // Use generic []base.Section handler. return getSpecificGenericSections(justification.SatisfiesData.GetNarratives(), text, specifiedSections) }
// LoadComponent imports components into a Component struct and adds it to the // Components map. func (openControl *OpenControl) LoadComponent(componentDir string) error { // Get file system assistance. fs := fs.OSUtil{} // Read the component file. fileName := filepath.Join(componentDir, "component.yaml") componentData, err := fs.OpenAndReadFile(fileName) if err != nil { return errors.New(constants.ErrComponentFileDNE) } // Parse the component. var component base.Component component, err = versions.ParseComponent(componentData, fileName) if err != nil { return err } // Ensure we have a key for the component. if component.GetKey() == "" { component.SetKey(getKey(componentDir)) } // If the component is new, make sure we load the justifications as well. if openControl.Components.CompareAndAdd(component) { openControl.Justifications.LoadMappings(component) } return nil }
func loadValidAndTestComponent(path string, t *testing.T, example base.Component) { openControl := models.OpenControl{ Justifications: models.NewJustifications(), Components: components.NewComponents(), } err := openControl.LoadComponent(path) if !assert.Nil(t, err) { t.Fatalf("Expected reading component found in %s to be successful", path) } // Check the test set with the GetAndApply function openControl.Components.GetAndApply(example.GetKey(), func(actual base.Component) { testSet(example, actual, t) }) // Check the test set with the simple Get function actualComponent := openControl.Components.Get(example.GetKey()) testSet(example, actualComponent, t) }
// getAllNarrativeSection will print both the section header and the section text for all narrative sections. func getAllNarrativeSections(text string, justification models.Verification, component base.Component) string { // Add the component name. text = fmt.Sprintf("%s%s\n", text, component.GetName()) for _, section := range justification.SatisfiesData.GetNarratives() { // If we want to print out all the sections... // If section header exists, let's print it. Key could be empty, in that case // just print the text for the section. if section.GetKey() != "" { text = fmt.Sprintf("%s%s:\n", text, section.GetKey()) } text = fmt.Sprintf("%s%s\n", text, section.GetText()) // Automatically assume foundText is true as long as the length of // justification.SatisfiesData.Narrative is > 0, which is implied if we reach here. // Also, in case the section in the YAML is explicitly "", we accept empty string here too. } return text }
// getResponsibleRoleInfo will just print the responsible role if it exists. func getResponsibleRoleInfo(text string, component base.Component) string { // Add the component name. text = fmt.Sprintf("%s%s: ", text, component.GetName()) // Print out the component name and the responsible for that component. if component.GetResponsibleRole() != "" { return fmt.Sprintf("%s%s\n", text, component.GetResponsibleRole()) } // Else, print warning indicating there was no info. return fmt.Sprintf("%s%s\n", text, constants.WarningNoInformationAvailable) }
func (openControl *OpenControlGitBook) getCoveredByVerification(text string, component base.Component, coveredBy common.CoveredBy) string { if component != nil { verification := component.GetVerifications().Get(coveredBy.VerificationKey) text += exportLink( fmt.Sprintf("%s - %s", component.GetName(), verification.Name), filepath.Join("..", "components", component.GetKey()+".md"), ) } return text }
// CompareAndAdd compares to see if the component exists in the map. If not, it adds the component. // This function is thread-safe. func (components *Components) CompareAndAdd(component base.Component) bool { components.Lock() defer components.Unlock() added := false if _, exists := components.mapping[component.GetKey()]; !exists { components.mapping[component.GetKey()] = component added = true } else { log.Fatalf("Component: %s exisits!\n", component.GetKey()) } return added }
// Add adds a new component to the component map func (components *Components) Add(component base.Component) { components.Lock() components.mapping[component.GetKey()] = component components.Unlock() }
func (openControl *OpenControlGitBook) getResponsibleRole(text string, component base.Component) string { if component.GetResponsibleRole() != "" { text = fmt.Sprintf("%s\n##### Responsible Role: %s\n", text, component.GetResponsibleRole()) } return text }
func testSet(example base.Component, actual base.Component, t *testing.T) { // Check that the key was loaded if example.GetKey() != actual.GetKey() { t.Errorf("Expected %s, Actual: %s", example.GetKey(), actual.GetKey()) } // Check that the name was loaded if example.GetName() != actual.GetName() { t.Errorf("Expected %s, Actual: %s", example.GetName(), actual.GetName()) } // Check that the schema version was loaded if example.GetVersion().NE(actual.GetVersion()) { t.Errorf("Expected %f, Actual: %f", example.GetVersion(), actual.GetVersion()) } // Check that the references were loaded if example.GetReferences().Len() != actual.GetReferences().Len() { t.Errorf("Expected %d, Actual: %d", example.GetReferences().Len(), actual.GetReferences().Len()) } // Check that the satisfies data was loaded if len(example.GetAllSatisfies()) != len(actual.GetAllSatisfies()) { t.Errorf("Expected %d, Actual: %d", len(example.GetAllSatisfies()), len(actual.GetAllSatisfies())) } // Check Narratives and Parameters. for idx, _ := range actual.GetAllSatisfies() { assert.Equal(t, (example.GetAllSatisfies())[idx].GetNarratives(), (actual.GetAllSatisfies())[idx].GetNarratives()) assert.Equal(t, (example.GetAllSatisfies())[idx].GetParameters(), (actual.GetAllSatisfies())[idx].GetParameters()) } // Check the responsible role. assert.Equal(t, example.GetResponsibleRole(), actual.GetResponsibleRole()) // Check that the verifications were loaded if example.GetVerifications().Len() != actual.GetVerifications().Len() { t.Errorf("Expected %d, Actual: %d", example.GetVerifications().Len(), actual.GetVerifications()) } }
// LoadMappings loads a set of mappings from a component func (justifications *Justifications) LoadMappings(component base.Component) { for _, satisfies := range component.GetAllSatisfies() { justifications.Add(satisfies.GetStandardKey(), satisfies.GetControlKey(), component.GetKey(), satisfies) } }