Skip to content

Commit 1d21153

Browse files
author
Kairo Araujo
committed
fixup! feat: Enable Witness Policy verify from Archivista
Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>
1 parent b6acb3a commit 1d21153

File tree

5 files changed

+224
-3
lines changed

5 files changed

+224
-3
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ bin/
22
build/
33
vendor/
44
.dccache
5+
.vscode
6+
.profile.cov
57
test/testapp
68
test/test-attestation.json
79
test/policy-signed.json
@@ -15,4 +17,4 @@ sarif-report.json
1517
test/log
1618
node_modules
1719
.DS_Store
18-
docs-website/.docusaurus
20+
docs-website/.docusaurus

cmd/verify.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import (
2626
"github.com/in-toto/go-witness/cryptoutil"
2727
"github.com/in-toto/go-witness/log"
2828
"github.com/in-toto/go-witness/source"
29+
archivista_client "github.com/in-toto/witness/internal/archivista"
30+
"github.com/in-toto/witness/internal/policy"
2931
"github.com/in-toto/witness/options"
30-
"github.com/in-toto/witness/pkg"
3132
"github.com/spf13/cobra"
3233
)
3334

@@ -95,7 +96,7 @@ func runVerify(ctx context.Context, vo options.VerifyOptions, verifiers ...crypt
9596
verifiers = append(verifiers, v)
9697
}
9798

98-
policyEnvelope, err := pkg.LoadPolicy(ctx, vo.PolicyFilePath, pkg.NewArchivistaClient(vo.ArchivistaOptions.Url, archivistaClient))
99+
policyEnvelope, err := policy.LoadPolicy(ctx, vo.PolicyFilePath, archivista_client.NewArchivistaClient(vo.ArchivistaOptions.Url, archivistaClient))
99100
if err != nil {
100101
return fmt.Errorf("failed to load policy: %w", err)
101102
}

internal/archivista/archivista.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2024 The Witness Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package archivista
16+
17+
import (
18+
"context"
19+
20+
"github.com/in-toto/go-witness/archivista"
21+
"github.com/in-toto/go-witness/dsse"
22+
)
23+
24+
type aClient struct {
25+
url string
26+
client Clienter
27+
}
28+
29+
// Define Client Interface for Archivista
30+
type Clienter interface {
31+
Download(ctx context.Context, gitoid string) (dsse.Envelope, error)
32+
Store(ctx context.Context, env dsse.Envelope) (string, error)
33+
SearchGitoids(ctx context.Context, vars archivista.SearchGitoidVariables) ([]string, error)
34+
}
35+
36+
func NewArchivistaClient(url string, client *archivista.Client) Clienter {
37+
38+
if client == nil {
39+
return nil
40+
}
41+
42+
return &aClient{
43+
url: url,
44+
client: client,
45+
}
46+
}
47+
48+
func (ac *aClient) Download(ctx context.Context, gitoid string) (dsse.Envelope, error) {
49+
return ac.client.Download(ctx, gitoid)
50+
}
51+
52+
func (ac *aClient) Store(ctx context.Context, env dsse.Envelope) (string, error) {
53+
return ac.client.Store(ctx, env)
54+
}
55+
56+
func (ac *aClient) SearchGitoids(ctx context.Context, vars archivista.SearchGitoidVariables) ([]string, error) {
57+
return ac.client.SearchGitoids(ctx, vars)
58+
}

