Skip to content

Commit

Permalink
fix: update constraint templates to work with new type field (#1217)
Browse files Browse the repository at this point in the history
  • Loading branch information
akashsinghal authored Jan 4, 2024
1 parent 5333fe9 commit 23b143d
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 27 deletions.
61 changes: 61 additions & 0 deletions library/rego/sbom-validation.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

# Copyright The Ratify Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

package ratify.policy

# This template defines policy for SBOM validation.
# It checks the following:
# - There is at least one SBOM report that was verified
# - Only considers ONE SBOM report
# - The SBOM is valid (isSuccess = true)
# - The SBOM has a valid notary project signature (if require_signature = true)

import future.keywords.if
import future.keywords.in

default require_signature := false # change to true to require notary project signature on SBOM
default valid := false

valid {
not failed_verify(input)
}

failed_verify(reports) {
not process_sboms(reports)
}

process_sboms(subject_result) if {
# collect verifier reports from sbom verifier
sbom_results := [res | subject_result.verifierReports[i].verifierReports[j].type == "sbom"; res := subject_result.verifierReports[i].verifierReports[j]]
count(sbom_results) > 0
# validate SBOM contents for ONLY the first report found
process_sbom(sbom_results[0])
}

process_sbom(report) if {
report.isSuccess == true
valid_signatures(report)
}

valid_signatures(_) := true {
require_signature == false
}

valid_signatures(report) := true {
require_signature
count(report.nestedResults) > 0
some nestedResult in report.nestedResults
nestedResult.artifactType == "application/vnd.cncf.notary.signature"
nestedResult.isSuccess
}
4 changes: 1 addition & 3 deletions library/rego/vulnerability-report-validation.rego
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import future.keywords.every

# This template defines policy for vulnerability report validation.
# It checks the following:
# - If there are any system errors
# - If there are errors for any of the images
# - There is at least one vulnerability report that was verified
# - Only considers the latest vulnerability report
# - The latest vulnerability report is valid (isSuccess = true)
Expand All @@ -40,7 +38,7 @@ failed_verify(reports) {

process_vuln_reports(subject_result) if {
# collect verifier reports from vulnerabilityreport verifier
vuln_results := [res | subject_result.verifierReports[i].verifierReports[j].name == "vulnerabilityreport"; res := subject_result.verifierReports[i].verifierReports[j]]
vuln_results := [res | subject_result.verifierReports[i].verifierReports[j].type == "vulnerabilityreport"; res := subject_result.verifierReports[i].verifierReports[j]]
count(vuln_results) > 0
# calculate the timestamp between current time and creation time
timestamp_diff_results_map := {diff_in_ns: i | diff_in_ns := time.now_ns() - time.parse_rfc3339_ns(vuln_results[i].extensions["createdAt"])}
Expand Down
11 changes: 11 additions & 0 deletions library/sbom-validation/samples/constraint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: SbomValidation
metadata:
name: sbom-validation-constraint
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces: ["default"]
58 changes: 44 additions & 14 deletions library/sbom-validation/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ spec:
rego: |
package sbomvalidation
# This template defines policy for SBOM validation.
# It checks the following:
# - If there are any system errors
# - If there are errors for any of the images
# - There is at least one SBOM report that was verified
# - Only considers ONE SBOM report
# - The SBOM is valid (isSuccess = true)
# - The SBOM has a valid notary project signature (if require_signature = true)s
import future.keywords.if
import future.keywords.in
default require_signature := false # change to true to require notary project signature on SBOM
# Get data from Ratify
remote_data := response {
images := [img | img = input.review.object.spec.containers[_].image]
Expand All @@ -31,28 +45,44 @@ spec:
general_violation[{"result": result}] {
err := remote_data.system_error
err != ""
result := sprintf("System error calling external data provider: %s", [err])
result := sprintf("System error calling external data provider for SBOM verification: %s", [err])
}
# Check if there are errors for any of the images
general_violation[{"result": result}] {
count(remote_data.errors) > 0
result := sprintf("Error validating one or more images: %s", remote_data.errors)
result := sprintf("Error validating one or more images for SBOM verification: %s", remote_data.errors)
}
# Check if the success criteria is true
general_violation[{"result": result}] {
subject_validation := remote_data.responses[_]
subject_validation[1].isSuccess == false
result := sprintf("Subject failed verification: %s", [subject_validation[0]])
subject_result := subject_validation[1]
not process_sboms(subject_result)
result := sprintf("Subject failed SBOM verification: %s", [subject_validation[0]])
}
# Check for failed sbom validation
general_violation[{"result": result}] {
subject_results := remote_data.responses[_]
subject_result := subject_results[1]
sbom_results := [res | subject_result.verifierReports[i].name == "sbom"; res := subject_result.verifierReports[i]]
sbom_result := sbom_results[_]
sbom_result.isSuccess == false
result = sprintf("Subject %s failed sbom validation: %s", [subject_results[0], sbom_result.message])
process_sboms(subject_result) if {
# collect verifier reports from sbom verifier
sbom_results := [res | subject_result.verifierReports[i].type == "sbom"; res := subject_result.verifierReports[i]]
count(sbom_results) > 0
# validate SBOM contents for ONLY the first report found
process_sbom(sbom_results[0])
}
process_sbom(report) if {
report.isSuccess == true
valid_signatures(report)
}
valid_signatures(_) := true {
require_signature == false
}
valid_signatures(report) := true {
require_signature
count(report.nestedResults) > 0
some nestedResult in report.nestedResults
nestedResult.artifactType == "application/vnd.cncf.notary.signature"
nestedResult.isSuccess
}
8 changes: 4 additions & 4 deletions library/vulnerability-report-validation/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,26 @@ spec:
general_violation[{"result": result}] {
err := remote_data.system_error
err != ""
result := sprintf("System error calling external data provider: %s", [err])
result := sprintf("System error calling external data provider for vulnerability report verification: %s", [err])
}
# Check if there are errors for any of the images
general_violation[{"result": result}] {
count(remote_data.errors) > 0
result := sprintf("Error validating one or more images: %s", remote_data.errors)
result := sprintf("Error validating one or more images for vulnerability report verification: %s", remote_data.errors)
}
# Check if the success criteria is true
general_violation[{"result": result}] {
subject_validation := remote_data.responses[_]
subject_result := subject_validation[1]
not process_vuln_reports(subject_result)
result := sprintf("Subject failed verification: %s", [subject_validation[0]])
result := sprintf("Subject failed vulnerability report verification: %s", [subject_validation[0]])
}
process_vuln_reports(subject_result) if {
# collect verifier reports from vulnerabilityreport verifier
vuln_results := [res | subject_result.verifierReports[i].name == "vulnerabilityreport"; res := subject_result.verifierReports[i]]
vuln_results := [res | subject_result.verifierReports[i].type == "vulnerabilityreport"; res := subject_result.verifierReports[i]]
count(vuln_results) > 0
# calculate the timestamp between current time and creation time
timestamp_diff_results_map := {diff_in_ns: i | diff_in_ns := time.now_ns() - time.parse_rfc3339_ns(vuln_results[i].extensions["createdAt"])}
Expand Down
2 changes: 1 addition & 1 deletion plugins/verifier/cosign/cosign.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe
if err != nil {
return nil, err
}
verifierType := ""
verifierType := input.Config.Name
if input.Config.Type != "" {
verifierType = input.Config.Type
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/verifier/licensechecker/licensechecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, desc
if err != nil {
return nil, err
}
verifierType := ""
verifierType := input.Name
if input.Type != "" {
verifierType = input.Type
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/verifier/sample/sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func VerifyReference(args *skel.CmdArgs, _ common.Reference, referenceDescriptor
if err != nil {
return nil, err
}
verifierType := ""
verifierType := input.Name
if input.Type != "" {
verifierType = input.Type
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/verifier/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe
if err != nil {
return nil, err
}
verifierType := ""
verifierType := input.Name
if input.Type != "" {
verifierType = input.Type
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/verifier/schemavalidator/schema_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe
if err != nil {
return nil, err
}
verifierType := ""
verifierType := input.Name
if input.Type != "" {
verifierType = input.Type
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe
if err != nil {
return nil, err
}
verifierType := ""
verifierType := input.Name
if input.Type != "" {
verifierType = input.Type
}
Expand Down

0 comments on commit 23b143d

Please sign in to comment.