Showing with 47 additions and 18 deletions.
  1. +8 −0 CHANGELOG.md
  2. +2 −2 REFERENCE.md
  3. +3 −2 lib/puppet/functions/azure_key_vault/lookup.rb
  4. +2 −1 lib/puppet/functions/azure_key_vault/secret.rb
  5. +1 −1 metadata.json
  6. +31 −12 spec/functions/azure_key_vault_lookup_spec.rb
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org).

## [v3.0.0](https://github.com/tragiccode/tragiccode-azure_key_vault/tree/v3.0.0) (2022-08-14)

[Full Changelog](https://github.com/tragiccode/tragiccode-azure_key_vault/compare/v2.1.0...v3.0.0)

### Changed

- \(GH-95\) Wrap hiera return in puppet sensitive data type [\#96](https://github.com/TraGicCode/tragiccode-azure_key_vault/pull/96) ([TraGicCode](https://github.com/TraGicCode))

## [v2.1.0](https://github.com/tragiccode/tragiccode-azure_key_vault/tree/v2.1.0) (2022-08-08)

[Full Changelog](https://github.com/tragiccode/tragiccode-azure_key_vault/compare/v2.0.2...v2.1.0)
Expand Down
4 changes: 2 additions & 2 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The azure_key_vault::lookup function.

The azure_key_vault::lookup function.

Returns: `Any`
Returns: `Variant[Sensitive, Undef]`

##### `secret_name`

Expand Down Expand Up @@ -57,7 +57,7 @@ Returns: `Sensitive[String]` Returns the secret as a String wrapped with the Sen

Data type: `String`

Name of the vault in your Azure subcription.
Name of the vault in your Azure subscription.

##### `secret_name`

Expand Down
5 changes: 3 additions & 2 deletions lib/puppet/functions/azure_key_vault/lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
param 'Variant[String, Numeric]', :secret_name
param 'Struct[{vault_name => String, vault_api_version => String, metadata_api_version => String, confine_to_keys => Array[String], Optional[key_replacement_token] => String}]', :options
param 'Puppet::LookupContext', :context
return_type 'Variant[Sensitive, Undef]'
end

def lookup_key(secret_name, options, context)
Expand All @@ -31,7 +32,7 @@ def lookup_key(secret_name, options, context)

normalized_secret_name = TragicCode::Azure.normalize_object_name(secret_name, options['key_replacement_token'] || '-')
context.explain { "Using normalized KeyVault secret key for lookup: #{normalized_secret_name}" }
return context.cached_value(normalized_secret_name) if context.cache_has_key(normalized_secret_name)
return Puppet::Pops::Types::PSensitiveType::Sensitive.new(context.cached_value(normalized_secret_name)) if context.cache_has_key(normalized_secret_name)
access_token = context.cached_value('access_token')
if access_token.nil?
access_token = TragicCode::Azure.get_access_token(options['metadata_api_version'])
Expand All @@ -54,6 +55,6 @@ def lookup_key(secret_name, options, context)
context.not_found
return
end
context.cache(normalized_secret_name, secret_value)
Puppet::Pops::Types::PSensitiveType::Sensitive.new(context.cache(normalized_secret_name, secret_value))
end
end
3 changes: 2 additions & 1 deletion lib/puppet/functions/azure_key_vault/secret.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Retrieves secrets from Azure's Key Vault.
Puppet::Functions.create_function(:'azure_key_vault::secret', Puppet::Functions::InternalFunction) do
# @param vault_name Name of the vault in your Azure subcription.
# @param vault_name Name of the vault in your Azure subscription.
# @param secret_name Name of the secret to be retrieved.
# @param api_versions_hash A Hash of the exact versions of the metadata_api_version and vault_api_version to use.
# @param secret_version The version of the secret you want to retrieve. This parameter is optional and if not passed the default behavior is to retrieve the latest version.
Expand All @@ -13,6 +13,7 @@
required_param 'String', :secret_name
required_param 'Hash', :api_versions_hash
optional_param 'String', :secret_version
return_type 'Sensitive[String]'
end

def secret(cache, vault_name, secret_name, api_versions_hash, secret_version = '')
Expand Down
2 changes: 1 addition & 1 deletion metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tragiccode-azure_key_vault",
"version": "2.1.0",
"version": "3.0.0",
"author": "tragiccode",
"summary": "The azure_key_vault module allows you to easily fetch secrets securely within your puppet manifests.",
"license": "Apache-2.0",
Expand Down
43 changes: 31 additions & 12 deletions spec/functions/azure_key_vault_lookup_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@
'profile::windows::sqlserver::sensitive_azure_sql_user_password', { 'key1' => 'value1' }, lookup_context
).and_raise_error(ArgumentError)
end

# rubocop:disable RSpec/NamedSubject
it 'uses the cache' do
expect(lookup_context).to receive(:cache_has_key).with('profile--windows--sqlserver--sensitive-azure-sql-user-password').and_return(true)
expect(lookup_context).to receive(:cached_value).with('profile--windows--sqlserver--sensitive-azure-sql-user-password').and_return('value')
is_expected.to run.with_params(
'profile::windows::sqlserver::sensitive_azure_sql_user_password', options, lookup_context
).and_return('value')

expect(subject.execute('profile::windows::sqlserver::sensitive_azure_sql_user_password', options, lookup_context).unwrap).to eq 'value'
end
# rubocop:enable RSpec/NamedSubject

# rubocop:disable RSpec/NamedSubject
it 'caches the access token after a cache miss' do
access_token_value = 'access_value'
secret_value = 'secret_value'
Expand All @@ -48,10 +52,10 @@
expect(lookup_context).to receive(:cache).with('access_token', access_token_value).ordered
expect(TragicCode::Azure).to receive(:get_secret).and_return(secret_value)
expect(lookup_context).to receive(:cache).and_return(secret_value).ordered
is_expected.to run.with_params(
'profile::windows::sqlserver::sensitive_azure_sql_user_password', options, lookup_context
).and_return(secret_value)

expect(subject.execute('profile::windows::sqlserver::sensitive_azure_sql_user_password', options, lookup_context).unwrap).to eq secret_value
end
# rubocop:enable RSpec/NamedSubject

it 'call context.not_found for the lookup_options key' do
expect(lookup_context).to receive(:not_found)
Expand All @@ -60,17 +64,18 @@
)
end

# rubocop:disable RSpec/NamedSubject
it 'uses - as the default key_replacement_token' do
secret_name = 'profile::windows::sqlserver::sensitive_azure_sql_user_password'
access_token_value = 'access_value'
secret_value = 'secret_value'
expect(TragicCode::Azure).to receive(:normalize_object_name).with(secret_name, '-')
expect(TragicCode::Azure).to receive(:get_access_token).and_return(access_token_value)
expect(TragicCode::Azure).to receive(:get_secret).and_return(secret_value)
is_expected.to run.with_params(
'profile::windows::sqlserver::sensitive_azure_sql_user_password', options, lookup_context
).and_return(secret_value)

expect(subject.execute('profile::windows::sqlserver::sensitive_azure_sql_user_password', options, lookup_context).unwrap).to eq secret_value
end
# rubocop:enable RSpec/NamedSubject

it 'errors when confine_to_keys is no array' do
is_expected.to run.with_params(
Expand All @@ -84,15 +89,17 @@
).and_raise_error(ArgumentError, %r{creating regexp failed with}i)
end

# rubocop:disable RSpec/NamedSubject
it 'returns the key if regex matches confine_to_keys' do
access_token_value = 'access_value'
secret_value = 'secret_value'
expect(TragicCode::Azure).to receive(:get_access_token).and_return(access_token_value)
expect(TragicCode::Azure).to receive(:get_secret).and_return(secret_value)
is_expected.to run.with_params(
'profile::windows::sqlserver::sensitive_azure_sql_user_password', options.merge({ 'confine_to_keys' => ['^.*sensitive_azure.*'] }), lookup_context
).and_return(secret_value)

expect(subject.execute('profile::windows::sqlserver::sensitive_azure_sql_user_password', options.merge({ 'confine_to_keys' => ['^.*sensitive_azure.*'] }), lookup_context).unwrap)
.to eq secret_value
end
# rubocop:enable RSpec/NamedSubject

it 'does not return the key if regex does not match confine_to_keys' do
access_token_value = 'access_value'
Expand All @@ -118,4 +125,16 @@
'profile::windows::sqlserver::sensitive_azure_sql_user_password', options.merge({ 'confine_to_keys' => ['^.*sensitive_azure.*'] }), lookup_context
)
end

# rubocop:disable RSpec/NamedSubject
it 'returns the secret wrapped in the sensitive data type' do
access_token_value = 'access_value'
secret_value = 'secret_value'
expect(TragicCode::Azure).to receive(:get_access_token).and_return(access_token_value)
expect(TragicCode::Azure).to receive(:get_secret).and_return(secret_value)

expect(subject.execute('profile::windows::sqlserver::sensitive_azure_sql_user_password', options.merge({ 'confine_to_keys' => ['^.*sensitive_azure.*'] }), lookup_context))
.to be_an_instance_of(Puppet::Pops::Types::PSensitiveType::Sensitive)
end
# rubocop:enable RSpec/NamedSubject
end