Showing with 134 additions and 91 deletions.
  1. +3 −0 .gitignore
  2. +18 −0 .pdkignore
  3. +0 −23 .project
  4. +1 −0 .puppet-lint.rc
  5. +6 −2 .rubocop.yml
  6. +20 −22 .travis.yml
  7. +6 −0 .vscode/extensions.json
  8. +8 −0 CHANGELOG.md
  9. +14 −12 Gemfile
  10. +6 −1 README.md
  11. +13 −3 Rakefile
  12. +1 −16 appveyor.yml
  13. +9 −4 lib/puppet/functions/azure_key_vault/secret.rb
  14. +8 −7 metadata.json
  15. +10 −0 spec/functions/azure_key_vault_secret_spec.rb
  16. +11 −1 spec/spec_helper.rb
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
/convert_report.txt
/update_report.txt
.DS_Store
.project
.envrc
/inventory.yaml
18 changes: 18 additions & 0 deletions .pdkignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,21 @@
/convert_report.txt
/update_report.txt
.DS_Store
.project
.envrc
/inventory.yaml
/appveyor.yml
/.fixtures.yml
/Gemfile
/.gitattributes
/.gitignore
/.gitlab-ci.yml
/.pdkignore
/Rakefile
/rakelib/
/.rspec
/.rubocop.yml
/.travis.yml
/.yardopts
/spec/
/.vscode/
23 changes: 0 additions & 23 deletions .project

This file was deleted.

1 change: 1 addition & 0 deletions .puppet-lint.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--relative
8 changes: 6 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
require: rubocop-rspec
require:
- rubocop-rspec
- rubocop-i18n
AllCops:
DisplayCopNames: true
TargetRubyVersion: '2.1'
Expand All @@ -19,10 +21,12 @@ AllCops:
Metrics/LineLength:
Description: People have wide screens, use them.
Max: 200
GetText:
Enabled: false
GetText/DecorateString:
Description: We don't want to decorate test output.
Exclude:
- spec/*
- spec/**/*
RSpec/BeforeAfterAll:
Description: Beware of using after(:all) as it may cause state to leak between tests.
A necessary evil in acceptance testing.
Expand Down
42 changes: 20 additions & 22 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,45 @@
---
sudo: false
dist: trusty
dist: xenial
language: ruby
cache: bundler
before_install:
- bundle -v
- rm -f Gemfile.lock
- gem update --system
- gem update --system $RUBYGEMS_VERSION
- gem --version
- bundle -v
script:
- 'bundle exec rake $CHECK'
bundler_args: --without system_tests
rvm:
- 2.5.1
env:
global:
- BEAKER_PUPPET_COLLECTION=puppet6 PUPPET_GEM_VERSION="~> 6.0"
- 2.5.3
stages:
- static
- spec
- acceptance
-
if: tag =~ ^v\d
name: deploy
matrix:
fast_finish: true
include:
-
env: CHECK="syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop"
-
env: CHECK=parallel_spec
env: CHECK="check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop syntax lint metadata_lint"
stage: static
-
env: PUPPET_GEM_VERSION="~> 5.0" CHECK=parallel_spec
rvm: 2.4.4
rvm: 2.4.5
stage: spec
-
env: PUPPET_GEM_VERSION="~> 6.0" CHECK=parallel_spec
rvm: 2.5.3
stage: spec
-
env: PUPPET_GEM_VERSION="~> 4.0" CHECK=parallel_spec
rvm: 2.1.9
env: DEPLOY_TO_FORGE=yes
stage: deploy
branches:
only:
- master
- /^v\d/
notifications:
email: false
deploy:
provider: puppetforge
user: puppet
password:
secure: ""
on:
tags: true
all_branches: true
condition: "$DEPLOY_TO_FORGE = yes"
6 changes: 6 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"recommendations": [
"jpogran.puppet-vscode",
"rebornix.Ruby"
]
}
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).

## [v1.1.0](https://github.com/tragiccode/tragiccode-azure_key_vault/tree/v1.1.0) (2020-02-17)

