aboutsummaryrefslogtreecommitdiff
path: root/upload_amo.sh
blob: 2d16c63a760f55f9dc59fd36ec0a69be0856bdd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/bin/sh

# This file is part of Haketilo
#
# Copyright (C) 2021, Wojtek Kosior
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
#
# I, Wojtek Kosior, thereby promise not to sue for violation of this file's
# license. Although I request that you do not make use this code in a
# proprietary program, I am not going to enforce this in court.

set -e

. ./shell_utils.sh

_PROG_NAME="$0"
OPERATION="$1"
API_KEY="$2"
SECRET="$3"
XPI_PATH="$4"

base64url() {
    ech "$1" | base64 -w 0 | tr '/+' '_-' | tr -d '='
}

sha256hmac() {
    base64url "$(ech "$2" | openssl dgst -sha256 -hmac "$1" -binary -)"
}

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)"
}

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",
    "iat": $ISSUED_AT_TIME,
    "exp": $EXPIRATION_TIME
}
EOF
	  )"
    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")"

    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

    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