diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 94fa6e0..d751dd2 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -1,12 +1,6 @@ name: main on: [push, pull_request] -# TODO: implement support for [skip ci], https://timheuer.com/blog/skipping-ci-github-actions-workflows/ -# TODO: bonus: can we achiever apple codesigning in CI and remove the local script step? -# TODO: update CI/CD section in readme to remove azure refs -# TODO: switch readme CI badge to github actions -# TODO: document autotag git branch+tags stuff in autotag README - jobs: lint: strategy: @@ -80,7 +74,7 @@ jobs: needs: [lint, test] # don't waste time running a goreleaser test build on master since we will run a full release: if: github.ref != 'refs/heads/master' - runs-on: ubuntu-latest + runs-on: macos-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 @@ -90,15 +84,33 @@ jobs: key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - - name: install go deps - run: make deps + + - uses: apple-actions/import-codesign-certs@v1 + with: + p12-file-base64: ${{ secrets.APPLE_CODESIGN_CERTIFICATES_P12 }} + p12-password: ${{ secrets.APPLE_CODESIGN_CERTIFICATES_PASSWORD }} + + - name: import GPG signing key + env: + GPG_KEY: ${{ secrets.GPG_KEY }} + run: | + echo "$GPG_KEY" \ + | base64 --decode \ + | gpg --batch --allow-secret-key-import --import + gpg --keyid-format LONG --list-secret-keys + + - name: install release deps + run: | + brew install goreleaser/tap/goreleaser + brew install FiloSottile/musl-cross/musl-cross + - run: make snapshot release: needs: [lint, test] # only create a release on master builds: if: github.ref == 'refs/heads/master' - runs-on: ubuntu-latest + runs-on: macos-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 @@ -108,6 +120,21 @@ jobs: key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- + + - uses: apple-actions/import-codesign-certs@v1 + with: + p12-file-base64: ${{ secrets.APPLE_CODESIGN_CERTIFICATES_P12 }} + p12-password: ${{ secrets.APPLE_CODESIGN_CERTIFICATES_PASSWORD }} + + - name: import GPG signing key + env: + GPG_KEY: ${{ secrets.GPG_KEY }} + run: | + echo "$GPG_KEY" \ + | base64 --decode \ + | gpg --batch --allow-secret-key-import --import + gpg --keyid-format LONG --list-secret-keys + - name: Unshallow run: | # fetch all tags and history so that goreleaser can generate a proper changelog @@ -118,21 +145,20 @@ jobs: # ensure a local 'master' branch exists for autotag to work correctly: git branch --track master origin/master fi - - name: install go deps - run: make deps - - name: install autotag + - name: install release deps run: | - curl -sL https://git.io/autotag-install | sudo sh -s -- -b /usr/local/bin + brew install goreleaser/tap/goreleaser + brew install FiloSottile/musl-cross/musl-cross - name: run autotag to increment version run: | + curl -sL https://git.io/autotag-install | sudo sh -s -- -b /usr/local/bin autotag - name: build and push release artifacts env: GITHUB_TOKEN: ${{ secrets.BREW_GITHUB_TOKEN }} - # GPG_KEY contents must be base64 encoded: - GPG_KEY: ${{ secrets.GPG_KEY }} run: | + make deps make release diff --git a/.goreleaser.yml b/.goreleaser.yml index 3b2c233..22a2bef 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -4,39 +4,43 @@ env: - GOPROXY=https://proxy.golang.org builds: - binary: vault-token-helper - id: windows - ldflags: - - -s -w -X github.com/joemiller/vault-token-helper/cmd.version={{.Version}}+{{.ShortCommit}} - - "-extldflags '-static'" + id: macos + ldflags: -s -w -X github.com/joemiller/vault-token-helper/cmd.version={{.Version}}+{{.ShortCommit}} env: - CGO_ENABLED=1 - - CC=x86_64-w64-mingw32-gcc - - CXX=x86_64-w64-mingw32-g++ goos: - - windows + - darwin goarch: - amd64 + hooks: + post: ./scripts/macos-codesign.sh "{{ .Path }}" + # cross-compile windows binary - binary: vault-token-helper - id: macos - ldflags: -s -w -X github.com/joemiller/vault-token-helper/cmd.version={{.Version}}+{{.ShortCommit}} + id: windows + ldflags: + - -s -w -X github.com/joemiller/vault-token-helper/cmd.version={{.Version}}+{{.ShortCommit}} + - "-extldflags '-static'" env: - CGO_ENABLED=1 - - CC=o64-clang - - CXX=o64-clang++ + - CC=x86_64-w64-mingw32-gcc + - CXX=x86_64-w64-mingw32-g++ goos: - - darwin + - windows goarch: - amd64 - # TODO: find a way to codesign from linux and integrate into azure pipelines ci/cd - # hooks: - # post: ./macos-codesign.sh + # cross-compile static linux bin on macos using https://github.com/FiloSottile/homebrew-musl-cross + # brew install FiloSottile/musl-cross/musl-cross - binary: vault-token-helper id: linux - ldflags: -s -w -X github.com/joemiller/vault-token-helper/cmd.version={{.Version}}+{{.ShortCommit}} + ldflags: + - -s -w -X github.com/joemiller/vault-token-helper/cmd.version={{.Version}}+{{.ShortCommit}} + - "-linkmode external -extldflags '-static'" env: - CGO_ENABLED=1 + - CC=x86_64-linux-musl-gcc + - CXX=x86_64-linux-musl-g++ goos: - linux goarch: diff --git a/Makefile b/Makefile index bc9e5d6..0468bec 100644 --- a/Makefile +++ b/Makefile @@ -19,28 +19,11 @@ build: @go build . release: - @docker run \ - --rm \ - -e "GITHUB_TOKEN=$$GITHUB_TOKEN" \ - -e "GPG_KEY=$$GPG_KEY" \ - -v `pwd`:/src \ - -w /src \ - dockercore/golang-cross \ - /src/scripts/release.sh $(GORELEASER_ARGS) + @goreleaser $(GORELEASER_ARGS) snapshot: GORELEASER_ARGS= --rm-dist --snapshot snapshot: release -sign-and-promote-release: - bash ./scripts/sign-and-promote-release.sh - -build-dev-docker-image: - @docker build -t joemiller/vault-token-helper-dev -f ./dev/Dockerfile.dev ./dev - -run-dev-docker-image: - #docker run --rm -it -v$$(PWD):/src -w /src joemiller/vault-token-helper-dev /bin/bash - docker run --rm -it -v$$(PWD):/src --privileged -w /src joemiller/vault-token-helper-dev /bin/bash - todo: @grep \ --exclude-dir=vendor \ diff --git a/README.md b/README.md index 4ea2515..847cac3 100644 --- a/README.md +++ b/README.md @@ -239,14 +239,7 @@ $ GPG_KEY="$(cat vault-token-helper.signing-key.gpg | base64)" make snapshot #### Apple codesign In order to avoid macOS keychain from always prompting for passwords the macOS binaries -are codesigned with a cert issued by Apple. Unfortunately this can't be done easily in CI -while still being able to leverage all the advantages of [goreleaser](https://goreleaser.com/). -This will hopefully change one day when there is a `codesign` compatible binary available -for Linux. - -In the meantime, all releases pushed by CI are created as draft releases. In order to promote -a release, run `make sign-and-promote-release TAG=vX.Y.Z` from a macOS system with both the -project GPG key and an apple code signing cert available. +are codesigned with a cert issued by Apple. TODO ---- @@ -257,5 +250,5 @@ TODO * [x] add a flag like `--extended` to `list` that will query vault for additional token info, eg: valid/invalid, ttl, policies * ci/cd: * [x] `sign` checksum.txt and assets in goreleaser.yaml GPG key - * [ ] apple `codesign` the macos binaries + * [x] apple `codesign` the macos binaries * [ ] linux tests, figure out how to test dbus secret-service in headless CI. probably need a stub to connect to Dbus and provide the 'prompt' service diff --git a/go.mod b/go.mod index 3a3d3d9..cd7b438 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/99designs/keyring v0.0.0-20190704105226-2c916c935b9f github.com/PuerkitoBio/purell v1.1.0 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/davecgh/go-spew v1.1.1 github.com/hashicorp/vault/api v1.0.2 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 github.com/mitchellh/go-homedir v1.1.0 @@ -14,7 +13,6 @@ require ( github.com/spf13/cobra v0.0.5 github.com/spf13/viper v1.4.0 github.com/stretchr/testify v1.3.0 - google.golang.org/appengine v1.4.0 // indirect ) // replace github.com/99designs/keyring v0.0.0-20190531235905-2e3b4e59b02e => ../keyring diff --git a/scripts/macos-codesign.sh b/scripts/macos-codesign.sh new file mode 100755 index 0000000..fc3ae7f --- /dev/null +++ b/scripts/macos-codesign.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -eou pipefail + +CODESIGN_CERT="Developer ID Application: JOSEPH MILLER (P3MF48HUD7)" + +path="$1" + +# sign +codesign -s "$CODESIGN_CERT" -i "vault-token-helper" "$path" + +# display signature +codesign -v -d "$path" diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100755 index 8079dcf..0000000 --- a/scripts/release.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -# this script is intended to be run inside the dockercore/golang-cross docker image, eg: -# -# docker run \ -# --rm \ -# -e "GITHUB_TOKEN=$GITHUB_TOKEN" \ -# -e "GPG_KEY=$GPG_KEY" \ -# -v `pwd`:/src \ -# -w /src \ -# dockercore/golang-cross \ -# /src/release.sh -# -# (optional) arguments will be passed to goreleaser, eg: -# -# /src/release.sh --snapshot --rm-dist -# -# (optional) sign releases with $GPG_KEY. The key should be base64 encoded. - -set -eou pipefail - -GORELEASER_ARGS=("$@") - -if [[ -n "${GPG_KEY:-}" ]]; then - GNUPGHOME="$HOME/releaser-gpg" - export GNUPGHOME - mkdir -p "$GNUPGHOME" - chmod 0700 "$GNUPGHOME" - - echo "$GPG_KEY" \ - | base64 --decode --ignore-garbage \ - | gpg --batch --allow-secret-key-import --import - - gpg --keyid-format LONG --list-secret-keys - - trap 'rm -rf -- "$GNUPGHOME"' EXIT -else - echo "==> WARNING: Missing GPG_KEY env var, skipping GPG signing of the release" - GORELEASER_ARGS+=("--skip-sign") -fi - -apt-get -qy update -apt-get -qy install rpm - -curl -sL https://git.io/goreleaser | bash -s -- "${GORELEASER_ARGS[@]}" diff --git a/scripts/sign-and-promote-release.sh b/scripts/sign-and-promote-release.sh deleted file mode 100755 index d64eb39..0000000 --- a/scripts/sign-and-promote-release.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/bash -# inputs: -# - $TAG, eg: v0.1.1 -# -# outcome: -# - download all existing artifacts from the release -# - codesign the macos binary -# - create a shasum file of all assets -# - sign the shasum file with GPG (created a detached sig file) -# - re-upload the codesign'd macos binary -# - upload the shasum file -# - upload the shasum signature file -# - promote release from draft to published -# -# requires: -# - github-release: https://github.com/aktau/github-release -# - jq -# - gpg - -set -eou pipefail -shopt -s nullglob - -TAG="${TAG:-}" -ORG="joemiller" -REPO="vault-token-helper" -BINARY="vault-token-helper" -CODESIGN_CERT="Developer ID Application: JOSEPH MILLER (P3MF48HUD7)" -GPG_KEY="6720A9FD78AC13F5" - -if [[ -z "$TAG" ]]; then - echo "Missing env var 'TAG'" - exit 1 -fi - -release_info_json='' -assets=() -modified_assets=() -checksum_file='' -sig_file='' -description='' -tempdir="$(mktemp -d)" - -echo "==> Created tempdir: $tempdir" -trap 'echo "Cleaning up."; rm -rf -- "$tempdir"' EXIT - -echo -echo "==> Fetching existing release info for $TAG" -release_info_json=$(github-release info -t "$TAG" -u "$ORG" -r "$REPO" -j) - -echo -echo "==> Generating a list of assets" -for i in $(jq -r '.Releases[0].assets[] | .name' <<<"$release_info_json"); do - assets+=("$i") - echo "$i" -done -echo "==> Found: ${#assets[@]} assets" - -echo -echo "==> Downloading assets to: $tempdir" -pushd "$tempdir" >/dev/null -for i in "${assets[@]}"; do - echo "==> Downloading: $i" - github-release download -t "$TAG" -u "$ORG" -r "$REPO" -n "$i" -done -ls -l "$tempdir" - -echo -echo "==> Apple codesigning the macOS binaries" -for i in ./*_darwin_amd64*; do - modified_assets+=("$i") - - if [[ "$i" =~ (.tar|.zip) ]]; then - echo "==> untarring and codesigning archived macOS binary: $i" - tartmp="./tar-tmp" - mkdir "$tartmp" - tar -xzf "$i" -C "$tartmp" - codesign -s "$CODESIGN_CERT" -i "$BINARY" "$tartmp/$BINARY" - tar -czf "$i" -C "$tartmp" $(ls "$tartmp") - rm -rf -- "$tartmp" - else - echo "==> codesigning binary: $i" - codesign -s "$CODESIGN_CERT" -i "$BINARY" "$i" - fi -done - -echo -echo "==> Generating new checksum file" -# delete existing checksum file before gathering new checksums -checksum_file="${BINARY}_$(sed -e 's/^v//' <<<"$TAG")_checksums.txt" -rm -f -- "$checksum_file" -shasum -a 256 -- * >"$checksum_file" -cat "$checksum_file" -modified_assets+=("$checksum_file") - -echo -echo "==> GPG-singing checksum file" -sig_file="${checksum_file}.sig" -rm -f -- "$sig_file" -gpg --batch -u "$GPG_KEY" --output "$sig_file" --detach-sign "$checksum_file" -modified_assets+=("$sig_file") - -echo -echo "==> Re-uploading modified assets" -#for i in ./*; do -for i in "${modified_assets[@]}"; do - echo "==> Uploading: $i" - github-release upload -t "$TAG" -u "$ORG" -r "$REPO" -n "$(basename "$i")" -f "$i" --replace -done - -echo -echo "==> Promoting release from draft to published" -# in order to preserve the current description we must provide it to the edit command: -description="$(jq -r '.Releases[0].body' <<<"$release_info_json")" -github-release edit -t "$TAG" -u "$ORG" -r "$REPO" -d "$description" - -echo -echo "DONE!" -echo "Next steps:" -echo "- Download the macos tarball from: https://github.com/joemiller/vault-token-helper/releases/latest" -echo "- update sha256 sum in the homebrew formula: https://github.com/joemiller/homebrew-taps/blob/master/Formula/vault-token-helper.rb" diff --git a/vagrant/README.md b/vagrant/README.md index dfd8cfb..8ab4415 100644 --- a/vagrant/README.md +++ b/vagrant/README.md @@ -14,14 +14,14 @@ Using 1. Install vagrant 2. Install vagrant plugins: -```sh +``` vagrant plugin install vagrant-vbguest vagrant plugin install vagrant-reload ``` **Launch**: -```sh +``` cd vagrant/fedora vagrant up ``` @@ -32,12 +32,14 @@ to install all the packages and reboot at least once. You may want to use `vagrant halt` instead of `destroy` to suspend the VM until you're done with dev/test. -The root of the project will be mounted as a host folder to `/src`. +The root of the project will be mounted as a host folder to `/vault-token-helper`. Run tests from an SSH or GUI Terminal session in the fedora VM: -```sh -cd /src +``` +cd /vault-token-helper +make test +# or: go test -v ./... ``` @@ -49,7 +51,7 @@ go test -v ./... **Launch**: -```sh +``` cd vagrant/windows vagrant up ``` diff --git a/vagrant/fedora/Vagrantfile b/vagrant/fedora/Vagrantfile index a6b1663..f421374 100644 --- a/vagrant/fedora/Vagrantfile +++ b/vagrant/fedora/Vagrantfile @@ -5,13 +5,13 @@ # Vagrant.configure("2") do |config| - # https://app.vagrantup.com/generic/boxes/fedora29 - config.vm.box = "generic/fedora29" - config.vm.box_version = "1.9.14" + # https://app.vagrantup.com/generic/boxes/fedora32 + config.vm.box = "generic/fedora32" + config.vm.box_version = '3.0.2' config.vm.provider "virtualbox" do |vb| vb.gui = true - vb.memory = 1024 + vb.memory = 2048 vb.cpus = 2 vb.customize ["modifyvm", :id, "--vram", "128"] vb.customize ["modifyvm", :id, "--accelerate3d", "off"] @@ -44,17 +44,14 @@ SHELL # pass config.vm.provision "shell", inline: "sudo dnf install -y pass" - config.vm.provision "shell", inline: <<-SHELL - sudo rpm --import https://mirror.go-repo.io/fedora/RPM-GPG-KEY-GO-REPO - curl -s https://mirror.go-repo.io/fedora/go-repo.repo | sudo tee /etc/yum.repos.d/go-repo.repo - sudo dnf install -y golang -SHELL + # install go + config.vm.provision "shell", inline: "sudo dnf install -y golang" # vagrant plugin install vagrant-reload config.vm.provision :reload - # mount the project into /src - config.vm.synced_folder "../..", "/src" + # mount the project into /vault-token-helper + config.vm.synced_folder "../..", "/vault-token-helper" # TODO: remove below when done using local fork - config.vm.synced_folder "../../../keyring", "/keyring" + # config.vm.synced_folder "../../../keyring", "/keyring" end \ No newline at end of file