From 419cd789b6d0908bbcfae40f47e32cb1ded5dd85 Mon Sep 17 00:00:00 2001 From: Bert DEFERME Date: Thu, 5 Feb 2026 15:18:54 +0100 Subject: [PATCH] Remove comma separated path support This feature does not make sense. A node should only have one role anyway. Also, the feature breaks using '/' as a path. --- README.md | 29 ------- lib/puppet/functions/hiera_vault.rb | 29 +------ .../hiera_vault_path_interpolation_spec.rb | 87 ------------------- 3 files changed, 1 insertion(+), 144 deletions(-) delete mode 100644 spec/functions/hiera_vault_path_interpolation_spec.rb diff --git a/README.md b/README.md index c9a6639..7c49625 100644 --- a/README.md +++ b/README.md @@ -243,39 +243,10 @@ would result in following lookups: - http://vault.foobar.com:8200/some_secret/data/foo.example.com/cool_key (for v2) - http://vault.foobar.com:8200/some_secret/data/common/cool_key (for v2) -#### Multiple keys in trusted certname - -Often you want to whitelist multiple paths for each host (e.g. due to host having multiple roles). In this case simply add keys delimited with comma to trusted field. For example: - -```yaml -mounts: - secret: - - "%{trusted.extensions.pp_role}" -``` - -and host configured with - -```yaml ---- -extension_requests: - pp_role: api,ssl -``` - -would result in lookups in: - -- http://vault.foobar.com:8200/secret/api/cool_key (for v1) -- http://vault.foobar.com:8200/secret/api/data/cool_key (for v2) -- http://vault.foobar.com:8200/secret/data/api/cool_key (for v2) -- http://vault.foobar.com:8200/secret/ssl/cool_key (for v1) -- http://vault.foobar.com:8200/secret/ssl/data/cool_key (for v2) -- http://vault.foobar.com:8200/secret/data/ssl/cool_key (for v2) - #### More verbose paths in Hiera Often implicit path extension makes it hard to understand which exact paths are used for given host - as you need to inspect both Hiera and trusted field for each host. -With above configuration and lookup `$cool_key = lookup({"name" => "cool_key"})` you cannot be sure whether `api/cool_key` or `ssl/cool_key` will be used (whichever happens to be first in lookup list). - To alleviate this problem you can use full paths in Hiera, provided `v2_guess_mount: false` configuration is active. For example with: ```yaml diff --git a/lib/puppet/functions/hiera_vault.rb b/lib/puppet/functions/hiera_vault.rb index a1c1a96..2e74919 100644 --- a/lib/puppet/functions/hiera_vault.rb +++ b/lib/puppet/functions/hiera_vault.rb @@ -208,7 +208,7 @@ def vault_get(key, options, context) # Only kv mounts supported so far kv_mounts.each_pair do |mount, paths| - interpolate(context, paths).each do |path| + paths.each do |path| secretpath = context.interpolate(File.join(mount, path)) context.explain { "[hiera-vault] Looking in path #{secretpath} for #{key}" } @@ -308,31 +308,4 @@ def stringify_keys(value) value end end - - def interpolate(context, paths) - allowed_paths = [] - paths.each do |path| - path = context.interpolate(path) - # TODO: Unify usage of '/' - File.join seems to be a mistake, since it won't work on Windows - # secret/puppet/scope1,scope2 => [[secret], [puppet], [scope1, scope2]] - segments = path.split('/').map { |segment| segment.split(',') } - allowed_paths += build_paths(segments) unless segments.empty? - end - allowed_paths - end - - # [[secret], [puppet], [scope1, scope2]] => ['secret/puppet/scope1', 'secret/puppet/scope2'] - def build_paths(segments) - paths = [[]] - segments.each do |segment| - p = paths.dup - paths.clear - segment.each do |option| - p.each do |path| - paths << (path + [option]) - end - end - end - paths.map { |p| File.join(*p) } - end end diff --git a/spec/functions/hiera_vault_path_interpolation_spec.rb b/spec/functions/hiera_vault_path_interpolation_spec.rb deleted file mode 100644 index 11b31ba..0000000 --- a/spec/functions/hiera_vault_path_interpolation_spec.rb +++ /dev/null @@ -1,87 +0,0 @@ -require 'spec_helper' -require 'support/vault_server' -require 'puppet/functions/hiera_vault' - -VAULT_PATH = 'puppetv2_interpolation' - -describe FakeFunction do - let :function do - described_class.new - end - - let :context do - ctx = instance_double('Puppet::LookupContext') - allow(ctx).to receive(:cache_has_key).and_return(false) - if ENV['DEBUG'] - allow(ctx).to receive(:explain) { |&block| puts(block.call) } - else - allow(ctx).to receive(:explain).and_return(:nil) - end - allow(ctx).to receive(:not_found) - allow(ctx).to receive(:cache).with(String, anything) do |_, val| - val - end - allow(ctx).to receive(:interpolate).with(anything) do |val| - val - end - ctx - end - - let :vault_options do - { - 'address' => RSpec::VaultServer.address, - 'token' => RSpec::VaultServer.token, - 'v2_guess_mount' => false, - 'v1_lookup' => false, - 'mounts' => { - VAULT_PATH + '/data' => [ - 'common', - 'rproxy,api' - ] - } - } - end - - def vault_test_client - Vault::Client.new( - address: RSpec::VaultServer.address, - token: RSpec::VaultServer.token - ) - end - - describe '#lookup_key' do - context 'when paths contain options' do - context 'when vault is unsealed' do - before(:context) do - vault_test_client.sys.mount(VAULT_PATH, 'kv', 'puppet secrets v2', { 'options' => { version: '2' } }) - vault_test_client.kv(VAULT_PATH).write('common/test_key', { value: 'default' }) - vault_test_client.kv(VAULT_PATH).write('rproxy/ssl', { value: 'ssl' }) - vault_test_client.kv(VAULT_PATH).write('api/oauth', { value: 'oauth' }) - vault_test_client.kv(VAULT_PATH).write('api', { value: 'api_specific' }) - end - - context 'reading secrets' do - it 'returns key from first option' do - expect(function.lookup_key('ssl', vault_options, context)). - to include('value' => 'ssl') - end - - it 'returns key from second option' do - expect(function.lookup_key('oauth', vault_options, context)). - to include('value' => 'oauth') - end - - it 'returns key from second option without leaf node' do - expect(function.lookup_key('api', vault_options, context)). - to include('value' => 'api_specific') - end - - it 'returns key from second option with full path to node' do - expect(function.lookup_key('api/oauth', vault_options, context)). - to include('value' => 'oauth') - end - end - end - end - end -end