To use this backend, specify "opa"
as the policy.backend
in the config:
import "github.com/veraison/services/config"
cfg := config.Config{
"policy.backend": "opa",
}
agent, err := CreateAgent(cfg)
This is also the default backend, so if no other backend is specified, opa
will be used.
Please see the OPA official documentation for information on how to write Rego policies. This section describes what is necessary to implement a valid Veraison policy, and assumes a general familiarity with Rego.
Your policy should specify policy
as the package.
package policy
Data to be evaluated is defined as the following variables in the policy
package:
evidence
contains the JSON representation of proto.EvidenceContext.Evidence
structure. This is the scheme-specific values extracted from the attestation
token.
endorsements
is an array of endorsement JSON objects. Their structure is
scheme-specific.
result
is a JSON object representing proto.AttestationResult
that was
generated by the scheme.
scheme
is the name of the attestation scheme.
You can update the attestation result by defining one or more of the following rules:
status
hw_authenticity
sw_integrity
sw_up_to_dateness
config_integrity
runtime_integrity
certification_status
The first overwrites the overall attestation result status. The subsequent rules overwrite the corresponding entries in the trust vector.
The rules must be defined such that they produce the string "SUCCESS"
if the
conditions have been met, and the string "FAILURE"
otherwise.
As various versions are often represented using Semantic Versioning, policy
package provides a utility function, semver_cmp
to aid in their comparison
(note: currently, pre-release suffixes are not supported).
For example:
sw_integrity = "SUCCESS" {
# note: This is an example. The evidence entries do not correspond to any
# actual scheme.
evidence["application-hash"] == "h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc="
evidence["firmware-hash"] == "h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc="
semver_cmp(evidence["firmware-version"], "1.2.0") >= 0
} else = "FAILURE"
If you expect your policy to be applied to inputs from multiple attestation
schemes, you differentiate between them using the format
variable defined by
the policy
package. For example you can define rules for each scheme, and
then alias the generic rules above to one of them based on the value of the
format
variable. For example:
sw_up_to_dateness = psa_sw_up_to_dateness { format == "PSA_IOT" }
else = enacttrust_sw_up_to_dateness { format == "TPM_ENACTTRUST" }
psa_sw_up_to_dateness = "SUCCESS" {
# ...
} else = "FAILURE"
enacttrust_sw_up_to_dateness = "SUCCESS" {
# ...
} else = "FAILURE"
This is a example of a policy that sets the SoftwareUpToDateness
value in the
trust vector for PSA_IOT
and TPM_ENACTTRUST
schemes (neither scheme has
built-in definition for software up-to-dateness, and so that entry is undefined
in the results generated by the schemes).
package policy
# Use the psa_sw_up_to_dateness rules iff the attestation format is PSA_IOT, and
# to enacttrust_sw_up_to_dateness iff the format is TPM_ENACTTRUST, otherwise,
# sw_up_to_dateness will remain undefined.
sw_up_to_dateness = psa_sw_up_to_dateness { format == "PSA_IOT" }
else = enacttrust_sw_up_to_dateness { format == "TPM_ENACTTRUST" }
# This sets sw-up-to-dateness trust vector value to success iff BL version is
# 3.5 or greater, and to failure otherwise.
psa_sw_up_to_dateness = "SUCCESS" {
# there exisists some i such that...
some i
# ...the i'th software component has type "BL", and...
evidence["psa-software-components"][i]["measurement-type"] == "BL"
# ...the version of this component is greater or equal to 3.5.
# (semver_cmp is defined by the policy package. It returns 1 if the first
# parameter is greater than the second, -1 if it is less than the second,
# and 0 if they are equal.)
semver_cmp(evidence["psa-software-components"][i].version, "3.5") >= 0
} else = "FAILURE" # unless the above condition is met, return "FAILURE"
# Unlike the PSA token, the EnactTrust token does not include information about
# multiple sofware componets and instead has a single "firmware" entry.
enacttrust_sw_up_to_dateness = "SUCCESS" {
evidence["firmware"] >= 8
} else = "FAILURE"