From 3983dd594a98fe0b2650cc410fccee8560d332e1 Mon Sep 17 00:00:00 2001 From: Jennifer Power Date: Fri, 22 Nov 2024 08:18:14 -0500 Subject: [PATCH] feat: initial setup with OSCAL Go type creation and extensions (#3) * feat: initial implementation using go_oscal types Creates OSCAL objects Compass OSCAL extensions definitions Signed-off-by: Jennifer Power * docs: refines public symbol comments for clarity Signed-off-by: Jennifer Power * chore: cleanup Makefile and wording errors in extension doc.go Signed-off-by: Jennifer Power * docs: updates make fmt to make format in README.md Signed-off-by: Jennifer Power --------- Signed-off-by: Jennifer Power --- .gitignore | 9 ++++- LICENSE | 2 +- MAINTAINERS.md | 12 ++++++ Makefile | 25 ++++++++++++ README.md | 41 ++++++++++++++++++- extensions/doc.go | 10 +++++ extensions/rules.go | 52 ++++++++++++++++++++++++ generators/doc.go | 5 +++ generators/loader.go | 94 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 5 +++ go.sum | 2 + 11 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 MAINTAINERS.md create mode 100644 Makefile create mode 100644 extensions/doc.go create mode 100644 extensions/rules.go create mode 100644 generators/doc.go create mode 100644 generators/loader.go create mode 100644 go.mod create mode 100644 go.sum diff --git a/.gitignore b/.gitignore index 6f72f89..718f1bd 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ *.out # Dependency directories (remove the comment below to include it) -# vendor/ +vendor/ # Go workspace file go.work @@ -23,3 +23,10 @@ go.work.sum # env file .env + +# IDE things +.idea +.vscode + +# OSCAL artifacts +oscal_complete_schema.json diff --git a/LICENSE b/LICENSE index 261eeb9..312d57d 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2024 The OSCAL Compass Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000..6551371 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,12 @@ +- [Overview](#overview) +- [Current Maintainers](#current-maintainers) + +## Overview + +This document contains a list of maintainers in `oscal-sdk-go`. + +## Current Maintainers + +| Maintainer | GitHub ID | Affiliation | +|----------------|--------------------------------------------|-------------| +| Jennifer Power | [jpower432](https://github.com/jpower432) | Red Hat | \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b34058c --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +vendor: + go mod tidy + go mod verify + go mod vendor +.PHONY: vendor + +test-unit: + go test -race -v -coverprofile=coverage.out ./... +.PHONY: test-unit + +sanity: vendor format vet + git diff --exit-code +.PHONY: sanity + +format: + go fmt ./... +.PHONY: format + +vet: + go vet ./... +.PHONY: vet + +lint: + @golangci-lint run ./... +.PHONY: lint diff --git a/README.md b/README.md index 6825ea9..7ed4adc 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ -# oscal-sdk-go \ No newline at end of file +# oscal-sdk-go + +`oscal-sdk-go` complements the `compliance-trestle` SDK by providing the core SDK functionality in Go. + +> WARNING: This project is currently under initial development. APIs may be changed incompatibly from one commit to another. + +## Supported Functionality + +Below is a table to show what is currently supported by the SDK. + +| SDK Functionality | Supported | +|-------------------------------------------|-----------| +| OSCAL Types with Basic Trestle Extensions | ✓ | +| OSCAL Schema Validation | | +| Target Components Extension | | +| Multiple Parameters per Rule | | +| OSCAL to OSCAL Transformation | | +| OSCAL Constraints Validation | | + +## Run tests + +```bash +make test-unit +``` + +## Format and Style + +**Requires [`golangci-lint`](https://golangci-lint.run/welcome/quick-start/)** + +```bash +make format +# For issue identification +make vet +# Linting +make lint +``` + +# Acknowledgments + +This project leverages [`go_oscal`](https://github.com/defenseunicorns/go-oscal) to provide Go types for the OSCAL schema. diff --git a/extensions/doc.go b/extensions/doc.go new file mode 100644 index 0000000..855a10d --- /dev/null +++ b/extensions/doc.go @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* +Package extensions defines types that represent OSCAL-based extensions defined by OSCAL Compass. + +These are defined through OSCAL properties and links. +https://pages.nist.gov/OSCAL/learn/tutorials/general/extension/ +*/ + +package extensions diff --git a/extensions/rules.go b/extensions/rules.go new file mode 100644 index 0000000..e9fe650 --- /dev/null +++ b/extensions/rules.go @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: Apache-2.0 + +package extensions + +// Below are defined oscal.Property names for compass-based extensions +const ( + RuleIdProp = "Rule_Id" + RuleDescriptionProp = "Rule_Description" + CheckIdProp = "Check_Id" + CheckDescriptionProp = "Check_Description" + ParameterIdProp = "Parameter_Id" + ParameterDescriptionProp = "Parameter_Description" + ParameterDefaultProp = "Parameter_Value_Default" +) + +// RuleSet defines a Rule instance with associated +// Check implementation data. +type RuleSet struct { + // Rule is a single rule instance associated with the set. + Rule Rule + // Checks include all associated check data registered for the rule. + Checks []Check +} + +// Rule defines a single compliance rule which can also be defined +// as a technical control or a way to validate implemented requirements. +type Rule struct { + // ID is a string representation of the rule identifier. + ID string + // Description defines description of what the rule does. + Description string + // Parameter is optional information for tuning rule logic. + Parameter *Parameter +} + +// Check defines a single concrete implementation of a Rule. +type Check struct { + // ID is a string representation of the check identifier. + ID string + // Description defines description of what the check does. + Description string +} + +// Parameter identifies a parameter or variable that can be used to alter rule logic. +type Parameter struct { + // ID is a string representation of the parameter identifier. + ID string + // Description defines description of what the parameter does. + Description string + // Value is the selected value or option for the parameter. + Value string +} diff --git a/generators/doc.go b/generators/doc.go new file mode 100644 index 0000000..3ca9687 --- /dev/null +++ b/generators/doc.go @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + +// Package generators generates OSCAL-based objects for use. This includes loading objects from existing content or +// generating sample objects. +package generators diff --git a/generators/loader.go b/generators/loader.go new file mode 100644 index 0000000..77e06fa --- /dev/null +++ b/generators/loader.go @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: Apache-2.0 + +package generators + +import ( + "encoding/json" + "io" + + oscal112 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-2" +) + +// NewCatalog creates a new OSCAL-based control catalog using types from `go-oscal`. +func NewCatalog(reader io.Reader) (catalog *oscal112.Catalog, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.Catalog, nil +} + +// NewProfile creates a new OSCAL-based profile using types from `go-oscal`. +func NewProfile(reader io.Reader) (profile *oscal112.Profile, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.Profile, nil +} + +// NewComponentDefinition creates a new OSCAL-based component definition using types from `go-oscal`. +func NewComponentDefinition(reader io.Reader) (componentDefinition *oscal112.ComponentDefinition, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.ComponentDefinition, nil +} + +// NewSystemSecurityPlan creates a new OSCAL-based system security plan using types from `go-oscal`. +func NewSystemSecurityPlan(reader io.Reader) (systemSecurityPlan *oscal112.SystemSecurityPlan, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.SystemSecurityPlan, nil +} + +// NewAssessmentPlan creates a new OSCAL-based assessment plan using types from `go-oscal`. +func NewAssessmentPlan(reader io.Reader) (assessmentPlan *oscal112.AssessmentPlan, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.AssessmentPlan, nil +} + +// NewAssessmentResults creates a new OSCAL-based assessment results set using types from `go-oscal`. +func NewAssessmentResults(reader io.Reader) (assessmentResult *oscal112.AssessmentResults, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.AssessmentResults, nil +} + +// NewPOAM creates a new OSCAL-based plan of action and milestones using types from `go-oscal`. +func NewPOAM(reader io.Reader) (pOAM *oscal112.PlanOfActionAndMilestones, err error) { + var oscalModels oscal112.OscalModels + dec := json.NewDecoder(reader) + dec.DisallowUnknownFields() + if err = dec.Decode(&oscalModels); err != nil { + return nil, err + } + + return oscalModels.PlanOfActionAndMilestones, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..662e2ed --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/oscal-compass/oscal-sdk-go + +go 1.22.7 + +require github.com/defenseunicorns/go-oscal v0.6.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a50eb8b --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/defenseunicorns/go-oscal v0.6.0 h1:eflEKfk7edu4L4kWf6aNQpS94ljfGP8lgWpsPYNtE1Q= +github.com/defenseunicorns/go-oscal v0.6.0/go.mod h1:UHp2yK9ty2mYJDun7oNhbstCq6SAAwP4YGbw9n7uG6o=