-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Boostrap oscal generator and subcommand #194
base: main
Are you sure you want to change the base?
Conversation
cmd/pkg/baseline/generator_oscal.go
Outdated
Parts: &[]oscal.Part{ | ||
{ | ||
ID: strings.TrimPrefix(criteria.ID, "OSPS-") + "_level", | ||
Name: "maturity-level", | ||
Prose: fmt.Sprintf("%d", criteria.MaturityLevel), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would strongly recommend using OSCAL props: []
in the JSON data format) over parts for this.
Here is the official OSCAL documentation for that in the catalog model. They nest inside the control similarly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback, love the suggestion! I've pushed a new commit moving maturity level to a property. Check out the new output here
https://gist.github.com/puerco/e4a18354c281d45fc900cfb626adf286
cmd/pkg/baseline/generator_oscal.go
Outdated
|
||
enc := json.NewEncoder(w) | ||
enc.SetIndent("", " ") | ||
if err := enc.Encode(catalog); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will produce the file for all of the content within the catalog model - but if we look at a catalog example we need the catalog
object key included for validity of the model.
This can be done a number of ways. Typically we use the complete schema to reference the catalog and encode the complete schema.
go-oscal has a CLI with a validate
command that can perform schema validation of models if that is helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks for the tip! I've wrapped the doc into a "catalog" label and fixed the validation:
go run . validate --input-file ../ossf/security-baseline/cmd/oscal.json
go-oscal: 2025/02/20 19:05:13 Successfully validated ../ossf/security-baseline/cmd/oscal.json is valid OSCAL version 1.1.3 catalog
) | ||
|
||
const ( | ||
VersionOSPS = "devel" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So how will this work when we release a version? Currently, the SOP is to copy the rendered .md to a directory. How do we generate the OSCAL JSON with the correct version strings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is just "this current version" the issue at hand, @funnelfiasco, or you want to consider how you manage "the lifecycle of versions and say where this version is a series of versions" kind of perspective? OSCAL can encode both, not sure how you all want to handle it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is that including a link to the "devel" version of a control may not give the right information if the file was generated against a previous version of the OSPS Baseline. It's not clear to me what @puerco intends to do with the generated json. Is it something we'll publish alongside the versioned baseline files? Is it something that we expect people to generate ad hoc if they need it? Something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK cool. So there is simple and complex ways to handle this in OSCAL, I am not sure which one suits the group best. Each OSCAL model, of course the beloved catalog, uses the same //metadata
assembly and that can have zero, one or many revisions
. Now you could "reinvent all of git" (and I say that sarcastically, who would do that?) and enumerate every revision. But there is another thing you could do here, if it suits you all. You see the docs talk about this:
Constraint (1)
allowed values for link/@rel
The value may be locally defined, or one of the following:
canonical: The link identifies the authoritative location for this resource. Defined by RFC 6596.
alternate: The link identifies an alternative location or format for this resource. Defined by the HTML Living Standard
predecessor-version: This link identifies a resource containing the predecessor version in the version history. Defined by RFC 5829.
successor-version: This link identifies a resource containing the predecessor version in the version history. Defined by RFC 5829.
version-history: This link identifies a resource containing the version history of this document. Defined by RFC 5829.
So why do I bring this up? You could decide to keep the version at devel
for now or figure out some other ID. And you can point to the version-history
to say where all releases are, before or after you release them. Something like so:
---
catalog:
uuid: 394c88cf-07c0-4380-899b-053810d8b21e
version: devel # or maybe something different?
oscal-version: 1.1.3
last-modified: 2025-02-20T03:43:57Z
published: 2025-02-20T03:43:57Z
metadata:
revisions:
- title: OpenSSF Security Baseline Releases
links:
- rel: version-history
href: https://github.com/ossf/security-baseline/releases
You could also do something different with predecessor-version
or successor-version
once you have a release or two under your belt, but I find that more complicated than this approach with that @rel
type. That's why it got added. As for devel
there are some other things you could try but I will say my goto that is problematic is a git SHA1 hash? Why not that? Well, because if you want to hash the content and make that the version of the catalog before a release, it is kind of a recursive hell where you need to answer "how do I embed the hash of the content into the content I am hashing?" so I am out of good pre-release ideas, but this facility does give you what you need for the "link to previous versions of the baseline" scenario maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is the version string of the baseline the generator renders. This will be automatically picked up from the relases once we have them. For now it is hardcoded to"devel". I'll work on the tagging machinery once we cut our second release.
Thanks for the version-history @xee5ch! I'll make sure we generate those once we start releasing the oscal files as part of the releases .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I thought you would appreciate that. From NIST or other community adopters, you are one of the few to take this tact and it is the smart play. Happy to see it!
cmd/pkg/baseline/generator_oscal.go
Outdated
Props: &[]oscal.Property{ | ||
{ | ||
Name: "maturity-level", | ||
UUID: catalogUUID, | ||
Value: fmt.Sprintf("%d", criteria.MaturityLevel), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the update here to use prop
, but another minor recommendation given extending and customizing data, it might make sense to namespace (with ns
) that maturity-level
has a specific meaning in the context of OpenSSF and if other organizations have a similar prop, they do not "collide" with its use or downstream code assumes some other group's use of the term applies here. The go-oscal library seems to support this, so I'd recommend picking a ns URL to use in props and other things and sticking to it through the codebase for namespacing per the guidance.
I am not saying it has to be that specific value, but just giving you an idea of where I am going with it.
Props: &[]oscal.Property{ | |
{ | |
Name: "maturity-level", | |
UUID: catalogUUID, | |
Value: fmt.Sprintf("%d", criteria.MaturityLevel), | |
}, | |
Props: &[]oscal.Property{ | |
{ | |
Ns: "http://openssf.org/ns/oscal", | |
Name: "maturity-level", | |
UUID: catalogUUID, | |
Value: fmt.Sprintf("%d", criteria.MaturityLevel), | |
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took out the maturity level for now as I need to introduce some changes to the new schema to handle them properly.
cmd/pkg/baseline/generator_oscal.go
Outdated
pts := append(*newCtl.Parts, oscal.Part{ | ||
ID: strings.TrimPrefix(criteria.ID, "OSPS-") + "_implementation", | ||
Name: "implementation", | ||
Prose: strings.TrimSpace(criteria.Implementation), | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend per the OSCAL docs on /catalog/parts/@name
to change this to example
.
pts := append(*newCtl.Parts, oscal.Part{ | |
ID: strings.TrimPrefix(criteria.ID, "OSPS-") + "_implementation", | |
Name: "implementation", | |
Prose: strings.TrimSpace(criteria.Implementation), | |
}) | |
pts := append(*newCtl.Parts, oscal.Part{ | |
ID: strings.TrimPrefix(criteria.ID, "OSPS-") + "_example", | |
Name: "example", | |
Prose: strings.TrimSpace(criteria.Implementation), | |
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one was also deprecated with the new schema
This command initializes the first oscal output and generator for the baseline data. Signed-off-by: Adolfo García Veytia (Puerco) <adolfo.garcia@uservers.net>
Signed-off-by: Adolfo García Veytia (Puerco) <adolfo.garcia@uservers.net>
Signed-off-by: Adolfo García Veytia (Puerco) <adolfo.garcia@uservers.net>
cc8786c
to
7988aa8
Compare
@xee5ch I see that the NIST namespace url (https://csrc.nist.gov/ns/oscal) does not return anything. Does this mean that the IRI is just used as a label? Going through the docs it seems that the namespace does not really need to be defined anywhere, other linked data formats namespace with an URI/IRI but also expect a definition file (for example the Context in JSONLD). I guess we are fine just defining our namespace and not really worrying about writing a definition? |
Correct it is just a label. |
Signed-off-by: Adolfo García Veytia (Puerco) <adolfo.garcia@uservers.net>
OK, I pushed commits with updates for the new schema and to fix the validation with @defenseunicorns go-oscal. The new output is published here: https://gist.github.com/puerco/e4a18354c281d45fc900cfb626adf286 |
Name: "recomemendation", | ||
Ns: OpenSSFNS, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to try and dig into this over the weekend, but in the short-term you may want to correct the spelling of the part name.
Name: "recomemendation", | |
Ns: OpenSSFNS, | |
Name: "recommendation", | |
Ns: OpenSSFNS, |
I would say a higher-level issue from using the maintained oscal-cli
community fork is that there may be specific OSCAL rules that say a part should have a certain name if it is in the "default" core NIST OSCAL namespace. Weirdly, yours is not. You did it right. However, the error still persists in the tooling, so I will look into that; it might be a bug on that end so you can safely ignore it. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it seems it is related to the NIST's definition in the OSCAL model, not the tooling. More to follow after usnistgov/OSCAL#2112 is resolved and released in a new model version. You helped find an interesting edge case!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed it too, it also seems that it is ignoring namespaced names.
This command initializes the first oscal output and generator for the base line data.
This lets us generate a first draft of an OSCAL catalog to start testing and iterating on the format.
Here's a sample of the output for feedback
https://gist.github.com/puerco/e4a18354c281d45fc900cfb626adf286
/cc @brandtkeller
Signed-off-by: Adolfo García Veytia (Puerco) adolfo.garcia@uservers.net