Skip to content

Commit

Permalink
Tarball Signature check
Browse files Browse the repository at this point in the history
Some tarballs have extra compression on top after making the signature,
which eventually leads to failing of signature check.
So new changes are made which take care of decompressing the tarball
to correct level where the tarball can be verified by its signature.
Checks also has been added to look for valid tarball signature pair,
so that processing can be terminated earlier if invalid pair found.
Test cases are added for followling scenarios:
1. Right decompression of tarball to match its signature
2. Mismatch check in tarbal and its signautre naming i.e., either wrong
   sig file is provided or naming convention is not followed
  • Loading branch information
manishk-arista committed Sep 3, 2024
1 parent 7374f58 commit 8c03965
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ RUN dnf install -y epel-release-9* git-2.* jq-1.* \
rpmdevtools-9.* sudo-1.* && \
dnf install -y mock-5.* automake-1.16.* && \
dnf install -y wget-1.21.* && \
dnf install -y vim-enhanced-2:8.2.* emacs-27.* && dnf clean all
dnf install -y vim-enhanced-2:8.2.* emacs-27.* p7zip-16.* && dnf clean all
RUN useradd -s /bin/bash mockbuild -p "$(openssl passwd -1 mockbuild)"
CMD ["bash"]

Expand Down
6 changes: 3 additions & 3 deletions barney.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ images:
units:
- floor: .%internal/alma-9.1-bootstrap
sources: []
build: install-rpms autoconf automake coreutils git rpm rpmdevtools rpm-build make mock python3-devel quilt
build: install-rpms autoconf automake coreutils git rpm rpmdevtools rpm-build make mock python3-devel quilt p7zip

go-binaries:
description: |
Expand Down Expand Up @@ -125,12 +125,12 @@ images:
units:
- floor: .%eext-testfloor
build: |
go test code.arista.io/eos/tools/eext/cmd -tags privileged
go test code.arista.io/eos/tools/eext/cmd
go test code.arista.io/eos/tools/eext/dnfconfig
go test code.arista.io/eos/tools/eext/srcconfig
go test code.arista.io/eos/tools/eext/manifest
go test code.arista.io/eos/tools/eext/impl
go test code.arista.io/eos/tools/eext/cmd
go test code.arista.io/eos/tools/eext/cmd -tags privileged
go vet code.arista.io/eos/tools/eext/...
test -z "$(gofmt -l .)"
Expand Down
38 changes: 38 additions & 0 deletions cmd/create_srpm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,44 @@ func testCreateSrpm(t *testing.T,
}
}

func testTarballSig(t *testing.T, folder string) {
curPath, _ := os.Getwd()
workingDir := filepath.Join(curPath, "testData/tarballSig", folder)
tarballPath := filepath.Join(workingDir, "libpcap-1.10.4.tar.gz.xz.gz")
if folder == "verifyTarball" {
tarballPath = filepath.Join(workingDir, "linux.10.4.1.tar.gz")
}
tarballSigPath := filepath.Join(workingDir, "libpcap-1.10.4.tar.gz.sig")
publicKey := filepath.Join(workingDir, "../../../../pki/trustedDetachedSigners/tcpdump/tcpdumpPubKey.pem")
var errPrefix util.ErrPrefix = "TestMatchTarballSignature(error) : "
expecatedTarballName := "libpcap-1.10.4.tar.gz"

gotTarballName, err := util.VerifyTarballSignature(tarballPath, tarballSigPath,
publicKey, workingDir, errPrefix)

if folder == "matchTarball" {
if err != nil {
t.Fatal(err)
}
require.Equal(t, expecatedTarballName, gotTarballName)
} else {
if err == nil {
t.Fatal("Error in verifying tarball signature")
}
}

}

func TestMatchTarballSignature(t *testing.T) {
t.Log("Test tarball Signatue Match")
testTarballSig(t, "matchTarball")
}

func TestVerifyTarballSignature(t *testing.T) {
t.Log("Test tarball Signatue Verify")
testTarballSig(t, "verifyTarball")
}

