Skip to content

Commit 0e63e0d

Browse files
refactor(vts): extract (reusable) appraisal logic into separate function
Extract (most) of the appraisal logic from GRPC::GetAttestation() into GRPC::getAttestation() so that it can be reused from other RPC service endpoints, e.g., when appraising composite evidence. Signed-off-by: Thomas Fossati <thomas.fossati@linaro.org>
1 parent c46900d commit 0e63e0d

14 files changed

Lines changed: 1586 additions & 94 deletions

vts/appraisal/appraisal.go

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2022-2023 Contributors to the Veraison project.
1+
// Copyright 2022-2026 Contributors to the Veraison project.
22
// SPDX-License-Identifier: Apache-2.0
33

44
package appraisal
@@ -12,16 +12,17 @@ import (
1212
"github.com/veraison/services/config"
1313
"github.com/veraison/services/policy"
1414
"github.com/veraison/services/proto"
15+
"google.golang.org/protobuf/types/known/structpb"
1516
)
1617

1718
// Appraisal provides an appraisal context internally within the VTS (e.g. for
18-
// policy evaluation). It is the analog of proto.AppraisalContext, but with a
19-
// deserialized AttestationResult.
19+
// policy evaluation).
2020
type Appraisal struct {
2121
Scheme string
2222
EvidenceContext *proto.EvidenceContext
2323
Result *ear.AttestationResult
2424
SignedEAR []byte
25+
Endorsements []string
2526
}
2627

2728
func New(tenantID string, nonce []byte, scheme string) *Appraisal {
@@ -33,31 +34,56 @@ func New(tenantID string, nonce []byte, scheme string) *Appraisal {
3334
Result: ear.NewAttestationResult(scheme, config.Version, config.Developer),
3435
}
3536

36-
encodedNonce := base64.URLEncoding.EncodeToString(nonce)
37-
appraisal.Result.Nonce = &encodedNonce
38-
39-
appraisal.Result.VerifierID.Build = &config.Version
40-
appraisal.Result.VerifierID.Developer = &config.Developer
41-
37+
appraisal.setResultNonce(nonce)
4238
appraisal.InitPolicyID()
4339

4440
return &appraisal
4541
}
4642

43+
func (o *Appraisal) setResultNonce(v []byte) {
44+
encodedNonce := base64.URLEncoding.EncodeToString(v)
45+
o.Result.Nonce = &encodedNonce
46+
}
47+
48+
func (o *Appraisal) SetTrustAnchorIDs(v []string) {
49+
o.EvidenceContext.TrustAnchorIds = v
50+
}
51+
52+
func (o *Appraisal) SetReferenceIDs(v []string) {
53+
o.EvidenceContext.ReferenceIds = v
54+
}
55+
56+
func (o Appraisal) GetReferenceIDs() []string {
57+
return o.EvidenceContext.ReferenceIds
58+
}
59+
60+
func (o *Appraisal) SetEvidenceClaims(v *structpb.Struct) {
61+
o.EvidenceContext.Evidence = v
62+
}
63+
64+
func (o *Appraisal) SetEndorsements(v []string) {
65+
o.Endorsements = v
66+
}
67+
68+
func (o *Appraisal) SetResultWithNonce(result *ear.AttestationResult, nonce []byte) {
69+
o.Result = result
70+
o.setResultNonce(nonce)
71+
}
72+
4773
func (o Appraisal) GetContext() *proto.AppraisalContext {
4874
return &proto.AppraisalContext{
4975
Evidence: o.EvidenceContext,
5076
Result: o.SignedEAR,
5177
}
5278
}
5379