[Full Changelog](https://github.com/tragiccode/tragiccode-azure_key_vault/compare/1.0.2...v1.1.0)

### Added

- \(GH-58\) Cache Metadata API Token for lifetime of puppet run [\#59](https://github.com/TraGicCode/tragiccode-azure_key_vault/pull/59) ([TraGicCode](https://github.com/TraGicCode))

## [1.0.2](https://github.com/tragiccode/tragiccode-azure_key_vault/tree/1.0.2) (2018-12-19)

[Full Changelog](https://github.com/tragiccode/tragiccode-azure_key_vault/compare/1.0.1...1.0.2)
Expand Down
26 changes: 14 additions & 12 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments
minor_version = ruby_version_segments[0..1].join('.')

group :development do
gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0')
gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0')
gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9')
gem "json", '<= 2.0.4', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.4.4')
gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby]
gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby]
gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw]
gem "puppet-module-win-dev-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw]
gem "github_changelog_generator", require: false, git: 'https://github.com/skywinder/github-changelog-generator', ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2')
gem "puppet-strings", require: false
gem "webmock", require: false
gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0')
gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0')
gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9')
gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw]
gem "puppet-module-posix-default-r#{minor_version}", '~> 0.3', require: false, platforms: [:ruby]
gem "puppet-module-posix-dev-r#{minor_version}", '~> 0.3', require: false, platforms: [:ruby]
gem "puppet-module-win-default-r#{minor_version}", '~> 0.3', require: false, platforms: [:mswin, :mingw, :x64_mingw]
gem "puppet-module-win-dev-r#{minor_version}", '~> 0.3', require: false, platforms: [:mswin, :mingw, :x64_mingw]
gem "github_changelog_generator", require: false, git: 'https://github.com/skywinder/github-changelog-generator', ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2')
gem "puppet-strings", require: false
gem "webmock", require: false
end

puppet_version = ENV['PUPPET_GEM_VERSION']
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# azure_key_vault

