Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

コマンドの引数が間違えていた場合のメッセージ改善 #33

Closed
KEINOS opened this issue Jun 2, 2021 · 2 comments
Closed
Assignees
Labels
enhancement New feature or request

Comments

@KEINOS
Copy link
Member

KEINOS commented Jun 2, 2021

下記は引数の順番を間違えているのに、公開鍵のアクセス権に問題があるように見えます。

$ verify ~/.ssh/github hello.txt emadurandal

/home/emadurandal/.ssh/github を電子署名 emadurandal で検証します

- hello.txt の GitHub 上の公開鍵を取得中 ... OK
- RSA 形式の公開鍵を PKCS8 形式に変換中 ... @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0664 for '/tmp/verify-/hello.txt.pub' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/tmp/verify-/hello.txt.pub": bad permissions
NG:RSA -> PKCS8 変換中にエラーが発生しました。

(Issue #31 より)

引数の順番の検知、もしくはエラー内容に引数の順番に間違いがないかなど、もう少しユーザに優しくてもいいと思います。

@KEINOS KEINOS added the enhancement New feature or request label Jun 2, 2021
@yoshi389111
Copy link
Collaborator

全体的に入力チェックを厳しくするという話なのかもしれませんが、とりあえず curl のエラーが取得できていないのも1つの原因だと思うので、それについて調査しました。

調査

現在の curl で公開鍵を取得する処理は以下のような感じになっています。

if ! curl -s "https://github.com/${USERNAME}.keys" | head -n 1 >"$PATHPUBKEY"; then
    echo "NG:公開鍵を取得・保存できませんでした。"
    exit 1
fi

上記処理の curl で 404 not found が起きても、どうやら続行してしまうようです(Ubuntu で確認)。
問題は2つありそう。

1つ目は、curl404 not found の場合にエラーメッセージを標準出力に出力して、正常終了をしていることです。
(以下の例では、エラーメッセージとして "Not Found" (改行無し)を出力している)

$ curl -s https://github.com/hello.txt.keys
Not Found$ echo $?
0

対策としては curl--fail を指定して、エラーメッセージを出力せず、終了コードを 0 以外にすることだと思います。

$ curl --fail -s https://github.com/hello.txt.keys
$ echo $?
22

2つ目は、curl の終了コードが、パイプのため握りつぶされていることです。

$ exit 1 | exit 0
$ echo $?
0

対策はパイプをやめてファイル経由で処理するか、出力した公開キーが空でないことをチェックするかでしょうか。
(以下は、公開キーが空の場合にエラーとしている例)

curl --fail -s "https://github.com/${USERNAME}.keys" | head -n 1 >"$PATHPUBKEY"
if [ ! -s "$PATHPUBKEY" ]; then
    echo "NG:公開鍵を取得・保存できませんでした。"
    exit 1
fi

影響範囲

curl で公開鍵を取得しているのは以下の4本
(今回の物も含めて、同様の処理をしているコマンド)

  • checkkeylength
  • enc
  • sign
  • verify

また、パイプでつないで終了コードを判定しているものは上記以外では、以下があります。

  • archive
if ! (tar cz "$INPUTFILE" | openssl enc -e -aes-256-cbc -salt -k "$PASSWORD" -out "${TEMPDIR}${OUTPUTFILE}"); then
    echo "NG:ファイルを圧縮・暗号化できませんでした。"
    exit 1
fi

@KEINOS
Copy link
Member Author

KEINOS commented Jun 4, 2021

確かに POSIX 対応を考えた場合 -o pipefail も使えないので、パイプ渡しのネストは気をつけないといけないですね。

以下のように愚直に 1 ステップずつ確認していった方がいいかもしれませんね。(テストも作りやすくなるし)

list_keys="$(curl --fail -s "https://github.com/${USERNAME}.keys")" || {
    echo "NG:公開鍵を取得できませんでした。"
    exit 1
}

# 公開鍵の保存
echo "$list_keys" | head -n 1 >"$PATHPUBKEY" || {
    echo "NG:公開鍵を保存できませんでした。"
    exit 1
}
テストの例
#shellcheck shell=sh

getContents()  {
    url_target="${1:?'URL missing'}"

    list_keys="$(curl --fail -s "$url_target" 2>&1)" || {
        echo >&2 "NG: ファイルの取得に失敗しました。(URL: ${url_target})"
        echo >&2 "$list_keys"

        return 1
    }

    echo "$list_keys"
}

getKeyPublic() {
    name_user="${1:?'GitHub user name missing'}"
    url_github_pubkey="https://github.com/${name_user}.keys"

    key_user="$(getContents "$url_github_pubkey") 2>&1" || {
        echo >&2 "NG: 公開鍵の取得に失敗しました。(URL: ${url_github_pubkey})"
        echo >&2 "$list_keys"

        return 1
    }

    echo "$key_user"
}

Describe "getKeyPublic"
    It 'should print the list of pub keys in GitHub'
        name_user='KEINOS'

        When call getKeyPublic "$name_user"

        The status should be success
        The stdout should include 'ssh-rsa'
        The stderr should be blank
    End

    It 'should print err with status 1 when GitHub user name is missing or empty'
        When run getKeyPublic "$UNKNOWN"

        The status should be failure # status is 1-255
        The stdout should be blank
        The stderr should include "GitHub user name missing"
    End
End

Describe 'getContents'
    It 'should print err with status 1 when URL is 404'
        url_ng='https://github.com/KEINOS/unknown_repo/'

        When call getContents "$url_ng"

        The status should be failure # status is 1-255
        The stdout should be blank
        The stderr should include "ファイルの取得に失敗しました"
    End

    It 'should print err with status 1 when URL is invalid'
        url_ng='https://gitogitohub.com/FOOBAR/unknown_repo/'

        When call getContents "$url_ng"

        The status should be failure # status is 1-255
        The stdout should be blank
        The stderr should include "ファイルの取得に失敗しました"
    End
End

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants