summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2021-09-09 10:15:13 -0700
committerGitHub <noreply@github.com>2021-09-09 10:15:13 -0700
commit611a9eecf45c0876a7591ec101ba6792aaa47194 (patch)
treeb3169822a73b20748db7415ec30e98158c3f7559
parentc81c085f6f6d3fc058d71c8295d0b5620709198b (diff)
parentd29beb0a64b9d1f9986abf73267789a756658734 (diff)
downloadchef-611a9eecf45c0876a7591ec101ba6792aaa47194.tar.gz
Merge pull request #12012 from chef/mp/11825
Add AKeyless Vault support
-rw-r--r--lib/chef/secret_fetcher.rb7
-rw-r--r--lib/chef/secret_fetcher/akeyless_vault.rb57
-rw-r--r--lib/chef/secret_fetcher/hashi_vault.rb2
-rw-r--r--spec/unit/secret_fetcher/akeyless_vault_spec.rb37
4 files changed, 100 insertions, 3 deletions
diff --git a/lib/chef/secret_fetcher.rb b/lib/chef/secret_fetcher.rb
index e8e4602bb2..af3e1d5cbb 100644
--- a/lib/chef/secret_fetcher.rb
+++ b/lib/chef/secret_fetcher.rb
@@ -21,7 +21,7 @@ require_relative "exceptions"
class Chef
class SecretFetcher
- SECRET_FETCHERS = %i{example aws_secrets_manager azure_key_vault hashi_vault}.freeze
+ SECRET_FETCHERS = %i{example aws_secrets_manager azure_key_vault hashi_vault akeyless_vault}.freeze
# Returns a configured and validated instance
# of a [Chef::SecretFetcher::Base] for the given
@@ -45,10 +45,13 @@ class Chef
when :hashi_vault
require_relative "secret_fetcher/hashi_vault"
Chef::SecretFetcher::HashiVault.new(config, run_context)
+ when :akeyless_vault
+ require_relative "secret_fetcher/akeyless_vault"
+ Chef::SecretFetcher::AKeylessVault.new(config, run_context)
when nil, ""
raise Chef::Exceptions::Secret::MissingFetcher.new(SECRET_FETCHERS)
else
- raise Chef::Exceptions::Secret::InvalidFetcherService.new("Unsupported secret service: #{service}", SECRET_FETCHERS)
+ raise Chef::Exceptions::Secret::InvalidFetcherService.new("Unsupported secret service: '#{service}'", SECRET_FETCHERS)
end
fetcher.validate!
fetcher
diff --git a/lib/chef/secret_fetcher/akeyless_vault.rb b/lib/chef/secret_fetcher/akeyless_vault.rb
new file mode 100644
index 0000000000..f80eeba7bc
--- /dev/null
+++ b/lib/chef/secret_fetcher/akeyless_vault.rb
@@ -0,0 +1,57 @@
+#
+# Author:: Marc Paradise (<marc@chef.io>)
+# Copyright:: Copyright (c) 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_relative "base"
+require_relative "hashi_vault"
+
+class Chef
+ class SecretFetcher
+ # == Chef::SecretFetcher::AKeylessVault
+ # A fetcher that fetches a secret from AKeyless Vault. Initial implementation is
+ # based on HashiVault , because AKeyless provides a compatibility layer that makes this possible.
+ # Future revisions will use native akeyless authentication.
+ #
+ # Required config:
+ # :access_id - the access id of the API key
+ # :access_key - the access key of the API key
+ #
+ #
+ # @example
+ #
+ # fetcher = SecretFetcher.for_service(:akeyless_vault, { access_id: "my-access-id", access_key: "my-access-key" }, run_context )
+ # fetcher.fetch("/secret/data/secretkey1")
+ #
+ AKEYLESS_VAULT_PROXY_ADDR = "https://hvp.akeyless.io".freeze
+ class AKeylessVault < HashiVault
+ def validate!
+ if config[:access_key].nil?
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the secret access key in the configuration as :secret_access_key")
+ end
+ if config[:access_id].nil?
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the access key id in the configuration as :access_key_id")
+ end
+
+ config[:vault_addr] ||= AKEYLESS_VAULT_PROXY_ADDR
+ config[:auth_method] = :token
+ config[:token] = "#{config[:access_id]}..#{config[:access_key]}"
+ super
+ end
+ end
+ end
+end
+
diff --git a/lib/chef/secret_fetcher/hashi_vault.rb b/lib/chef/secret_fetcher/hashi_vault.rb
index 7cca57542f..47bf78f5c1 100644
--- a/lib/chef/secret_fetcher/hashi_vault.rb
+++ b/lib/chef/secret_fetcher/hashi_vault.rb
@@ -57,7 +57,7 @@ class Chef
SUPPORTED_AUTH_TYPES = %i{iam_role token}.freeze
class HashiVault < Base
- # Validate and authenticate the current session using the configurated auth strategy and parameters
+ # Validate and authenticate the current session using the configured auth strategy and parameters
def validate!
if config[:vault_addr].nil?
raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the Vault address in the configuration as :vault_addr")
diff --git a/spec/unit/secret_fetcher/akeyless_vault_spec.rb b/spec/unit/secret_fetcher/akeyless_vault_spec.rb
new file mode 100644
index 0000000000..f827e99399
--- /dev/null
+++ b/spec/unit/secret_fetcher/akeyless_vault_spec.rb
@@ -0,0 +1,37 @@
+#
+# Author:: Marc Paradise <marc@chef.io>
+# Copyright:: Copyright (c) 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_relative "../../spec_helper"
+require "chef/secret_fetcher/akeyless_vault"
+
+describe Chef::SecretFetcher::AKeylessVault do
+ let(:node) { {} }
+ let(:run_context) { double("run_context", node: node) }
+
+ context "when validating provided AKeyless Vault configuration" do
+ it "raises ConfigurationInvalid when :secret_access_key is not provided" do
+ fetcher = Chef::SecretFetcher::AKeylessVault.new( { access_id: "provided" }, run_context)
+ expect { fetcher.validate! }.to raise_error(Chef::Exceptions::Secret::ConfigurationInvalid, /:secret_access_key/)
+ end
+
+ it "raises ConfigurationInvalid when :access_key_id is not provided" do
+ fetcher = Chef::SecretFetcher::AKeylessVault.new( { access_key: "provided" }, run_context)
+ expect { fetcher.validate! }.to raise_error(Chef::Exceptions::Secret::ConfigurationInvalid, /:access_key_id/)
+ end
+ end
+end