mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 17:26:28 +00:00
Merge pull request #3484 from deitch/eliminate-jq
eliminate manifest-push-script, jq dependency, odd logic
This commit is contained in:
commit
3716b312f6
@ -5,16 +5,32 @@ package pkglib
|
||||
//go:generate ./gen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
const dctEnableEnv = "DOCKER_CONTENT_TRUST=1"
|
||||
const (
|
||||
dctEnableEnv = "DOCKER_CONTENT_TRUST=1"
|
||||
registry = "https://index.docker.io/v1/"
|
||||
notaryServer = "https://notary.docker.io"
|
||||
notaryDelegationPassphraseEnvVar = "NOTARY_DELEGATION_PASSPHRASE"
|
||||
notaryAuthEnvVar = "NOTARY_AUTH"
|
||||
dctEnvVar = "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"
|
||||
)
|
||||
|
||||
var platforms = []string{
|
||||
"linux/amd64", "linux/arm64", "linux/s390x",
|
||||
}
|
||||
|
||||
type dockerRunner struct {
|
||||
dct bool
|
||||
@ -133,18 +149,13 @@ func (dr dockerRunner) pushWithManifest(img, suffix string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var dctArg string
|
||||
var trust bool
|
||||
if dr.dct {
|
||||
dctArg = "1"
|
||||
trust = true
|
||||
}
|
||||
|
||||
fmt.Printf("Pushing %s to manifest %s\n", img+suffix, img)
|
||||
cmd := exec.Command("/bin/sh", "-c", manifestPushScript, "manifest-push-script", img, dctArg)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
log.Debugf("Executing: %v", cmd.Args)
|
||||
|
||||
return cmd.Run()
|
||||
return manifestPush(img, trust)
|
||||
}
|
||||
|
||||
func (dr dockerRunner) tag(ref, tag string) error {
|
||||
@ -166,3 +177,99 @@ func (dr dockerRunner) save(tgt string, refs ...string) error {
|
||||
args := append([]string{"image", "save", "-o", tgt}, refs...)
|
||||
return dr.command(args...)
|
||||
}
|
||||
|
||||
func manifestPush(img string, trust bool) error {
|
||||
imgParts := strings.Split(img, ":")
|
||||
if len(imgParts) < 2 {
|
||||
return fmt.Errorf("image not composed of <repo>:<tag> '%s'", img)
|
||||
}
|
||||
repo := imgParts[0]
|
||||
tag := imgParts[1]
|
||||
|
||||
cfgFile := config.LoadDefaultConfigFile(os.Stderr)
|
||||
auth, err := cfgFile.GetAuthConfig(registry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get auth for %s: %v", registry, err)
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"push",
|
||||
"from-args",
|
||||
"--ignore-missing",
|
||||
"--platforms",
|
||||
strings.Join(platforms, ","),
|
||||
"--template",
|
||||
fmt.Sprintf("%s-ARCH", img),
|
||||
"--target",
|
||||
img,
|
||||
}
|
||||
manTool := "manifest-tool"
|
||||
// we do this separately to avoid printing username and password to debug output
|
||||
log.Debugf("Executing (will add username/password): %v", append([]string{manTool}, args...))
|
||||
args = append([]string{
|
||||
"--username",
|
||||
auth.Username,
|
||||
"--password",
|
||||
auth.Password,
|
||||
}, args...)
|
||||
cmd := exec.Command(manTool, args...)
|
||||
|
||||
var stdout bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to execute manifest-tool: %v", err)
|
||||
}
|
||||
|
||||
if !trust {
|
||||
fmt.Printf("trust disabled, not signing %s\n", img)
|
||||
return nil
|
||||
}
|
||||
|
||||
// get the image hash and the length from the manifest tool output
|
||||
manToolOut := string(stdout.Bytes())
|
||||
manToolOutParts := strings.Fields(manToolOut)
|
||||
if len(manToolOutParts) < 3 {
|
||||
return fmt.Errorf("manifest-tool output was less then required 3 parts '%s'", manToolOut)
|
||||
}
|
||||
hashParts := strings.Split(manToolOutParts[1], ":")
|
||||
if len(hashParts) < 2 {
|
||||
return fmt.Errorf("manifest-tool output hash was not in format <repo>:<hash> '%s'", manToolOutParts[1])
|
||||
}
|
||||
hash := hashParts[1]
|
||||
length := manToolOutParts[2]
|
||||
|
||||
notaryAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", auth.Username, auth.Password)))
|
||||
// run the notary command to sign
|
||||
args = []string{
|
||||
"-s",
|
||||
notaryServer,
|
||||
"-d",
|
||||
path.Join(os.Getenv("HOME"), ".docker/trust"),
|
||||
"addhash",
|
||||
"-p",
|
||||
fmt.Sprintf("docker.io/%s", repo),
|
||||
tag,
|
||||
length,
|
||||
"--sha256",
|
||||
hash,
|
||||
"-r",
|
||||
"targets/releases",
|
||||
}
|
||||
cmd = exec.Command("notary", args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", notaryDelegationPassphraseEnvVar, os.Getenv(dctEnvVar)), fmt.Sprintf("%s=%s", notaryAuthEnvVar, notaryAuth))
|
||||
log.Debugf("Executing: %v", cmd.Args)
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to execute notary-tool: %v", err)
|
||||
}
|
||||
|
||||
// report output
|
||||
fmt.Printf("New signed multi-arch image: %s:%s\n", repo, tag)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
(
|
||||
echo package pkglib
|
||||
echo
|
||||
echo const manifestPushScript = \`
|
||||
# TODO(ijc) once everything is ported this script can move to this source directory
|
||||
cat ../../../../scripts/push-manifest.sh
|
||||
echo \`
|
||||
) > manifest_push_script.go.new
|
||||
mv manifest_push_script.go.new manifest_push_script.go
|
@ -1,89 +0,0 @@
|
||||
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 <org>/<image>:<tag> and this is what
|
||||
# the manifest is pushed to. It assumes that there is are images of
|
||||
# the form <org>/<image>:<tag>-<arch> 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)
|
||||
# Prior to 2018-03-27 D4M used a .bin suffix on the keychain utility binary name. Support the old name for a while
|
||||
if [ -f /Applications/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain.bin ]; then
|
||||
CREDHELPER="/Applications/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain.bin"
|
||||
else
|
||||
CREDHELPER="/Applications/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain"
|
||||
fi
|
||||
;;
|
||||
Linux)
|
||||
CREDSTORE=$(cat ~/.docker/config.json | jq -r '.credsStore // empty')
|
||||
if [ -n "$CREDSTORE" ] ; then
|
||||
CREDHELPER="docker-credential-$CREDSTORE"
|
||||
else
|
||||
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=
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported platform"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if [ -n "$CREDHELPER" ] ; then
|
||||
CRED=$(echo "https://index.docker.io/v1/" | "$CREDHELPER" get)
|
||||
USER=$(echo "$CRED" | jq -r '.Username')
|
||||
PASS=$(echo "$CRED" | jq -r '.Secret')
|
||||
MT_ARGS="--username $USER --password $PASS"
|
||||
fi
|
||||
|
||||
# Push manifest list
|
||||
OUT=$(manifest-tool $MT_ARGS push from-args \
|
||||
--ignore-missing \
|
||||
--platforms linux/amd64,linux/arm64,linux/s390x \
|
||||
--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 0.6.0 accepts authentication as base64-encoded "username:password"
|
||||
export NOTARY_AUTH=$(echo "$USER:$PASS" | base64)
|
||||
export NOTARY_DELEGATION_PASSPHRASE="$DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"
|
||||
|
||||
notary -s https://notary.docker.io -d $HOME/.docker/trust addhash \
|
||||
-p docker.io/$REPO $TAG $LEN --sha256 $SHA256 \
|
||||
-r targets/releases
|
||||
|
||||
echo
|
||||
echo "New signed multi-arch image: $REPO:$TAG"
|
||||
echo
|
||||
`
|
Loading…
Reference in New Issue
Block a user