aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2021-10-01 22:05:29 +0200
committerWojtek Kosior <koszko@koszko.org>2021-10-01 22:05:29 +0200
commitd7e48c5855156b65335b228bb5de81fc500d8ace (patch)
tree85ca96f9a08c982523e340574b988563d6a48f3a
parentea30326e242a73d3cb06589fb97cf81b674ae2e3 (diff)
downloadbrowser-extension-d7e48c5855156b65335b228bb5de81fc500d8ace.tar.gz
browser-extension-d7e48c5855156b65335b228bb5de81fc500d8ace.zip
Add complete firefox extension upload and download functionality
-rw-r--r--shell_utils.sh6
-rwxr-xr-xupload_amo.sh112
2 files changed, 96 insertions, 22 deletions
diff --git a/shell_utils.sh b/shell_utils.sh
index 95e0d4e..30dfead 100644
--- a/shell_utils.sh
+++ b/shell_utils.sh
@@ -6,6 +6,12 @@
ENDL="
"
+# A "raw" echo, interprets neither backclash escapes nor command-line options.
+# Does not emit trailing newline.
+ech() {
+ printf %s "$*"
+}
+
errcho() {
echo "$@" >&2
}
diff --git a/upload_amo.sh b/upload_amo.sh
index 3ac7028..2d16c63 100755
--- a/upload_amo.sh
+++ b/upload_amo.sh
@@ -24,27 +24,45 @@
set -e
+. ./shell_utils.sh
+
+_PROG_NAME="$0"
+OPERATION="$1"
+API_KEY="$2"
+SECRET="$3"
+XPI_PATH="$4"
+
base64url() {
- echo -n "$1" | base64 -w 0 | tr '/+' '_-' | tr -d '='
+ ech "$1" | base64 -w 0 | tr '/+' '_-' | tr -d '='
}
sha256hmac() {
- base64url "$(echo -n "$2" | openssl dgst -sha256 -hmac "$1" -binary -)"
+ base64url "$(ech "$2" | openssl dgst -sha256 -hmac "$1" -binary -)"
}
-if [ $# != 3 ]; then
- echo "Usage: $0 API_KEY SECRET XPI_PATH" 1>&2
- exit 1
-fi
+escape_regex_special() {
+ ech "$1" | sed 's/\([]\.*?{},()[-]\)/\\\1/g'
+}
+
+# Note: We don't actually parse JSON. We extract needed keys with sed regexes
+# which does not work in the general case but is sufficient for now.
+get_json_key() {
+ local KEY_REG="$(escape_regex_special "$1")"
+ ech "$2" |
+ sed 's/\(.*"'"$KEY_REG"'"[[:space:]]*:[[:space:]]*"\([^"]*\)"\)\?.*/\2/' |
+ grep . | head -1
+}
+
+get_manifest_key() {
+ get_json_key "$1" "$(unzip -p "$2" manifest.json)"
+}
-API_KEY="$1"
-SECRET="$2"
-XPI_PATH="$3"
-JWT_HEAD='{"alg":"HS256", "typ":"JWT"}'
-JWT_ID=$(dd if=/dev/random bs=21 count=1 2>/dev/null | base64)
-ISSUED_AT_TIME=$(date -u +%s)
-EXPIRATION_TIME=$((ISSUED_AT_TIME + 300))
-JWT_PAYLOAD=$(cat <<EOF
+generate_jwt() {
+ local JWT_HEAD='{"alg":"HS256", "typ":"JWT"}'
+ local JWT_ID=$(dd if=/dev/random bs=21 count=1 2>/dev/null | base64)
+ local ISSUED_AT_TIME=$(date -u +%s)
+ local EXPIRATION_TIME=$((ISSUED_AT_TIME + 300))
+ local JWT_PAYLOAD="$(cat <<EOF
{
"iss": "$API_KEY",
"jti": "$JWT_ID",
@@ -52,13 +70,63 @@ JWT_PAYLOAD=$(cat <<EOF
"exp": $EXPIRATION_TIME
}
EOF
- )
-JWT_MESSAGE=$(base64url "$JWT_HEAD").$(base64url "$JWT_PAYLOAD")
-JWT_SIGNATURE=$(sha256hmac "$SECRET" "$JWT_MESSAGE")
-JWT=$JWT_MESSAGE.$JWT_SIGNATURE
+ )"
+ local JWT_MESSAGE=$(base64url "$JWT_HEAD").$(base64url "$JWT_PAYLOAD")
+ local JWT_SIGNATURE=$(sha256hmac "$SECRET" "$JWT_MESSAGE")
+ local JWT=$JWT_MESSAGE.$JWT_SIGNATURE
+ errcho "Using JWT: $JWT"
+ ech $JWT
+}
+
+get_extension_url() {
+ EXTENSION_ID="$(get_manifest_key id "$XPI_PATH")"
+ EXTENSION_VER="$(get_manifest_key version "$XPI_PATH")"
-# Query one of Mozilla endpoints to verify that JWT authentication works.
-curl "https://addons.mozilla.org/api/v5/accounts/profile/" \
- -H "Authorization: JWT $JWT"
+ if [ -z "$EXTENSION_ID" -o -z "$EXTENSION_VER" ]; then
+ errcho "Couldn't extract extension id and version. Please check if $XPI_PATH contains proper manifest.json file."
+ exit 1
+ fi
-# TODO: Do the actual upload.
+ ech "https://addons.mozilla.org/api/v4/addons/$EXTENSION_ID/versions/$EXTENSION_VER/"
+}
+
+usage() {
+ errcho "Usage: $_PROG_NAME upload|check|test API_KEY SECRET XPI_PATH"
+}
+
+if [ $# != 4 ]; then
+ usage
+ exit 1
+fi
+
+unset RETURNED_DATA
+
+case "$OPERATION" in
+ test)
+ curl "https://addons.mozilla.org/api/v4/accounts/profile/" \
+ -g -H "Authorization: JWT $(generate_jwt)"
+ echo
+ ;;
+ check)
+ RETURNED_DATA="$(curl $(get_extension_url) \
+ -g -H "Authorization: JWT $(generate_jwt)")"
+ ;;
+ upload)
+ RETURNED_DATA="$(curl $(get_extension_url) \
+ -g -XPUT --form "upload=@$XPI_PATH" \
+ -H "Authorization: JWT $(generate_jwt)")"
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+esac
+
+if [ -n "$RETURNED_DATA" ]; then
+ printf "addons.mozilla.org says:\n%s\n" "$RETURNED_DATA"
+ DOWNLOAD_URL="$(get_json_key download_url "$RETURNED_DATA")"
+ if [ -n "$DOWNLOAD_URL" ]; then
+ printf "Downloading extension file from %s\n" "$DOWNLOAD_URL"
+ curl "$DOWNLOAD_URL" -g -H "Authorization: JWT $(generate_jwt)" -O
+ fi
+fi