Skip to content

Commit df719da

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 <[email protected]>
1 parent c46900d commit df719da

File tree

14 files changed

+1280
-92
lines changed

14 files changed

+1280
-92
lines changed

vts/appraisal/appraisal.go

Lines changed: 34 additions & 9 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,6 +12,7 @@ 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
@@ -22,6 +23,7 @@ type Appraisal struct {
2223
EvidenceContext *proto.EvidenceContext
2324
Result *ear.AttestationResult
2425
SignedEAR []byte
26+
Endorsements []string
2527
}
2628

2729
func New(tenantID string, nonce []byte, scheme string) *Appraisal {
@@ -33,31 +35,52 @@ func New(tenantID string, nonce []byte, scheme string) *Appraisal {
3335
Result: ear.NewAttestationResult(scheme, config.Version, config.Developer),
3436
}
3537

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-
38+
appraisal.setResultNonce(nonce)
4239
appraisal.InitPolicyID()
4340

4441
return &appraisal
4542
}
4643

44+
func (o *Appraisal) setResultNonce(v []byte) {
45+
encodedNonce := base64.URLEncoding.EncodeToString(v)
46+
o.Result.Nonce = &encodedNonce
47+
}
48+
49+
func (o *Appraisal) SetTrustAnchorIDs(v []string) {
50+
o.EvidenceContext.TrustAnchorIds = v
51+
}
52+
53+
func (o *Appraisal) SetReferenceIDs(v []string) {
54+
o.EvidenceContext.ReferenceIds = v
55+
}
56+
57+
func (o *Appraisal) SetEvidenceClaims(v *structpb.Struct) {
58+
o.EvidenceContext.Evidence = v
59+
}
60+
61+
func (o *Appraisal) SetEndorsements(v []string) {
62+
o.Endorsements = v
63+
}
64+
65+
func (o *Appraisal) SetResultWithNonce(result *ear.AttestationResult, nonce []byte) {
66+
o.Result = result
67+
o.setResultNonce(nonce)
68+
}
69+
4770
func (o Appraisal) GetContext() *proto.AppraisalContext {
4871
return &proto.AppraisalContext{
4972
Evidence: o.EvidenceContext,
5073
Result: o.SignedEAR,
5174
}
5275
}
5376

54-
func (o Appraisal) SetAllClaims(claim ear.TrustClaim) {
77+
func (o *Appraisal) SetAllClaims(claim ear.TrustClaim) {
5578
for _, submod := range o.Result.Submods {
5679
submod.TrustVector.SetAll(claim)
5780
}
5881
}
5982

60-
func (o Appraisal) AddPolicyClaim(name, claim string) {
83+
func (o *Appraisal) AddPolicyClaim(name, claim string) {
6184
for _, submod := range o.Result.Submods {
6285
if submod.AppraisalExtensions.VeraisonPolicyClaims == nil {
6386
claimsMap := make(map[string]interface{})
@@ -82,6 +105,8 @@ func (o *Appraisal) UpdatePolicyID(pol *policy.Policy) error {
82105
return nil
83106
}
84107

108+
// InitPolicyID must be called before sending the appraisal to policy manager
109+
// for evaluation.
85110
func (o *Appraisal) InitPolicyID() {
86111
for _, submod := range o.Result.Submods {
87112
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)