Documentation ¶
Overview ¶
Package ar4si implements an EAT attestation result format based on the information model defined in https://datatracker.ietf.org/doc/draft-ietf-rats-ar4si/
Construction ¶
An AttestationResult object is constructed by populating the relevant fields. The mandatory attributes are: status, timestamp and profile. For example, a simple AttestationResult payload with only the bare minimum claims could be created as follows:
myStatus := TrustTierAffirming myTimestamp := time.Now().Format(time.RFC3339) myPolicyID := `https://veraison.example/policy/1A4DF345-B512-4F3B-8461-967DE7F60ECA` myProfile := EatProfile ar := AttestationResult{ Status: &myStatus, Timestamp: &testTimestamp, AppraisalPolicyID: &testPolicyID, Profile: &testProfile, }
A richer one would normally include the Trustworthiness Vector, which provides details about the appraised attester components. In the example below, the attester has been assessed as genuine, i.e., all claims are in the "affirming" range. (See §2.3 of draft-ietf-rats-ar4si-03 for details about the allowed values and their meaning.)
tv := TrustVector{ InstanceIdentity: 2, Configuration: 2, Executables: 2, Hardware: 2, } ar.TrustVector := &tv
Signing and Serializing ¶
Once the AttestationResult is populated, it can be signed (i.e., wrapped in a JWT) by invoking the Sign method:
myECDSAPrivateKey = `{ "kty": "EC", "crv": "P-256", "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8", "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4", "d": "V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM" }` sigK, _ := jwk.ParseKey([]byte(myECDSAPrivateKey)) buf, _ = ar.Sign(jwa.ES256, sigK)
In this case, the returned buf contains a signed ES256 JWT with the JSON serialization of the AttestationResult object as its payload. This is the usual JWT format that can be used as-is for interchange with other applications.
Parsing and Verifying ¶
On the consumer end of the protocol, when the EAT containing the attestation result is received from a veraison verifier, the relying party needs to first parse it and verify the signature using the Verify method:
myECDSAPublicKey = `{ "kty": "EC", "crv": "P-256", "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8", "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4" }` vfyK, _ := jwk.ParseKey([]byte(myECDSAPublicKey)) var ar AttestationResult err := ar.Verify(token, jwa.ES256, vfyK) if err != nil { // handle verification error }
If there are no errors, the relying party can trust the attestation result and inspect the relevant fields to decide about the trustworthiness of the attested entity.
if *ar.Status != TrustTierAffirming { // handle troubles with appraisal }
Pretty printing ¶
The package provides a Report method that allows pretty printing of the Trustworthiness Vector. The caller can request a short summary or a detailed printout, as well as using colors when displaying the claims' values.
short, color := true, true fmt.Print(ar.TrustVector.Report(short, color))
Example (Colors) ¶
j := `{ "ear.status": "contraindicated", "iat":1666091373, "ear.appraisal-policy-id": "https://veraison.example/policy/1/60a0068d", "ear.trustworthiness-vector": { "instance-identity": 96, "configuration": 96, "executables": 32, "hardware": 2 }, "eat_profile": "tag:github.com/veraison/ar4si,2022-10-17" }` var ar AttestationResult _ = ar.FromJSON([]byte(j)) short, color := true, true fmt.Print(ar.TrustVector.Report(short, color))
Output: Instance Identity [\033[41mcontraindicated\033[0m]: recognized but not trustworthy Configuration [\033[41mcontraindicated\033[0m]: unacceptable security vulnerabilities Executables [\033[43mwarning\033[0m]: recognized but known bugs or vulnerabilities File System [\033[47mnone\033[0m]: no claim being made Hardware [\033[42maffirming\033[0m]: genuine Runtime Opaque [\033[47mnone\033[0m]: no claim being made Storage Opaque [\033[47mnone\033[0m]: no claim being made Sourced Data [\033[47mnone\033[0m]: no claim being made
Example (Decode_veraison_extensions) ¶
j := `{ "ear.status": "affirming", "iat":1666091373, "ear.appraisal-policy-id": "https://veraison.example/policy/1/60a0068d", "ear.veraison.processed-evidence": { "k1": "v1", "k2": "v2" }, "ear.veraison.verifier-added-claims": { "bar": "baz", "foo": "bar" }, "eat_profile": "tag:github.com/veraison/ar4si,2022-10-17" }` var ar AttestationResult _ = ar.FromJSON([]byte(j)) fmt.Println(StatusTierToString[*ar.Status]) fmt.Println((*ar.VeraisonProcessedEvidence)["k1"]) fmt.Println((*ar.VeraisonVerifierAddedClaims)["bar"])
Output: affirming v1 baz
Example (Encode_hefty) ¶
rawEvidence := []byte{0xde, 0xad, 0xbe, 0xef} ar := AttestationResult{ Status: &testStatus, TrustVector: &TrustVector{ InstanceIdentity: 2, Configuration: 2, Executables: 3, FileSystem: 2, Hardware: 2, RuntimeOpaque: 2, StorageOpaque: 2, SourcedData: 2, }, RawEvidence: &rawEvidence, IssuedAt: &testIAT, AppraisalPolicyID: &testPolicyID, Profile: &testProfile, } j, _ := ar.ToJSON() fmt.Println(string(j))
Output: {"ear.status":"affirming","eat_profile":"tag:github.com/veraison/ar4si,2022-10-17","ear.trustworthiness-vector":{"instance-identity":2,"configuration":2,"executables":3,"file-system":2,"hardware":2,"runtime-opaque":2,"storage-opaque":2,"sourced-data":2},"ear.raw-evidence":"3q2+7w==","iat":1666091373,"ear.appraisal-policy-id":"https://veraison.example/policy/1/60a0068d"}
Example (Encode_minimalist) ¶
ar := AttestationResult{ Status: &testStatus, IssuedAt: &testIAT, AppraisalPolicyID: &testPolicyID, Profile: &testProfile, } j, _ := ar.ToJSON() fmt.Println(string(j))
Output: {"ear.status":"affirming","eat_profile":"tag:github.com/veraison/ar4si,2022-10-17","iat":1666091373,"ear.appraisal-policy-id":"https://veraison.example/policy/1/60a0068d"}
Example (Encode_veraison_extensions) ¶
ar := testAttestationResultsWithVeraisonExtns j, _ := ar.ToJSON() fmt.Println(string(j))
Output: {"ear.status":"affirming","eat_profile":"tag:github.com/veraison/ar4si,2022-10-17","iat":1666091373,"ear.appraisal-policy-id":"https://veraison.example/policy/1/60a0068d","ear.veraison.processed-evidence":{"k1":"v1","k2":"v2"},"ear.veraison.verifier-added-claims":{"bar":"baz","foo":"bar"}}
Index ¶
- Constants
- Variables
- type AttestationResult
- func (o *AttestationResult) FromJSON(data []byte) error
- func (o AttestationResult) Sign(alg jwa.KeyAlgorithm, key interface{}) ([]byte, error)
- func (o AttestationResult) ToJSON() ([]byte, error)
- func (o AttestationResult) ToJSONPretty() ([]byte, error)
- func (o *AttestationResult) Verify(data []byte, alg jwa.KeyAlgorithm, key interface{}) error
- type Extensions
- type TClaim
- type TrustTier
- type TrustVector
Examples ¶
Constants ¶
const EatProfile = "tag:github.com/veraison/ar4si,2022-10-17"
EatProfile is the EAT profile implemented by this package
Variables ¶
var ( StatusTierToString = map[TrustTier]string{ TrustTierNone: "none", TrustTierAffirming: "affirming", TrustTierWarning: "warning", TrustTierContraindicated: "contraindicated", } StringToTrustTier = map[string]TrustTier{ "none": TrustTierNone, "affirming": TrustTierAffirming, "warning": TrustTierWarning, "contraindicated": TrustTierContraindicated, } )
Functions ¶
This section is empty.
Types ¶
type AttestationResult ¶
type AttestationResult struct { Status *TrustTier `json:"ear.status"` Profile *string `json:"eat_profile"` TrustVector *TrustVector `json:"ear.trustworthiness-vector,omitempty"` RawEvidence *[]byte `json:"ear.raw-evidence,omitempty"` IssuedAt *int64 `json:"iat"` AppraisalPolicyID *string `json:"ear.appraisal-policy-id,omitempty"` Extensions }
AttestationResult represents the result of an evidence appraisal by the verifier. It wraps the AR4SI trustworthiness vector together with other metadata that are relevant to establish the appraisal context - the evidence itself, the appraisal policy used, the time of appraisal. The AttestationResult is serialized to JSON and signed by the verifier using JWT.
func (*AttestationResult) FromJSON ¶
func (o *AttestationResult) FromJSON(data []byte) error
FromJSON de-serializes an AttestationResult object from its JSON representation and validates it.
func (AttestationResult) Sign ¶
func (o AttestationResult) Sign(alg jwa.KeyAlgorithm, key interface{}) ([]byte, error)
Sign validates the AttestationResult object, encodes it to JSON and wraps it in a JWT using the supplied private key for signing. The key must be compatible with the requested signing algorithm. On success, the complete JWT token is returned.
func (AttestationResult) ToJSON ¶
func (o AttestationResult) ToJSON() ([]byte, error)
ToJSON validates and serializes to JSON an AttestationResult object
func (AttestationResult) ToJSONPretty ¶ added in v0.0.2
func (o AttestationResult) ToJSONPretty() ([]byte, error)
ToJSONPretty does the same as ToJSON but add NL and indentation to improve readability
func (*AttestationResult) Verify ¶
func (o *AttestationResult) Verify(data []byte, alg jwa.KeyAlgorithm, key interface{}) error
Verify cryptographically verifies the JWT data using the supplied key and algorithm. The payload is then parsed and validated. On success, the target AttestationResult object is populated with the decoded claims (possibly including the Trustworthiness vector).
type Extensions ¶
type Extensions struct { VeraisonProcessedEvidence *map[string]interface{} `json:"ear.veraison.processed-evidence,omitempty"` VeraisonVerifierAddedClaims *map[string]interface{} `json:"ear.veraison.verifier-added-claims,omitempty"` }
Extensions contains any proprietary claims that can be optionally attached to the AttestationResult. For now only veraison-specific extensions are supported.
type TClaim ¶
type TClaim int8
trustworthiness claim
func (TClaim) IsAffirming ¶
func (TClaim) IsContraindicated ¶
type TrustTier ¶
type TrustTier int8
TrustTier represents the overall state of an evidence appraisal.
TrustTierNone means appraisal could not be conducted for whatever reason (e.g., a processing error).
TrustTierAffirming means appraisal was fully successful and the attester can be considered trustworthy.
TrustTierWarning means appraisal was mostly successful, but there are specific checks that need further attention from the relying party to assess whether the attester can be considered trustworthy or not.
TrustTierContraindicated means some specific checks have failed and the attester cannot be considered trustworthy.
func (TrustTier) MarshalJSON ¶
func (*TrustTier) UnmarshalJSON ¶
type TrustVector ¶
type TrustVector struct { InstanceIdentity TClaim `json:"instance-identity"` Configuration TClaim `json:"configuration"` Executables TClaim `json:"executables"` FileSystem TClaim `json:"file-system"` Hardware TClaim `json:"hardware"` RuntimeOpaque TClaim `json:"runtime-opaque"` StorageOpaque TClaim `json:"storage-opaque"` SourcedData TClaim `json:"sourced-data"` }
TrustVector is an implementation of the Trustworthiness Vector (and Claims) described in §2.3 of draft-ietf-rats-ar4si-03, using a JSON serialization.
func (TrustVector) Report ¶
func (o TrustVector) Report(short, color bool) string
Report provides an annotated view of the TrustVector state. short and color are used to control the level of details and the use of colors when printing the trust tier, respectively