internal/policy/policy.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2024 The Witness Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package policy
16+
17+
import (
18+
"context"
19+
"encoding/json"
20+
"fmt"
21+
"os"
22+
23+
"github.com/in-toto/go-witness/dsse"
24+
"github.com/in-toto/go-witness/log"
25+
"github.com/in-toto/witness/internal/archivista"
26+
)
27+
28+
// Load policy from a file or Archivista
29+
//
30+
// It prefers to load from a file, if it fails, it tries to load from Archivista
31+
func LoadPolicy(ctx context.Context, policy string, ac archivista.Clienter) (dsse.Envelope, error) {
32+
policyEnvelope := dsse.Envelope{}
33+
34+
filePolicy, err := os.Open(policy)
35+
if err != nil {
36+
log.Debug("failed to open policy file: ", policy)
37+
if ac == nil {
38+
return policyEnvelope, fmt.Errorf("failed to open file to sign: %w", err)
39+
} else {
40+
log.Debug("attempting to fetch policy " + policy + " from archivista")
41+
policyEnvelope, err = ac.Download(ctx, policy)
42+
if err != nil {
43+
return policyEnvelope, fmt.Errorf("failed to fetch policy from archivista: %w", err)
44+
}
45+
log.Debug("policy " + policy + " downloaded from archivista")
46+
}
47+
48+
} else {
49+
defer filePolicy.Close()
50+
decoder := json.NewDecoder(filePolicy)
51+
if err := decoder.Decode(&policyEnvelope); err != nil {
52+
return policyEnvelope, fmt.Errorf("could not unmarshal policy envelope: %w", err)
53+
}
54+
}
55+
56+
return policyEnvelope, nil
57+
}

internal/policy/policy_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2024 The Witness Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package policy
16+
17+
import (
18+
"context"
19+
"errors"
20+
"testing"
21+
22+
"github.com/in-toto/go-witness/dsse"
23+
"github.com/in-toto/witness/internal/archivista"
24+
"github.com/stretchr/testify/mock"
25+
"github.com/stretchr/testify/suite"
26+
)
27+
28+
// Mock archivista client
29+
type ArchivistaClienterMock struct {
30+
mock.Mock
31+
archivista.Clienter
32+
}
33+
34+
func (m *ArchivistaClienterMock) Download(ctx context.Context, path string) (dsse.Envelope, error) {
35+
args := m.Called()
36+
return dsse.Envelope{}, args.Error(1)
37+
}
38+
39+
// Define test suite
40+
type UTPolicySuite struct {
41+
suite.Suite
42+
mockedAC *ArchivistaClienterMock
43+
}
44+
45+
func TestUTPolicySuite(t *testing.T) {
46+
suite.Run(t, new(UTPolicySuite))
47+
}
48+
49+
// Setup test suite
50+
func (ut *UTPolicySuite) SetupTest() {
51+
ut.mockedAC = &ArchivistaClienterMock{}
52+
53+
}
54+
55+
// Test LoadPolicy with file
56+
func (ut *UTPolicySuite) TestLoadPolicyFile() {
57+
ctx := context.Background()
58+
policy := "../../test/policy-hello-signed.json"
59+
60+
// Load policy from file
61+
policyEnvelope, err := LoadPolicy(ctx, policy, nil)
62+
ut.NoError(err)
63+
ut.NotNil(policyEnvelope)
64+
}
65+
66+
// Test LoadPolicy with file not found
67+
func (ut *UTPolicySuite) TestLoadPolicyFileNotFound() {
68+
ctx := context.Background()
69+
policy := "notfound"
70+
71+
// Load policy from file
72+
_, err := LoadPolicy(ctx, policy, nil)
73+
ut.Error(err)
74+
ut.Contains(err.Error(), "no such file or directory")
75+
}
76+
77+
// Test LoadPolicy with archivista
78+
func (ut *UTPolicySuite) TestLoadPolicyArchivista() {
79+
ctx := context.Background()
80+
policy := "testgitoid"
81+
82+
// Mock archivista client
83+
ut.mockedAC.On("Download").Return(dsse.Envelope{}, nil)
84+
85+
// Load policy from archivista
86+
policyEnvelope, err := LoadPolicy(ctx, policy, ut.mockedAC)
87+
ut.NoError(err)
88+
ut.NotNil(policyEnvelope)
89+
}
90+
91+
// Test LoadPolicy with archivista not found
92+
func (ut *UTPolicySuite) TestLoadPolicyArchivistaNotFound() {
93+
ctx := context.Background()
94+
policy := "testgitoid"
95+
96+
// Mock archivista client
97+
ut.mockedAC.On("Download").Return(dsse.Envelope{}, errors.New("not found"))
98+
99+
// Load policy from archivista
100+
_, err := LoadPolicy(ctx, policy, ut.mockedAC)
101+
ut.Error(err)
102+
ut.Contains(err.Error(), "failed to fetch policy from archivista")
103+
}

0 commit comments

Comments
 (0)