Skip to content

Commit

Permalink
Added trustedSum in checker module
Browse files Browse the repository at this point in the history
Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com>
  • Loading branch information
NishantBansal2003 committed Sep 3, 2024
1 parent 107ee87 commit 1b1ac7c
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 63 deletions.
77 changes: 71 additions & 6 deletions pkg/checker/checker.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package checker

import (
"encoding/json"
"fmt"
"regexp"

"github.com/hashicorp/go-version"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras-go/v2"

"kcl-lang.io/kpm/pkg/client"
"kcl-lang.io/kpm/pkg/constants"
"kcl-lang.io/kpm/pkg/opt"
pkg "kcl-lang.io/kpm/pkg/package"
"kcl-lang.io/kpm/pkg/reporter"
"kcl-lang.io/kpm/pkg/utils"
)

// Checker defines an interface for KclPkg dependencies checkers.
Expand Down Expand Up @@ -59,15 +68,23 @@ func (c *VersionChecker) Check(kclPkg pkg.KclPkg) error {
}

// SumChecker validates the dependencies checksum in kclPkg.
type SumChecker struct{}
type SumChecker struct {
kpmcli *client.KpmClient
}

// NewSumChecker initializes a SumChecker with the given KpmClient.
func NewSumChecker(kpmcli *client.KpmClient) *SumChecker {
return &SumChecker{kpmcli: kpmcli}
}

