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

Can't stub encrypted data bag items #249

Closed
sommestad opened this issue Oct 30, 2013 · 6 comments
Closed

Can't stub encrypted data bag items #249

sommestad opened this issue Oct 30, 2013 · 6 comments

Comments

@sommestad
Copy link

I can't figure out how to stub encrypted data bag items. I've tried a number of various approaches, without success.

I'm getting different errors with different approaches:

Failure/Error: chef_run.converge(described_recipe)
...
Failure/Error: <something-about-key-probably-not-being-valid>

Isn't there support for this yet? Or am I just not understanding how to use it?

Thanks.

– – –

This is what my actual impl looks like in mycookbook (which obviously has another name in real life):

recipes/default.rb:

aws_secret = node['mycookbook']['key'];
aws_credentials = Chef::EncryptedDataBagItem.load("credentials", "aws", aws_secret)

spec/default_spec.rb:

chef_run.node.set['s3cmd']['key'] = "mysecret"
chef_run.converge(described_recipe)

# Failed attempt 1
Chef::EncryptedDataBagItem.any_instance.stub(:load).and_return(Hash.new)
Chef::EncryptedDataBagItem.any_instance.stub(:load).with("credentials", "aws").and_return({"access_key_id" => "abc123", "secrect_access_key" => "secret", "gpg_passphrase" => "pass"})

# Failed attempt 2
Chef::Recipe.any_instance
            .stub(:data_bag_item)
            .and_return(Hash.new)

Chef::Recipe.any_instance
            .stub(:data_bag_item)
            .with("credentials", "aws")
            .and_return({"access_key_id" => "abc123", "secrect_access_key" => "secret", "gpg_passphrase" => "pass"})

# Failed attempt 3
before do
  cookbook_root = File.expand_path('../../../../',  __FILE__)
  Chef::Config[:data_bag_path] = File.join(cookbook_root, 'data_bags')
  Chef::Config[:encrypted_data_bag_secret] = "mysecret"
end
@sethvargo
Copy link
Contributor

The load method is a class method of Chef::EncryptedDataBag, so your attempt 1 failed because you were stubbing the instance method load instead of the class method:

Chef::EncryptedDataBagItem.any_instance.stub(:load) # bad
Chef::EncryptedDataBagItem.stub(:load) # good

Attempt 2 failed because 1. that's the old syntax for stubbing a data_bag_item and 2. the data_bag_item method isn't being used in your recipe. You are calling the Chef::EncryptedDataBagItem directly, so you're stubbing the wrong thing. For learning purposes though, you can now do this in ChefSpec 3:

stub_data_bag('users').and_return(['bill'])
stub_data_bag_item('users', 'bill').and_return({ ... })

@sommestad
Copy link
Author

Thanks for the quick response!
Yeah, it ended up as a shotgun-attempt to make it work... Still not getting it to work, though, so I'm probably missing something else obvious. I'm now using:

# Set node attributes and converge
chef_run.node.set['s3cmd']['key'] = "<the-actual-secret-key>"
chef_run.converge(described_recipe)

stub_data_bag('credentials').and_return({id: 'aws'})
stub_data_bag_item('credentials', 'aws').and_return({"access_key_id" => "abc123", "secrect_access_key" => "secret", "gpg_passphrase" => "pass"})

This renders the following error:

Failure/Error: chef_run.converge(described_recipe)
Chef::EncryptedDataBagItem::DecryptionFailure:
Error decrypting data bag value: 'wrong final block length'. Most likely the provided key is incorrect

Any clues?

@sethvargo
Copy link
Contributor

@esset09 you're using an EncryptedDataBagItem.load, not data_bag_item, so you can't use those stub methods (they only work with regular data bags). You need to do this:

describe 'mycookbook::default' do
  let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }

  before do
    Chef::EncryptedDataBagItem.stub(:load).with('credentials', 'aws').and_return({
      'access_key_id' => 'abc123',
      'secrect_access_key' => 'secret',
      'gpg_passphrase' => 'pass'
    })
  end

  it 'does whatever' do
    expect(chef_run).to do_something('thing')
  end
end

@sommestad
Copy link
Author

Ah, yes, that's it. Actually, I had to do:

Chef::EncryptedDataBagItem.stub(:load).with('credentials', 'aws', 'secret').and_return({...})
...
chef_run.node.set['s3cmd']['key'] = "secret"

Great success! Thanks a lot!

@jeffbyrnes
Copy link

@sethvargo this was vastly helpful in my stubbing out an encrypted data bag, any chance this could end up in the README?

@sethvargo
Copy link
Contributor

@jeffbyrnes cd51d6a

@lock lock bot locked as resolved and limited conversation to collaborators Aug 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants