Skip to content

Commit

Permalink
[bitwarden] ability to fetch all fields from an item
Browse files Browse the repository at this point in the history
Sometimes a projects has a lot of secrets (more than 10). And its
cumbersome to write $(kama secrets fetch ...) with a lot of field
names.

I want to be able to just fetch all the fields from a given item
 and then just use these with $(kamal extract NAME)
  • Loading branch information
honzasterba committed Oct 5, 2024
1 parent 4b2c9cd commit e87349a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
22 changes: 14 additions & 8 deletions lib/kamal/secrets/adapters/bitwarden.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,31 @@ def fetch_secrets(secrets, account:, session:)
{}.tap do |results|
items_fields(secrets).each do |item, fields|
item_json = run_command("get item #{item.shellescape}", session: session, raw: true)
raise RuntimeError, "Could not read #{secret} from Bitwarden" unless $?.success?
raise RuntimeError, "Could not read #{item} from Bitwarden" unless $?.success?
item_json = JSON.parse(item_json)

if fields.any?
fields.each do |field|
item_field = item_json["fields"].find { |f| f["name"] == field }
raise RuntimeError, "Could not find field #{field} in item #{item} in Bitwarden" unless item_field
value = item_field["value"]
results["#{item}/#{field}"] = value
end
fetch_secrets_from_fields fields, item, item_json, results
elsif item_json.dig("login", "password")
results[item] = item_json.dig("login", "password")
elsif item_json["fields"]&.any?
fields = item_json["fields"].pluck("name")
fetch_secrets_from_fields fields, item, item_json, results
else
raise RuntimeError, "Item #{item} is not a login type item and no fields were specified"
end
end
end
end

def fetch_secrets_from_fields(fields, item, item_json, results)
fields.each do |field|
item_field = item_json["fields"].find { |f| f["name"] == field }
raise RuntimeError, "Could not find field #{field} in item #{item} in Bitwarden" unless item_field
value = item_field["value"]
results["#{item}/#{field}"] = value
end
end

def items_fields(secrets)
{}.tap do |items|
secrets.each do |secret|
Expand Down
50 changes: 48 additions & 2 deletions test/secrets/bitwarden_adapter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ class BitwardenAdapterTest < SecretAdapterTestCase
assert_equal expected_json, json
end

test "fetch all with from" do
stub_unlocked
stub_ticks.with("bw sync").returns("")
stub_noteitem_with_fields

json = JSON.parse(shellunescape(run_command("fetch", "mynotefields")))

expected_json = {
"mynotefields/field1"=>"secret1", "mynotefields/field2"=>"blam", "mynotefields/field3"=>"fewgrwjgk",
"mynotefields/field4"=>"auto"
}

assert_equal expected_json, json
end

test "fetch with multiple items" do
stub_unlocked

Expand Down Expand Up @@ -214,7 +229,37 @@ def stub_noteitem(session: nil)
"collectionIds":[]
}
JSON
end
end

def stub_noteitem_with_fields(session: nil)
stub_ticks
.with("#{"BW_SESSION=#{session} " if session}bw get item mynotefields")
.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,
"fields":[
{"name":"field1","value":"secret1","type":1,"linkedId":null},
{"name":"field2","value":"blam","type":1,"linkedId":null},
{"name":"field3","value":"fewgrwjgk","type":1,"linkedId":null},
{"name":"field4","value":"auto","type":1,"linkedId":null}
],
"secureNote":{"type":0},
"collectionIds":[]
}
JSON
end

def stub_myitem
stub_ticks
Expand All @@ -237,7 +282,8 @@ def stub_myitem
"fields":[
{"name":"field1","value":"secret1","type":1,"linkedId":null},
{"name":"field2","value":"blam","type":1,"linkedId":null},
{"name":"field3","value":"fewgrwjgk","type":1,"linkedId":null}
{"name":"field3","value":"fewgrwjgk","type":1,"linkedId":null},
{"name":"field4","value":"auto","type":1,"linkedId":null}
],
"login":{"fido2Credentials":[],"uris":[],"username":null,"password":null,"totp":null,"passwordRevisionDate":null},"collectionIds":[]
}
Expand Down

0 comments on commit e87349a

Please sign in to comment.