From 29b02f5c3028f087472386e3728afc0259ad04fe Mon Sep 17 00:00:00 2001 From: Jan Sterba Date: Sat, 28 Sep 2024 12:03:07 +0200 Subject: [PATCH] [bitwarden] default fetch raises NoMethodError When fetched item is not a login, Bitwarden adapter raises NoMethodError because the returned JSON does not have the login.password value. Add a nicer error message for that case. --- lib/kamal/secrets/adapters/bitwarden.rb | 4 ++- test/secrets/bitwarden_adapter_test.rb | 35 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/kamal/secrets/adapters/bitwarden.rb b/lib/kamal/secrets/adapters/bitwarden.rb index 95716997..e84a0d93 100644 --- a/lib/kamal/secrets/adapters/bitwarden.rb +++ b/lib/kamal/secrets/adapters/bitwarden.rb @@ -35,8 +35,10 @@ class Kamal::Secrets::Adapters::Bitwarden < Kamal::Secrets::Adapters::Base value = item_field["value"] results["#{item}/#{field}"] = value end + elsif item_json.dig("login", "password") + results[item] = item_json.dig("login", "password") else - results[item] = item_json["login"]["password"] + raise RuntimeError, "Item #{item} is not a login type item and no fields were specified" end end end diff --git a/test/secrets/bitwarden_adapter_test.rb b/test/secrets/bitwarden_adapter_test.rb index ff3f2a1c..e2a3ac37 100644 --- a/test/secrets/bitwarden_adapter_test.rb +++ b/test/secrets/bitwarden_adapter_test.rb @@ -13,6 +13,17 @@ class BitwardenAdapterTest < SecretAdapterTestCase assert_equal expected_json, json end + test "fetch with no login" do + stub_unlocked + stub_ticks.with("bw sync").returns("") + stub_noteitem + + error = assert_raises RuntimeError do + JSON.parse(shellunescape(run_command("fetch", "mynote"))) + end + assert_match(/not a login type item/, error.message) + end + test "fetch with from" do stub_unlocked stub_ticks.with("bw sync").returns("") @@ -181,6 +192,30 @@ class BitwardenAdapterTest < SecretAdapterTestCase JSON end + def stub_noteitem(session: nil) + stub_ticks + .with("#{"BW_SESSION=#{session} " if session}bw get item mynote") + .returns(<<~JSON) + { + "passwordHistory":null, + "revisionDate":"2024-09-28T09:07:27.461Z", + "creationDate":"2024-09-28T09:07:00.740Z", + "deletedDate":null, + "object":"item", + "id":"aaaaaaaa-cccc-eeee-0000-222222222222", + "organizationId":null, + "folderId":null, + "type":2, + "reprompt":0, + "name":"noteitem", + "notes":"NOTES", + "favorite":false, + "secureNote":{"type":0}, + "collectionIds":[] + } + JSON + end + def stub_myitem stub_ticks .with("bw get item myitem")