Is it possible to perform compound searches of encrypted data bags?

I support numerous applications and am wanting to store the credentials to those apps in data bags and then search for them within cookbooks using the application and environment so I can reuse the recipe. For example, for app1 in the production environment I’d have the following data bag item in the users data bag:

When it’s unencrypted:

knife data bag show users app1up --secret-file=secret.pem

app1: application
id: app1up
password: d093kekv;@x9
production: environment

Note the key/values for environment and app are swapped so they won’t be encrypted for searches:

knife data bag show users app1up

app1:
cipher: aes-256-cbc
encrypted_data: OhQVqYCC+4wFXXyy1HL7dHqJUtdQGpl3TLJWgC2FWCg=

iv: 3WZrbIjQNRkuW3wr7yjfuA==

version: 1
id: app1up
password:
cipher: aes-256-cbc
encrypted_data: 6OZzWcDCdVAUSGhcdZhM8Gzd/OuvoweiMzeeGyHEczI=

iv: pkX1LAVWNeukHbEmzzNTpw==

version: 1
production:
cipher: aes-256-cbc
encrypted_data: r2tqUuPP6wFtX44tOwkURhRHuKP5vggUvgPXJrO42uQ=

iv: FyA0plsx6+5EowuNdkiMZw==

version: 1

While I’m able to search for it without decrypting:

chef > app_creds = search(:users, “app1:* AND production:*”)
=> [data_bag_item[“users”, “app1up”, {“id”=>“app1up”, “app1”=>{“encrypted_data”=>“OhQVqYCC+4wFXXyy1HL7dHqJUtdQGpl3TLJWgC2FWCg=\n”, “iv”=>“3WZrbIjQNRkuW3wr7yjfuA==\n”, “version”=>1, “cipher”=>“aes-256-cbc”}, “production”=>{“encrypted_data”=>“r2tqUuPP6wFtX44tOwkURhRHuKP5vggUvgPXJrO42uQ=\n”, “iv”=>“FyA0plsx6+5EowuNdkiMZw==\n”, “version”=>1, “cipher”=>“aes-256-cbc”}, “password”=>{“encrypted_data”=>“6OZzWcDCdVAUSGhcdZhM8Gzd/OuvoweiMzeeGyHEczI=\n”, “iv”=>“pkX1LAVWNeukHbEmzzNTpw==\n”, “version”=>1, “cipher”=>“aes-256-cbc”}}]]

I’m unable to search and decrypt it:

chef > app_creds = Chef::EncryptedDataBagItem.load(:users, "app1:* AND production:")
URI::InvalidURIError: bad URI(is not URI?): https://chef-dev.spanning.co/data/users/app1:
AND production:*
from /opt/chef/embedded/lib/ruby/1.9.1/uri/common.rb:176:in split' from /opt/chef/embedded/lib/ruby/1.9.1/uri/common.rb:211:inparse’
from /opt/chef/embedded/lib/ruby/1.9.1/uri/common.rb:747:in parse' from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/rest.rb:143:increate_url’
from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/rest.rb:99:in get' from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/data_bag_item.rb:149:inload’
from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/encrypted_data_bag_item.rb:294:in load' from (irb):16 from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/shell.rb:73:inblock in start’
from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/shell.rb:72:in catch' from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/shell.rb:72:instart’
from /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/bin/chef-shell:34:in <top (required)>' from /usr/bin/chef-shell:23:inload’
from /usr/bin/chef-shell:23:in `’

On Friday, November 8, 2013 at 1:44 PM, Clif Smith wrote:

I support numerous applications and am wanting to store the credentials to those apps in data bags and then search for them within cookbooks using the application and environment so I can reuse the recipe. For example, for app1 in the production environment I’d have the following data bag item in the users data bag:

...

While I’m able to search for it without decrypting:

chef > app_creds = search(:users, "app1:* AND production:*")
=> [data_bag_item["users", "app1up", {"id"=>"app1up", "app1"=>{"encrypted_data"=>"OhQVqYCC+4wFXXyy1HL7dHqJUtdQGpl3TLJWgC2FWCg=\n", "iv"=>"3WZrbIjQNRkuW3wr7yjfuA==\n", "version"=>1, "cipher"=>"aes-256-cbc"}, "production"=>{"encrypted_data"=>"r2tqUuPP6wFtX44tOwkURhRHuKP5vggUvgPXJrO42uQ=\n", "iv"=>"FyA0plsx6+5EowuNdkiMZw==\n", "version"=>1, "cipher"=>"aes-256-cbc"}, "password"=>{"encrypted_data"=>"6OZzWcDCdVAUSGhcdZhM8Gzd/OuvoweiMzeeGyHEczI=\n", "iv"=>"pkX1LAVWNeukHbEmzzNTpw==\n", "version"=>1, "cipher"=>"aes-256-cbc"}}]]

I’m unable to search and decrypt it:

chef > app_creds = Chef::EncryptedDataBagItem.load(:users, "app1:* AND production:*")
You can’t just stick search syntax in there, as the arguments you pass in are used to construct a URL like https://yourchef.example.com/data/DATA_BAG/ITEM whereas search goes to /search.

You should be able to convert the data bag items with encrypted values to EncryptedDataBagItem objects doing something like:

secret = Chef::EncryptedDataBagItem.load_secret
enc_app_creds = search(:users, "app1:* AND production:*”)
app_creds = enc_app_creds.map { |enc_item| Chef::EncryptedDataBagItem.new(enc_item, secret) }

I haven’t tried this out so there could be some additional munging required, but it should get you started.

--
Daniel DeLeo