From 3141ca0bef2f78638e4ac0a8a4aedd2406cb5e21 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 6 Oct 2017 14:00:22 +0100 Subject: [PATCH] Embed scripts/push-manifest.sh into linuxkit tool This is a bit gross, but hopefully this script will be written in go sooner rather than later and in the meantime this avoids the need to install yet another tool on user's systems (and get it into brew etc). Checkin the result of `go:generate` for now. Once there are no more users of push-manifest.sh it can be moved alongside the go code (if it hasn't been rewritten in go along the way). Signed-off-by: Ian Campbell --- Makefile | 5 +- src/cmd/linuxkit/pkglib/docker.go | 4 +- .../linuxkit/pkglib/manifest_push_script.go | 112 ++++++++++++++++++ 3 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/cmd/linuxkit/pkglib/manifest_push_script.go diff --git a/Makefile b/Makefile index b2531564f..de7e5950e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .PHONY: default all -default: bin/moby bin/linuxkit bin/rtf bin/linuxkit-push-manifest +default: bin/moby bin/linuxkit bin/rtf all: default VERSION="0.0" # dummy for now @@ -20,9 +20,6 @@ endif PREFIX?=/usr/local/ -bin/linuxkit-push-manifest: scripts/push-manifest.sh | bin - cp $< $@ - MOBY_REPO=https://github.com/moby/tool.git MOBY_COMMIT=177969dc4a0fb843f635e45ab8e87d2cd2c531cd MOBY_VERSION=0.0 diff --git a/src/cmd/linuxkit/pkglib/docker.go b/src/cmd/linuxkit/pkglib/docker.go index b05da8c98..0efe290d7 100644 --- a/src/cmd/linuxkit/pkglib/docker.go +++ b/src/cmd/linuxkit/pkglib/docker.go @@ -2,6 +2,8 @@ package pkglib // Thin wrappers around Docker CLI invocations +//go:generate ./gen + import ( "fmt" "os" @@ -66,7 +68,7 @@ func (dr dockerRunner) pushWithManifest(img, suffix string) error { dctArg = "1" } - cmd := exec.Command("linuxkit-push-manifest", img, dctArg) + cmd := exec.Command("/bin/sh", "-c", manifestPushScript, "manifest-push-script", img, dctArg) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if debugDockerCommands { diff --git a/src/cmd/linuxkit/pkglib/manifest_push_script.go b/src/cmd/linuxkit/pkglib/manifest_push_script.go new file mode 100644 index 000000000..9b6d81b7b --- /dev/null +++ b/src/cmd/linuxkit/pkglib/manifest_push_script.go @@ -0,0 +1,112 @@ +package pkglib + +const manifestPushScript = ` +#! /bin/sh + +set -e + +# This script pushes a multiarch manifest for packages and signs it. +# +# The TARGET must be of the form /: and this is what +# the manifest is pushed to. It assumes that there is are images of +# the form /:- already on hub. +# +# If TRUST is not set, the manifest will not be signed. +# +# For signing, DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE must be set. + +# This should all be replaced with 'docker manifest' once it lands. + +TARGET=$1 +TRUST=$2 + +REPO=$(echo "$TARGET" | cut -d':' -f1) +TAG=$(echo "$TARGET" | cut -d':' -f2) + +# Work out credentials. On macOS they are needed for manifest-tool and +# we need them for notary on all platforms. +case $(uname -s) in + Darwin) + CRED=$(echo "https://index.docker.io/v1/" | /Applications/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain.bin get) + USER=$(echo "$CRED" | jq -r '.Username') + PASS=$(echo "$CRED" | jq -r '.Secret') + MT_ARGS="--username $USER --password $PASS" + ;; + Linux) + CRED=$(cat ~/.docker/config.json | jq -r '.auths."https://index.docker.io/v1/".auth' | base64 -d -) + USER=$(echo $CRED | cut -d ':' -f 1) + PASS=$(echo $CRED | cut -d ':' -f 2-) + # manifest-tool can use docker credentials directly + MT_ARGS= + ;; + *) + echo "Unsupported platform" + exit 1 + ;; +esac + +# Push manifest list +OUT=$(manifest-tool $MT_ARGS push from-args \ + --ignore-missing \ + --platforms linux/amd64,linux/arm64 \ + --template "$TARGET"-ARCH \ + --target "$TARGET") + +echo "$OUT" +if [ -z "$TRUST" ]; then + echo "Not signing $TARGET" + exit 0 +fi + +# Extract sha256 and length from the manifest-tool output +SHA256=$(echo "$OUT" | cut -d' ' -f2 | cut -d':' -f2) +LEN=$(echo "$OUT" | cut -d' ' -f3) + +# Notary requires a PTY for username/password so use expect for that. +export NOTARY_DELEGATION_PASSPHRASE="$DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE" +NOTARY_CMD="notary -s https://notary.docker.io -d $HOME/.docker/trust addhash \ + -p docker.io/$REPO $TAG $LEN --sha256 $SHA256 \ + -r targets/releases" + +echo ' +spawn '"$NOTARY_CMD"' +set pid [exp_pid] +set timeout 60 +expect { + timeout { + puts "Expected username prompt" + exec kill -9 $pid + exit 1 + } + "username: " { + send "'"$USER"'\n" + } +} +expect { + timeout { + puts "Expected password prompt" + exec kill -9 $pid + exit 1 + } + "password: " { + send "'"$PASS"'\n" + } +} +expect { + timeout { + puts "Expected password prompt" + exec kill -9 $pid + exit 1 + } + eof { + } +} +set waitval [wait -i $spawn_id] +set exval [lindex $waitval 3] +exit $exval +' | expect -f - + +echo +echo "New signed multi-arch image: $REPO:$TAG" +echo +`