This commit is contained in:
Aaron Meihm 2017-07-19 10:55:45 -05:00
Родитель bba2ac14e0
Коммит 29c5f68bb4
18 изменённых файлов: 87 добавлений и 46 удалений

Просмотреть файл

@ -11,8 +11,8 @@ import (
"fmt"
)
// A scribe document. Contains all tests and other information used to execute
// the document.
// Document describes a scribe document; a document contains all tests and other
// infomration used to execute a policy check
type Document struct {
Variables []Variable `json:"variables,omitempty" yaml:"variables,omitempty"`
Objects []Object `json:"objects,omitempty" yaml:"objects,omitempty"`
@ -38,7 +38,8 @@ func (d *Document) Validate() error {
return nil
}
// Return the test IDs of all tests present in a document.
// GetTestIdentifiers returns the test identifiers for all tests present in
// the document.
func (d *Document) GetTestIdentifiers() []string {
ret := make([]string, 0)
for _, x := range d.Tests {

5
evr.go
Просмотреть файл

@ -11,6 +11,9 @@ import (
"fmt"
)
// EVRTest describes the EVR option that will be performed as part of a test.
// For example, Operation may be "<" and Value may be a version string such as
// "1.2.3".
type EVRTest struct {
Operation string `json:"operation,omitempty" yaml:"operation,omitempty"`
Value string `json:"value,omitempty" yaml:"value,omitempty"`
@ -19,7 +22,7 @@ type EVRTest struct {
func (e *EVRTest) evaluate(c evaluationCriteria) (ret evaluationResult, err error) {
debugPrint("evaluate(): evr %v \"%v\", %v \"%v\"\n", c.identifier, c.testValue, e.Operation, e.Value)
evrop := evrLookupOperation(e.Operation)
if evrop == EVROP_UNKNOWN {
if evrop == EvropUnknown {
return ret, fmt.Errorf("invalid evr operation %v", e.Operation)
}
ret.criteria = c

Просмотреть файл

@ -23,10 +23,10 @@ import (
// EVR operation constants
const (
_ = iota
EVROP_LESS_THAN
EVROP_GREATER_THAN
EVROP_EQUALS
EVROP_UNKNOWN
EvropLessThan
EvropGreaterThan
EvropEquals
EvropUnknown
)
type evr struct {
@ -38,20 +38,20 @@ type evr struct {
func evrLookupOperation(s string) int {
switch s {
case "<":
return EVROP_LESS_THAN
return EvropLessThan
case ">":
return EVROP_GREATER_THAN
return EvropGreaterThan
case "=":
return EVROP_EQUALS
return EvropEquals
}
return EVROP_UNKNOWN
return EvropUnknown
}
func evrOperationStr(val int) string {
switch val {
case EVROP_LESS_THAN:
case EvropLessThan:
return "<"
case EVROP_EQUALS:
case EvropEquals:
return "="
default:
return "?"
@ -66,9 +66,8 @@ func evrIsNumber(s string) bool {
_, err := strconv.Atoi(s)
if err != nil {
return false
} else {
return true
}
return true
}
func evrExtract(s string) (evr, error) {
@ -282,17 +281,17 @@ func evrCompare(op int, actual string, check string) (bool, error) {
return false, err
}
switch op {
case EVROP_EQUALS:
case EvropEquals:
if ret != 0 {
return false, nil
}
return true, nil
case EVROP_LESS_THAN:
case EvropLessThan:
if ret == 1 {
return true, nil
}
return false, nil
case EVROP_GREATER_THAN:
case EvropGreaterThan:
if ret == -1 {
return true, nil
}
@ -301,9 +300,9 @@ func evrCompare(op int, actual string, check string) (bool, error) {
return false, fmt.Errorf("evrCompare: unknown operator")
}
// An exported version of the EVR comparison operation. op is used to specify
// an EVR comparison operation (e.g., EVROP_LESS_THAN). actual and check are
// the version strings to test. Returns status of test evaluation, or an error
// TestEvrCompare is an exported version of the EVR comparison operation. op is
// used to specify an EVR comparison operation (e.g., EvropLessThan). actual and
// check are the version strings to test. Returns status of test evaluation, or an error
// if an error occurs.
func TestEvrCompare(op int, actual string, check string) (bool, error) {
return evrCompare(op, actual, check)

Просмотреть файл

@ -43,11 +43,11 @@ func main() {
operator := fields[1]
switch operator {
case "=":
opmode = scribe.EVROP_EQUALS
opmode = scribe.EvropEquals
case "<":
opmode = scribe.EVROP_LESS_THAN
opmode = scribe.EvropLessThan
case ">":
opmode = scribe.EVROP_GREATER_THAN
opmode = scribe.EvropGreaterThan
default:
fmt.Fprintf(os.Stderr, "unknown operation %v\n", operator)
os.Exit(1)

Просмотреть файл

@ -7,6 +7,8 @@
package scribe
// ExactMatch is used to indicate a test should match Value exactly against
// the referenced object
type ExactMatch struct {
Value string `json:"value,omitempty" yaml:"value,omitempty"`
}

Просмотреть файл

@ -18,6 +18,8 @@ import (
"regexp"
)
// FileContent is used to perform tests against the content of a given file
// on the file system.
type FileContent struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
File string `json:"file,omitempty" yaml:"file,omitempty"`

Просмотреть файл

@ -13,6 +13,8 @@ import (
"regexp"
)
// FileName is used to perform tests against a given file name on
// the file system
type FileName struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
File string `json:"file,omitempty" yaml:"file,omitempty"`

Просмотреть файл

@ -12,6 +12,8 @@ import (
"regexp"
)
// HasLine is used to perform tests against whether or not a file contains a given
// regular expression
type HasLine struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
File string `json:"file,omitempty" yaml:"file,omitempty"`

Просмотреть файл

@ -11,6 +11,10 @@ import (
"fmt"
)
// Object describes data that will be sourced from the system and used in a
// test. Tests specify the criteria that will be applied to determine a true
// or false result, and tests reference an Object which provides the data the
// criteria will be compared to.
type Object struct {
Object string `json:"object" yaml:"object"`
FileContent FileContent `json:"filecontent" yaml:"filecontent"`

Просмотреть файл

@ -12,6 +12,9 @@ import (
"regexp"
)
// Pkg is used to perform tests against packages that are installed on the
// system, for example package version tests.
//
// Normally when a Pkg object is prepared, the pkgInfo list will be filled with
// information related to any package installed which exactly matches Name. If
// the optional CollectMatch parameter is set, this regular expression will be
@ -82,7 +85,7 @@ func newestPackage(r pkgmgrResult) (ret packageInfo, err error) {
pinfo = &r.results[i]
continue
}
f, err := evrCompare(EVROP_LESS_THAN, pinfo.version, r.results[i].version)
f, err := evrCompare(EvropLessThan, pinfo.version, r.results[i].version)
if err != nil {
return ret, err
}

Просмотреть файл

@ -17,9 +17,9 @@ import (
"gopkg.in/yaml.v2"
)
// Load a scribe JSON or YAML document from the reader specified by r.
// Returns a Document type that can be passed to AnalyzeDocument().
// On error, LoadDocument() returns the error that occurred.
// LoadDocument loads a scribe JSON or YAML document from the reader
// specified by r. Returns a Document type that can be passed to
// AnalyzeDocument(). On error, LoadDocument() returns the error that occurred.
func LoadDocument(r io.Reader) (Document, error) {
var ret Document
@ -58,9 +58,9 @@ func LoadDocument(r io.Reader) (Document, error) {
return ret, nil
}
// Analyze a scribe document on the host system. The will prepare and
// execute all tests specified in the scribe document. Returns an error
// if a fatal error occurs.
// AnalyzeDocument analyzes a scribe document on the host system. The will
// prepare and execute all tests specified in the scribe document. Returns
// an error if a fatal error occurs.
//
// Note that an error in an individual test does not necessarily represent
// a fatal error condition. In these cases, the test itself will be marked

Просмотреть файл

@ -27,7 +27,7 @@ type pkgmgrInfo struct {
arch string
}
// Package information from the system as returned by QueryPackages().
// PackageInfo stores information from the system as returned by QueryPackages().
type PackageInfo struct {
Name string `json:"name" yaml:"name"` // Package name.
Version string `json:"version" yaml:"version"` // Package version.
@ -35,8 +35,8 @@ type PackageInfo struct {
Arch string `json:"arch" yaml:"arch"` // Package architecture
}
// Query packages on the system, returning a slice of all identified packages
// in PackageInfo form.
// QueryPackages will query packages on the system, returning a slice of all
// identified packages in PackageInfo form.
func QueryPackages() []PackageInfo {
ret := make([]PackageInfo, 0)
for _, x := range getAllPackages().results {

6
raw.go
Просмотреть файл

@ -11,10 +11,16 @@ import (
"fmt"
)
// Raw can be used to create an object that has values already defined directly
// in the policy file. For example, an object with a raw entry is not populated from
// the system, but the raw values themselves are referencable from a test or from
// another object using an import-chain.
type Raw struct {
Identifiers []RawIdentifiers `json:"identifiers,omitempty" yaml:"identifiers,omitempty"`
}
// RawIdentifiers are the identifier/value pairs that make up raw entries in an
// object.
type RawIdentifiers struct {
Identifier string `json:"identifier,omitempty" yaml:"identifier,omitempty"`
Value string `json:"value,omitempty" yaml:"value,omitempty"`

Просмотреть файл

@ -11,6 +11,7 @@ import (
"regexp"
)
// Regex is used to specify regular expression matching criteria within a test.
type Regex struct {
Value string `json:"value,omitempty" yaml:"value,omitempty"`
}

Просмотреть файл

@ -13,7 +13,7 @@ import (
"strings"
)
// Describes the results of a test. The type can be marshaled into a JSON
// TestResult describes the results of a test. The type can be marshaled into a JSON
// string as required.
type TestResult struct {
TestID string `json:"testid" yaml:"testid"` // The identifier for the test.
@ -30,15 +30,17 @@ type TestResult struct {
Results []TestSubResult `json:"results" yaml:"results"` // The sub-results for the test.
}
// TestSubResult describes a sub-result for a test.
//
// For a given test, a number of sources can be identified that match the
// criteria. For example, multiple files can be identifier with a given
// criteria. For example, multiple files can be identified with a given
// filename. Each test tracks individual results for these cases.
type TestSubResult struct {
Result bool `json:"result" yaml:"result"` // The result of evaluation for an identifier source.
Identifier string `json:"identifier" yaml:"identifier"` // The identifier for the source.
}
// Return test results for a given test. Returns an error if for
// GetResults returns test results for a given test. Returns an error if for
// some reason the results can not be returned.
func GetResults(d *Document, name string) (TestResult, error) {
t, err := d.getTest(name)
@ -66,9 +68,9 @@ func GetResults(d *Document, name string) (TestResult, error) {
return ret, nil
}
// A helper function to convert Testresult r into a slice of greppable single
// line results. Note that each line returned is not terminated with a line
// feed.
// SingleLineResults is a helper function to convert Testresult r into a slice
// of greppable single line results. Note that each line returned is not terminated
// with a line feed.
func (r *TestResult) SingleLineResults() []string {
lns := make([]string, 0)
@ -102,7 +104,7 @@ func (r *TestResult) SingleLineResults() []string {
return lns
}
// A helper function to convert TestResult into a JSON string.
// JSON is a helper function to convert TestResult into a JSON string.
func (r *TestResult) JSON() string {
buf, err := json.Marshal(r)
if err != nil {

Просмотреть файл

@ -4,6 +4,8 @@
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com
// Package scribe implements the Mozilla scribe host policy evaluator.
package scribe
import (
@ -19,6 +21,7 @@ type runtime struct {
fileLocator func(string, bool, string, int) ([]string, error)
}
// Version is the scribe library version
const Version = "0.5"
var sRuntime runtime
@ -40,14 +43,18 @@ func Bootstrap() (err error) {
return err
}
// Set an expected result callback. f should be a function that takes a Test
// ExpectedCallback can be used to set a callback function for test results.
//
// Set an expected result callback. f should be a function that takes a TestResult
// type as an argument. When this is set, if the result of a test does not
// match the value set in "expectedresult" for the test, the function is
// immediately called with the applicable test as an argument.
// immediately called with the applicable TestResult as an argument.
func ExpectedCallback(f func(TestResult)) {
sRuntime.excall = f
}
// InstallFileLocator installs alternate file walking functions.
//
// Install an alternate file location function. This overrides use of the
// SimpleFileLocator locate() function, and allows specification of an
// alternate function to use for locating candidate files on the filesystem.
@ -58,6 +65,8 @@ func InstallFileLocator(f func(string, bool, string, int) ([]string, error)) {
sRuntime.fileLocator = f
}
// TestHooks enables or disables testing hooks in the library.
//
// Enable or disable test hooks. If test hooks are enabled, certain functions
// such as requesting package data from the host system are bypassed in favor
// of test tables.
@ -73,7 +82,7 @@ func debugPrint(s string, args ...interface{}) {
fmt.Fprintf(sRuntime.debugWriter, "[scribe] %v", buf)
}
// Enable or disable debugging. If debugging is enabled, output is written
// SetDebug enables or disables debugging. If debugging is enabled, output is written
// to the io.Writer specified by w.
func SetDebug(f bool, w io.Writer) {
sRuntime.debugging = f

Просмотреть файл

@ -12,12 +12,15 @@ import (
"strings"
)
// Describes arbitrary key value tags that can be associated with a test
// TestTag describes arbitrary key value tags that can be associated with a test
type TestTag struct {
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Value string `json:"value,omitempty" yaml:"value,omitempty"`
}
// Test is a test within the policy document that will be executed. Tests specify
// various criteria, and then compare this criteria against the data returned by the
// object the test references.
type Test struct {
TestID string `json:"test" yaml:"test"` // The ID for this test.
TestName string `json:"name" yaml:"name"` // An optional name for this test

Просмотреть файл

@ -11,6 +11,8 @@ import (
"regexp"
)
// Variable defines variables that can be included in the policy document.
// Variables are expanded in objects at runtime.
type Variable struct {
Key string `json:"key" yaml:"key"`
Value string `json:"value" yaml:"value"`