From bd4f57778c5e5bac539d14955e594ee15312c39c Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Tue, 8 Oct 2024 22:03:58 -0400 Subject: [PATCH] feat(domains): file domain (#703) * feat(domains): file domain * fmt and tidy * add not-satisfied and invalid e2e test cases * too many apostrophes * update docs to clarify that absolute file paths are required for complex composition --- docs/reference/domains/file-domain.md | 128 +++++++++++++++ go.mod | 30 +++- go.sum | 154 +++++++++++++++++- src/cmd/dev/common.go | 3 +- src/cmd/tools/lint.go | 4 +- src/cmd/validate/validate.go | 16 +- src/pkg/common/common.go | 3 + src/pkg/common/schemas/validation.json | 36 +++- src/pkg/common/types.go | 3 + .../validation-store/validation-store.go | 5 +- .../validation-store/validation-store_test.go | 5 +- src/pkg/domains/api/types.go | 3 +- src/pkg/domains/files/files.go | 105 ++++++++++++ src/pkg/domains/files/files_test.go | 34 ++++ src/pkg/domains/files/spec.go | 10 ++ src/pkg/domains/files/testdata/bar.json | 1 + src/pkg/domains/files/testdata/foo.yaml | 1 + .../files/testdata/nested-directory/baz.hcl2 | 3 + src/pkg/domains/kubernetes/types.go | 2 +- src/test/e2e/api_validation_test.go | 4 +- .../e2e/composition_component_def_test.go | 4 +- src/test/e2e/create_resource_data_test.go | 4 +- src/test/e2e/file_validation_test.go | 117 +++++++++++++ .../e2e/multi_resource_validation_test.go | 2 +- src/test/e2e/outputs_test.go | 2 +- src/test/e2e/pod_validation_test.go | 6 +- src/test/e2e/pod_wait_test.go | 2 +- src/test/e2e/remote_validation_test.go | 2 +- src/test/e2e/resource_data_test.go | 2 +- .../fail/component-definition.yaml | 83 ++++++++++ .../file-validations/fail/config.json | 5 + .../fail/oscal-component-kyverno.yaml | 69 ++++++++ .../invalid/oscal-component.yaml | 0 .../pass/component-definition.yaml | 83 ++++++++++ .../file-validations/pass/config.json | 5 + .../pass/oscal-component-kyverno.yaml | 69 ++++++++ src/test/e2e/validation_composition_test.go | 4 +- src/types/context_keys.go | 7 + src/types/types.go | 7 +- 39 files changed, 978 insertions(+), 45 deletions(-) create mode 100644 docs/reference/domains/file-domain.md create mode 100644 src/pkg/domains/files/files.go create mode 100644 src/pkg/domains/files/files_test.go create mode 100644 src/pkg/domains/files/spec.go create mode 100644 src/pkg/domains/files/testdata/bar.json create mode 100644 src/pkg/domains/files/testdata/foo.yaml create mode 100644 src/pkg/domains/files/testdata/nested-directory/baz.hcl2 create mode 100644 src/test/e2e/file_validation_test.go create mode 100644 src/test/e2e/scenarios/file-validations/fail/component-definition.yaml create mode 100644 src/test/e2e/scenarios/file-validations/fail/config.json create mode 100644 src/test/e2e/scenarios/file-validations/fail/oscal-component-kyverno.yaml create mode 100644 src/test/e2e/scenarios/file-validations/invalid/oscal-component.yaml create mode 100644 src/test/e2e/scenarios/file-validations/pass/component-definition.yaml create mode 100644 src/test/e2e/scenarios/file-validations/pass/config.json create mode 100644 src/test/e2e/scenarios/file-validations/pass/oscal-component-kyverno.yaml create mode 100644 src/types/context_keys.go diff --git a/docs/reference/domains/file-domain.md b/docs/reference/domains/file-domain.md new file mode 100644 index 00000000..25f5135d --- /dev/null +++ b/docs/reference/domains/file-domain.md @@ -0,0 +1,128 @@ +# File Domain +The File domain allows for validation of arbitrary file contents from a list of supported file types. The file domain can evaluate local files and network files. Files are copied to a temporary directory for evaluation and deleted afterwards. + +## Specification +The File domain specification accepts a descriptive name for the file as well as its path. The filenames and descriptive names must be unique. + +```yaml +domain: + type: file + file-spec: + filepaths: + - name: config + path: grafana.ini +``` + +## Supported File Types +The file domain uses OPA's [conftest](https://conftest.dev) to parse files into a json-compatible format for validations. ∑Both OPA and Kyverno (using [kyverno-json](https://kyverno.github.io/kyverno-json/latest/)) can validate files parsed by the file domain. + +The file domain supports the following file formats for validation: +* CUE +* CycloneDX +* Dockerfile +* EDN +* Environment files (.env) +* HCL and HCL2 +* HOCON +* Ignore files (.gitignore, .dockerignore) +* INI +* JSON +* Jsonnet +* Property files (.properties) +* SPDX +* TextProto (Protocol Buffers) +* TOML +* VCL +* XML +* YAML + +## Validations +When writing validations against files, the filepath `Name` must be included as +the top-level key in the validation. The placement varies between providers. + +Given the following ini file: + +```grafana.ini +[server] +# Protocol (http, https, socket) +protocol = http +``` + +The below Kyverno policy validates the protocol is https by including Grafana as the top-level key under `check`: + +```yaml +metadata: + name: check-grafana-protocol + uuid: ad38ef57-99f6-4ac6-862e-e0bc9f55eebe +domain: + type: file + file-spec: + filepaths: + - name: 'grafana' + path: 'custom.ini' +provider: + type: kyverno + kyverno-spec: + policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: grafana-config + spec: + rules: + - name: protocol-is-https + assert: + all: + - check: + grafana: + server: + protocol: https +``` + +While in an OPA policy, the filepath `Name` is the input key to access the config: + +```yaml +metadata: + name: validate-grafana-config + uuid: ad38ef57-99f6-4ac6-862e-e0bc9f55eebe +domain: + type: file + file-spec: + filepaths: + - name: 'grafana' + path: 'custom.ini' +provider: + type: opa + opa-spec: + rego: | + package validate + import rego.v1 + + # Default values + default validate := false + default msg := "Not evaluated" + + validate if { + check_grafana_config.result + } + msg = check_grafana_config.msg + + config := input["grafana"] + protocol := config.server.protocol + + check_grafana_config = {"result": true, "msg": msg} if { + protocol == "https" + msg := "Server protocol is set to https" + } else = {"result": false, "msg": msg} if { + protocol == "http" + msg := "Grafana protocol is insecure" + } + + output: + validation: validate.validate + observations: + - validate.msg +``` + +## Note on Compose +While the file domain is capable of referencing relative file paths in the `file-spec`, Lula does not de-reference those paths during composition. If you are composing multiple files together, you must either use absolute filepaths (including network filepaths), or ensure that all referenced filepaths are relative to the output directory of the compose command. diff --git a/go.mod b/go.mod index f09b6327..24348440 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/kyverno/kyverno-json v0.0.3 github.com/mattn/go-runewidth v0.0.16 github.com/muesli/termenv v0.15.2 + github.com/open-policy-agent/conftest v0.55.0 github.com/open-policy-agent/opa v0.69.0 github.com/pterm/pterm v0.12.79 github.com/sergi/go-diff v1.3.1 @@ -35,26 +36,38 @@ require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect + cuelang.org/go v0.9.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/CycloneDX/cyclonedx-go v0.9.0 // indirect github.com/IGLOU-EU/go-wildcard v1.0.3 // indirect + github.com/KeisukeYamashita/go-vcl v0.4.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect + github.com/agext/levenshtein v1.2.3 // indirect github.com/agnivade/levenshtein v1.2.0 // indirect + github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect + github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/aquilax/truncate v1.0.0 // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.0 // indirect + github.com/basgys/goxml2json v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect + github.com/bufbuild/protocompile v0.6.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/charmbracelet/x/ansi v0.3.2 // indirect github.com/charmbracelet/x/exp/golden v0.0.0-20240919170804-a4978c8e603a // indirect github.com/charmbracelet/x/term v0.2.0 // indirect - github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/containerd/console v1.0.4 // indirect + github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/daviddengcn/go-colortext v1.0.0 // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.11.2 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect @@ -62,6 +75,7 @@ require ( github.com/fatih/camelcase v1.0.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-akka/configuration v0.0.0-20200606091224-a002c0330665 // indirect github.com/go-errors/errors v1.5.1 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -74,6 +88,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/google/go-jsonnet v0.20.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect @@ -83,6 +98,7 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/hcl/v2 v2.17.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect @@ -103,6 +119,8 @@ require ( github.com/mattn/go-localereader v0.0.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/buildkit v0.15.1 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/spdystream v0.4.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -113,6 +131,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect @@ -128,13 +147,17 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sahilm/fuzzy v0.1.1 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/shteou/go-ignore v0.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spdx/tools-golang v0.5.5 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect + github.com/tmccombs/hcl2json v0.3.1 // indirect + github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect github.com/vladimirvivien/gexe v0.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -143,6 +166,7 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea // indirect + github.com/zclconf/go-cty v1.13.2 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect @@ -169,6 +193,8 @@ require ( k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/metrics v0.31.1 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + muzzammil.xyz/jsonc v1.0.0 // indirect + olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect sigs.k8s.io/controller-runtime v0.18.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.17.2 // indirect diff --git a/go.sum b/go.sum index c2ee2f39..d118a088 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,21 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= +cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2 h1:BnG6pr9TTr6CYlrJznYUDj6V7xldD1W+1iXPum0wT/w= +cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2/go.mod h1:pK23AUVXuNzzTpfMCA06sxZGeVQ/75FdVtW249de9Uo= +cuelang.org/go v0.9.2 h1:pfNiry2PdRBr02G/aKm5k2vhzmqbAOoaB4WurmEbWvs= +cuelang.org/go v0.9.2/go.mod h1:qpAYsLOf7gTM1YdEg6cxh553uZ4q9ZDWlPbtZr9q1Wk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= +github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= github.com/IGLOU-EU/go-wildcard v1.0.3 h1:r8T46+8/9V1STciXJomTWRpPEv4nGJATDbJkdU0Nou0= github.com/IGLOU-EU/go-wildcard v1.0.3/go.mod h1:/qeV4QLmydCbwH0UMQJmXDryrFKJknWi/jjO8IiuQfY= +github.com/KeisukeYamashita/go-vcl v0.4.0 h1:dFxZq2yVeaCWBJAT7Oh9Z+Pp8y32i7b11QHdzsuBcsk= +github.com/KeisukeYamashita/go-vcl v0.4.0/go.mod h1:af2qGlXbsHDQN5abN7hyGNKtGhcFSaDdbLl4sfud+AU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= @@ -23,12 +34,25 @@ github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= +github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= +github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/aquilax/truncate v1.0.0 h1:UgIGS8U/aZ4JyOJ2h3xcF5cSQ06+gGBnjxH2RUHJe0U= github.com/aquilax/truncate v1.0.0/go.mod h1:BeMESIDMlvlS3bmg4BVvBbbZUNwWtS8uzYPAKXwwhLw= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= @@ -38,10 +62,18 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= +github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw= +github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= +github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= +github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= +github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -66,9 +98,17 @@ github.com/charmbracelet/x/exp/teatest v0.0.0-20240919170804-a4978c8e603a h1:sS4 github.com/charmbracelet/x/exp/teatest v0.0.0-20240919170804-a4978c8e603a/go.mod h1:NDRRSMP6bZbCs4jyc4i1/4UG4M+0PEiQdpivQgD0Mio= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= +github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= +github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -87,16 +127,20 @@ github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWa github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustinkirkland/golang-petname v0.0.0-20231002161417-6a283f1aaaf2 h1:S6Dco8FtAhEI/qkg/00H6RdEGC+MCy5GPiQ+xweNRFE= github.com/dustinkirkland/golang-petname v0.0.0-20231002161417-6a283f1aaaf2/go.mod h1:8AuBTZBRSFqEYBPYULd+NN474/zZBLP+6WeT5S9xlAc= github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU= github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/proto v1.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw= +github.com/emicklei/proto v1.10.0/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= @@ -115,10 +159,13 @@ github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7Dlme github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-akka/configuration v0.0.0-20200606091224-a002c0330665 h1:Iz3aEheYgn+//VX7VisgCmF/wW3BMtXCLbvHV4jMQJA= +github.com/go-akka/configuration v0.0.0-20200606091224-a002c0330665/go.mod h1:19bUnum2ZAeftfwwLZ/wRe7idyfoW2MfmXO464Hrfbw= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= @@ -136,17 +183,26 @@ github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdX github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godoctor/godoctor v0.0.0-20181123222458-69df17f3a6f6/go.mod h1:+tyhT8jBF8E0XvdlSXOSL7Iko7DlNiongHq3q+wcsPs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -158,13 +214,17 @@ github.com/golangplus/testing v1.0.0 h1:+ZeeiKZENNOMkTTELoSySazi+XaEhVO0mb+eanrS github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v22.9.29+incompatible h1:3UBb679lq3V/O9rgzoJmnkP1jJzmC9OdFzITUBkLU/A= +github.com/google/flatbuffers v22.9.29+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-jsonnet v0.20.0 h1:WG4TTSARuV7bSm4PMB4ohjxe33IHT5WVTrJSU33uT4g= +github.com/google/go-jsonnet v0.20.0/go.mod h1:VbgWF9JX7ztlv770x/TolZNGGFfiHEVx9G6ca2eUmeA= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -194,8 +254,12 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= +github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY= +github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= @@ -210,6 +274,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= @@ -226,12 +291,15 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyverno/kyverno-json v0.0.3 h1:EImI/YV41dG4hDQer/W0qMZHfxqul1yiHrBEXxFrkGM= github.com/kyverno/kyverno-json v0.0.3/go.mod h1:KUgXPXwUh0Sm/UgtHPomZAfEX8v79I3B5RZbUlzNihg= github.com/kyverno/pkg/ext v0.0.0-20240418121121-df8add26c55c h1:lAolpR9H8BwM5lRRvgCQ8JowswyxZRH+fgtIQzHFVCk= github.com/kyverno/pkg/ext v0.0.0-20240418121121-df8add26c55c/go.mod h1:02vxM0GNXz9+B/i6+rMfWAIwibUuAH+qFsd73IFskgQ= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= @@ -240,10 +308,13 @@ github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8 github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= @@ -253,10 +324,17 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/buildkit v0.15.1 h1:J6wrew7hphKqlq1wuu6yaUb/1Ra7gEzDAovylGztAKM= +github.com/moby/buildkit v0.15.1/go.mod h1:Yis8ZMUJTHX9XhH9zVyK2igqSHV3sxi3UN0uztZocZk= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -282,10 +360,15 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/open-policy-agent/conftest v0.55.0 h1:M6QXrrfQjmyFRsy11Q2ucFGNbbelhyaX0vtNcfcYS3I= +github.com/open-policy-agent/conftest v0.55.0/go.mod h1:qL8de2Sr5QsDG0HVM3iZiHS2Qea3bLzut6OsYyiRyEY= github.com/open-policy-agent/opa v0.69.0 h1:s2igLw2Z6IvGWGuXSfugWkVultDMsM9pXiDuMp7ckWw= github.com/open-policy-agent/opa v0.69.0/go.mod h1:+qyXJGkpEJ6kpB1kGo8JSwHtVXbTdsGdQYPWWNYNj+4= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= @@ -303,6 +386,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 h1:sadMIsgmHpEOGbUs6VtHBXRR1OHevnj7hLx9ZcdNGW4= +github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= @@ -319,6 +404,7 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -329,9 +415,12 @@ github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/shteou/go-ignore v0.3.1 h1:/DVY4w06eKliWrbkwKfBHJgUleld+QAlmlQvfRQOigA= +github.com/shteou/go-ignore v0.3.1/go.mod h1:hMVyBe+qt5/Z11W/Fxxf86b5SuL8kM29xNWLYob9Vos= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smarty/assertions v1.15.1 h1:812oFiXI+G55vxsFf+8bIZ1ux30qtkdqzKbEFwyX3Tk= @@ -340,14 +429,24 @@ github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sS github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM= +github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk= +github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -355,6 +454,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -368,19 +468,34 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= +github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= +github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= +github.com/tmccombs/hcl2json v0.3.1 h1:Pf+Lb9OpZ5lkQuIC0BB5txdCQskZ2ud/l8sz/Nkjf3A= +github.com/tmccombs/hcl2json v0.3.1/go.mod h1:ljY0/prd2IFUF3cagQjV3cpPEEQKzqyGqnKI7m5DBVY= +github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8= +github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/vektah/gqlparser v1.2.0/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74= github.com/vladimirvivien/gexe v0.2.0 h1:nbdAQ6vbZ+ZNsolCgSVb9Fno60kzSuvtzVh6Ytqi/xY= github.com/vladimirvivien/gexe v0.2.0/go.mod h1:LHQL00w/7gDUKIak24n801ABp8C+ni6eBht9vGVst8w= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yashtewari/glob-intersection v0.2.0 h1:8iuHdN88yYuCzCdjt0gDe+6bAhUwBeEWqThExu54RFg= github.com/yashtewari/glob-intersection v0.2.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -388,6 +503,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI= github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h1:eNr558nEUjP8acGw8FFjTeWvSgU1stO7FAO6eknhHe4= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.6.1/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o= +github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0= +github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= @@ -414,7 +533,9 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -428,9 +549,12 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -439,6 +563,7 @@ golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -446,8 +571,11 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -473,6 +601,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -482,7 +611,9 @@ golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -493,16 +624,21 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -547,6 +683,10 @@ k8s.io/metrics v0.31.1 h1:h4I4dakgh/zKflWYAOQhwf0EXaqy8LxAIyE/GBvxqRc= k8s.io/metrics v0.31.1/go.mod h1:JuH1S9tJiH9q1VCY0yzSCawi7kzNLsDzlWDJN4xR+iA= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +muzzammil.xyz/jsonc v1.0.0 h1:B6kaT3wHueZ87mPz3q1nFuM1BlL32IG0wcq0/uOsQ18= +muzzammil.xyz/jsonc v1.0.0/go.mod h1:rFv8tUUKe+QLh7v02BhfxXEf4ZHhYD7unR93HL/1Uvo= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw= sigs.k8s.io/controller-runtime v0.18.2 h1:RqVW6Kpeaji67CY5nPEfRz6ZfFMk0lWQlNrLqlNpx+Q= sigs.k8s.io/controller-runtime v0.18.2/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= sigs.k8s.io/e2e-framework v0.4.0 h1:4yYmFDNNoTnazqmZJXQ6dlQF1vrnDbutmxlyvBpC5rY= diff --git a/src/cmd/dev/common.go b/src/cmd/dev/common.go index 407bec9e..d8e065b6 100644 --- a/src/cmd/dev/common.go +++ b/src/cmd/dev/common.go @@ -1,6 +1,7 @@ package dev import ( + "context" "fmt" "io" "strings" @@ -95,7 +96,7 @@ func RunSingleValidation(validationBytes []byte, opts ...types.LulaValidationOpt return lulaValidation, err } - err = lulaValidation.Validate(opts...) + err = lulaValidation.Validate(context.Background(), opts...) if err != nil { return lulaValidation, err } diff --git a/src/cmd/tools/lint.go b/src/cmd/tools/lint.go index 6c31f382..b69198d1 100644 --- a/src/cmd/tools/lint.go +++ b/src/cmd/tools/lint.go @@ -25,8 +25,8 @@ To lint existing OSCAL files: ` var lintCmd = &cobra.Command{ - Use: "lint", - Short: "Validate OSCAL against schema", + Use: "lint", + Short: "Validate OSCAL against schema", Long: "Validate OSCAL documents are properly configured against the OSCAL schema", Example: lintHelp, Run: func(cmd *cobra.Command, args []string) { diff --git a/src/cmd/validate/validate.go b/src/cmd/validate/validate.go index d1da332f..ef9bd297 100644 --- a/src/cmd/validate/validate.go +++ b/src/cmd/validate/validate.go @@ -14,6 +14,7 @@ import ( requirementstore "github.com/defenseunicorns/lula/src/pkg/common/requirement-store" validationstore "github.com/defenseunicorns/lula/src/pkg/common/validation-store" "github.com/defenseunicorns/lula/src/pkg/message" + "github.com/defenseunicorns/lula/src/types" "github.com/spf13/cobra" ) @@ -67,7 +68,8 @@ var validateCmd = &cobra.Command{ message.Fatalf(err, "Invalid file extension: %s, requires .json or .yaml", opts.InputFile) } - assessment, err := ValidateOnPath(cmd.Context(), opts.InputFile, opts.Target) + ctx := context.WithValue(cmd.Context(), types.LulaValidationWorkDir, filepath.Dir(opts.InputFile)) + assessment, err := ValidateOnPath(ctx, opts.InputFile, opts.Target) if err != nil { message.Fatalf(err, "Validation error: %s", err) } @@ -146,7 +148,7 @@ func ValidateOnPath(ctx context.Context, path string, target string) (assessment return assessmentResult, fmt.Errorf("component definition is nil") } - results, err := ValidateOnCompDef(oscalModel.ComponentDefinition, target) + results, err := ValidateOnCompDef(ctx, oscalModel.ComponentDefinition, target) if err != nil { return assessmentResult, err } @@ -162,7 +164,7 @@ func ValidateOnPath(ctx context.Context, path string, target string) (assessment // ValidateOnCompDef takes a single ComponentDefinition object // It will perform a validation and return a slice of results that can be written to an assessment-results object -func ValidateOnCompDef(compDef *oscalTypes_1_1_2.ComponentDefinition, target string) (results []oscalTypes_1_1_2.Result, err error) { +func ValidateOnCompDef(ctx context.Context, compDef *oscalTypes_1_1_2.ComponentDefinition, target string) (results []oscalTypes_1_1_2.Result, err error) { if compDef == nil { return results, fmt.Errorf("cannot validate a component definition that is nil") } @@ -187,7 +189,7 @@ func ValidateOnCompDef(compDef *oscalTypes_1_1_2.ComponentDefinition, target str // this will only produce a single result if target != "" { if controlImplementation, ok := controlImplementations[target]; ok { - findings, observations, err := ValidateOnControlImplementations(&controlImplementation, validationStore, target) + findings, observations, err := ValidateOnControlImplementations(ctx, &controlImplementation, validationStore, target) if err != nil { return results, err } @@ -206,7 +208,7 @@ func ValidateOnCompDef(compDef *oscalTypes_1_1_2.ComponentDefinition, target str // loop over the controlImplementations map & validate // we lose context of source if not contained within the loop for source, controlImplementation := range controlImplementations { - findings, observations, err := ValidateOnControlImplementations(&controlImplementation, validationStore, source) + findings, observations, err := ValidateOnControlImplementations(ctx, &controlImplementation, validationStore, source) if err != nil { return results, err } @@ -224,7 +226,7 @@ func ValidateOnCompDef(compDef *oscalTypes_1_1_2.ComponentDefinition, target str } -func ValidateOnControlImplementations(controlImplementations *[]oscalTypes_1_1_2.ControlImplementationSet, validationStore *validationstore.ValidationStore, target string) (map[string]oscalTypes_1_1_2.Finding, []oscalTypes_1_1_2.Observation, error) { +func ValidateOnControlImplementations(ctx context.Context, controlImplementations *[]oscalTypes_1_1_2.ControlImplementationSet, validationStore *validationstore.ValidationStore, target string) (map[string]oscalTypes_1_1_2.Finding, []oscalTypes_1_1_2.Observation, error) { // Create requirement store for all implemented requirements requirementStore := requirementstore.NewRequirementStore(controlImplementations) @@ -251,7 +253,7 @@ func ValidateOnControlImplementations(controlImplementations *[]oscalTypes_1_1_2 // Run Lula validations and generate observations & findings message.Title("\n📐 Running Validations", "") - observations := validationStore.RunValidations(ConfirmExecution, SaveResources, ResourcesDir) + observations := validationStore.RunValidations(ctx, ConfirmExecution, SaveResources, ResourcesDir) message.Title("\n💡 Findings", "") findings := requirementStore.GenerateFindings(validationStore) diff --git a/src/pkg/common/common.go b/src/pkg/common/common.go index 52769344..66f45df2 100644 --- a/src/pkg/common/common.go +++ b/src/pkg/common/common.go @@ -12,6 +12,7 @@ import ( oscalTypes_1_1_2 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-2" "github.com/defenseunicorns/lula/src/pkg/domains/api" + "github.com/defenseunicorns/lula/src/pkg/domains/files" kube "github.com/defenseunicorns/lula/src/pkg/domains/kubernetes" "github.com/defenseunicorns/lula/src/pkg/message" "github.com/defenseunicorns/lula/src/pkg/providers/kyverno" @@ -148,6 +149,8 @@ func GetDomain(domain *Domain, ctx context.Context) (types.Domain, error) { return kube.CreateKubernetesDomain(ctx, domain.KubernetesSpec) case "api": return api.CreateApiDomain(domain.ApiSpec) + case "file": + return files.CreateDomain(domain.FileSpec) default: return nil, fmt.Errorf("domain is unsupported") } diff --git a/src/pkg/common/schemas/validation.json b/src/pkg/common/schemas/validation.json index 2bad3f85..0d733ed4 100644 --- a/src/pkg/common/schemas/validation.json +++ b/src/pkg/common/schemas/validation.json @@ -44,7 +44,8 @@ "type": "string", "enum": [ "kubernetes", - "api" + "api", + "file" ], "description": "The type of domain (Required)" }, @@ -88,6 +89,20 @@ "api-spec" ] } + }, + { + "if": { + "properties": { + "type": { + "const": "file" + } + } + }, + "then": { + "required": [ + "file-spec" + ] + } } ] }, @@ -344,6 +359,25 @@ } } }, + "file-spec": { + "type": "object", + "properties": { + "filepaths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "path": { + "type": "string" + } + } + } + } + } + }, "provider": { "type": "object", "properties": { diff --git a/src/pkg/common/types.go b/src/pkg/common/types.go index 1f9eeb70..3260ba9d 100644 --- a/src/pkg/common/types.go +++ b/src/pkg/common/types.go @@ -13,6 +13,7 @@ import ( "github.com/defenseunicorns/lula/src/config" "github.com/defenseunicorns/lula/src/pkg/common/schemas" "github.com/defenseunicorns/lula/src/pkg/domains/api" + "github.com/defenseunicorns/lula/src/pkg/domains/files" kube "github.com/defenseunicorns/lula/src/pkg/domains/kubernetes" "github.com/defenseunicorns/lula/src/pkg/providers/kyverno" "github.com/defenseunicorns/lula/src/pkg/providers/opa" @@ -98,6 +99,8 @@ type Domain struct { KubernetesSpec *kube.KubernetesSpec `json:"kubernetes-spec,omitempty" yaml:"kubernetes-spec,omitempty"` // ApiSpec is the specification for an API domain, required if type is api ApiSpec *api.ApiSpec `json:"api-spec,omitempty" yaml:"api-spec,omitempty"` + // FileSpec is the specification for a File domain, required if type is file + FileSpec *files.Spec `json:"file-spec,omitempty" yaml:"file-spec,omitempty"` } type Provider struct { diff --git a/src/pkg/common/validation-store/validation-store.go b/src/pkg/common/validation-store/validation-store.go index 7f5e78fd..eb89c66f 100644 --- a/src/pkg/common/validation-store/validation-store.go +++ b/src/pkg/common/validation-store/validation-store.go @@ -1,6 +1,7 @@ package validationstore import ( + "context" "fmt" "os" "path/filepath" @@ -105,7 +106,7 @@ func (v *ValidationStore) DryRun() (executable bool, msg string) { } // RunValidations runs the validations in the store -func (v *ValidationStore) RunValidations(confirmExecution, saveResources bool, resourcesDir string) []oscalTypes_1_1_2.Observation { +func (v *ValidationStore) RunValidations(ctx context.Context, confirmExecution, saveResources bool, resourcesDir string) []oscalTypes_1_1_2.Observation { observations := make([]oscalTypes_1_1_2.Observation, 0, len(v.validationMap)) for k, val := range v.validationMap { @@ -113,7 +114,7 @@ func (v *ValidationStore) RunValidations(confirmExecution, saveResources bool, r spinnerMessage := fmt.Sprintf("Running validation %s", k) spinner := message.NewProgressSpinner(spinnerMessage) defer spinner.Stop() - err := val.Validate(types.ExecutionAllowed(confirmExecution)) + err := val.Validate(ctx, types.ExecutionAllowed(confirmExecution)) if err != nil { message.Debugf("Error running validation %s: %v", k, err) // Update validation with failed results diff --git a/src/pkg/common/validation-store/validation-store_test.go b/src/pkg/common/validation-store/validation-store_test.go index dc43051f..73843ebf 100644 --- a/src/pkg/common/validation-store/validation-store_test.go +++ b/src/pkg/common/validation-store/validation-store_test.go @@ -1,6 +1,7 @@ package validationstore_test import ( + "context" "testing" "github.com/defenseunicorns/go-oscal/src/pkg/uuid" @@ -164,7 +165,7 @@ func TestRunValidations(t *testing.T) { v.AddLulaValidation(validation, uuid.NewUUID()) } - observations := v.RunValidations(true, false, "") + observations := v.RunValidations(context.Background(), true, false, "") if len(observations) != tt.expectedObservations { t.Errorf("Expected %d observations, but got %d", tt.expectedObservations, len(observations)) } @@ -180,7 +181,7 @@ func TestGetRelatedObservation(t *testing.T) { v.AddLulaValidation(validationPass, "1") v.AddLulaValidation(validationFail, "2") - v.RunValidations(true, false, "") + v.RunValidations(context.Background(), true, false, "") tests := []struct { name string diff --git a/src/pkg/domains/api/types.go b/src/pkg/domains/api/types.go index bbd28398..bc67c47d 100644 --- a/src/pkg/domains/api/types.go +++ b/src/pkg/domains/api/types.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "github.com/defenseunicorns/lula/src/types" @@ -35,7 +36,7 @@ func CreateApiDomain(spec *ApiSpec) (types.Domain, error) { }, nil } -func (a ApiDomain) GetResources() (types.DomainResources, error) { +func (a ApiDomain) GetResources(_ context.Context) (types.DomainResources, error) { return MakeRequests(a.Spec.Requests) } diff --git a/src/pkg/domains/files/files.go b/src/pkg/domains/files/files.go new file mode 100644 index 00000000..7886ff73 --- /dev/null +++ b/src/pkg/domains/files/files.go @@ -0,0 +1,105 @@ +package files + +import ( + "context" + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/defenseunicorns/lula/src/pkg/common/network" + "github.com/defenseunicorns/lula/src/types" + "github.com/open-policy-agent/conftest/parser" +) + +type Domain struct { + Spec *Spec `json:"spec,omitempty" yaml:"spec,omitempty"` +} + +// GetResources gathers the input files to be tested. +func (d Domain) GetResources(ctx context.Context) (types.DomainResources, error) { + var workDir string + var ok bool + if workDir, ok = ctx.Value(types.LulaValidationWorkDir).(string); !ok { + // if unset, assume lula is working in the same directory the inputFile is in + workDir = "." + } + + // see TODO below: maybe this is a REAL directory? + dst, err := os.MkdirTemp("", "lula-files") + if err != nil { + return nil, err + } + + // TODO? this might be a nice configurable option (for debugging) - store + // the files into a local .lula directory that doesn't necessarily get + // removed. + defer os.RemoveAll(dst) + + // make a map of rel filepaths to the user-supplied name, so we can re-key the DomainResources later on. + filenames := make(map[string]string, len(d.Spec.Filepaths)) + + // Copy files to a temporary location + for _, path := range d.Spec.Filepaths { + file := filepath.Join(workDir, path.Path) + bytes, err := network.Fetch(file) + if err != nil { + return nil, fmt.Errorf("error getting source files: %w", err) + } + + // We'll just use the filename when writing the file so it's easier to reference later + relname := filepath.Base(path.Path) + + err = os.WriteFile(filepath.Join(dst, relname), bytes, 0666) + if err != nil { + return nil, fmt.Errorf("error writing local files: %w", err) + } + // and save this info for later + filenames[relname] = path.Name + } + + // get a list of all the files we just downloaded in the temporary directory + files := make([]string, 0) + err = filepath.WalkDir(dst, func(path string, d fs.DirEntry, err error) error { + if !d.IsDir() { + files = append(files, path) + } + return nil + }) + if err != nil { + return nil, fmt.Errorf("error walking downloaded file tree: %w", err) + } + + // conftest's parser returns a map[string]interface where the filenames are + // the primary map keys. + config, err := parser.ParseConfigurations(files) + if err != nil { + return nil, err + } + + // clean up the resources so it's using the filepath.Name as the map key, + // instead of the file path. + drs := make(types.DomainResources, len(config)) + for k, v := range config { + rel, err := filepath.Rel(dst, k) + if err != nil { + return nil, fmt.Errorf("error determining relative file path: %w", err) + } + drs[filenames[rel]] = v + } + return drs, nil +} + +// IsExecutable returns false; the file domain is read-only. +// +// The files domain will download remote files into a temporary directory if the +// file paths are remote, but that is temporary and it is not mutating existing +// resources. +func (d Domain) IsExecutable() bool { return false } + +func CreateDomain(spec *Spec) (types.Domain, error) { + if len(spec.Filepaths) == 0 { + return nil, fmt.Errorf("file-spec must not be empty") + } + return Domain{spec}, nil +} diff --git a/src/pkg/domains/files/files_test.go b/src/pkg/domains/files/files_test.go new file mode 100644 index 00000000..2824fa0d --- /dev/null +++ b/src/pkg/domains/files/files_test.go @@ -0,0 +1,34 @@ +package files + +import ( + "context" + "testing" + + "github.com/defenseunicorns/lula/src/types" + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" +) + +var _ types.Domain = (*Domain)(nil) + +func TestGetResource(t *testing.T) { + t.Run("local files", func(t *testing.T) { + d := Domain{Spec: &Spec{Filepaths: []FileInfo{ + {Name: "foo.yaml", Path: "foo.yaml"}, + {Name: "bar.json", Path: "bar.json"}, + {Name: "arbitraryname", Path: "nested-directory/baz.hcl2"}, + }}} + + resources, err := d.GetResources(context.WithValue(context.Background(), types.LulaValidationWorkDir, "testdata")) + require.NoError(t, err) + if diff := cmp.Diff(resources, types.DomainResources{ + "bar.json": map[string]interface{}{"cat": "Cheetarah"}, + "foo.yaml": "cat = Li Shou", + "arbitraryname": map[string]any{ + "resource": map[string]any{"catname": map[string]any{"blackcat": map[string]any{"name": "robin"}}}, + }, + }); diff != "" { + t.Fatalf("wrong result:\n%s\n", diff) + } + }) +} diff --git a/src/pkg/domains/files/spec.go b/src/pkg/domains/files/spec.go new file mode 100644 index 00000000..45dd78d0 --- /dev/null +++ b/src/pkg/domains/files/spec.go @@ -0,0 +1,10 @@ +package files + +type Spec struct { + Filepaths []FileInfo `json:"filepaths" yaml:"filepaths"` +} + +type FileInfo struct { + Name string `json:"name" yaml:"name"` + Path string `json:"path" yaml:"path"` +} diff --git a/src/pkg/domains/files/testdata/bar.json b/src/pkg/domains/files/testdata/bar.json new file mode 100644 index 00000000..a30ce675 --- /dev/null +++ b/src/pkg/domains/files/testdata/bar.json @@ -0,0 +1 @@ +{ "cat": "Cheetarah"} \ No newline at end of file diff --git a/src/pkg/domains/files/testdata/foo.yaml b/src/pkg/domains/files/testdata/foo.yaml new file mode 100644 index 00000000..e2723e35 --- /dev/null +++ b/src/pkg/domains/files/testdata/foo.yaml @@ -0,0 +1 @@ +cat = Li Shou \ No newline at end of file diff --git a/src/pkg/domains/files/testdata/nested-directory/baz.hcl2 b/src/pkg/domains/files/testdata/nested-directory/baz.hcl2 new file mode 100644 index 00000000..0635204e --- /dev/null +++ b/src/pkg/domains/files/testdata/nested-directory/baz.hcl2 @@ -0,0 +1,3 @@ +resource "catname" "blackcat" { + name = "robin" +} \ No newline at end of file diff --git a/src/pkg/domains/kubernetes/types.go b/src/pkg/domains/kubernetes/types.go index e276093e..9da54acd 100644 --- a/src/pkg/domains/kubernetes/types.go +++ b/src/pkg/domains/kubernetes/types.go @@ -87,7 +87,7 @@ func CreateKubernetesDomain(ctx context.Context, spec *KubernetesSpec) (types.Do }, nil } -func (k KubernetesDomain) GetResources() (resources types.DomainResources, err error) { +func (k KubernetesDomain) GetResources(_ context.Context) (resources types.DomainResources, err error) { // Evaluate the wait condition if k.Spec.Wait != nil { err := EvaluateWait(*k.Spec.Wait) diff --git a/src/test/e2e/api_validation_test.go b/src/test/e2e/api_validation_test.go index 4bb9f868..e55db58b 100644 --- a/src/test/e2e/api_validation_test.go +++ b/src/test/e2e/api_validation_test.go @@ -55,7 +55,7 @@ func TestApiValidation(t *testing.T) { oscalPath := "./scenarios/api-field/oscal-component.yaml" message.NoProgress = true - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } @@ -139,7 +139,7 @@ func TestApiValidation(t *testing.T) { oscalPath := "./scenarios/api-field/oscal-component.yaml" message.NoProgress = true - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/composition_component_def_test.go b/src/test/e2e/composition_component_def_test.go index ce14ef64..05d19d40 100644 --- a/src/test/e2e/composition_component_def_test.go +++ b/src/test/e2e/composition_component_def_test.go @@ -42,7 +42,7 @@ func TestComponentDefinitionComposition(t *testing.T) { compDefPath := "../../test/unit/common/composition/component-definition-import-multi-compdef.yaml" // Validate results using ValidateOnPath - assessment, err := validate.ValidateOnPath(ctx, compDefPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), compDefPath, "") if err != nil { t.Errorf("Error validating component definition: %v", err) } @@ -101,7 +101,7 @@ func TestComponentDefinitionComposition(t *testing.T) { t.Errorf("component definition is nil") } - composeResults, err := validate.ValidateOnCompDef(oscalModel.ComponentDefinition, "") + composeResults, err := validate.ValidateOnCompDef(context.Background(), oscalModel.ComponentDefinition, "") if err != nil { t.Error(err) } diff --git a/src/test/e2e/create_resource_data_test.go b/src/test/e2e/create_resource_data_test.go index 0ef33f5c..b2bbf0c7 100644 --- a/src/test/e2e/create_resource_data_test.go +++ b/src/test/e2e/create_resource_data_test.go @@ -40,7 +40,7 @@ func TestCreateResourceDataValidation(t *testing.T) { validate.RunNonInteractively = true validate.SaveResources = false - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } @@ -114,7 +114,7 @@ func TestDeniedCreateResources(t *testing.T) { // Check that validation fails validate.ConfirmExecution = false validate.RunNonInteractively = true - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/file_validation_test.go b/src/test/e2e/file_validation_test.go new file mode 100644 index 00000000..275378a4 --- /dev/null +++ b/src/test/e2e/file_validation_test.go @@ -0,0 +1,117 @@ +package test + +import ( + "context" + "testing" + + "github.com/defenseunicorns/lula/src/cmd/validate" + "github.com/defenseunicorns/lula/src/types" +) + +func TestFileValidation(t *testing.T) { + failDir := "./scenarios/file-validations/fail" + passDir := "./scenarios/file-validations/pass" + oscalFile := "/component-definition.yaml" + kyvernoFile := "/oscal-component-kyverno.yaml" + + t.Run("success - opa", func(t *testing.T) { + ctx := context.WithValue(context.Background(), types.LulaValidationWorkDir, passDir) + assessment, err := validate.ValidateOnPath(ctx, passDir+oscalFile, "") + if err != nil { + t.Fatal(err) + } + + if len(assessment.Results) == 0 { + t.Fatal("Expected greater than zero results") + } + + result := assessment.Results[0] + if result.Findings == nil { + t.Fatal("Expected findings to be not nil") + } + + for _, finding := range *result.Findings { + state := finding.Target.Status.State + if state != "satisfied" { + t.Fatal("State should be satisfied, but got :", state) + } + } + }) + t.Run("success - kyverno", func(t *testing.T) { + ctx := context.WithValue(context.Background(), types.LulaValidationWorkDir, passDir) + assessment, err := validate.ValidateOnPath(ctx, passDir+kyvernoFile, "") + if err != nil { + t.Fatal(err) + } + + if len(assessment.Results) == 0 { + t.Fatal("Expected greater than zero results") + } + + result := assessment.Results[0] + if result.Findings == nil { + t.Fatal("Expected findings to be not nil") + } + + for _, finding := range *result.Findings { + state := finding.Target.Status.State + if state != "satisfied" { + t.Fatal("State should be satisfied, but got :", state) + } + } + }) + t.Run("fail - opa", func(t *testing.T) { + ctx := context.WithValue(context.Background(), types.LulaValidationWorkDir, failDir) + assessment, err := validate.ValidateOnPath(ctx, failDir+oscalFile, "") + if err != nil { + t.Fatal(err) + } + + if len(assessment.Results) == 0 { + t.Fatal("Expected greater than zero results") + } + + result := assessment.Results[0] + if result.Findings == nil { + t.Fatal("Expected findings to be not nil") + } + + for _, finding := range *result.Findings { + state := finding.Target.Status.State + if state != "not-satisfied" { + t.Fatal("State should be non-satisfied, but got :", state) + } + } + }) + t.Run("fail - kyverno", func(t *testing.T) { + ctx := context.WithValue(context.Background(), types.LulaValidationWorkDir, failDir) + assessment, err := validate.ValidateOnPath(ctx, failDir+kyvernoFile, "") + if err != nil { + t.Fatal(err) + } + + if len(assessment.Results) == 0 { + t.Fatal("Expected greater than zero results") + } + + result := assessment.Results[0] + if result.Findings == nil { + t.Fatal("Expected findings to be not nil") + } + + for _, finding := range *result.Findings { + state := finding.Target.Status.State + if state != "not-satisfied" { + t.Fatal("State should be non-satisfied, but got :", state) + } + } + }) + + t.Run("invalid input", func(t *testing.T) { + ctx := context.WithValue(context.Background(), types.LulaValidationWorkDir, "scenarios/file-validations/invalid") + _, err := validate.ValidateOnPath(ctx, "scenarios/file-validations/invalid/oscal-component.yaml", "") + if err == nil { + t.Fatal("expected error, got success") + } + }) +} diff --git a/src/test/e2e/multi_resource_validation_test.go b/src/test/e2e/multi_resource_validation_test.go index fd296665..173ad984 100644 --- a/src/test/e2e/multi_resource_validation_test.go +++ b/src/test/e2e/multi_resource_validation_test.go @@ -103,7 +103,7 @@ func TestMultiResourceValidation(t *testing.T) { oscalPath := "./scenarios/multi-resource/oscal-component.yaml" message.NoProgress = true - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/outputs_test.go b/src/test/e2e/outputs_test.go index 57692a5f..60c0a02a 100644 --- a/src/test/e2e/outputs_test.go +++ b/src/test/e2e/outputs_test.go @@ -57,7 +57,7 @@ func TestOutputs(t *testing.T) { components := *compDef.Components validationStore := validationstore.NewValidationStoreFromBackMatter(*compDef.BackMatter) - findingMap, observations, err := validate.ValidateOnControlImplementations(components[0].ControlImplementations, validationStore, "") + findingMap, observations, err := validate.ValidateOnControlImplementations(context.Background(), components[0].ControlImplementations, validationStore, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/pod_validation_test.go b/src/test/e2e/pod_validation_test.go index e1052cbb..6f6cc2cd 100644 --- a/src/test/e2e/pod_validation_test.go +++ b/src/test/e2e/pod_validation_test.go @@ -228,7 +228,7 @@ func validatePodLabelPass(ctx context.Context, t *testing.T, config *envconf.Con } message.Infof("Successfully upgraded %s to %s with OSCAL version %s %s\n", oscalPath, revisionOptions.OutputFile, revisionResponse.Reviser.GetSchemaVersion(), revisionResponse.Reviser.GetModelType()) - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatalf("Failed to validate oscal file: %s", oscalPath) } @@ -321,7 +321,7 @@ func validatePodLabelFail(ctx context.Context, t *testing.T, oscalPath string) ( validate.RunNonInteractively = true validate.SaveResources = false - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatalf("Failed to validate oscal file: %s", oscalPath) } @@ -367,7 +367,7 @@ func validateSaveResources(ctx context.Context, t *testing.T, oscalPath string) validate.ResourcesDir = tempDir // Validate on path - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatalf("Failed to validate oscal file: %s", oscalPath) } diff --git a/src/test/e2e/pod_wait_test.go b/src/test/e2e/pod_wait_test.go index faca5c15..8b183d69 100644 --- a/src/test/e2e/pod_wait_test.go +++ b/src/test/e2e/pod_wait_test.go @@ -32,7 +32,7 @@ func TestPodWaitValidation(t *testing.T) { oscalPath := "./scenarios/wait-field/oscal-component.yaml" message.NoProgress = true - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/remote_validation_test.go b/src/test/e2e/remote_validation_test.go index 087ca22b..3bf36f7c 100644 --- a/src/test/e2e/remote_validation_test.go +++ b/src/test/e2e/remote_validation_test.go @@ -36,7 +36,7 @@ func TestRemoteValidation(t *testing.T) { Assess("Validate local validation file", func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context { oscalPath := "./scenarios/remote-validations/component-definition.yaml" - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/resource_data_test.go b/src/test/e2e/resource_data_test.go index ebea164a..3547164d 100644 --- a/src/test/e2e/resource_data_test.go +++ b/src/test/e2e/resource_data_test.go @@ -71,7 +71,7 @@ func TestResourceDataValidation(t *testing.T) { oscalPath := "./scenarios/resource-data/oscal-component.yaml" message.NoProgress = true - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } diff --git a/src/test/e2e/scenarios/file-validations/fail/component-definition.yaml b/src/test/e2e/scenarios/file-validations/fail/component-definition.yaml new file mode 100644 index 00000000..fef12405 --- /dev/null +++ b/src/test/e2e/scenarios/file-validations/fail/component-definition.yaml @@ -0,0 +1,83 @@ +component-definition: + uuid: E6A291A4-2BC8-43A0-B4B2-FD67CAAE1F8F + metadata: + title: OSCAL Demo Tool + last-modified: "2022-09-13T12:00:00Z" + version: "20220913" + oscal-version: 1.1.1 + parties: + # Should be consistent across all of the packages, but where is ground truth? + - uuid: C18F4A9F-A402-415B-8D13-B51739D689FF + type: organization + name: Defense Unicorns + links: + - href: https://github.com/defenseunicorns/lula + rel: website + components: + - uuid: A9D5204C-7E5B-4C43-BD49-34DF759B9F04 + type: software + title: lula + description: | + Defense Unicorns lula + purpose: Validate compliance controls + responsible-roles: + - role-id: provider + party-uuids: + - C18F4A9F-A402-415B-8D13-B51739D689FF # matches parties entry for Defense Unicorns + control-implementations: + - uuid: A584FEDC-8CEA-4B0C-9F07-85C2C4AE751A + source: https://github.com/defenseunicorns/lula + description: Validate generic security requirements + implemented-requirements: + - uuid: 42C2FFDC-5F05-44DF-A67F-EEC8660AEFFD + control-id: ID-1 + description: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + links: + - href: "#88AB3470-B96B-4D7C-BC36-02BF9563C46C" + rel: lula + back-matter: + resources: + - uuid: 88AB3470-B96B-4D7C-BC36-02BF9563C46C + rlinks: + - href: lula + description: | + domain: + type: file + file-spec: + filepaths: + - Name: config + path: config.json + provider: + type: opa + opa-spec: + rego: | + package validate + import rego.v1 + + # Default values + default validate := false + default msg := "Not evaluated" + + validate if { + check_server_protocol.result + } + msg = check_server_protocol.msg + + config := input["config"] + protocol := config.server.protocol + + check_server_protocol = {"result": true, "msg": msg} if { + protocol == "https" + msg := "Server protocol is set to https" + } else = {"result": false, "msg": msg} if { + protocol == "http" + msg := "Server Protocol must be https - http is disallowed" + } + + output: + validation: validate.validate + observations: + - validate.msg \ No newline at end of file diff --git a/src/test/e2e/scenarios/file-validations/fail/config.json b/src/test/e2e/scenarios/file-validations/fail/config.json new file mode 100644 index 00000000..0f433c1e --- /dev/null +++ b/src/test/e2e/scenarios/file-validations/fail/config.json @@ -0,0 +1,5 @@ +{ + "server": { + "protocol": "http" + } +} \ No newline at end of file diff --git a/src/test/e2e/scenarios/file-validations/fail/oscal-component-kyverno.yaml b/src/test/e2e/scenarios/file-validations/fail/oscal-component-kyverno.yaml new file mode 100644 index 00000000..3a3e7561 --- /dev/null +++ b/src/test/e2e/scenarios/file-validations/fail/oscal-component-kyverno.yaml @@ -0,0 +1,69 @@ +component-definition: + uuid: E6A291A4-2BC8-43A0-B4B2-FD67CAAE1F8F + metadata: + title: OSCAL Demo Tool + last-modified: "2022-09-13T12:00:00Z" + version: "20220913" + oscal-version: 1.1.1 + parties: + # Should be consistent across all of the packages, but where is ground truth? + - uuid: C18F4A9F-A402-415B-8D13-B51739D689FF + type: organization + name: Defense Unicorns + links: + - href: https://github.com/defenseunicorns/lula + rel: website + components: + - uuid: A9D5204C-7E5B-4C43-BD49-34DF759B9F04 + type: software + title: lula + description: | + Defense Unicorns lula + purpose: Validate compliance controls + responsible-roles: + - role-id: provider + party-uuids: + - C18F4A9F-A402-415B-8D13-B51739D689FF # matches parties entry for Defense Unicorns + control-implementations: + - uuid: A584FEDC-8CEA-4B0C-9F07-85C2C4AE751A + source: https://github.com/defenseunicorns/lula + description: Validate generic security requirements + implemented-requirements: + - uuid: 42C2FFDC-5F05-44DF-A67F-EEC8660AEFFD + control-id: ID-1 + description: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + links: + - href: "#88AB3470-B96B-4D7C-BC36-02BF9563C46C" + rel: lula + back-matter: + resources: + - uuid: 88AB3470-B96B-4D7C-BC36-02BF9563C46C + rlinks: + - href: lula + description: | + domain: + type: file + file-spec: + filepaths: + - name: config + path: config.json + provider: + type: kyverno + kyverno-spec: + policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: grafana-config + spec: + rules: + - name: protocol-is-https + assert: + all: + - check: + config: + server: + protocol: https \ No newline at end of file diff --git a/src/test/e2e/scenarios/file-validations/invalid/oscal-component.yaml b/src/test/e2e/scenarios/file-validations/invalid/oscal-component.yaml new file mode 100644 index 00000000..e69de29b diff --git a/src/test/e2e/scenarios/file-validations/pass/component-definition.yaml b/src/test/e2e/scenarios/file-validations/pass/component-definition.yaml new file mode 100644 index 00000000..fef12405 --- /dev/null +++ b/src/test/e2e/scenarios/file-validations/pass/component-definition.yaml @@ -0,0 +1,83 @@ +component-definition: + uuid: E6A291A4-2BC8-43A0-B4B2-FD67CAAE1F8F + metadata: + title: OSCAL Demo Tool + last-modified: "2022-09-13T12:00:00Z" + version: "20220913" + oscal-version: 1.1.1 + parties: + # Should be consistent across all of the packages, but where is ground truth? + - uuid: C18F4A9F-A402-415B-8D13-B51739D689FF + type: organization + name: Defense Unicorns + links: + - href: https://github.com/defenseunicorns/lula + rel: website + components: + - uuid: A9D5204C-7E5B-4C43-BD49-34DF759B9F04 + type: software + title: lula + description: | + Defense Unicorns lula + purpose: Validate compliance controls + responsible-roles: + - role-id: provider + party-uuids: + - C18F4A9F-A402-415B-8D13-B51739D689FF # matches parties entry for Defense Unicorns + control-implementations: + - uuid: A584FEDC-8CEA-4B0C-9F07-85C2C4AE751A + source: https://github.com/defenseunicorns/lula + description: Validate generic security requirements + implemented-requirements: + - uuid: 42C2FFDC-5F05-44DF-A67F-EEC8660AEFFD + control-id: ID-1 + description: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + links: + - href: "#88AB3470-B96B-4D7C-BC36-02BF9563C46C" + rel: lula + back-matter: + resources: + - uuid: 88AB3470-B96B-4D7C-BC36-02BF9563C46C + rlinks: + - href: lula + description: | + domain: + type: file + file-spec: + filepaths: + - Name: config + path: config.json + provider: + type: opa + opa-spec: + rego: | + package validate + import rego.v1 + + # Default values + default validate := false + default msg := "Not evaluated" + + validate if { + check_server_protocol.result + } + msg = check_server_protocol.msg + + config := input["config"] + protocol := config.server.protocol + + check_server_protocol = {"result": true, "msg": msg} if { + protocol == "https" + msg := "Server protocol is set to https" + } else = {"result": false, "msg": msg} if { + protocol == "http" + msg := "Server Protocol must be https - http is disallowed" + } + + output: + validation: validate.validate + observations: + - validate.msg \ No newline at end of file diff --git a/src/test/e2e/scenarios/file-validations/pass/config.json b/src/test/e2e/scenarios/file-validations/pass/config.json new file mode 100644 index 00000000..f551b8d0 --- /dev/null +++ b/src/test/e2e/scenarios/file-validations/pass/config.json @@ -0,0 +1,5 @@ +{ + "server": { + "protocol": "https" + } +} \ No newline at end of file diff --git a/src/test/e2e/scenarios/file-validations/pass/oscal-component-kyverno.yaml b/src/test/e2e/scenarios/file-validations/pass/oscal-component-kyverno.yaml new file mode 100644 index 00000000..3a3e7561 --- /dev/null +++ b/src/test/e2e/scenarios/file-validations/pass/oscal-component-kyverno.yaml @@ -0,0 +1,69 @@ +component-definition: + uuid: E6A291A4-2BC8-43A0-B4B2-FD67CAAE1F8F + metadata: + title: OSCAL Demo Tool + last-modified: "2022-09-13T12:00:00Z" + version: "20220913" + oscal-version: 1.1.1 + parties: + # Should be consistent across all of the packages, but where is ground truth? + - uuid: C18F4A9F-A402-415B-8D13-B51739D689FF + type: organization + name: Defense Unicorns + links: + - href: https://github.com/defenseunicorns/lula + rel: website + components: + - uuid: A9D5204C-7E5B-4C43-BD49-34DF759B9F04 + type: software + title: lula + description: | + Defense Unicorns lula + purpose: Validate compliance controls + responsible-roles: + - role-id: provider + party-uuids: + - C18F4A9F-A402-415B-8D13-B51739D689FF # matches parties entry for Defense Unicorns + control-implementations: + - uuid: A584FEDC-8CEA-4B0C-9F07-85C2C4AE751A + source: https://github.com/defenseunicorns/lula + description: Validate generic security requirements + implemented-requirements: + - uuid: 42C2FFDC-5F05-44DF-A67F-EEC8660AEFFD + control-id: ID-1 + description: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + links: + - href: "#88AB3470-B96B-4D7C-BC36-02BF9563C46C" + rel: lula + back-matter: + resources: + - uuid: 88AB3470-B96B-4D7C-BC36-02BF9563C46C + rlinks: + - href: lula + description: | + domain: + type: file + file-spec: + filepaths: + - name: config + path: config.json + provider: + type: kyverno + kyverno-spec: + policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: grafana-config + spec: + rules: + - name: protocol-is-https + assert: + all: + - check: + config: + server: + protocol: https \ No newline at end of file diff --git a/src/test/e2e/validation_composition_test.go b/src/test/e2e/validation_composition_test.go index 6f8d8af8..494b50c7 100644 --- a/src/test/e2e/validation_composition_test.go +++ b/src/test/e2e/validation_composition_test.go @@ -71,7 +71,7 @@ func validateComposition(ctx context.Context, t *testing.T, oscalPath, expectedF t.Error(err) } - assessment, err := validate.ValidateOnPath(ctx, oscalPath, "") + assessment, err := validate.ValidateOnPath(context.Background(), oscalPath, "") if err != nil { t.Fatal(err) } @@ -117,7 +117,7 @@ func validateComposition(ctx context.Context, t *testing.T, oscalPath, expectedF // Create a validation store from the back-matter if it exists validationStore := validationstore.NewValidationStoreFromBackMatter(*compDef.BackMatter) - findingMap, observations, err := validate.ValidateOnControlImplementations(components[0].ControlImplementations, validationStore, "") + findingMap, observations, err := validate.ValidateOnControlImplementations(context.Background(), components[0].ControlImplementations, validationStore, "") if err != nil { t.Fatalf("Error with validateOnControlImplementations: %v", err) } diff --git a/src/types/context_keys.go b/src/types/context_keys.go new file mode 100644 index 00000000..b96e5dce --- /dev/null +++ b/src/types/context_keys.go @@ -0,0 +1,7 @@ +package types + +type contextKey int + +const ( + LulaValidationWorkDir contextKey = iota +) diff --git a/src/types/types.go b/src/types/types.go index 193a5ce3..7f8b78e5 100644 --- a/src/types/types.go +++ b/src/types/types.go @@ -1,6 +1,7 @@ package types import ( + "context" "encoding/json" "errors" "fmt" @@ -116,7 +117,7 @@ func GetResourcesOnly(onlyResources bool) LulaValidationOption { } // Perform the validation, and store the result in the LulaValidation struct -func (val *LulaValidation) Validate(opts ...LulaValidationOption) error { +func (val *LulaValidation) Validate(ctx context.Context, opts ...LulaValidationOption) error { if !val.Evaluated { var result Result var err error @@ -157,7 +158,7 @@ func (val *LulaValidation) Validate(opts ...LulaValidationOption) error { if config.staticResources != nil { resources = config.staticResources } else { - resources, err = (*val.Domain).GetResources() + resources, err = (*val.Domain).GetResources(ctx) if err != nil { return fmt.Errorf("%w: %v", ErrDomainGetResources, err) } @@ -196,7 +197,7 @@ func (val *LulaValidation) GetDomainResourcesAsJSON() []byte { type DomainResources map[string]interface{} type Domain interface { - GetResources() (DomainResources, error) + GetResources(context.Context) (DomainResources, error) IsExecutable() bool }