// Check verifies the checksums of the dependencies in the given KclPkg.
func (c *SumChecker) Check(kclPkg pkg.KclPkg) error {
if kclPkg.NoSumCheck {
return nil
}
for _, key := range kclPkg.Dependencies.Deps.Keys() {
dep, _ := kclPkg.Dependencies.Deps.Get(key)
trustedSum, err := getTrustedSum(dep)
trustedSum, err := c.getTrustedSum(dep)
if err != nil {
return fmt.Errorf("failed to get checksum from trusted source: %w", err)
}
Expand All @@ -91,8 +108,56 @@ func isValidDependencyVersion(v string) bool {
return err == nil
}

// Placeholder for getTrustedSum function
func getTrustedSum(dep pkg.Dependency) (string, error) {
// Need to be implemented to get the trusted checksum.
return "", nil
func (c *SumChecker) getTrustedSum(dep pkg.Dependency) (string, error) {
if dep.Source.Oci == nil {
return "", fmt.Errorf("dependency is not from OCI")
}

c.populateOciFields(dep)

manifest, err := c.fetchOciManifest(dep)
if err != nil {
return "", err
}

return c.extractChecksumFromManifest(manifest)
}

func (c *SumChecker) populateOciFields(dep pkg.Dependency) {
if len(dep.Source.Oci.Reg) == 0 {
dep.Source.Oci.Reg = c.kpmcli.GetSettings().DefaultOciRegistry()
}

if len(dep.Source.Oci.Repo) == 0 {
dep.Source.Oci.Repo = utils.JoinPath(c.kpmcli.GetSettings().DefaultOciRepo(), dep.Name)
}
}

func (c *SumChecker) fetchOciManifest(dep pkg.Dependency) (ocispec.Manifest, error) {
manifest := ocispec.Manifest{}
jsonDesc, err := c.kpmcli.FetchOciManifestIntoJsonStr(opt.OciFetchOptions{
FetchBytesOptions: oras.DefaultFetchBytesOptions,
OciOptions: opt.OciOptions{
Reg: dep.Source.Oci.Reg,
Repo: dep.Source.Oci.Repo,
Tag: dep.Source.Oci.Tag,
},
})
if err != nil {
return manifest, reporter.NewErrorEvent(reporter.FailedFetchOciManifest, err, fmt.Sprintf("failed to fetch the manifest of '%s'", dep.Name))
}

err = json.Unmarshal([]byte(jsonDesc), &manifest)
if err != nil {
return manifest, fmt.Errorf("failed to unmarshal manifest: %w", err)
}

return manifest, nil
}

func (c *SumChecker) extractChecksumFromManifest(manifest ocispec.Manifest) (string, error) {
if value, ok := manifest.Annotations[constants.DEFAULT_KCL_OCI_MANIFEST_SUM]; ok {
return value, nil
}
return "", fmt.Errorf("checksum annotation not found in manifest")
}
200 changes: 143 additions & 57 deletions pkg/checker/checker_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package checker

import (
"os/exec"
"testing"

"github.com/elliotchance/orderedmap/v2"
"gotest.tools/v3/assert"

"kcl-lang.io/kpm/pkg/client"
"kcl-lang.io/kpm/pkg/downloader"
pkg "kcl-lang.io/kpm/pkg/package"
)

Expand All @@ -14,77 +18,42 @@ func TestDepCheckerCheck(t *testing.T) {
&VersionChecker{},
&SumChecker{},
)

deps1 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps1.Set("kcl1", pkg.Dependency{
Name: "kcl1",
FullName: "kcl1",
Version: "0.0.1",
Sum: "",
Sum: "no-sum-check-enabled",
})
deps1.Set("kcl2", pkg.Dependency{
Name: "kcl2",
FullName: "kcl2",
Version: "0.2.1",
Sum: "",
Sum: "no-sum-check-enabled",
})

deps2 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps2.Set("kcl1", pkg.Dependency{
Name: "kcl1",
FullName: "kcl1",
Version: "0.0.1",
Sum: "no-sum-check-enabled",
})
deps2.Set("kcl2", pkg.Dependency{
Name: "kcl2",
FullName: "kcl2",
Version: "0.2.1",
Sum: "no-sum-check-enabled",
})

deps3 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps3.Set("kcl1", pkg.Dependency{
Name: ".kcl1",
FullName: "kcl1",
Version: "0.0.1",
Sum: "",
})

deps4 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps4.Set("kcl1", pkg.Dependency{
deps3 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps3.Set("kcl1", pkg.Dependency{
Name: "kcl1",
FullName: "kcl1",
Version: "1.0.0-alpha#",
Sum: "",
})

deps5 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps5.Set("kcl1", pkg.Dependency{
Name: "kcl1",
FullName: "kcl1",
Version: "0.0.1",
Sum: "invalid-no-sum-check-disabled",
})

tests := []struct {
name string
KclPkg pkg.KclPkg
wantErr bool
}{
{
name: "valid kcl package - with sum check",
KclPkg: pkg.KclPkg{
ModFile: pkg.ModFile{
HomePath: "path/to/modfile",
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps1,
},
NoSumCheck: false,
},
wantErr: false,
},
{
name: "valid kcl package - with no sum check enabled",
KclPkg: pkg.KclPkg{
Expand All @@ -93,7 +62,7 @@ func TestDepCheckerCheck(t *testing.T) {
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps2,
Deps: deps1,
},
NoSumCheck: true,
},
Expand All @@ -107,7 +76,7 @@ func TestDepCheckerCheck(t *testing.T) {
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps3,
Deps: deps2,
},
NoSumCheck: false,
},
Expand All @@ -121,21 +90,7 @@ func TestDepCheckerCheck(t *testing.T) {
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps4,
},
NoSumCheck: false,
},
wantErr: true,
},
{
name: "Invalid kcl package - with no sum check disabled - checksum mismatches",
KclPkg: pkg.KclPkg{
ModFile: pkg.ModFile{
HomePath: "path/to/modfile",
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps5,
Deps: deps3,
},
NoSumCheck: false,
},
Expand Down Expand Up @@ -221,3 +176,134 @@ func TestIsValidDependencyVersion(t *testing.T) {
})
}
}

// startDockerRegistry starts a local Docker registry by executing a shell script.
func startDockerRegistry() error {
cmd := exec.Command("../../scripts/reg.sh")
return cmd.Run()
}

// pushPkgToRegistry pushes the test package to the local Docker registry.
func pushPkgToRegistry() error {
cmd := exec.Command("./test_script/push_pkg.sh")
return cmd.Run()
}

// cleanTestEnv cleans up the test environment by executing a cleanup script.
func cleanTestEnv() error {
cmd := exec.Command("./test_script/cleanup_test_environment.sh")
return cmd.Run()
}

func TestDepCheckerCheck_WithTrustedSum(t *testing.T) {
// Start the local Docker registry required for testing
err := startDockerRegistry()
assert.Equal(t, err, nil)

// Push the test package to the local OCI registry
err = pushPkgToRegistry()
assert.Equal(t, err, nil)

// Initialize a new KpmClient instance for use with the DepChecker
kpmcli, err := client.NewKpmClient()
assert.Equal(t, err, nil)

// Initialize the DepChecker with required checkers
depChecker := NewDepChecker(
&IdentChecker{},
&VersionChecker{},
NewSumChecker(kpmcli),
)

deps1 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps1.Set("kcl1", pkg.Dependency{
Name: "test_data",
FullName: "test_data",
Version: "0.0.1",
Sum: "RpZZIvrXwfn5dpt6LqBR8+FlPE9Y+BEou47L3qaCCqk=",
Source: downloader.Source{
Oci: &downloader.Oci{
Reg: "localhost:5001",
Repo: "test",
Tag: "0.0.1",
},
},
})

deps2 := orderedmap.NewOrderedMap[string, pkg.Dependency]()
deps2.Set("kcl1", pkg.Dependency{
Name: "test_data",
FullName: "test_data",
Version: "0.0.1",
Sum: "Invalid-sum",
Source: downloader.Source{
Oci: &downloader.Oci{
Reg: "localhost:5001",
Repo: "test",
Tag: "0.0.1",
},
},
})

tests := []struct {
name string
KclPkg pkg.KclPkg
wantErr bool
}{
{
name: "valid kcl package - with sum check",
KclPkg: pkg.KclPkg{
ModFile: pkg.ModFile{
HomePath: "path/to/modfile",
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps1,
},
NoSumCheck: false,
},
wantErr: false,
},
{
name: "valid kcl package - with no sum check enabled",
KclPkg: pkg.KclPkg{
ModFile: pkg.ModFile{
HomePath: "path/to/modfile",
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps2,
},
NoSumCheck: true,
},
wantErr: false,
},
{
name: "Invalid kcl package - with no sum check disabled - checksum mismatches",
KclPkg: pkg.KclPkg{
ModFile: pkg.ModFile{
HomePath: "path/to/modfile",
},
HomePath: "path/to/kcl/pkg",
Dependencies: pkg.Dependencies{
Deps: deps2,
},
NoSumCheck: false,
},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotErr := depChecker.Check(tt.KclPkg)
if (gotErr != nil) != tt.wantErr {
t.Errorf("depChecker.Check(%v) = %v, want error %v", tt.KclPkg, gotErr, tt.wantErr)
}
})
}

// Clean the environment after all tests have been run
err = cleanTestEnv()
assert.Equal(t, err, nil)
}
8 changes: 8 additions & 0 deletions pkg/checker/test_data/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "test_data"
edition = "v0.9.0"
version = "0.0.1"

[dependencies]
k8s = "1.31"

5 changes: 5 additions & 0 deletions pkg/checker/test_data/kcl.mod.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[dependencies]
[dependencies.k8s]
name = "k8s"
full_name = "k8s_1.31"
version = "1.31"
1 change: 1 addition & 0 deletions pkg/checker/test_data/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The_first_kcl_program = 'Hello World!'
Loading

0 comments on commit 1b1ac7c

Please sign in to comment.