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

Add chef_vault_secret resource from chef-vault cookbook #9364

Merged
merged 3 commits into from Feb 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile.lock
Expand Up @@ -33,6 +33,7 @@ PATH
bundler (>= 1.10)
chef-config (= 16.0.63)
chef-utils (= 16.0.63)
chef-vault
chef-zero (>= 14.0.11)
diff-lcs (~> 1.2, >= 1.2.4)
ed25519 (~> 1.2)
Expand Down Expand Up @@ -65,6 +66,7 @@ PATH
bundler (>= 1.10)
chef-config (= 16.0.63)
chef-utils (= 16.0.63)
chef-vault
chef-zero (>= 14.0.11)
diff-lcs (~> 1.2, >= 1.2.4)
ed25519 (~> 1.2)
Expand Down
1 change: 1 addition & 0 deletions chef.gemspec
Expand Up @@ -41,6 +41,7 @@ Gem::Specification.new do |s|
s.add_dependency "diff-lcs", "~> 1.2", ">= 1.2.4"
s.add_dependency "ffi-libarchive"
s.add_dependency "chef-zero", ">= 14.0.11"
s.add_dependency "chef-vault"

s.add_dependency "plist", "~> 3.2"
s.add_dependency "iniparse", "~> 1.4"
Expand Down
32 changes: 32 additions & 0 deletions kitchen-tests/cookbooks/end_to_end/recipes/chef-vault.rb
@@ -0,0 +1,32 @@
#
# Cookbook:: end_to_end
# Recipe:: chef-vault
#
# Copyright:: 2020, Chef Software, Inc.
#

chef_data_bag 'creds'

openssl_rsa_private_key '/root/bob_bobberson.pem' do
key_length 2048
action :create
end

chef_client 'bob_bobberson' do
source_key_path '/root/bob_bobberson.pem'
end

chef_node 'bob_bobberson'

chef_vault_secret 'super_secret_1' do
data_bag 'creds'
raw_data('auth' => '1234')
admins 'bob_bobberson'
search '*:*'
end

chef_vault_secret 'super_secret_2' do
data_bag 'creds'
raw_data('auth' => '4321')
admins 'bob_bobberson'
end
6 changes: 4 additions & 2 deletions kitchen-tests/cookbooks/end_to_end/recipes/default.rb
Expand Up @@ -2,7 +2,7 @@
# Cookbook:: end_to_end
# Recipe:: default
#
# Copyright:: 2014-2019, Chef Software Inc.
# Copyright:: 2014-2020, Chef Software Inc.
#

hostname "chef-bk-ci.chef.io"
Expand Down Expand Up @@ -33,7 +33,7 @@
gpgkey "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node["platform_version"].to_i}"
gpgcheck true
mirrorlist "https://mirrors.fedoraproject.org/metalink?repo=epel-#{node["platform_version"].to_i}&arch=$basearch"
only_if { platform_family?("rhel") }
only_if { rhel? }
end

build_essential do
Expand Down Expand Up @@ -118,4 +118,6 @@
end
end

include_recipe "::chef-vault" unless includes_recipe?("end_to_end::chef-vault")

include_recipe "::tests"
134 changes: 134 additions & 0 deletions lib/chef/resource/chef_vault_secret.rb
@@ -0,0 +1,134 @@
#
# Author:: Joshua Timberman <joshua@chef.io>
# Copyright:: 2014-2020, Chef Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require_relative "../resource"
require "chef-vault"

class Chef
class Resource
class ChefVaultSecret < Chef::Resource
resource_name :chef_vault_secret
provides :chef_vault_secret

introduced "16.0"
description "Use the chef_vault_secret resource to store secrets in Chef Vault items. Where possible and relevant, this resource attempts to map behavior and functionality to the knife vault sub-commands."
examples <<~DOC
To create a 'foo' item in an existing 'bar' data bag:

```ruby
chef_vault_secret 'foo' do
data_bag 'bar'
raw_data({'auth' => 'baz'})
admins 'jtimberman'
search '*:*'
end
```

To allow multiple admins access to an item:

