Как создать утверждение RS256 JWT с помощью сценариев bash/shell?

Я пытаюсь настроить скрипт оболочки, чтобы получить файл из учетной записи Box. Для этого требуется авторизационный токен. Аутентификационный токен должен генерироваться автоматически с помощью скрипта, поэтому никаких ручных действий не требуется. Это можно сделать, составив и отправив претензию JWT.

В документации Box указано, что они принимают только "RS256", "RS384" и "RS512". Я смог настроить все, что мне нужно, кроме создания подтверждения с помощью документации Box и этого веб-сайта:

http://willhaley.com/blog/generate-jwt-with-bash/

Я провел часы, просматривая веб-сайты, чтобы узнать, смогу ли я найти какие-либо указания на то, как сгенерировать утверждение с помощью сценариев bash / shell, но безрезультатно. Веб-сайт, на который я ссылаюсь, является самым близким, что я нашел, но он использует HS256, который не поддерживается Box.

Мой сценарий в настоящее время практически идентичен первому сценарию на веб-сайте, на который я ссылался ранее (у меня есть отдельный сценарий, который я использовал для проверки фактического получения файла с помощью созданного вручную токена авторизации). Пожалуйста, помогите с командами, необходимыми для генерации утверждения.

1 ответ

Решение

Рассмотрим следующее, которое поддерживает как HS256, так и RS256:

#!/usr/bin/env bash

# Inspired by implementation by Will Haley at:
#   http://willhaley.com/blog/generate-jwt-with-bash/

set -o pipefail

# Shared content to use as template
header_template='{
    "typ": "JWT",
    "kid": "0001",
    "iss": "https://stackru.com/questions/46657001/how-do-you-create-an-rs256-jwt-assertion-with-bash-shell-scripting"
}'

build_header() {
        jq -c \
                --arg iat_str "$(date +%s)" \
                --arg alg "${1:-HS256}" \
        '
        ($iat_str | tonumber) as $iat
        | .alg = $alg
        | .iat = $iat
        | .exp = ($iat + 1)
        ' <<<"$header_template" | tr -d '\n'
}

b64enc() { openssl enc -base64 -A | tr '+/' '-_' | tr -d '='; }
json() { jq -c . | LC_CTYPE=C tr -d '\n'; }
hs_sign() { openssl dgst -binary -sha"${1}" -hmac "$2"; }
rs_sign() { openssl dgst -binary -sha"${1}" -sign <(printf '%s\n' "$2"); }

sign() {
        local algo payload header sig secret=$3
        algo=${1:-RS256}; algo=${algo^^}
        header=$(build_header "$algo") || return
        payload=${2:-$test_payload}
        signed_content="$(json <<<"$header" | b64enc).$(json <<<"$payload" | b64enc)"
        case $algo in
                HS*) sig=$(printf %s "$signed_content" | hs_sign "${algo#HS}" "$secret" | b64enc) ;;
                RS*) sig=$(printf %s "$signed_content" | rs_sign "${algo#RS}" "$secret" | b64enc) ;;
                *) echo "Unknown algorithm" >&2; return 1 ;;
        esac
        printf '%s.%s\n' "${signed_content}" "${sig}"
}

(( $# )) && sign "$@"

... использование как:

rsa_secret='
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtHEDjwkBpsjhit+wXZMMj2AaRHyWSKatjzLtVEGdyXrbQGgQ
PjbfqPtqKsBPjcifHh8VAgrEtETbLN8pbE/XLRaB9P76hib6DATBn2JC6XG/NkAu
0b2F8WB6ZuJh3fbubSOZaORRIyRvfidV5Wjb7NbEDhuSxFLaq0ad2+rQHyBgMfQS
43OqhEa463WQt5F9NuWRTqweh5UotT6Mg9YgkvmBdA4IbJMEDWGFNecUzAGuESYq
wzJaaQ4S58ce7HxFDywM0nFXlNx1pxZwZOZfG7bddUD8FuwbBMx5c3Z3U8LAA+J/
50A/kxuZoa6sRTb7gXfBxy2riechlOTL+5ut3wIDAQABAoIBAD8bm5wGEV7MuR1B
+MPxbx4iBW3YiRMlwGPp8tlaDZ5u6onPG4c21+iY7du/4NL8zLHTOxy4uW02+9To
w+sOzXoGejM+jk4nCaL0cueUjURqNO77aaSPfW4bSRP8ry/bci4Xmkr2N25sCtZ7
WW5fyzM9NdqdSCqDs9jdXM6ShHGt4aG1w4Q38pfl2O2KUqgGYA8j8S7oEpcuApIj
sNH8o2PIFaFuRoUBq6WxSZBY7YdvKM0xlE0NKiDMAUIeTIRqtm8GPo7ot8dV6VHU
EglN7gaEve75XW0DAkK2lDDpGPlVHJwLgKGiSuW0qMh6lY+dKjsZ8wyz85DqTnyo
+42ZI6kCgYEA36X4c4a/tlh0A6i+EaA1CqmN8jh3nNMYgZvovTnIezCvO+RuJJEG
KQQjr8/z+E8FYobImrrZsuSL+UFs1trl/nSndWh22B7fQQbJBdHwhv39YWReS0tW
7t3LJJG3oQnR/ChlqyTToHfS0WcdtYQ0cnFWSx73Hg/S+cu0vHtcUrUCgYEAzosH
dXq1VGRgf3TIoI9s4xJt/SnH+VHtP4dvLKzY7NN4K76DIYdQIn1xQ1Y3705v/XG+
xTNAaoOaH6hBnRxwxcv6GmCpICJ2C21puxA63RqCslab5fc23wvMv/wwoEWPtXhf
3OOKZxszLR1vFqZaYTWzVmTxg+r5b2aNBB0MtsMCgYBAv+6Ek/ihNE6yWIJe3AE/
SwOboxmOP9eSfq8NSdNvRxMUxffVgl9ENLyYRB6gP1CRy+/8TCiHEIAt8/Es60c3
OlLZPRtbSuTcELjWhIecraBUOBjMt809bt1HgyCk8RDoblGxEQJsLQTON4p0aQg+
Me4H5bkp7O7p/z4ea6C5GQKBgQCewy+QliocHKwwTMyK3rSMNvZky2DzvI3pb2l9
pb95C3Qr691QQHrQiCwv3m5QfLKI1o4VdzfkqBQokWUeJ2ZoJEqzS+m00ch7MDc9
m1Qj8OTVwM1FD6oV+TQBvxCBofa9PzIw0JbqenX0D9P8TRLb9jNMDXu4Mz5Y6zMq
HkpPkQKBgQCgrcW7U0Q+081N25VfghCPRd/o+dtqP3udXgj0nIX6y3qeCJiPeamZ
plMNqdZScaK37wMouAIPD0u5w1OCnlepuUxU3h5y55Lzx3PnDlU1H+yfBsTi1KL/
sDjgs31j//w80krxJNj5/i2AeYzATmybPwyM/c/PVBv/hecreUbTlQ==
-----END RSA PRIVATE KEY-----
'

test_payload='{
    "Id": 1,
    "Name": "Hello, world!"
}'
sign rs256 "$test_payload" "$rsa_secret"
Другие вопросы по тегам