diff --git a/cli/cmd/generate/code.go b/cli/cmd/generate/code.go index 80e52302..0558c328 100644 --- a/cli/cmd/generate/code.go +++ b/cli/cmd/generate/code.go @@ -78,6 +78,10 @@ var Code = cli.Command{ } 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) + } catalogs, err := generator.CreateCatalogsFromProfile(profile) if err != nil { return cli.NewExitError(fmt.Sprintf("cannot create catalogs from profile, err: %v", err), 1) diff --git a/generator/manipulation.go b/generator/manipulation.go index 921fd166..14ee38e5 100644 --- a/generator/manipulation.go +++ b/generator/manipulation.go @@ -98,8 +98,13 @@ func FindAlter(call profile.Call, p *profile.Profile) (*profile.Alter, error) { 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) + traverseProfile(ctx, call, p, altCh, ec, basePath) }(i) } @@ -114,7 +119,7 @@ func FindAlter(call profile.Call, p *profile.Profile) (*profile.Alter, error) { } -func traverseProfile(ctx context.Context, call profile.Call, p *profile.Profile, altCh chan *profile.Alter, errCh chan error) { +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") @@ -135,7 +140,18 @@ func traverseProfile(ctx context.Context, call profile.Call, p *profile.Profile, } } + 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") @@ -161,7 +177,7 @@ func traverseProfile(ctx context.Context, call profile.Call, p *profile.Profile, logrus.Warn("catalog found") return } - traverseProfile(ctx, call, o.Profile, altCh, errCh) + traverseProfile(ctx, call, o.Profile, altCh, errCh, basePath) }(imp) } diff --git a/generator/mapper.go b/generator/mapper.go index a24d3f14..41a9753e 100644 --- a/generator/mapper.go +++ b/generator/mapper.go @@ -24,14 +24,17 @@ func CreateCatalogsFromProfile(profileArg *profile.Profile) ([]*catalog.Catalog, } // Get first import of the profile (which is a catalog) for _, profileImport := range profileArg.Imports { + err := ValidateHref(profileImport.Href) + if err != nil { + return nil, err + } go func(profileImport profile.Import) { c := make(chan *catalog.Catalog) e := make(chan error) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - // ForEach Import's Href, Fetch the Catalog JSON file - getCatalogForImport(ctx, profileImport, c, e) + getCatalogForImport(ctx, profileImport, c, e, profileImport.Href.String()) select { case importedCatalog := <-c: // Prepare a new catalog object to merge into the final List of OutputCatalogs @@ -132,9 +135,10 @@ func GetMappedCatalogControlsFromImport(importedCatalog *catalog.Catalog, profil return newCatalog, nil } -func getCatalogForImport(ctx context.Context, i profile.Import, c chan *catalog.Catalog, e chan error) { +func getCatalogForImport(ctx context.Context, i profile.Import, c chan *catalog.Catalog, e chan error, basePath string) { go func(i profile.Import) { - if i.Href == nil { + err := ValidateHref(i.Href) + if err != nil { e <- fmt.Errorf("href cannot be nil") return } @@ -158,9 +162,15 @@ func getCatalogForImport(ctx context.Context, i profile.Import, c chan *catalog. c <- o.Catalog return } + newP, err := SetBasePath(o.Profile, basePath) + if err != nil { + e <- err + return + } + o.Profile = newP for _, p := range o.Profile.Imports { go func(p profile.Import) { - getCatalogForImport(ctx, p, c, e) + getCatalogForImport(ctx, p, c, e, basePath) }(p) } }(i) diff --git a/generator/profile.go b/generator/profile.go index 675616bb..d3054a52 100644 --- a/generator/profile.go +++ b/generator/profile.go @@ -1,6 +1,13 @@ package generator import ( + "fmt" + "net/url" + "path" + "path/filepath" + + "github.com/docker/oscalkit/types/oscal/catalog" + "github.com/docker/oscalkit/types/oscal/profile" ) @@ -32,3 +39,25 @@ func AppendAlterations(p *profile.Profile) (*profile.Profile, error) { } return p, nil } + +//SetBasePath sets up base paths for profiles +func SetBasePath(p *profile.Profile, parentPath string) (*profile.Profile, error) { + + for i, x := range p.Imports { + + if x.Href == nil { + return nil, fmt.Errorf("href cannot be nil") + } + path := fmt.Sprintf("%s/%s", path.Dir(parentPath), path.Base(x.Href.String())) + path, err := filepath.Abs(path) + if err != nil { + return nil, err + } + uri, err := url.Parse(path) + if err != nil { + return nil, err + } + p.Imports[i].Href = &catalog.Href{URL: uri} + } + return p, nil +} diff --git a/generator/validator.go b/generator/validator.go new file mode 100644 index 00000000..0c1235b3 --- /dev/null +++ b/generator/validator.go @@ -0,0 +1,20 @@ +package generator + +import ( + "fmt" + "net/url" + + "github.com/docker/oscalkit/types/oscal/catalog" +) + +func ValidateHref(href *catalog.Href) error { + if href == nil { + return fmt.Errorf("Href cannot be empty") + } + + _, err := url.Parse(href.String()) + if err != nil { + return err + } + return nil +}