[![Puppet Forge Version](https://img.shields.io/puppetforge/v/tragiccode/azure_key_vault.svg)](https://forge.puppetlabs.com/tragiccode/azure_key_vault)
[![Puppet Forge Pdk Version](http://img.shields.io/puppetforge/pdk-version/tragiccode/azure_key_vault.svg)](https://forge.puppetlabs.com/tragiccode/azure_key_vault)
[![Puppet Forge Downloads](https://img.shields.io/puppetforge/dt/tragiccode/azure_key_vault.svg)](https://forge.puppetlabs.com/tragiccode/azure_key_vault)
[![Puppet Forge Endorsement](https://img.shields.io/puppetforge/e/tragiccode/azure_key_vault.svg)](https://forge.puppetlabs.com/tragiccode/azure_key_vault)



#### Table of Contents

1. [Description](#description)
Expand All @@ -25,7 +28,7 @@ This module provides a Puppet function and a Hiera backend that allows you to ea

The module requires the following:

* Puppet Agent 4.7.1 or later.
* Puppet Agent 6.0.0 or later.
* Azure Subscription with one or more vaults already created and loaded with secrets.
* Puppet Server running on a machine with Managed Service Identity ( MSI ) and assigned the appropriate permissions
to pull secrets from the vault. To learn more or get help with this please visit https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/tutorial-windows-vm-access-nonaad
Expand All @@ -43,6 +46,8 @@ $important_secret = azure_key_vault::secret('production-vault', 'important-secre

This example fetches the latest secret with the name "important-secret" from the vault named "production-vault". Under the covers it calls the Azure instance metadata service api to get an access token in order to make authenticated requests to the vault api on-behalf-of the MSI. Once the secret is returned you can begin to use it throughout your puppet code.

> NOTE: In order to improve performance and avoid the request limit for the metadata service api the api token retrieved once then stored in a cache that exists for the duration of the puppet run.
In the above example the api_versions hash is important. It is pinning both of the Azure specific api's ( instance metadata api & vault api ) used under the hood to specific versions so that you have full control as to when your puppet code starts calling newer/older versions of the apis. In order to understand what versions are available to your regions please visit the azure documentation

* Instance Metadata Service Versions ( https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service )
Expand Down
16 changes: 13 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any?
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-syntax/tasks/puppet-syntax'
require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any?
Expand All @@ -15,15 +16,24 @@ end

def changelog_project
return unless Rake.application.top_level_tasks.include? "changelog"
returnVal = nil || JSON.load(File.read('metadata.json'))['name']
raise "unable to find the changelog_project in .sync.yml or the name in metadata.json" if returnVal.nil?

returnVal = nil
returnVal ||= begin
metadata_source = JSON.load(File.read('metadata.json'))['source']
metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z})

metadata_source_match && metadata_source_match[1]
end

raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil?

puts "GitHubChangelogGenerator project:#{returnVal}"
returnVal
end

def changelog_future_release
return unless Rake.application.top_level_tasks.include? "changelog"
returnVal = JSON.load(File.read('metadata.json'))['version']
returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version']
raise "unable to find the future_release (version) in metadata.json" if returnVal.nil?
puts "GitHubChangelogGenerator future_release:#{returnVal}"
returnVal
Expand Down
17 changes: 1 addition & 16 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ version: 1.1.x.{build}
branches:
only:
- master
- release
skip_commits:
message: /^\(?doc\)?.*/
clone_depth: 10
Expand All @@ -17,22 +18,6 @@ environment:
-
RUBY_VERSION: 24-x64
CHECK: syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop
-
PUPPET_GEM_VERSION: ~> 4.0
RUBY_VERSION: 21
CHECK: parallel_spec
-
PUPPET_GEM_VERSION: ~> 4.0
RUBY_VERSION: 21-x64
CHECK: parallel_spec
-
PUPPET_GEM_VERSION: ~> 5.0
RUBY_VERSION: 24
CHECK: parallel_spec
-
PUPPET_GEM_VERSION: ~> 5.0
RUBY_VERSION: 24-x64
CHECK: parallel_spec
-
PUPPET_GEM_VERSION: ~> 6.0
RUBY_VERSION: 25
Expand Down
13 changes: 9 additions & 4 deletions lib/puppet/functions/azure_key_vault/secret.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
require_relative '../../../puppet_x/tragiccode/azure'

# Retrieves secrets from Azure's Key Vault.
Puppet::Functions.create_function(:'azure_key_vault::secret') do
Puppet::Functions.create_function(:'azure_key_vault::secret', Puppet::Functions::InternalFunction) do
# @param vault_name Name of the vault in your Azure subcription.
# @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.
# @return [Sensitive[String]] Returns the secret as a String wrapped with the Sensitive data type.
dispatch :secret do
cache_param
required_param 'String', :vault_name
required_param 'String', :secret_name
required_param 'Hash', :api_versions_hash
optional_param 'String', :secret_version
end

def secret(vault_name, secret_name, api_versions_hash, secret_version = '')
def secret(cache, vault_name, secret_name, api_versions_hash, secret_version = '')
Puppet.debug("vault_name: #{vault_name}")
Puppet.debug("secret_name: #{secret_name}")
Puppet.debug("secret_version: #{secret_version}")
Puppet.debug("metadata_api_version: #{api_versions_hash['metadata_api_version']}")
Puppet.debug("vault_api_version: #{api_versions_hash['vault_api_version']}")
access_token = TragicCode::Azure.get_access_token(api_versions_hash['metadata_api_version'])
cache_hash = cache.retrieve(self)
unless cache_hash.key?(:access_token)
Puppet.debug("retrieving access token since it's not in the cache")
cache_hash[:access_token] = TragicCode::Azure.get_access_token(api_versions_hash['metadata_api_version'])
end
secret_value = TragicCode::Azure.get_secret(
vault_name,
secret_name,
api_versions_hash['vault_api_version'],
access_token,
cache_hash[:access_token],
secret_version,
)

Expand Down
15 changes: 8 additions & 7 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tragiccode-azure_key_vault",
"version": "1.0.2",
"version": "1.1.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 Expand Up @@ -52,14 +52,15 @@
"operatingsystemrelease": [
"2008 R2",
"2012 R2",
"2016"
"2016",
"2019"
]
}
],
"requirements": [
{
"name": "puppet",
"version_requirement": ">= 4.7.0 < 7.0.0"
"version_requirement": ">= 6.0.0 < 7.0.0"
}
],
"tags": [
Expand All @@ -68,7 +69,7 @@
"azure key vault",
"azure vault"
],
"pdk-version": "1.8.0",
"template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git",
"template-ref": "1.8.0-0-g0d9da00"
}
"pdk-version": "1.13.0",
"template-url": "pdk-default#1.13.0",
"template-ref": "1.13.0-0-g66e1443"
}
10 changes: 10 additions & 0 deletions spec/functions/azure_key_vault_secret_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,14 @@
expect(subject.execute(vault_name, secret_name, api_versions_hash)).to be_an_instance_of(Puppet::Pops::Types::PSensitiveType::Sensitive)
end
# rubocop:enable RSpec/NamedSubject

# rubocop:disable RSpec/NamedSubject
it 'retrieves access_token from cache' do
expect(TragicCode::Azure).to receive(:get_access_token).with(api_versions_hash['metadata_api_version']).and_return(access_token).once
expect(TragicCode::Azure).to receive(:get_secret).with(vault_name, secret_name, api_versions_hash['vault_api_version'], access_token, '').and_return(secret_value).twice

subject.execute(vault_name, secret_name, api_versions_hash)
subject.execute(vault_name, secret_name, api_versions_hash)
end
# rubocop:enable RSpec/NamedSubject
end
Loading