54-
func (o Appraisal) SetAllClaims(claim ear.TrustClaim) {
80+
func (o *Appraisal) SetAllClaims(claim ear.TrustClaim) {
5581
for _, submod := range o.Result.Submods {
5682
submod.TrustVector.SetAll(claim)
5783
}
5884
}
5985

60-
func (o Appraisal) AddPolicyClaim(name, claim string) {
86+
func (o *Appraisal) AddPolicyClaim(name, claim string) {
6187
for _, submod := range o.Result.Submods {
6288
if submod.AppraisalExtensions.VeraisonPolicyClaims == nil {
6389
claimsMap := make(map[string]interface{})
@@ -82,6 +108,8 @@ func (o *Appraisal) UpdatePolicyID(pol *policy.Policy) error {
82108
return nil
83109
}
84110

111+
// InitPolicyID must be called before sending the appraisal to policy manager
112+
// for evaluation.
85113
func (o *Appraisal) InitPolicyID() {
86114
for _, submod := range o.Result.Submods {
87115
policyID := fmt.Sprintf("policy:%s", o.Scheme)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2026 Contributors to the Veraison project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package policymanager
4+
5+
import (
6+
"context"
7+
8+
"github.com/veraison/services/vts/appraisal"
9+
)
10+
11+
type IPolicyManager interface {
12+
Evaluate(ctx context.Context, appraisal *appraisal.Appraisal) error
13+
}

vts/policymanager/policymanager.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2022-2024 Contributors to the Veraison project.
1+
// Copyright 2022-2026 Contributors to the Veraison project.
22
// SPDX-License-Identifier: Apache-2.0
33
package policymanager
44

@@ -32,13 +32,12 @@ func New(v *viper.Viper, store *policy.Store, logger *zap.SugaredLogger) (*Polic
3232
return pm, nil
3333
}
3434

35+
// XXX(tho) revisit coupling between appraisal and policy manager
3536
func (o *PolicyManager) Evaluate(
3637
ctx context.Context,
37-
scheme string,
3838
appraisal *appraisal.Appraisal,
39-
endorsements []string,
4039
) error {
41-
policyKey := o.getPolicyKey(appraisal)
40+
policyKey := o.getPolicyKey(appraisal.EvidenceContext.TenantId, appraisal.Scheme)
4241

4342
pol, err := o.getPolicy(policyKey)
4443
if err != nil {
@@ -58,12 +57,12 @@ func (o *PolicyManager) Evaluate(
5857
evaluated, err := o.Agent.Evaluate(
5958
ctx,
6059
appraisalContext,
61-
scheme,
60+
appraisal.Scheme,
6261
pol,
6362
submod,
6463
submodAppraisal,
6564
appraisal.EvidenceContext,
66-
endorsements,
65+
appraisal.Endorsements,
6766
)
6867
if err != nil {
6968
return err
@@ -77,10 +76,10 @@ func (o *PolicyManager) Evaluate(
7776
return nil
7877
}
7978

80-
func (o *PolicyManager) getPolicyKey(a *appraisal.Appraisal) policy.PolicyKey {
79+
func (o *PolicyManager) getPolicyKey(tenantID string, scheme string) policy.PolicyKey {
8180
return policy.PolicyKey{
82-
TenantId: a.EvidenceContext.TenantId,
83-
Scheme: a.Scheme,
81+
TenantId: tenantID,
82+
Scheme: scheme,
8483
Name: o.Agent.GetBackendName(),
8584
}
8685
}

vts/policymanager/policymanager_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2022-2023 Contributors to the Veraison project.
1+
// Copyright 2022-2026 Contributors to the Veraison project.
22
// SPDX-License-Identifier: Apache-2.0
33
package policymanager
44

@@ -48,7 +48,7 @@ func TestPolicyMgr_getPolicy_not_found(t *testing.T) {
4848
pm := &PolicyManager{Store: &policy.Store{KVStore: store, Logger: log.Named("test")},
4949
Agent: agent}
5050

51-
polKey := pm.getPolicyKey(appraisal)
51+
polKey := pm.getPolicyKey(appraisal.EvidenceContext.TenantId, appraisal.Scheme)
5252
assert.Equal(t, "0:TPM_ENACTTRUST:opa", polKey.String())
5353

5454
pol, err := pm.getPolicy(polKey)
@@ -82,7 +82,7 @@ func TestPolicyMgr_getPolicy_OK(t *testing.T) {
8282

8383
pm := &PolicyManager{Store: &policy.Store{KVStore: store}, Agent: agent}
8484

85-
polKey := pm.getPolicyKey(appraisal)
85+
polKey := pm.getPolicyKey(appraisal.EvidenceContext.TenantId, appraisal.Scheme)
8686
assert.Equal(t, "0:TPM_ENACTTRUST:opa", polKey.String())
8787

8888
_, err = pm.getPolicy(polKey)
@@ -129,6 +129,7 @@ func TestPolicyMgr_Evaluate_OK(t *testing.T) {
129129
endorsements := []string{"h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc="}
130130
ar := ear.NewAttestationResult("test", "test", "test")
131131
ap := &appraisal.Appraisal{EvidenceContext: ec, Result: ar, Scheme: "TPM_ENACTTRUST"}
132+
ap.Endorsements = endorsements
132133

133134
polID := "policy:TPM_ENACTTRUST"
134135
tier := ear.TrustTierAffirming
@@ -140,7 +141,7 @@ func TestPolicyMgr_Evaluate_OK(t *testing.T) {
140141
Evaluate(
141142
context.TODO(),
142143
gomock.Any(),
143-
"test",
144+
"TPM_ENACTTRUST",
144145
gomock.Any(),
145146
gomock.Any(),
146147
ar.Submods["test"],
@@ -153,7 +154,7 @@ func TestPolicyMgr_Evaluate_OK(t *testing.T) {
153154
Agent: agent,
154155
logger: log.Named("manager"),
155156
}
156-
err := pm.Evaluate(context.TODO(), "test", ap, endorsements)
157+
err := pm.Evaluate(context.TODO(), ap)
157158
require.NoError(t, err)
158159
}
159160

@@ -174,17 +175,17 @@ func TestPolicyMgr_Evaluate_NOK(t *testing.T) {
174175
}
175176
endorsements := []string{"h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc="}
176177
ar := ear.NewAttestationResult("test", "test", "test")
177-
ap := &appraisal.Appraisal{EvidenceContext: ec, Result: ar, Scheme: "TPM_ENACTTRUST"}
178+
ap := &appraisal.Appraisal{EvidenceContext: ec, Result: ar, Scheme: "TPM_ENACTTRUST", Endorsements: endorsements}
178179
expectedErr := errors.New("could not evaluate policy: policy returned bad update")
179180
agent := mock_deps.NewMockIAgent(ctrl)
180181
agent.EXPECT().GetBackendName().Return("opa")
181-
agent.EXPECT().Evaluate(context.TODO(), gomock.Any(), "test", gomock.Any(), gomock.Any(), ar.Submods["test"], ec, endorsements).Return(nil, expectedErr)
182+
agent.EXPECT().Evaluate(context.TODO(), gomock.Any(), "TPM_ENACTTRUST", gomock.Any(), gomock.Any(), ar.Submods["test"], ec, endorsements).Return(nil, expectedErr)
182183
pm := &PolicyManager{
183184
Store: &policy.Store{KVStore: store, Logger: log.Named("store")},
184185
Agent: agent,
185186
logger: log.Named("manager"),
186187
}
187-
err := pm.Evaluate(context.TODO(), "test", ap, endorsements)
188+
err := pm.Evaluate(context.TODO(), ap)
188189
assert.ErrorIs(t, err, expectedErr)
189190

190191
}

vts/trustedservices/Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,17 @@
33

44
GOPKG := github.com/veraison/services/vts/trustedservices
55

6-
all-hook-pre test-hook-pre lint-hook-pre:
6+
INTERFACES += ../../plugin/imanager.go
7+
INTERFACES += ../../plugin/ipluggable.go
8+
INTERFACES += ../earsigner/iearsigner.go
9+
INTERFACES += ../../handler/ievidencehandler.go
10+
INTERFACES += ../../handler/istorehandler.go
11+
INTERFACES += ../../kvstore/ikvstore.go
12+
INTERFACES += ../policymanager/ipolicymanager.go
13+
14+
MOCKPKG := mocks
15+
16+
all-hook-pre test-hook-pre lint-hook-pre: _mocks
717
$(MAKE) -C ../../proto protogen
818

919
include ../../mk/common.mk

vts/trustedservices/mocks/iearsigner.go

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)