func TestCreateSrpmFromSrpm(t *testing.T) {
t.Log("Test createSrpm from SRPM")
testCreateSrpm(t,
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
18 changes: 11 additions & 7 deletions impl/create_srpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,18 +218,22 @@ func (bldr *srpmBuilder) verifyUpstream() error {
}
} else {
downloadDir := getDownloadDir(bldr.pkgSpec.Name)
for _, upstreamSrc := range bldr.upstreamSrc {
upstreamSourceFilePath := filepath.Join(downloadDir, upstreamSrc.sourceFile)

if !upstreamSrc.skipSigCheck {
upstreamSigFilePath := filepath.Join(downloadDir, upstreamSrc.sigFile)
if err := util.VerifyTarballSignature(
for index := range bldr.upstreamSrc {
upstreamSourceFilePath := filepath.Join(downloadDir, bldr.upstreamSrc[index].sourceFile)

if !bldr.upstreamSrc[index].skipSigCheck {
upstreamSigFilePath := filepath.Join(downloadDir, bldr.upstreamSrc[index].sigFile)
srcFile, err := util.VerifyTarballSignature(
upstreamSourceFilePath,
upstreamSigFilePath,
upstreamSrc.pubKeyPath,
bldr.errPrefix); err != nil {
bldr.upstreamSrc[index].pubKeyPath,
downloadDir,
bldr.errPrefix)
if err != nil {
return err
}
bldr.upstreamSrc[index].sourceFile = srcFile
}
}
}
Expand Down
80 changes: 74 additions & 6 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,82 @@ func VerifyRpmSignature(rpmPath string, errPrefix ErrPrefix) error {
return nil
}

func GetNewPath(tarballPath, cmprsn string) string {
tarballPath += "end"
suffix := "." + cmprsn + "end"
return strings.ReplaceAll(tarballPath, suffix, "")
}

// CheckValidSignature verifies that tarball anf signature
// correspond to same package
func CheckValidSignature(tarballCmprsn, tarballSigCmprsn []string) bool {
if len(tarballCmprsn) < len(tarballSigCmprsn)-1 {
return false
}
for i := 0; i < len(tarballSigCmprsn)-1; i++ {
if tarballCmprsn[i] != tarballSigCmprsn[i] {
return false
}
}
return true
}

// UncompressTarball decompresses the compression one layer at a time
// to match the tarball with its valid signature
func UncompressTarball(tarballPath string, downloadDir string) error {
if err := RunSystemCmd("7za", "x", "-y", tarballPath, "-o"+downloadDir); err != nil {
return err
}
// if err := CheckPath(tarballPath, true, true); err != nil {
// if err = RunSystemCmd("rm", tarballPath); err != nil {
// return err
// }
// }
return nil
}

// MatchtarballSignCmprsn evaluvates and finds correct compressed/uncompressed tarball
// that matches with the sign file.
func MatchtarballSignCmprsn(
tarballPath string, tarballSigPath string,
downloadDir string) (string, string, error) {
tarballCmprsn := strings.Split(tarballPath, ".")
tarballSigCmprsn := strings.Split(tarballSigPath, ".")
if !CheckValidSignature(tarballCmprsn, tarballSigCmprsn) {
return tarballPath, tarballSigPath,
fmt.Errorf("error : signature %s is invalid for tarball %s",
tarballSigPath, tarballPath)
}
tarballIndex, tarballSignIndex := len(tarballCmprsn)-1, len(tarballSigCmprsn)-2
for tarballIndex != tarballSignIndex {
if err := UncompressTarball(tarballPath, downloadDir); err != nil {
return tarballPath, tarballSigPath,
fmt.Errorf("UncompressTarball errored with %s, %s, %s", err, tarballPath, tarballSigPath)
}
tarballPath = GetNewPath(tarballPath, tarballCmprsn[tarballIndex])
tarballIndex--
}
return tarballPath, tarballSigPath, nil
}

// VerifyTarballSignature verifies that the detached signature of the tarball
// is valid.
func VerifyTarballSignature(
tarballPath string, tarballSigPath string, pubKeyPath string,
errPrefix ErrPrefix) error {
downloadDir string, errPrefix ErrPrefix) (string, error) {
// check for matching tarball compression for tarball signature file
if newTarballPath, newtarballSigPath, err := MatchtarballSignCmprsn(tarballPath,
tarballSigPath, downloadDir); err != nil {
return "Errored", fmt.Errorf("%s, while matching tarball and its signature", err)
} else {
tarballPath = newTarballPath
tarballSigPath = newtarballSigPath
}
srcFile := strings.ReplaceAll(tarballPath, downloadDir+"/", "")

tmpDir, mkdtErr := os.MkdirTemp("", "eext-keyring")
if mkdtErr != nil {
return fmt.Errorf("%sError '%s'creating temp dir for keyring",
return "Errored", fmt.Errorf("%sError '%s'creating temp dir for keyring",
errPrefix, mkdtErr)
}
defer os.RemoveAll(tmpDir)
Expand All @@ -184,23 +252,23 @@ func VerifyTarballSignature(
// Create keyring
createKeyRingCmdArgs := append(baseArgs, "--fingerprint")
if err := RunSystemCmd(gpgCmd, createKeyRingCmdArgs...); err != nil {
return fmt.Errorf("%sError '%s'creating keyring",
return "Errored", fmt.Errorf("%sError '%s'creating keyring",
errPrefix, err)
}

// Import public key
importKeyCmdArgs := append(baseArgs, "--import", pubKeyPath)
if err := RunSystemCmd(gpgCmd, importKeyCmdArgs...); err != nil {
return fmt.Errorf("%sError '%s' importing public-key %s",
return "Errored", fmt.Errorf("%sError '%s' importing public-key %s",
errPrefix, err, pubKeyPath)
}

verifySigArgs := append(baseArgs, "--verify", tarballSigPath, tarballPath)
if output, err := CheckOutput(gpgCmd, verifySigArgs...); err != nil {
return fmt.Errorf("%sError verifying signature %s for tarball %s with pubkey %s."+
return "Errored", fmt.Errorf("%sError verifying signature %s for tarball %s with pubkey %s."+
"\ngpg --verify err: %sstdout:%s",
errPrefix, tarballSigPath, tarballPath, pubKeyPath, err, output)
}

return nil
return srcFile, nil
}

0 comments on commit 8c03965

Please sign in to comment.