From 74f8a07166aea937a6511cdd74771f320754e981 Mon Sep 17 00:00:00 2001 From: Josh Rabinowitz Date: Sat, 1 Dec 2018 08:48:09 -0500 Subject: [PATCH] improve testing regarding expired keys and keys with only email addresses (#262) * test that hiding secret with expired key fails * add test of user key without username. * revert to performing most tests with 'user1'. * move user4 private/public key fixtures * factor code fetching emails from keyrings, add comments. * use factored _warn_or_abort() * add to, clean up, and clarify comments. --- CHANGELOG.md | 4 ++ src/_utils/_git_secret_tools.sh | 24 ++++--- tests/_test_base.bash | 11 +++- tests/fixtures/gpg/README.md | 17 ++++- .../gpg/user4@gitsecret.io/private.key | 59 +++++++++++++++++ .../gpg/user4@gitsecret.io/public.key | 30 +++++++++ tests/test_expiration.bats | 33 ++++++++++ tests/test_hide.bats | 8 +-- tests/test_noname.bats | 65 +++++++++++++++++++ 9 files changed, 230 insertions(+), 21 deletions(-) create mode 100644 tests/fixtures/gpg/user4@gitsecret.io/private.key create mode 100644 tests/fixtures/gpg/user4@gitsecret.io/public.key create mode 100644 tests/test_expiration.bats create mode 100644 tests/test_noname.bats diff --git a/CHANGELOG.md b/CHANGELOG.md index b8a9ac5e..7feb0489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## {{Next Version}} + +- Add tests for expired gpg keys, and gpg keys with only emails. + ## Version 0.2.4 - Added `git secret cat` feature (#141) diff --git a/src/_utils/_git_secret_tools.sh b/src/_utils/_git_secret_tools.sh index 4e086c4a..80167c42 100644 --- a/src/_utils/_git_secret_tools.sh +++ b/src/_utils/_git_secret_tools.sh @@ -620,30 +620,32 @@ function _get_encrypted_filename { function _get_users_in_gpg_keyring { + # show the users in the gpg keyring. + # `whoknows` command uses it internally. + # parses the `gpg` public keys local homedir=$1 local result local args=() if [[ -n "$homedir" ]]; then args+=( "--homedir" "$homedir" ) fi - result=$($SECRETS_GPG_COMMAND "${args[@]}" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode | grep ^uid: | gawk -F':' '{print $10;}' | sed 's/.*<\(.*\)>.*/\1/') + + # pluck out 'uid' lines, fetch 10th field, extract part in <> if it exists (else leave alone). + # we use --fixed-list-mode so older versions of gpg emit 'uid:' lines. + # sed at the end is to extract email from <>. (If there's no <>, then the line is just an email address anyway.) + result=$($SECRETS_GPG_COMMAND "${args[@]}" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode | grep ^uid: | cut -d: -f10 | sed 's/.*<\(.*\)>.*/\1/') echo "$result" } function _get_users_in_gitsecret_keyring { - # This function is required to show the users in the keyring. - # `whoknows` command uses it internally. - # It basically just parses the `gpg` public keys - + # show the users in the gitsecret keyring. local secrets_dir_keys secrets_dir_keys=$(_get_secrets_dir_keys) - # pluck out 'uid' lines, fetch 10th field, extract part in <> if it exists (else leave alone) - # we use --fixed-list-mode so older versions of gpg emit 'uid:' lines local result - result=$($SECRETS_GPG_COMMAND --homedir "$secrets_dir_keys" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode | grep ^uid: | gawk -F':' '{print $10;}' | sed 's/.*<\(.*\)>.*/\1/') + result=$(_get_users_in_gpg_keyring "$secrets_dir_keys") echo "$result" } @@ -707,11 +709,7 @@ function _decrypt { #echo "# gpg exit code: $exit_code, error_ok: $error_ok" >&3 if [[ "$exit_code" -ne "0" ]]; then local msg="problem decrypting file with gpg: exit code $exit_code: $filename" - if [[ "$error_ok" -eq "0" ]]; then - _abort "$msg" "$exit_code" - else - _warn "$msg" - fi + _warn_or_abort "$msg" "$exit_code" "$error_ok" fi } diff --git a/tests/_test_base.bash b/tests/_test_base.bash index 80d80a5f..2fe94d6e 100644 --- a/tests/_test_base.bash +++ b/tests/_test_base.bash @@ -33,9 +33,16 @@ GPGTEST="$SECRETS_GPG_COMMAND --homedir=$TEST_GPG_HOMEDIR --no-permission-warnin # Personal data: -# user3 created with '--quick-key-generate' and has only an email, no username. -TEST_DEFAULT_USER="user3@gitsecret.io" +# these two are 'normal' keys +TEST_DEFAULT_USER="user1@gitsecret.io" TEST_SECOND_USER="user2@gitsecret.io" + +# TEST_NONAME_USER (user3) created with '--quick-key-generate' and has only an email, no username. +TEST_NONAME_USER="user3@gitsecret.io" + +# TEST_EXPIRED_USER (user4) has expired +TEST_EXPIRED_USER="user4@gitsecret.io" # this key expires 2018-09-24 + TEST_ATTACKER_USER="attacker1@gitsecret.io" #TEST_DEFAULT_FILENAME="file_one" # no spaces diff --git a/tests/fixtures/gpg/README.md b/tests/fixtures/gpg/README.md index 22b313d0..c4dd8ad2 100644 --- a/tests/fixtures/gpg/README.md +++ b/tests/fixtures/gpg/README.md @@ -1,11 +1,24 @@ == public/private key pairs for test keys * user1 and user2 are normal gpg key sets for user1@gitsecret.io and - user2@gitsecret.io. They have the passwords 'user1pass' and 'user2pass', + user2@gitsecret.io. They have the passphrases 'user1pass' and 'user2pass', respectively. + user1 is not currently used. * user3 was created by `gpg --quick-generate user3@gitsecret.io` and therefore has only an email associated with it (no username). - It has the password 'user3pass' as the tests expect. + It has the passphrase 'user3pass' as the tests expect. This user was created to fix https://github.com/sobolevn/git-secret/issues/227 , "keys with no info but the email address not recognized by whoknows" + +* user4 was created with `gpg --gen-key`, using the name 'user4' + and the email address user4@gitsecret.io. As the tests expect, + it has the passphrase 'user4pass'. + + It is also set to expire on 2018-09-23. To make keys expire, I used the + `gpg --edit-key user@email` command's `expiry` function. + + The public and private key for user4 were exported with + `gpg --export --armor user4 > tests/fixtures/gpg/user4/public.key` + and + `gpg --export-secret-keys --armor user4 > tests/fixtures/gpg/user4/private.key` diff --git a/tests/fixtures/gpg/user4@gitsecret.io/private.key b/tests/fixtures/gpg/user4@gitsecret.io/private.key new file mode 100644 index 00000000..134c57c4 --- /dev/null +++ b/tests/fixtures/gpg/user4@gitsecret.io/private.key @@ -0,0 +1,59 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) + +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 +VJ97gZKyfwWA4E3gTZGuYr3s +=1Mtg +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/fixtures/gpg/user4@gitsecret.io/public.key b/tests/fixtures/gpg/user4@gitsecret.io/public.key new file mode 100644 index 00000000..48b5a489 --- /dev/null +++ b/tests/fixtures/gpg/user4@gitsecret.io/public.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) + +mQENBFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcAYGizfXh3rLm3QjBumR +EHET67sfOJUIbqGbhfw+/PbpxKG1um3BcV85gXWcqW77ch/YupyJH0NNP3sBZ76W +JqJXASGKR2JkBM5KSgNkS13LdMXTaXM9zwZuCOU1T4geapV/Zj4W614qzO8mRlOt +gIl8/moxP0IwZneJvBhYLCCQg8i+zedIUvF5eneW9kwEtS84/PLXQ/HfbEuDaq0O +dHmkXBNwp41PsnriMc78lahEXU9Xh9VUPwBYGs/kyXhhLEdhSBq/5zKdDldg2lc8 +yKqZyenvoS5iKzJJU9QDjHP6gsYlhJ3c5WM5ABEBAAG0GnVzZXI0IDx1c2VyNEBn +aXRzZWNyZXQuaW8+iQE/BBMBAgApAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC +F4AFAlumzxUFCQABUvEACgkQ5tTITN+BxCVXdwgAgLHoBd1Kgx9y7rqTmoHmQypZ +sUb/VUs3u0wtad9NHrpb4uDLBPy5WKDxnEtwWMYe31tAAzqy0ANpsS93DLiwdi+4 +DAcre/8I5jJnNLk1tYgl0MTHEW59vKaQRhJuIEbz9p+6yNHLv8TSnP8xSD2TnWsp +H/sn1mWWdtqlr2ypVouTA0GWB/QrBr7OgyqE1yjMb3yQssGSHyD0z30CxwSn1wpc +glLY/BaRUxhps7YXAHPeTIVwEqlsgKpVR4V3E4jrNY23nTUAxvaINKj5MCS7usjD +ymRhKYNKk7UwmZYs25UvL7zx1mIbf3v1ujF9LH2ZjpMHqLnVaM3AabYjKubyh7kB +DQRbps2kAQgAtKsvtB7W2ukWyycpiOvZCDeo0IVFA5kT8I/vO0IpVEzVGBWpcjzE ++nt6Imaa/6NWu+aHmZv/GLPPp6YqVK7eFwcnzuM0PnxfFOvtmKgjZ8mCJxRAgyPQ +rKLZY9x11C29NgOnUSgvYb7xh6CKC9gdLCGVGq12kurIVFCasR9WfOiOVf/3DFWJ +3ar701pHNyNRyE+ERyVBmyxzOXj52zYrDA8ZwgG/knafeTOy35WbR9Bqju0USrwl +4te5Qt+dlPDHSHfzrTeGrruyIQ1tnjgVDuPOnHqwy2GFZaoVwvaObSX8T8LQ0IiE +AsNT5q7T5zLS4V0UYOh/93lWPbWf1uAvTwARAQABiQEfBBgBAgAJBQJbps2kAhsM +AAoJEObUyEzfgcQl1pQH/1Ef1cQ79/ae2aZgQnWxiF5R4rDRm87FozPamhasQkAF +jgL+yU2lAvmtJ5nmNB/gal78hRZh39DbhvhwO9i+eAZD5zrcOUzalW1xUqTK9bIt +iaKavhZosvKTUliCqta4t9fCx3bHs7jYKbix6989BLWF+BpYh+D0ZvUJW2VsmGru +I7kEFjnE8BcbvQySxKpf887VqHf9kFa7N3rqdcEL+hfS1OPlbSEG5es6SMeFeHja +/boFfXGseCraK+6KrD88McYUngrnHcDo/PxS4A6URIlE96Y5P76lXUu8WWQZIZPG +s4hL/C89PeyQ15ezIM1Un3uBkrJ/BYDgTeBNka5ivew= +=L85k +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/test_expiration.bats b/tests/test_expiration.bats new file mode 100644 index 00000000..a6a9b190 --- /dev/null +++ b/tests/test_expiration.bats @@ -0,0 +1,33 @@ +#!/usr/bin/env bats + +load _test_base + +function setup { + install_fixture_key "$TEST_EXPIRED_USER" + + set_state_initial + set_state_git + set_state_secret_init + set_state_secret_tell "$TEST_EXPIRED_USER" +} + +function teardown { + uninstall_fixture_key "$TEST_EXPIRED_USER" + unset_current_state +} + +@test "test 'hide' using expired key" { + FILE_TO_HIDE="$TEST_DEFAULT_FILENAME" + FILE_CONTENTS="hidden content юникод" + set_state_secret_add "$FILE_TO_HIDE" "$FILE_CONTENTS" + + run git secret hide + + #echo "# output of hide: $output" >&3 + # output should look like 'abort: problem encrypting file with gpg: exit code 2: space file' + #echo "# status of hide: $status" >&3 + + [ $status -ne 0 ] # we expect failure here. Actual code is 2 +} + + diff --git a/tests/test_hide.bats b/tests/test_hide.bats index 77ba34d2..721284d1 100644 --- a/tests/test_hide.bats +++ b/tests/test_hide.bats @@ -28,7 +28,7 @@ function teardown { @test "run 'hide' normally" { run git secret hide - echo "# run hide normally: output: $output" >&3 + #echo "# run hide normally: output: $output" >&3 # Command must execute normally: [ "$status" -eq 0 ] @@ -46,7 +46,7 @@ function teardown { run git secret hide -P - echo "# run hide with -P: output: $output" >&3 + #echo "# run hide with -P: output: $output" >&3 # Command must execute normally: [ "$status" -eq 0 ] @@ -115,7 +115,7 @@ function teardown { # Now it should hide 2 files: run git secret hide - echo "# run hide with multiple files: output: $output" >&3 + #echo "# run hide with multiple files: output: $output" >&3 [ "$status" -eq 0 ] [ "$output" = "done. 2 of 2 files are hidden." ] @@ -145,7 +145,7 @@ function teardown { path_mappings=$(_get_secrets_dir_paths_mapping) run git secret hide -m - echo "# run hide with -m twice: output: $output" >&3 + #echo "# run hide with -m twice: output: $output" >&3 # Command must execute normally: [ "$status" -eq 0 ] diff --git a/tests/test_noname.bats b/tests/test_noname.bats new file mode 100644 index 00000000..60327dac --- /dev/null +++ b/tests/test_noname.bats @@ -0,0 +1,65 @@ +#!/usr/bin/env bats + +## this tests using TEST_NONAME_USER, which has a email but no username. +# This test is copied from the start of test_remove.bats, and exercises an add and a remove. + +load _test_base + +FIRST_FILE="$TEST_DEFAULT_FILENAME" +SECOND_FILE="$TEST_SECOND_FILENAME" + +function setup { + install_fixture_key "$TEST_NONAME_USER" + + set_state_initial + set_state_git + set_state_secret_init + set_state_secret_tell "$TEST_NONAME_USER" + set_state_secret_add "$FIRST_FILE" "somecontent" + set_state_secret_add "$SECOND_FILE" "somecontent2" + set_state_secret_hide +} + + +function teardown { + rm "$FIRST_FILE" "$SECOND_FILE" + + uninstall_fixture_key "$TEST_NONAME_USER" + unset_current_state +} + + +function _has_line { + local line="$1" + + local path_mappings + path_mappings=$(_get_secrets_dir_paths_mapping) + + local result=$(grep -q "$line" "$path_mappings"; echo $?) + echo "$result" +} + + +@test "run 'remove' for nameless user normally" { + run git secret remove "$SECOND_FILE" + [ "$status" -eq 0 ] + + # Test output: + [[ "$output" == *"removed from index."* ]] + [[ "$output" == *"ensure that files: [$SECOND_FILE] are now not ignored."* ]] + + # Mapping should not contain the second file: + local mapping_contains=$(_has_line "$SECOND_FILE") + [ "$mapping_contains" -eq 1 ] + + # But the first file must not change: + local other_files=$(_has_line "$FIRST_FILE") + [ "$other_files" -eq 0 ] + + # Both files should be present: + local first_encrypted_file=$(_get_encrypted_filename "$FIRST_FILE") + local second_encrypted_file=$(_get_encrypted_filename "$SECOND_FILE") + + [ -f "$first_encrypted_file" ] + [ -f "$second_encrypted_file" ] +}