summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith84@gmail.com>2020-02-12 16:34:07 -0800
committerTim Smith <tsmith84@gmail.com>2020-02-12 19:27:40 -0800
commit6495ac43693f202f93618cc7db3b4bea517810db (patch)
treee4f3cfe421f761d851b3d5a38f0d1411e70781cb
parent7ed90d771a40eefcc1c399e889871556d8e3dc8b (diff)
downloadchef-6495ac43693f202f93618cc7db3b4bea517810db.tar.gz
Add chef_vault_secret resource from chef-vault cookbook
Move this common resource into Chef itself to avoid the need to include this cookbook. Signed-off-by: Tim Smith <tsmith@chef.io>
-rw-r--r--lib/chef/resource/chef_vault_secret.rb134
-rw-r--r--lib/chef/resources.rb1
-rw-r--r--spec/unit/resource/chef_vault_secret_spec.rb40
3 files changed, 175 insertions, 0 deletions
diff --git a/lib/chef/resource/chef_vault_secret.rb b/lib/chef/resource/chef_vault_secret.rb
new file mode 100644
index 0000000000..a2292439e6
--- /dev/null
+++ b/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
+ 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
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 70b7c88fa8..3681d9bd54 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -29,6 +29,7 @@ require_relative "resource/cookbook_file"
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"
diff --git a/spec/unit/resource/chef_vault_secret_spec.rb b/spec/unit/resource/chef_vault_secret_spec.rb
new file mode 100644
index 0000000000..5190785de7
--- /dev/null
+++ b/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