Skip to content
This repository has been archived by the owner on Aug 20, 2021. It is now read-only.

Commit

Permalink
Fix alter append by traditional tree parsing (#71)
Browse files Browse the repository at this point in the history
* Fix alter append by traditional tree parsing

* Fix import path for http imported resources

Signed-off-by: farhankamalkhan <[email protected]>
  • Loading branch information
minhaj10p authored and anweiss committed Jan 30, 2019
1 parent 9b2c365 commit 8bda657
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 141 deletions.
6 changes: 6 additions & 0 deletions cli/cmd/generate/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ var Catalog = cli.Command{
if err != nil {
return cli.NewExitError(err, 1)
}

profile, err = generator.SetBasePath(profile, profilePath)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to setup href path for profiles: %v", err), 1)
}

catalogs, err := generator.CreateCatalogsFromProfile(profile)
if err != nil {
return cli.NewExitError(fmt.Sprintf("cannot create catalogs from profile, err: %v", err), 1)
Expand Down
3 changes: 1 addition & 2 deletions cli/cmd/generate/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,9 @@ var Code = cli.Command{
return cli.NewExitError("cannot create file for catalogs", 1)
}
defer newFile.Close()

profile, err = generator.SetBasePath(profile, profilePath)
if err != nil {
cli.NewExitError(fmt.Errorf("failed to setup href path for profiles: %v", err), 1)
return cli.NewExitError(fmt.Errorf("failed to setup href path for profiles: %v", err), 1)
}
catalogs, err := generator.CreateCatalogsFromProfile(profile)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func TestProcessAdditionWithSameClass(t *testing.T) {
},
}

o := ProcessAlteration(alters, &c)
o := ProcessAlterations(alters, &c)
for _, g := range o.Groups {
for _, c := range g.Controls {
for i := range c.Parts {
Expand Down Expand Up @@ -413,7 +413,7 @@ func TestProcessAdditionWithDifferentPartClass(t *testing.T) {
},
},
}
o := ProcessAlteration(alters, &c)
o := ProcessAlterations(alters, &c)
if len(o.Groups[0].Controls[0].Parts) != 2 {
t.Error("parts for controls not getting added properly")
}
Expand Down
114 changes: 2 additions & 112 deletions generator/manipulation.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package generator

import (
"context"
"fmt"
"os"
"time"

"github.com/sirupsen/logrus"

"github.com/docker/oscalkit/impl"
"github.com/docker/oscalkit/types/oscal"
"github.com/docker/oscalkit/types/oscal/catalog"
"github.com/docker/oscalkit/types/oscal/profile"
)
Expand Down Expand Up @@ -62,8 +56,8 @@ func ProcessAddition(alt profile.Alter, controls []catalog.Control) []catalog.Co
return controls
}

// ProcessAlteration processes alteration section of a profile
func ProcessAlteration(alterations []profile.Alter, c *catalog.Catalog) *catalog.Catalog {
// ProcessAlterations processes alteration section of a profile
func ProcessAlterations(alterations []profile.Alter, c *catalog.Catalog) *catalog.Catalog {
for _, alt := range alterations {
for i, g := range c.Groups {
c.Groups[i].Controls = ProcessAddition(alt, g.Controls)
Expand Down Expand Up @@ -110,107 +104,3 @@ func ModifyParts(p catalog.Part, controlParts []catalog.Part) []catalog.Part {
}
return parts
}

// FindAlter finds alter manipulation attribute in the profile import chain
func FindAlter(call profile.Call, p *profile.Profile) (*profile.Alter, error) {

ec := make(chan error)
altCh := make(chan *profile.Alter)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
for _, i := range p.Imports {
err := ValidateHref(i.Href)
if err != nil {
return nil, err
}
basePath := i.Href.String()
go func(i profile.Import) {
traverseProfile(ctx, call, p, altCh, ec, basePath)
}(i)
}

select {
case alt := <-altCh:
return alt, nil
case err := <-ec:
return nil, err
case <-ctx.Done():
return nil, timeoutErr(call)
}

}

func traverseProfile(ctx context.Context, call profile.Call, p *profile.Profile, altCh chan *profile.Alter, errCh chan error, basePath string) {

if p == nil {
errCh <- fmt.Errorf("profile cannot be nil")
return
}
if p.Modify == nil {
errCh <- fmt.Errorf("modify is nil")
return
}
for _, alt := range p.Modify.Alterations {
if alt.ControlId == call.ControlId {
altCh <- &alt
return
}
if alt.SubcontrolId == call.SubcontrolId {
altCh <- &alt
return
}
}

p, err := SetBasePath(p, basePath)
if err != nil {
errCh <- err
return
}

for _, imp := range p.Imports {
err := ValidateHref(imp.Href)
if err != nil {
errCh <- err
return
}
go func(imp profile.Import) {
if imp.Href == nil {
errCh <- fmt.Errorf("import href cannot be nil")
return
}
path, err := GetFilePath(imp.Href.String())
if err != nil {
errCh <- err
return
}
f, err := os.Open(path)
if err != nil {
errCh <- err
return
}
defer f.Close()
o, err := oscal.New(f)
if err != nil {
errCh <- err
return
}
if o.Profile == nil {
logrus.Warn("catalog found")
return
}
traverseProfile(ctx, call, o.Profile, altCh, errCh, basePath)
}(imp)

}

}

func timeoutErr(call profile.Call) error {
if call.ControlId != "" {
return fmt.Errorf("unable to find control id %s in the profile import chain, needs review", call.ControlId)
}
if call.SubcontrolId != "" {
return fmt.Errorf("unable to find sub-control id %s in the profile import chain, needs review", call.SubcontrolId)
}
return nil
}
18 changes: 13 additions & 5 deletions generator/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,31 @@ import (
"fmt"
"os"
"strings"
"time"

"github.com/docker/oscalkit/impl"
"github.com/docker/oscalkit/types/oscal"
"github.com/docker/oscalkit/types/oscal/catalog"
"github.com/docker/oscalkit/types/oscal/profile"
"github.com/sirupsen/logrus"
)

// CreateCatalogsFromProfile maps profile controls to multiple catalogs
func CreateCatalogsFromProfile(profileArg *profile.Profile) ([]*catalog.Catalog, error) {

t := time.Now()
done := 0
errChan := make(chan error)
catalogChan := make(chan *catalog.Catalog)
var outputCatalogs []*catalog.Catalog
// profileArg, err := AppendAlterations(profileArg)
// if err != nil {
// return nil, err
// }
logrus.Info("fetching alterations...")
alterations, err := GetAlters(profileArg)
if err != nil {
return nil, err
}
logrus.Info("fetching alterations from import chain complete")

logrus.Debug("processing alteration and parameters... \nmapping to controls...")
// Get first import of the profile (which is a catalog)
for _, profileImport := range profileArg.Imports {
err := ValidateHref(profileImport.Href)
Expand All @@ -41,7 +48,7 @@ func CreateCatalogsFromProfile(profileArg *profile.Profile) ([]*catalog.Catalog,
// Prepare a new catalog object to merge into the final List of OutputCatalogs
if profileArg.Modify != nil {
nc := impl.NISTCatalog{}
importedCatalog = ProcessAlteration(profileArg.Modify.Alterations, importedCatalog)
importedCatalog = ProcessAlterations(alterations, importedCatalog)
importedCatalog = ProcessSetParam(profileArg.Modify.ParamSettings, importedCatalog, &nc)
}
newCatalog, err := GetMappedCatalogControlsFromImport(importedCatalog, profileImport)
Expand Down Expand Up @@ -69,6 +76,7 @@ func CreateCatalogsFromProfile(profileArg *profile.Profile) ([]*catalog.Catalog,
outputCatalogs = append(outputCatalogs, newCatalog)
}
if done == len(profileArg.Imports) {
logrus.Infof("successfully mapped controls in %f seconds", time.Since(t).Seconds())
return outputCatalogs, nil
}
}
Expand Down
Loading

0 comments on commit 8bda657

Please sign in to comment.