'How to create a GitHub repository secret /encrypt it using bash on Ubuntu?

I'm trying to create/update a GitHub secret using bash on Ubuntu.

Their api docs say that I should

  1. get the public key from the repo
  2. encrypt the secret with it
  3. create/update the GitHub secret

but examples are only in NodeJS & Python & I'm not sure how to use the libsodium which is mentioned in bash on Ubuntu to achieve what I need.

https://docs.github.com/en/rest/reference/actions#create-or-update-a-repository-secret

I was able to get the public key & key_id using

$ curl -s \
-H "authorization: Bearer $MY_ACCESS_TOKEN" \
https://api.github.com/repos/MYORG/MYREPO/actions/secrets/public-key
{
  "key_id": "123456789012345678",
  "key": "abcdHXZ2BrPAFPrZHy1AAct3B12k7BPgxXgdtxcABCo="
}

I was able to generate what seems to be a valid encrypted value of my secret using Python 3 example:

#!/usr/bin/python3

from base64 import b64encode
from nacl import encoding, public

def encrypt(public_key: str, secret_value: str) -> str:
  public_key = public.PublicKey(public_key.encode("utf-8"), encoding.Base64Encoder())
  sealed_box = public.SealedBox(public_key)

  encrypted = sealed_box.encrypt(secret_value.encode("utf-8"))
  return b64encode(encrypted).decode("utf-8")

print(encrypt("abcdHXZ2BrPAFPrZHy1AAct3B12k7BPgxXgdtxcABCo=", "ABCDEF1234"))
$ ./encrypt-secret.py 
ST5Blke5GXO2FyMLUbYAhkmzLKJ3cljd1lI97q028gcrq3XC9aTqPlNzbMQAI5iHoj/70ao0/GOrhg==

But I'm looking for a bash implementation.



Solution 1:[1]

Looks like it's possible to use github cli utility (gh) to create secrets without the need to run python/nodejs code which looks like a solution I've been looking for. Here is how you do it:

export DEBIAN_FRONTEND=noninteractive
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
sudo apt update && \
sudo apt-get install -y gh
export GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" && \
export SECRET_VALUE_FILE_PATH="your_file_with_secret_value" && \
gh secret set KUBECONFIG < "$SECRET_VALUE_FILE_PATH"

https://cli.github.com/manual/gh_secret_set

Solution 2:[2]

My own project https://github.com/J-Siu/mygit have that implemented.

Following is the implementation(Ln:544 in script):

# get repo key
_API=${_URI}/repos/${_USR}/${REPO}/actions/secrets/public-key
_result=$(API_CURL "${_API}" "${_TOK}" "${_X}" "${_D}" "${_JQ}")
_kid=$(echo ${_result} | jq -r .key_id)
_key=$(echo ${_result} | jq -r .key)
# set DOCKER_HUB_USERNAME
_val=$(go-crypto box sealanonymous -k ${_key} -m ${DOCKER_HUB_USERNAME})
_API=${_URI}/repos/${_USR}/${REPO}/actions/secrets/DOCKER_HUB_USERNAME
_X="PUT"
_D="{\"encrypted_value\":\"${_val}\",\"key_id\":\"${_kid}\"}"
API_CURL "${_API}" "${_TOK}" "${_X}" "${_D}" "${_JQ}"
# set DOCKER_HUB_ACCESS_TOKEN
_val=$(go-crypto box sealanonymous -k ${_key} -m ${DOCKER_HUB_ACCESS_TOKEN})
_API=${_URI}/repos/${_USR}/${REPO}/actions/secrets/DOCKER_HUB_ACCESS_TOKEN
_X="PUT"
_D="{\"encrypted_value\":\"${_val}\",\"key_id\":\"${_kid}\"}"
API_CURL "${_API}" "${_TOK}" "${_X}" "${_D}" "${_JQ}"
  1. Use jq to extract public key and its id.
  2. Use command line tool go-crypto(see PS1) to do the box encryption.
  3. Use ${_USR}(github username), ${REPO}(repository name) and name of secret(DOCKER_HUB_ACCESS_TOKEN and DOCKER_HUB_USERNAME) to generate the api url
  4. Put encrypted value and key id into _D
  5. Run API_CURL(see below)

PS1: go-crypto https://github.com/J-Siu/go-crypto is another tool I wrote. I created it because I cannot find any command line tool to do the NACL box encryption.

PS2: API_CURL:

# ${1} _API
# ${2} _TOK
# ${3} _X
# ${4} _D
# ${5} _JQ
API_CURL() {
    local _me="API_CURL"

    local _API=${1}
    local _TOK=${2}
    local _X=${3}
    local _D=${4}
    local _JQ=${5}

    local _d=''
    [[ ! ${_D} = ' ' ]] && _d="-d"

    local _x=''
    [[ ! ${_X} = ' ' ]] && _x="-X"

    if [[ ${_DEBUG} ]]; then
        LOG "${_me}:_API:${_API}"
        LOG "${_me}:_D:${_D}"
        LOG "${_me}:_JQ:${_JQ}"
        LOG "${_me}:_TOK:${_TOK}"
        LOG "${_me}:_X:${_X}"
        LOG "${_me}:_d:${_d}"
        LOG "${_me}:_x:${_x}"
    fi

    curl -s \
        ${_x} ${_X} \
        -H "Accept: application/vnd.github.mercy-preview+json" \
        -H "Accept: application/vnd.github.v3+json" \
        -H "Content-Type: application/json" \
        -H "Authorization: token ${_TOK}" \
        ${_d} "${_D}" \
        ${_API} | jq ${_JQ}
}

If you are looking for github command line tools, you can also check out my other project: https://github.com/J-Siu/go-mygit

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 GTXBxaKgCANmT9D9
Solution 2