```ruby
chef_vault_secret 'root-password' do
admins 'jtimberman,paulmooring'
data_bag 'secrets'
raw_data({'auth' => 'DontUseThisPasswordForRoot'})
search '*:*'
end
```
DOC

property :id, String, name_property: true,
description: "The name of the data bag item if it differs from the name of the resource block"

property :data_bag, String, required: true, desired_state: false,
description: "The data bag that contains the item."

property :admins, [String, Array], required: true, desired_state: false,
description: "A list of admin users who should have access to the item. Corresponds to the 'admin' option when using the chef-vault knife plugin. Can be specified as a comma separated string or an array."

property :clients, [String, Array], desired_state: false,
description: "A search query for the nodes' API clients that should have access to the item."

property :search, String, default: "*:*", desired_state: false,
description: "Search query that would match the same used for the clients, gets stored as a field in the item."

property :raw_data, [Hash, Mash], default: {},
description: "The raw data, as a Ruby Hash, that will be stored in the item."

property :environment, [String, NilClass], desired_state: false,
description: "The Chef environment of the data if storing per environment values."

load_current_value do
begin
item = ChefVault::Item.load(data_bag, id)
raw_data item.raw_data
clients item.get_clients
admins item.get_admins
search item.search
rescue ChefVault::Exceptions::KeysNotFound
current_value_does_not_exist!
rescue Net::HTTPServerException => e
current_value_does_not_exist! if e.response_code == "404"
end
end

action :create do
description "Creates the item, or updates it if it already exists."

converge_if_changed do
item = ChefVault::Item.new(new_resource.data_bag, new_resource.id)

Chef::Log.debug("#{new_resource.id} environment: '#{new_resource.environment}'")
item.raw_data = if new_resource.environment.nil?
new_resource.raw_data.merge("id" => new_resource.id)
else
{ "id" => new_resource.id, new_resource.environment => new_resource.raw_data }
end

Chef::Log.debug("#{new_resource.id} search query: '#{new_resource.search}'")
item.search(new_resource.search)
Chef::Log.debug("#{new_resource.id} clients: '#{new_resource.clients}'")
item.clients([new_resource.clients].flatten.join(",")) unless new_resource.clients.nil?
Chef::Log.debug("#{new_resource.id} admins (users): '#{new_resource.admins}'")
item.admins([new_resource.admins].flatten.join(","))
item.save
end
end

action :create_if_missing do
description "Calls the create action unless it exists."

action_create if current_resource.nil?
end

action :delete do
description "Deletes the item and the item's keys ('id'_keys)."

converge_by("remove #{new_resource.id} and #{new_resource.id}_keys from #{new_resource.data_bag}") do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete doesn't look properly idempotent here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally isn't

chef_data_bag_item new_resource.id do
data_bag new_resource.data_bag
action :delete
end

chef_data_bag_item [new_resource.id, "keys"].join("_") do
data_bag new_resource.data_bag
action :delete
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/chef/resources.rb
Expand Up @@ -29,6 +29,7 @@
require_relative "resource/chef_gem"
require_relative "resource/chef_handler"
require_relative "resource/chef_sleep"
require_relative "resource/chef_vault_secret"
require_relative "resource/chocolatey_config"
require_relative "resource/chocolatey_feature"
require_relative "resource/chocolatey_package"
Expand Down
40 changes: 40 additions & 0 deletions spec/unit/resource/chef_vault_secret_spec.rb
@@ -0,0 +1,40 @@
#
# Copyright:: 2020, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require "spec_helper"

describe Chef::Resource::ChefVaultSecret do
let(:resource) { Chef::Resource::ChefVaultSecret.new("foo") }

it "has a resource name of :chef_vault_secret" do
expect(resource.resource_name).to eql(:chef_vault_secret)
end

it "sets the default action as :create" do
expect(resource.action).to eql([:create])
end

it "id is the name property" do
expect(resource.id).to eql("foo")
end

it "supports :create, :create_if_missing, and :delete actions" do
expect { resource.action :create }.not_to raise_error
expect { resource.action :create_if_missing }.not_to raise_error
expect { resource.action :delete }.not_to raise_error
end
end