From 42f5a3e38ea6e23f5aff146f65ad20025088fc84 Mon Sep 17 00:00:00 2001
From: liyuanr <liyuanrong1@huawei.com>
Date: Mon, 29 May 2023 11:12:52 +0800
Subject: [PATCH] KubeOS: add oci image digests check when upgrade and fix the
 issue with the software version display

add check of digests of the oci image for upgrade after
os-agent pulls image when os upgrading.

Fix the issue where the softwares version is empty

Signed-off-by: liyuanr <liyuanrong1@huawei.com>
---
 Makefile                             |  2 +-
 cmd/agent/server/containerd_image.go |  3 ++
 cmd/agent/server/docker_image.go     |  3 ++
 cmd/agent/server/utils.go            | 44 ++++++++++++++++++++++++++++
 docs/quick-start.md                  |  8 ++---
 5 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 9d9fbea..27cf175 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ endif
 
 VERSION_FILE := ./VERSION
 VERSION := $(shell cat $(VERSION_FILE))
-PACKAGE:=openeuler.org/saiyan/pkg/version
+PACKAGE:=openeuler.org/KubeOS/pkg/version
 BUILDFLAGS = -buildmode=pie -trimpath
 LDFLAGS = -w -s -buildid=IdByKubeOS -linkmode=external -extldflags=-static -extldflags=-zrelro -extldflags=-Wl,-z,now -X ${PACKAGE}.Version=${VERSION}
 ENV = CGO_CFLAGS="-fstack-protector-all" CGO_CPPFLAGS="-D_FORTIFY_SOURCE=2 -O2"
diff --git a/cmd/agent/server/containerd_image.go b/cmd/agent/server/containerd_image.go
index 0b614b5..b019b72 100644
--- a/cmd/agent/server/containerd_image.go
+++ b/cmd/agent/server/containerd_image.go
@@ -48,6 +48,9 @@ func (c conImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath prep
 	if err := runCommand("crictl", "pull", imageName); err != nil {
 		return "", err
 	}
+	if err := checkOCIImageDigestMatch("containerd", imageName, req.CheckSum); err != nil {
+		return "", err
+	}
 	if err := checkAndCleanMount(mountPath); err != nil {
 		logrus.Errorln("containerd clean environment error", err)
 		return "", err
diff --git a/cmd/agent/server/docker_image.go b/cmd/agent/server/docker_image.go
index 2a52634..e6fa9d6 100644
--- a/cmd/agent/server/docker_image.go
+++ b/cmd/agent/server/docker_image.go
@@ -38,6 +38,9 @@ func (d dockerImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath p
 	if err := runCommand("docker", "pull", imageName); err != nil {
 		return "", err
 	}
+	if err := checkOCIImageDigestMatch("docker", imageName, req.CheckSum); err != nil {
+		return "", err
+	}
 	containerName := "kubeos-temp"
 	dockerPsCmd := "docker ps -a -f=name=" + containerName + "| awk 'NR==2' | awk '{print $1}'"
 	existId, err := runCommandWithOut("bash", "-c", dockerPsCmd)
diff --git a/cmd/agent/server/utils.go b/cmd/agent/server/utils.go
index 111497c..092417b 100644
--- a/cmd/agent/server/utils.go
+++ b/cmd/agent/server/utils.go
@@ -264,3 +264,47 @@ func checkFileExist(path string) (bool, error) {
 		return false, err
 	}
 }
+
+func checkOCIImageDigestMatch(containerRuntime string, imageName string, checkSum string) error {
+	var cmdOutput string
+	var err error
+	switch containerRuntime {
+	case "containerd":
+		cmdOutput, err = runCommandWithOut("crictl", "inspecti", "--output", "go-template",
+			"--template", "{{.status.repoDigests}}", imageName)
+		if err != nil {
+			return err
+		}
+	case "docker":
+		cmdOutput, err = runCommandWithOut("docker", "inspect", "--format", "{{.RepoDigests}}", imageName)
+		if err != nil {
+			return err
+		}
+	default:
+		logrus.Errorln("containerRuntime ", containerRuntime, " cannot be recognized")
+		return fmt.Errorf("containerRuntime %s cannot be recognized", containerRuntime)
+	}
+	// cmdOutput format is as follows:
+	// [imageRepository/imageName:imageTag@sha256:digests]
+	// parse the output and get digest
+	var imageDigests string
+	outArray := strings.Split(cmdOutput, "@")
+	if strings.HasPrefix(outArray[len(outArray)-1], "sha256") {
+		pasredArray := strings.Split(strings.TrimSuffix(outArray[len(outArray)-1], "]"), ":")
+		// 2 is the expected length of the array after dividing "imageName:imageTag@sha256:digests" based on ':'
+		rightLen := 2
+		if len(pasredArray) == rightLen {
+			digestIndex := 1 // 1 is the index of digest data in pasredArray
+			imageDigests = pasredArray[digestIndex]
+		}
+	}
+	if imageDigests == "" {
+		logrus.Errorln("error when get ", imageName, " digests")
+		return fmt.Errorf("error when get %s digests", imageName)
+	}
+	if imageDigests != checkSum {
+		logrus.Errorln("checkSumFailed ", imageDigests, " mismatch to ", checkSum)
+		return fmt.Errorf("checkSumFailed %s mismatch to %s", imageDigests, checkSum)
+	}
+	return nil
+}
-- 
2.33.0.windows.2

