From 6bf8992a0a8712161c890c93d60fb34d12c2bfa5 Mon Sep 17 00:00:00 2001 From: Jonathan Perry Date: Wed, 20 Apr 2022 04:14:35 -0400 Subject: [PATCH] Rust Binary Checks SHA256 (#449) * add shasum check of init payload * fix path to rust injector in workflow * update zarf-ijector to version that checks sha * switch to govcloud KMS * update rust injector cargo version * add cosign annotations * include github url in release-engineer annotation Co-authored-by: Jeff McCoy --- .github/workflows/build-rust-injector.yml | 18 ++++++++++----- cosign.pub | 16 +++++++++++--- packages/zarf-injector/zarf.yaml | 2 +- src/injector/stage1/Cargo.lock | 7 ++++++ src/injector/stage1/Cargo.toml | 3 ++- src/injector/stage1/src/main.rs | 5 +++-- src/internal/packager/injector.go | 27 ++++++++++++++--------- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build-rust-injector.yml b/.github/workflows/build-rust-injector.yml index 59635c14fe..3c426bd55c 100644 --- a/.github/workflows/build-rust-injector.yml +++ b/.github/workflows/build-rust-injector.yml @@ -1,4 +1,8 @@ name: Build Rust Binary + +env: + zarfInjectorPath: 'src/injector/stage1/target/x86_64-unknown-linux-musl/release/zarf-injector' + on: workflow_dispatch: inputs: @@ -29,13 +33,13 @@ jobs: args: cargo build --target x86_64-unknown-linux-musl --release --manifest-path src/injector/stage1/Cargo.toml - name: "Strip The Binary Down" - run: sudo strip src/injector/stage1/target/x86_64-unknown-linux-musl/release/zarf-injector + run: sudo strip ${{ env.zarfInjectorPath }} - name: "Upload Rust Binary" uses: actions/upload-artifact@v2 with: name: zarf-injector - path: src/injector/stage1/target/x86_64-unknown-linux-musl/release/zarf-injector + path: ${{ env.zarfInjectorPath }} - name: Login to Docker Hub uses: docker/login-action@v1 @@ -44,9 +48,13 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: "Upload Binary To DockerHub" - run: cosign upload blob -f zarf-injector defenseunicorns/zarf-injector:${{ github.event.inputs.versionTag }} + run: cosign upload blob -f ${{ env.zarfInjectorPath }} defenseunicorns/zarf-injector:${{ github.event.inputs.versionTag }} - name: "Sign the binary" - run: cosign sign --key ${{ secrets.COSIGN_SIGNING_KEY }} defenseunicorns/zarf-injector:${{ github.event.inputs.versionTag }} + run: cosign sign --key awskms:///${{ secrets.COSIGN_AWS_KMS_KEY }} -a release-engineer=https://github.com/${{ github.actor }} -a version=${{ github.event.inputs.versionTag }} defenseunicorns/zarf-injector:${{ github.event.inputs.versionTag }} env: - COSIGN_EXPERIMENTAL: 1 + COSIGN_EXPERIMENTAL: 1 + AWS_REGION: ${{ secrets.COSIGN_AWS_REGION }} + AWS_ACCESS_KEY_ID: ${{ secrets.COSIGN_AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.COSIGN_AWS_ACCESS_KEY }} + diff --git a/cosign.pub b/cosign.pub index 8eaec1b85e..6c8e8e4eb5 100644 --- a/cosign.pub +++ b/cosign.pub @@ -1,4 +1,14 @@ -----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkK3glLLNDKX7ny8wRzrh/G04huzV -QaiLEEMlVHpdzfwqkspAWxzbcUaTj5SPyaLT5TLDEXiOt4AS4D/Q3twxfw== ------END PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9u472y/wY0tjIiR2T6rY +zOG1q4qwx5ZdmnoGsiG0Zc3rYo2DMiuKciG0MI4opCf4IID7kfYOD4aWILymwFID +xW0L6pEbxknHRQacWZSf/qfA+aAcjbKOY3ZWU8/uLJJeq37Y4OLc17ThJ7ZOj1Yf +Uvj81Uz9ZWVW7kYY31vWCruJh4VxZLsUAmFc6CsQUtzSGordLhh1b1rDP6ZRAaIP +mQnniULogwIBqnUTkIVwxiRYG+V2a3IC5vqlBLQRQ3UOWQ9mgZcfcXuTA6Fh8bwO +2lG768UfI1RBYioXAgXbPwXK+kM3Idvjcr+X2F3VpYWhHTscMIQF0ERzK7BkRqRI +x9l/RRm5lP+9a1kt6giYtvX2OqEsWaG3lTen3ocwblaHRlmqnaiVBtAnVny6QDHX +9p1HPMD/NjWjZucxWMjtdL5FZxBywbJVlxhe7sFByMoBZYhea9vGGSn2M2Q9kPiq +Bgl6bKZdeYIhaKQ7wrNkS6YVHMIqqpCIUI6/YGYwnu0hodbjR0yA2LFx4TgFZAuY +uGEiRP4Oi7WEOPkjRjP7kPXGpEBB7ulZ/Wohq1B6pB1Odo8WlfJRAek319F2aqqh +J1c3YdZ/w3EvCLKd+Inp1UNbamb79UN6jtwhqwKw72YbZh/yP0rim49lQ++umwPX +JWqG8iY/UzGB/3ch4/Wb09UCAwEAAQ== +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/packages/zarf-injector/zarf.yaml b/packages/zarf-injector/zarf.yaml index 7291365001..4f2a528dc9 100644 --- a/packages/zarf-injector/zarf.yaml +++ b/packages/zarf-injector/zarf.yaml @@ -9,7 +9,7 @@ components: cosignKeyPath: ../../cosign.pub files: # Rust Injector Binary - - source: sget://defenseunicorns/zarf-injector:0.1.0 + - source: sget://defenseunicorns/zarf-injector:0.4.3 target: "###ZARF_TEMP###/zarf-injector" executable: true # Go Registry Binary diff --git a/src/injector/stage1/Cargo.lock b/src/injector/stage1/Cargo.lock index 852e1ed151..b4a96c5470 100644 --- a/src/injector/stage1/Cargo.lock +++ b/src/injector/stage1/Cargo.lock @@ -113,6 +113,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "libc" version = "0.2.119" @@ -209,6 +215,7 @@ version = "0.1.0" dependencies = [ "flate2", "glob", + "hex", "sha2", "tar", ] diff --git a/src/injector/stage1/Cargo.toml b/src/injector/stage1/Cargo.toml index 73f52594b0..144c182775 100644 --- a/src/injector/stage1/Cargo.toml +++ b/src/injector/stage1/Cargo.toml @@ -6,7 +6,7 @@ panic = "abort" [package] name = "zarf-injector" -version = "0.1.0" +version = "0.4.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,3 +16,4 @@ glob = "0.3.0" flate2 = "1.0.22" tar = "0.4.38" sha2 = "0.10.2" +hex = "0.4.3" diff --git a/src/injector/stage1/src/main.rs b/src/injector/stage1/src/main.rs index 3cc71dfe9b..2cf0c04fa6 100644 --- a/src/injector/stage1/src/main.rs +++ b/src/injector/stage1/src/main.rs @@ -7,6 +7,7 @@ use std::io::Read; use std::io::Write; use std::path::PathBuf; use tar::Archive; +use hex::ToHex; // Inspired by https://medium.com/@nlauchande/rust-coding-up-a-simple-concatenate-files-tool-and-first-impressions-a8cbe680e887 @@ -69,8 +70,8 @@ fn main() { // read hash digest and consume hasher let result = hasher.finalize(); - - assert_eq!(result[..], sha_sum.as_bytes()[..]); + let result_string = result.encode_hex::(); + assert_eq!(*sha_sum, result_string); } let tar = GzDecoder::new(&contents[..]); diff --git a/src/internal/packager/injector.go b/src/internal/packager/injector.go index b5b2d8d5bf..3ded821b24 100644 --- a/src/internal/packager/injector.go +++ b/src/internal/packager/injector.go @@ -1,6 +1,7 @@ package packager import ( + "crypto/sha256" "fmt" "io/ioutil" "os" @@ -31,6 +32,7 @@ func runInjectionMadness(tempPath tempPaths) { var images []string var envVars []corev1.EnvVar var payloadConfigmaps []string + var sha256sum string // Try to create the zarf namespace spinner.Updatef("Creating the Zarf namespace") @@ -62,7 +64,7 @@ func runInjectionMadness(tempPath tempPaths) { } spinner.Updatef("Loading the seed registry configmaps") - if payloadConfigmaps, err = createPayloadConfigmaps(tempPath, spinner); err != nil { + if payloadConfigmaps, sha256sum, err = createPayloadConfigmaps(tempPath, spinner); err != nil { message.Fatal(err, "Unable to generate the injector payload configmaps") } @@ -82,7 +84,7 @@ func runInjectionMadness(tempPath tempPaths) { _ = k8s.DeletePod(k8s.ZarfNamespace, "injector") // Update the podspec image path - pod := buildInjectionPod(image, envVars, payloadConfigmaps) + pod := buildInjectionPod(image, envVars, payloadConfigmaps, sha256sum) // Create the pod in the cluster pod, err = k8s.CreatePod(pod) @@ -103,13 +105,14 @@ func runInjectionMadness(tempPath tempPaths) { spinner.Fatalf(nil, "Unable to perform the injection") } -func createPayloadConfigmaps(tempPath tempPaths, spinner *message.Spinner) ([]string, error) { +func createPayloadConfigmaps(tempPath tempPaths, spinner *message.Spinner) ([]string, string, error) { message.Debugf("packager.tryInjectorPayloadDeploy(%v)", tempPath) var ( err error tarFile []byte chunks [][]byte configMaps []string + sha256sum string ) // Chunk size has to accomdate base64 encoding & etcd 1MB limit @@ -125,14 +128,19 @@ func createPayloadConfigmaps(tempPath tempPaths, spinner *message.Spinner) ([]st spinner.Updatef("Creating the seed registry archive to send to the cluster") // Create a tar archive of the injector payload if err = archiver.Archive(tarFileList, tarPath); err != nil { - return configMaps, err + return configMaps, "", err } + archiver.Archive(tarFileList, "/home/user/payload.tgz") + // Open the created archive for io.Copy if tarFile, err = ioutil.ReadFile(tarPath); err != nil { - return configMaps, err + return configMaps, "", err } + //Calculate the sha256sum of the tarFile before we split it up + sha256sum = fmt.Sprintf("%x", sha256.Sum256(tarFile)) + spinner.Updatef("Splitting the archive into binary configmaps") // Loop over the tarball breaking it into chunks based on the payloadChunkSize for { @@ -165,7 +173,7 @@ func createPayloadConfigmaps(tempPath tempPaths, spinner *message.Spinner) ([]st // Attempt to create the configmap in the cluster if _, err = k8s.ReplaceConfigmap(k8s.ZarfNamespace, fileName, labels, configData); err != nil { - return configMaps, err + return configMaps, "", err } // Add the configmap to the configmaps slice for later usage in the pod @@ -175,7 +183,7 @@ func createPayloadConfigmaps(tempPath tempPaths, spinner *message.Spinner) ([]st time.Sleep(100 * time.Millisecond) } - return configMaps, nil + return configMaps, sha256sum, nil } func hasSeedImages(spinner *message.Spinner) bool { @@ -295,7 +303,7 @@ func buildEnvVars(tempPath tempPaths) ([]corev1.EnvVar, error) { } // buildInjectionPod return a pod for injection with the appropriate containers to perform the injection -func buildInjectionPod(image string, envVars []corev1.EnvVar, payloadConfigmaps []string) *corev1.Pod { +func buildInjectionPod(image string, envVars []corev1.EnvVar, payloadConfigmaps []string, payloadShasum string) *corev1.Pod { pod := k8s.GeneratePod("injector", k8s.ZarfNamespace) executeMode := int32(0777) seedImage := config.GetSeedImage() @@ -303,13 +311,12 @@ func buildInjectionPod(image string, envVars []corev1.EnvVar, payloadConfigmaps pod.Labels["app"] = "zarf-injector" pod.Spec.RestartPolicy = corev1.RestartPolicyNever - pod.Spec.InitContainers = []corev1.Container{ { Name: "init-injector", Image: image, WorkingDir: "/zarf-stage1", - Command: []string{"/zarf-stage1/zarf-injector"}, + Command: []string{"/zarf-stage1/zarf-injector", payloadShasum}, VolumeMounts: []corev1.VolumeMount{ {