Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code signing for binaries #32

Merged
merged 1 commit into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 96 additions & 2 deletions ci.gocd.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@

---
format_version: 3
environments:
internal:
pipelines:
- gocd-cli
pipelines:
gocd-cli:
group: go-cd-contrib
materials:
github:
git: https://git.gocd.io/git/gocd-contrib/gocd-cli

git: https://github.com/gocd-contrib/gocd-cli
destination: cli
codesigning:
git: https://github.com/gocd/codesigning
destination: codesigning
signing-keys:
svn: https://github.com/gocd-private/signing-keys/trunk
username: gocd-ci-user
encrypted_password: "AES:taOvOCaXsoVwzIi+xIGLdA==:GSfhZ6KKt6MXKp/wdYYoyBQKKzbTiyDa+35kDgkEIOF75s9lzerGInbqbUM7nUKc"
destination: signing-keys
stages:
- build:
elastic_profile_id: ecs-golang-build
artifacts:
- build:
source: dist/**/*
destination: dist/
tasks:
- exec:
command: /bin/bash
Expand All @@ -21,3 +35,83 @@ pipelines:
- --verbose
- --prod
- --release=Edge
working_directory: cli
- exec:
command: mv
arguments:
- dist
- ..
working_directory: cli
- code-signing:
clean_workspace: yes
secure_variables:
GOCD_GPG_PASSPHRASE: "AES:7lAutKoRKMuSnh3Sbg9DeQ==:8fhND9w/8AWw6dJhmWpTcCdKSsEcOzriQNiKFZD6XtN+sJvZ65NH/QFXRNiy192+SSTKsbhOrFmw+kAKt5+MH1Erd6H54zJjpSgvJUmsJaQ="
jobs:
osx:
artifacts:
- build:
source: osx-cli.zip
resources:
- mac
- signer
tasks:
- fetch:
stage: build
job: build
source: dist/
- exec:
command: /bin/bash
arguments:
- cli/codesigning-helpers/osx-codesign.sh
- dist/darwin/amd64/gocd
win:
elastic_profile_id: window-dev-build
artifacts:
- build:
source: win-cli.zip
tasks:
- fetch:
stage: build
job: build
source: dist/
- exec:
command: call
arguments:
- cli\codesigning-helpers\win-codesign.bat
- bundle:
elastic_profile_id: ecs-golang-build
artifacts:
- build:
source: clis.zip
tasks:
- fetch:
stage: build
job: build
source: dist/
- fetch:
stage: code-signing
job: osx
source: osx-cli.zip
is_file: yes
- fetch:
stage: code-signing
job: win
source: win-cli.zip
is_file: yes
- exec:
command: /bin/bash
arguments:
- -c
- |
echo "Collating codesigned binaries..."
(cd dist/windows/amd64 && unzip -o ../../../win-cli.zip)
(cd dist/darwin/amd64 && unzip -o ../../../osx-cli.zip)
sha256sum dist/darwin/amd64/gocd
sha256sum dist/linux/amd64/gocd
sha256sum dist/windows/amd64/gocd.exe
- exec:
command: zip
arguments:
- -r
- clis.zip
- dist
115 changes: 115 additions & 0 deletions codesigning-helpers/osx-codesign.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/bin/bash

set -e

function main {
local progname=$(basename "$0")

if [ $# -eq 0 ]; then
die "${progname} requires at least 1 argument"
fi

check_for_files signing-keys/codesign.keychain.password.gpg
check_deps codesign security gpg

local binary="$1"

if [ ! -s "$binary" ]; then
die "Executable [${binary}] could not be found or is empty"
fi

decrypt_keychain_passwd codesign.keychain.password

unlock_codesign_keychain codesign.keychain.password

codesign_binary "$binary"

lock_codesign_keychain

package_binary
}

function package_binary {
(cd dist/darwin/amd64 && \
zip -r ../../../osx-cli.zip gocd)
}

function codesign_binary {
local binary="$1"
chmod a+rx "$binary"

echo "SHA-256 before codesign: $(shasum -a 256 -b "$binary")"
codesign --force --verify --verbose --sign "Developer ID Application: ThoughtWorks (LL62P32G5C)" "$binary"
echo "SHA-256 after codesign: $(shasum -a 256 -b "$binary")"
}

function unlock_codesign_keychain {
local passwd_file="$1"

security unlock-keychain -p "$(cat "$passwd_file")" "$(keychain_path)"
}

function lock_codesign_keychain {
security lock-keychain "$(keychain_path)"
}

function decrypt_keychain_passwd {
local outfile="$1"

if ! gpg --batch --yes --passphrase-file "$(gpg_passwd)" --output "$outfile" signing-keys/codesign.keychain.password.gpg; then
die "Failed to decrypt codesigning keychain password"
fi
}

function keychain_path {
if [ -r "${HOME}/Library/Keychains/codesign.keychain" ]; then
echo "${HOME}/Library/Keychains/codesign.keychain"
elif [ -r "${HOME}/Library/Keychains/codesign.keychain-db" ]; then
echo "${HOME}/Library/Keychains/codesign.keychain-db"
else
die "You don't appear to have the codesigning keychain"
fi
}

function gpg_passwd {
if [ -n "$GOCD_GPG_PASSPHRASE" ]; then
echo "$GOCD_GPG_PASSPHRASE" > gpg-passphrase
fi

if [ ! -s "gpg-passphrase" ]; then
die "Cannot codesign without the GPG passphrase! Please set the GOCD_GPG_PASSPHRASE env variable"
else
echo "gpg-passphrase"
fi
}

function check_for_files {
if [ $# -eq 0 ]; then
die "check_for_files() requires at least 1 argument"
fi

for f in $@; do
if [ ! -r "$f" ]; then
die "This script requires the file ${f} to exist and be readable"
fi
done
}

function check_deps {
if [ $# -eq 0 ]; then
die "check_deps() requires at least 1 argument"
fi

for dep in $@; do
if ! which "$dep" &> /dev/null; then
die "This script requires ${dep} to be in the PATH"
fi
done
}

function die {
>&2 echo $@
exit 1
}

main $@
10 changes: 10 additions & 0 deletions codesigning-helpers/win-codesign.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
:: setup
cd %~dp0..\..\codesigning
md src\win
move %~dp0..\..\dist\windows\amd64\gocd.exe src\win
call gem install bundler
call bundle install
call bundle exec rake --trace win:sign
:: package
cd out\win
call jar -cMf ..\..\..\win-cli.zip gocd.exe