#!/usr/bin/env bash

set -euo pipefail

# Apple certificate used to validate developer certificates https://www.apple.com/certificateauthority/
readonly APPLE_ROOT_CERTIFICATE="http://certs.apple.com/devidg2.der"

function print_usage {
	echo
	echo "Usage: $0 [OPTIONS] <Path to files used to sign...>"
	echo
	printf '  MACOS_CERTIFICATE\t\tMac developer certificate in P12 format, encoded in base64.\n'
	printf '  MACOS_CERTIFICATE_PASSWORD\tMac certificate password\n'
	echo
	echo "Optional Arguments:"
	printf '  --macos-skip-root-certificate\t\tSkip importing Apple Root certificate. Useful when running in already configured environment.\n'
	printf '  --help\t\t\t\tShow this help text and exit.\n'
	echo
	echo "Examples:"
	echo "  $0 sign.hcl"

	return 0
}

function main {
	local mac_skip_root_certificate=""
	local assets=()

	while [[ $# -gt 0 ]]; do
		local key="$1"
		case "$key" in
		--macos-skip-root-certificate)
			mac_skip_root_certificate=true
			shift
			;;
		--help)
			print_usage
			exit
			;;
		-*)
			echo "ERROR: Unrecognized argument: $key" >&2
			print_usage
			exit 1
			;;
		*)
			assets=("$@")
			break
			;;
		esac
	done
	ensure_macos
	import_certificate_mac "${mac_skip_root_certificate}"
	sign_mac "${assets[@]}"

	return 0
}

function ensure_macos {
	if [[ $OSTYPE != 'darwin'* ]]; then
		echo "Signing of Mac binaries is supported only on MacOS" >&2
		exit 1
	fi

	return 0
}

function sign_mac {
	local -r assets=("$@")
	local gon_cmd="gon"
	for filepath in "${assets[@]}"; do
		echo "Signing ${filepath}"
		"${gon_cmd}" -log-level=info "${filepath}"
	done

	return 0
}

function import_certificate_mac {
	local -r mac_skip_root_certificate="$1"
	assert_env_var_not_empty "MACOS_CERTIFICATE"
	assert_env_var_not_empty "MACOS_CERTIFICATE_PASSWORD"

	trap "rm -rf /tmp/*-keychain" EXIT

	local mac_certificate_pwd="${MACOS_CERTIFICATE_PASSWORD}"
	local keystore_pw="${RANDOM}"

	# create separated keychain file to store certificate and do quick cleanup of sensitive data
	local db_file
	db_file=$(mktemp "/tmp/XXXXXX-keychain")
	rm -rf "${db_file}"
	echo "Creating separated keychain for certificate"
	security create-keychain -p "${keystore_pw}" "${db_file}"
	security default-keychain -s "${db_file}"
	security unlock-keychain -p "${keystore_pw}" "${db_file}"
	echo "${MACOS_CERTIFICATE}" | base64 -d | security import /dev/stdin -f pkcs12 -k "${db_file}" -P "${mac_certificate_pwd}" -T /usr/bin/codesign
	if [[ "${mac_skip_root_certificate}" == "" ]]; then
		# download apple root certificate used as root for developer certificate
		curl -v "${APPLE_ROOT_CERTIFICATE}" --output certificate.der
		sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain certificate.der
	fi
	security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${keystore_pw}" "${db_file}"

	return 0
}

function assert_env_var_not_empty {
	local -r var_name="$1"
	local -r var_value="${!var_name}"

	if [[ -z "$var_value" ]]; then
		echo "ERROR: Required environment $var_name not set." >&2
		exit 1
	fi

	return 0
}

main "$@"
